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
25 extern rx_atomic_t rxinit_status;
28 rx_upcall(socket_t so, void *arg, __unused int waitflag)
34 struct sockaddr_storage ss;
35 struct sockaddr *sa = NULL;
36 struct sockaddr_in from;
40 afs_int32 savelen; /* was using rlen but had aliasing problems */
41 size_t nbytes, resid, noffset;
43 /* we stopped rx but the socket isn't closed yet */
44 if (rx_atomic_test_bit(&rxinit_status, 0))
47 /* See if a check for additional packets was issued */
50 p = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
51 rx_computelen(p, tlen);
52 rx_SetDataSize(p, tlen); /* this is the size of the user data area */
53 tlen += RX_HEADER_SIZE; /* now this is the size of the entire packet */
54 rlen = rx_maxJumboRecvSize; /* this is what I am advertising. Only check
55 * it once in order to avoid races. */
58 tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_RECV_CBUF);
65 /* add some padding to the last iovec, it's just to make sure that the
66 * read doesn't return more data than we expect, and is done to get around
67 * our problems caused by the lack of a length field in the rx header. */
68 savelen = p->wirevec[p->niovecs - 1].iov_len;
69 p->wirevec[p->niovecs - 1].iov_len = savelen + RX_EXTRABUFFERSIZE;
71 resid = nbytes = tlen + sizeof(afs_int32);
73 memset(&msg, 0, sizeof(struct msghdr));
75 msg.msg_namelen = sizeof(struct sockaddr_storage);
76 sa =(struct sockaddr *) &ss;
80 error = sock_receivembuf(so, &msg, &m, MSG_DONTWAIT, &nbytes);
82 size_t sz, offset = 0;
85 for (i=0;i<p->niovecs && resid;i++) {
86 sz=MIN(resid, p->wirevec[i].iov_len);
87 error = mbuf_copydata(m, offset, sz, p->wirevec[i].iov_base);
99 /* restore the vec to its correct state */
100 p->wirevec[p->niovecs - 1].iov_len = savelen;
102 if (error == EWOULDBLOCK && noffset > 0)
110 if (sa->sa_family == AF_INET)
111 from = *(struct sockaddr_in *)sa;
113 p->length = nbytes - RX_HEADER_SIZE;;
114 if ((nbytes > tlen) || (p->length & 0x8000)) { /* Bogus packet */
116 if (rx_stats_active) {
117 MUTEX_ENTER(&rx_stats_mutex);
118 rx_atomic_inc(&rx_stats.bogusPacketOnRead);
119 rx_stats.bogusHost = from.sin_addr.s_addr;
120 MUTEX_EXIT(&rx_stats_mutex);
122 dpf(("B: bogus packet from [%x,%d] nb=%d",
123 from.sin_addr.s_addr, from.sin_port, nbytes));
127 /* Extract packet header. */
128 rxi_DecodePacketHeader(p);
130 host = from.sin_addr.s_addr;
131 port = from.sin_port;
132 if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) {
133 if (rx_stats_active) {
134 rx_atomic_inc(&rx_stats.packetsRead[p->header.type - 1]);
138 #ifdef RX_TRIMDATABUFS
139 /* Free any empty packet buffers at the end of this packet */
140 rxi_TrimDataBufs(p, 1);
143 p = rxi_ReceivePacket(p, so, host, port, 0, 0);
153 /* in listener env, the listener shutdown does this. we have no listener */
155 osi_StopNetIfPoller(void)
159 if (afs_termState == AFSOP_STOP_NETIF) {
160 afs_termState = AFSOP_STOP_COMPLETE;
161 osi_rxWakeup(&afs_termState);
164 #elif defined(RXK_LISTENER_ENV)
166 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
167 int nvecs, int *alength)
169 #ifdef AFS_DARWIN80_ENV
170 socket_t asocket = (socket_t)so;
172 struct sockaddr_storage ss;
176 struct socket *asocket = (struct socket *)so;
180 struct iovec iov[RX_MAXIOVECS];
181 struct sockaddr *sa = NULL;
185 int haveGlock = ISAFS_GLOCK();
186 /*AFS_STATCNT(osi_NetReceive); */
188 if (nvecs > RX_MAXIOVECS)
189 osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
191 for (i = 0; i < nvecs; i++)
194 if ((afs_termState == AFSOP_STOP_RXK_LISTENER) ||
195 (afs_termState == AFSOP_STOP_COMPLETE))
200 #if defined(KERNEL_FUNNEL)
201 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
203 #ifdef AFS_DARWIN80_ENV
205 memset(&msg, 0, sizeof(struct msghdr));
207 msg.msg_namelen = sizeof(struct sockaddr_storage);
208 sa =(struct sockaddr *) &ss;
209 code = sock_receivembuf(asocket, &msg, &m, 0, alength);
213 for (i=0;i<nvecs && resid;i++) {
214 sz=MIN(resid, iov[i].iov_len);
215 code = mbuf_copydata(m, offset, sz, iov[i].iov_base);
226 u.uio_iovcnt = nvecs;
228 u.uio_resid = *alength;
229 u.uio_segflg = UIO_SYSSPACE;
232 code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
236 #if defined(KERNEL_FUNNEL)
237 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
246 if (sa->sa_family == AF_INET) {
248 *addr = *(struct sockaddr_in *)sa;
250 printf("Unknown socket family %d in NetReceive\n", sa->sa_family);
251 #ifndef AFS_DARWIN80_ENV
258 extern int rxk_ListenerPid;
260 osi_StopListener(void)
264 #if defined(KERNEL_FUNNEL)
265 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
268 #if defined(KERNEL_FUNNEL)
269 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
271 #ifndef AFS_DARWIN80_ENV
272 p = pfind(rxk_ListenerPid);
278 #error need upcall or listener
282 osi_NetSend(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
283 int nvecs, afs_int32 alength, int istack)
285 #ifdef AFS_DARWIN80_ENV
286 socket_t asocket = (socket_t)so;
290 struct socket *asocket = (struct socket *)so;
295 struct iovec iov[RX_MAXIOVECS];
296 int haveGlock = ISAFS_GLOCK();
298 AFS_STATCNT(osi_NetSend);
299 if (nvecs > RX_MAXIOVECS)
300 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
302 for (i = 0; i < nvecs; i++)
305 addr->sin_len = sizeof(struct sockaddr_in);
307 if ((afs_termState == AFSOP_STOP_RXK_LISTENER) ||
308 (afs_termState == AFSOP_STOP_COMPLETE))
314 #if defined(KERNEL_FUNNEL)
315 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
317 #ifdef AFS_DARWIN80_ENV
318 memset(&msg, 0, sizeof(struct msghdr));
320 msg.msg_namelen = ((struct sockaddr *)addr)->sa_len;
321 msg.msg_iov = &iov[0];
322 msg.msg_iovlen = nvecs;
323 code = sock_send(asocket, &msg, 0, &slen);
326 u.uio_iovcnt = nvecs;
328 u.uio_resid = alength;
329 u.uio_segflg = UIO_SYSSPACE;
330 u.uio_rw = UIO_WRITE;
332 code = sosend(asocket, (struct sockaddr *)addr, &u, NULL, NULL, 0);
335 #if defined(KERNEL_FUNNEL)
336 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);