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"
16 #ifdef AFS_DARWIN80_ENV
17 #define soclose sock_close
22 rx_upcall(socket_t so, void *arg, __unused int waitflag)
28 struct sockaddr_storage ss;
29 struct sockaddr *sa = NULL;
30 struct sockaddr_in from;
34 afs_int32 savelen; /* was using rlen but had aliasing problems */
35 size_t nbytes, resid, noffset;
37 p = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
38 rx_computelen(p, tlen);
39 rx_SetDataSize(p, tlen); /* this is the size of the user data area */
40 tlen += RX_HEADER_SIZE; /* now this is the size of the entire packet */
41 rlen = rx_maxJumboRecvSize; /* this is what I am advertising. Only check
42 * it once in order to avoid races. */
45 tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_RECV_CBUF);
52 /* add some padding to the last iovec, it's just to make sure that the
53 * read doesn't return more data than we expect, and is done to get around
54 * our problems caused by the lack of a length field in the rx header. */
55 savelen = p->wirevec[p->niovecs - 1].iov_len;
56 p->wirevec[p->niovecs - 1].iov_len = savelen + RX_EXTRABUFFERSIZE;
58 resid = nbytes = tlen + sizeof(afs_int32);
60 memset(&msg, 0, sizeof(struct msghdr));
62 msg.msg_namelen = sizeof(struct sockaddr_storage);
63 sa =(struct sockaddr *) &ss;
67 error = sock_receivembuf(so, &msg, &m, MSG_DONTWAIT, &nbytes);
69 size_t sz, offset = 0;
72 for (i=0;i<p->niovecs && resid;i++) {
73 sz=MIN(resid, p->wirevec[i].iov_len);
74 error = mbuf_copydata(m, offset, sz, p->wirevec[i].iov_base);
86 /* restore the vec to its correct state */
87 p->wirevec[p->niovecs - 1].iov_len = savelen;
89 if (error == EWOULDBLOCK && noffset > 0)
97 if (sa->sa_family == AF_INET)
98 from = *(struct sockaddr_in *)sa;
100 p->length = nbytes - RX_HEADER_SIZE;;
101 if ((nbytes > tlen) || (p->length & 0x8000)) { /* Bogus packet */
103 if (rx_stats_active) {
104 MUTEX_ENTER(&rx_stats_mutex);
105 rx_stats.bogusPacketOnRead++;
106 rx_stats.bogusHost = from.sin_addr.s_addr;
107 MUTEX_EXIT(&rx_stats_mutex);
109 dpf(("B: bogus packet from [%x,%d] nb=%d",
110 from.sin_addr.s_addr, from.sin_port, nbytes));
114 /* Extract packet header. */
115 rxi_DecodePacketHeader(p);
117 host = from.sin_addr.s_addr;
118 port = from.sin_port;
119 if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) {
120 if (rx_stats_active) {
121 MUTEX_ENTER(&rx_stats_mutex);
122 rx_stats.packetsRead[p->header.type - 1]++;
123 MUTEX_EXIT(&rx_stats_mutex);
127 #ifdef RX_TRIMDATABUFS
128 /* Free any empty packet buffers at the end of this packet */
129 rxi_TrimDataBufs(p, 1);
132 p = rxi_ReceivePacket(p, so, host, port, 0, 0);
142 /* in listener env, the listener shutdown does this. we have no listener */
144 osi_StopNetIfPoller(void)
147 if (afs_termState == AFSOP_STOP_NETIF) {
148 afs_termState = AFSOP_STOP_COMPLETE;
149 osi_rxWakeup(&afs_termState);
152 #elif defined(RXK_LISTENER_ENV)
154 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
155 int nvecs, int *alength)
157 #ifdef AFS_DARWIN80_ENV
158 socket_t asocket = (socket_t)so;
160 struct sockaddr_storage ss;
164 struct socket *asocket = (struct socket *)so;
168 struct iovec iov[RX_MAXIOVECS];
169 struct sockaddr *sa = NULL;
173 int haveGlock = ISAFS_GLOCK();
174 /*AFS_STATCNT(osi_NetReceive); */
176 if (nvecs > RX_MAXIOVECS)
177 osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
179 for (i = 0; i < nvecs; i++)
182 if ((afs_termState == AFSOP_STOP_RXK_LISTENER) ||
183 (afs_termState == AFSOP_STOP_COMPLETE))
188 #if defined(KERNEL_FUNNEL)
189 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
191 #ifdef AFS_DARWIN80_ENV
193 memset(&msg, 0, sizeof(struct msghdr));
195 msg.msg_namelen = sizeof(struct sockaddr_storage);
196 sa =(struct sockaddr *) &ss;
197 code = sock_receivembuf(asocket, &msg, &m, 0, alength);
201 for (i=0;i<nvecs && resid;i++) {
202 sz=MIN(resid, iov[i].iov_len);
203 code = mbuf_copydata(m, offset, sz, iov[i].iov_base);
214 u.uio_iovcnt = nvecs;
216 u.uio_resid = *alength;
217 u.uio_segflg = UIO_SYSSPACE;
220 code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
224 #if defined(KERNEL_FUNNEL)
225 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
234 if (sa->sa_family == AF_INET) {
236 *addr = *(struct sockaddr_in *)sa;
238 printf("Unknown socket family %d in NetReceive\n", sa->sa_family);
239 #ifndef AFS_DARWIN80_ENV
246 extern int rxk_ListenerPid;
248 osi_StopListener(void)
252 #if defined(KERNEL_FUNNEL)
253 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
256 #if defined(KERNEL_FUNNEL)
257 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
259 #ifndef AFS_DARWIN80_ENV
260 p = pfind(rxk_ListenerPid);
266 #error need upcall or listener
270 osi_NetSend(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
271 int nvecs, afs_int32 alength, int istack)
273 #ifdef AFS_DARWIN80_ENV
274 socket_t asocket = (socket_t)so;
278 struct socket *asocket = (struct socket *)so;
283 struct iovec iov[RX_MAXIOVECS];
284 int haveGlock = ISAFS_GLOCK();
286 AFS_STATCNT(osi_NetSend);
287 if (nvecs > RX_MAXIOVECS)
288 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
290 for (i = 0; i < nvecs; i++)
293 addr->sin_len = sizeof(struct sockaddr_in);
295 if ((afs_termState == AFSOP_STOP_RXK_LISTENER) ||
296 (afs_termState == AFSOP_STOP_COMPLETE))
302 #if defined(KERNEL_FUNNEL)
303 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
305 #ifdef AFS_DARWIN80_ENV
306 memset(&msg, 0, sizeof(struct msghdr));
308 msg.msg_namelen = ((struct sockaddr *)addr)->sa_len;
309 msg.msg_iov = &iov[0];
310 msg.msg_iovlen = nvecs;
311 code = sock_send(asocket, &msg, 0, &slen);
314 u.uio_iovcnt = nvecs;
316 u.uio_resid = alength;
317 u.uio_segflg = UIO_SYSSPACE;
318 u.uio_rw = UIO_WRITE;
320 code = sosend(asocket, (struct sockaddr *)addr, &u, NULL, NULL, 0);
323 #if defined(KERNEL_FUNNEL)
324 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);