2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "afs/param.h"
14 #include "rx/rx_kcommon.h"
15 #include "rx/rx_atomic.h"
16 #include "rx/rx_internal.h"
17 #include "rx/rx_packet.h"
18 #include "rx/rx_stats.h"
20 #ifdef AFS_DARWIN80_ENV
21 #define soclose sock_close
26 rx_upcall(socket_t so
, void *arg
, __unused
int waitflag
)
32 struct sockaddr_storage ss
;
33 struct sockaddr
*sa
= NULL
;
34 struct sockaddr_in from
;
38 afs_int32 savelen
; /* was using rlen but had aliasing problems */
39 size_t nbytes
, resid
, noffset
;
41 /* we stopped rx but the socket isn't closed yet */
45 /* See if a check for additional packets was issued */
48 p
= rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE
);
49 rx_computelen(p
, tlen
);
50 rx_SetDataSize(p
, tlen
); /* this is the size of the user data area */
51 tlen
+= RX_HEADER_SIZE
; /* now this is the size of the entire packet */
52 rlen
= rx_maxJumboRecvSize
; /* this is what I am advertising. Only check
53 * it once in order to avoid races. */
56 tlen
= rxi_AllocDataBuf(p
, tlen
, RX_PACKET_CLASS_RECV_CBUF
);
63 /* add some padding to the last iovec, it's just to make sure that the
64 * read doesn't return more data than we expect, and is done to get around
65 * our problems caused by the lack of a length field in the rx header. */
66 savelen
= p
->wirevec
[p
->niovecs
- 1].iov_len
;
67 p
->wirevec
[p
->niovecs
- 1].iov_len
= savelen
+ RX_EXTRABUFFERSIZE
;
69 resid
= nbytes
= tlen
+ sizeof(afs_int32
);
71 memset(&msg
, 0, sizeof(struct msghdr
));
73 msg
.msg_namelen
= sizeof(struct sockaddr_storage
);
74 sa
=(struct sockaddr
*) &ss
;
78 error
= sock_receivembuf(so
, &msg
, &m
, MSG_DONTWAIT
, &nbytes
);
80 size_t sz
, offset
= 0;
83 for (i
=0;i
<p
->niovecs
&& resid
;i
++) {
84 sz
=MIN(resid
, p
->wirevec
[i
].iov_len
);
85 error
= mbuf_copydata(m
, offset
, sz
, p
->wirevec
[i
].iov_base
);
97 /* restore the vec to its correct state */
98 p
->wirevec
[p
->niovecs
- 1].iov_len
= savelen
;
100 if (error
== EWOULDBLOCK
&& noffset
> 0)
108 if (sa
->sa_family
== AF_INET
)
109 from
= *(struct sockaddr_in
*)sa
;
111 p
->length
= nbytes
- RX_HEADER_SIZE
;;
112 if ((nbytes
> tlen
) || (p
->length
& 0x8000)) { /* Bogus packet */
114 if (rx_stats_active
) {
115 MUTEX_ENTER(&rx_stats_mutex
);
116 rx_atomic_inc(&rx_stats
.bogusPacketOnRead
);
117 rx_stats
.bogusHost
= from
.sin_addr
.s_addr
;
118 MUTEX_EXIT(&rx_stats_mutex
);
120 dpf(("B: bogus packet from [%x,%d] nb=%d",
121 from
.sin_addr
.s_addr
, from
.sin_port
, nbytes
));
125 /* Extract packet header. */
126 rxi_DecodePacketHeader(p
);
128 host
= from
.sin_addr
.s_addr
;
129 port
= from
.sin_port
;
130 if (p
->header
.type
> 0 && p
->header
.type
< RX_N_PACKET_TYPES
) {
131 if (rx_stats_active
) {
132 rx_atomic_inc(&rx_stats
.packetsRead
[p
->header
.type
- 1]);
136 #ifdef RX_TRIMDATABUFS
137 /* Free any empty packet buffers at the end of this packet */
138 rxi_TrimDataBufs(p
, 1);
141 p
= rxi_ReceivePacket(p
, so
, host
, port
, 0, 0);
151 /* in listener env, the listener shutdown does this. we have no listener */
153 osi_StopNetIfPoller(void)
157 if (afs_termState
== AFSOP_STOP_NETIF
) {
158 afs_termState
= AFSOP_STOP_COMPLETE
;
159 osi_rxWakeup(&afs_termState
);
162 #elif defined(RXK_LISTENER_ENV)
164 osi_NetReceive(osi_socket so
, struct sockaddr_in
*addr
, struct iovec
*dvec
,
165 int nvecs
, int *alength
)
168 struct iovec iov
[RX_MAXIOVECS
];
169 struct sockaddr
*sa
= NULL
;
173 int haveGlock
= ISAFS_GLOCK();
175 #ifdef AFS_DARWIN80_ENV
176 socket_t asocket
= (socket_t
)so
;
178 struct sockaddr_storage ss
;
182 struct socket
*asocket
= (struct socket
*)so
;
184 memset(&u
, 0, sizeof(u
));
186 memset(&iov
, 0, sizeof(iov
));
187 /*AFS_STATCNT(osi_NetReceive); */
189 if (nvecs
> RX_MAXIOVECS
)
190 osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs
);
192 for (i
= 0; i
< nvecs
; i
++)
195 if ((afs_termState
== AFSOP_STOP_RXK_LISTENER
) ||
196 (afs_termState
== AFSOP_STOP_COMPLETE
))
201 #if defined(KERNEL_FUNNEL)
202 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
204 #ifdef AFS_DARWIN80_ENV
206 memset(&msg
, 0, sizeof(struct msghdr
));
208 msg
.msg_namelen
= sizeof(struct sockaddr_storage
);
209 sa
=(struct sockaddr
*) &ss
;
210 code
= sock_receivembuf(asocket
, &msg
, &m
, 0, alength
);
214 for (i
=0;i
<nvecs
&& resid
;i
++) {
215 sz
=MIN(resid
, iov
[i
].iov_len
);
216 code
= mbuf_copydata(m
, offset
, sz
, iov
[i
].iov_base
);
227 u
.uio_iovcnt
= nvecs
;
229 u
.uio_resid
= *alength
;
230 u
.uio_segflg
= UIO_SYSSPACE
;
233 code
= soreceive(asocket
, &sa
, &u
, NULL
, NULL
, NULL
);
237 #if defined(KERNEL_FUNNEL)
238 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
247 if (sa
->sa_family
== AF_INET
) {
249 *addr
= *(struct sockaddr_in
*)sa
;
251 printf("Unknown socket family %d in NetReceive\n", sa
->sa_family
);
252 #ifndef AFS_DARWIN80_ENV
259 extern int rxk_ListenerPid
;
261 osi_StopListener(void)
265 #if defined(KERNEL_FUNNEL)
266 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
269 #if defined(KERNEL_FUNNEL)
270 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
272 #ifndef AFS_DARWIN80_ENV
273 p
= pfind(rxk_ListenerPid
);
279 #error need upcall or listener
283 osi_NetSend(osi_socket so
, struct sockaddr_in
*addr
, struct iovec
*dvec
,
284 int nvecs
, afs_int32 alength
, int istack
)
288 struct iovec iov
[RX_MAXIOVECS
];
289 int haveGlock
= ISAFS_GLOCK();
290 #ifdef AFS_DARWIN80_ENV
291 socket_t asocket
= (socket_t
)so
;
295 struct socket
*asocket
= (struct socket
*)so
;
297 memset(&u
, 0, sizeof(u
));
299 memset(&iov
, 0, sizeof(iov
));
301 AFS_STATCNT(osi_NetSend
);
302 if (nvecs
> RX_MAXIOVECS
)
303 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs
);
305 for (i
= 0; i
< nvecs
; i
++)
308 addr
->sin_len
= sizeof(struct sockaddr_in
);
310 if ((afs_termState
== AFSOP_STOP_RXK_LISTENER
) ||
311 (afs_termState
== AFSOP_STOP_COMPLETE
))
317 #if defined(KERNEL_FUNNEL)
318 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
320 #ifdef AFS_DARWIN80_ENV
321 memset(&msg
, 0, sizeof(struct msghdr
));
323 msg
.msg_namelen
= ((struct sockaddr
*)addr
)->sa_len
;
324 msg
.msg_iov
= &iov
[0];
325 msg
.msg_iovlen
= nvecs
;
326 code
= sock_send(asocket
, &msg
, 0, &slen
);
329 u
.uio_iovcnt
= nvecs
;
331 u
.uio_resid
= alength
;
332 u
.uio_segflg
= UIO_SYSSPACE
;
333 u
.uio_rw
= UIO_WRITE
;
335 code
= sosend(asocket
, (struct sockaddr
*)addr
, &u
, NULL
, NULL
, 0);
338 #if defined(KERNEL_FUNNEL)
339 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);