rx: Hide the rx_packet.h
[openafs.git] / src / rx / DARWIN / rx_knet.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #include "afs/param.h"
12
13
14 #include "rx/rx_kcommon.h"
15 #include "rx/rx_packet.h"
16 #include "rx/rx_atomic.h"
17 #include "rx/rx_stats.h"
18
19 #ifdef AFS_DARWIN80_ENV
20 #define soclose sock_close
21 #endif
22
23 #ifdef RXK_UPCALL_ENV
24 void
25 rx_upcall(socket_t so, void *arg, __unused int waitflag)
26 {
27     mbuf_t m;
28     int error = 0;
29     int i, flags = 0;
30     struct msghdr msg;
31     struct sockaddr_storage ss;
32     struct sockaddr *sa = NULL;
33     struct sockaddr_in from;
34     struct rx_packet *p;
35     afs_int32 rlen;
36     afs_int32 tlen;
37     afs_int32 savelen;          /* was using rlen but had aliasing problems */
38     size_t nbytes, resid, noffset;
39
40     p = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
41     rx_computelen(p, tlen);
42     rx_SetDataSize(p, tlen);    /* this is the size of the user data area */
43     tlen += RX_HEADER_SIZE;     /* now this is the size of the entire packet */
44     rlen = rx_maxJumboRecvSize; /* this is what I am advertising.  Only check
45                                  * it once in order to avoid races.  */
46     tlen = rlen - tlen;
47     if (tlen > 0) {
48         tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_RECV_CBUF);
49         if (tlen > 0) {
50             tlen = rlen - tlen;
51         } else
52             tlen = rlen;
53     } else
54         tlen = rlen;
55     /* add some padding to the last iovec, it's just to make sure that the
56      * read doesn't return more data than we expect, and is done to get around
57      * our problems caused by the lack of a length field in the rx header. */
58     savelen = p->wirevec[p->niovecs - 1].iov_len;
59     p->wirevec[p->niovecs - 1].iov_len = savelen + RX_EXTRABUFFERSIZE;
60
61     resid = nbytes = tlen + sizeof(afs_int32);
62
63     memset(&msg, 0, sizeof(struct msghdr));
64     msg.msg_name = &ss;
65     msg.msg_namelen = sizeof(struct sockaddr_storage);
66     sa =(struct sockaddr *) &ss;
67
68     do {
69         m = NULL;
70         error = sock_receivembuf(so, &msg, &m, MSG_DONTWAIT, &nbytes);
71         if (!error) {
72             size_t sz, offset = 0;
73             noffset = 0;
74             resid = nbytes;
75             for (i=0;i<p->niovecs && resid;i++) {
76                 sz=MIN(resid, p->wirevec[i].iov_len);
77                 error = mbuf_copydata(m, offset, sz, p->wirevec[i].iov_base);
78                 if (error)
79                     break;
80                 resid-=sz;
81                 offset+=sz;
82                 noffset += sz;
83             }
84         }
85     } while (0);
86
87     mbuf_freem(m);
88
89     /* restore the vec to its correct state */
90     p->wirevec[p->niovecs - 1].iov_len = savelen;
91
92     if (error == EWOULDBLOCK && noffset > 0)
93         error = 0;
94
95     if (!error) {
96         int host, port;
97
98         nbytes -= resid;
99
100         if (sa->sa_family == AF_INET)
101             from = *(struct sockaddr_in *)sa;
102
103         p->length = nbytes - RX_HEADER_SIZE;;
104         if ((nbytes > tlen) || (p->length & 0x8000)) {  /* Bogus packet */
105             if (nbytes <= 0) {
106                 if (rx_stats_active) {
107                     MUTEX_ENTER(&rx_stats_mutex);
108                     rx_atomic_inc(&rx_stats.bogusPacketOnRead);
109                     rx_stats.bogusHost = from.sin_addr.s_addr;
110                     MUTEX_EXIT(&rx_stats_mutex);
111                 }
112                 dpf(("B: bogus packet from [%x,%d] nb=%d",
113                      from.sin_addr.s_addr, from.sin_port, nbytes));
114             }
115             return;
116         } else {
117             /* Extract packet header. */
118             rxi_DecodePacketHeader(p);
119
120             host = from.sin_addr.s_addr;
121             port = from.sin_port;
122             if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) {
123                 if (rx_stats_active) {
124                     rx_atomic_inc(&rx_stats.packetsRead[p->header.type - 1]);
125                 }
126             }
127
128 #ifdef RX_TRIMDATABUFS
129             /* Free any empty packet buffers at the end of this packet */
130             rxi_TrimDataBufs(p, 1);
131 #endif
132             /* receive pcket */
133             p = rxi_ReceivePacket(p, so, host, port, 0, 0);
134         }
135     }
136     /* free packet? */
137     if (p)
138         rxi_FreePacket(p);
139
140     return;
141 }
142
143 /* in listener env, the listener shutdown does this. we have no listener */
144 void
145 osi_StopNetIfPoller(void)
146 {
147     shutdown_rx();
148     soclose(rx_socket);
149     if (afs_termState == AFSOP_STOP_NETIF) {
150         afs_termState = AFSOP_STOP_COMPLETE;
151         osi_rxWakeup(&afs_termState);
152     }
153 }
154 #elif defined(RXK_LISTENER_ENV)
155 int
156 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
157                int nvecs, int *alength)
158 {
159 #ifdef AFS_DARWIN80_ENV
160     socket_t asocket = (socket_t)so;
161     struct msghdr msg;
162     struct sockaddr_storage ss;
163     int rlen;
164     mbuf_t m;
165 #else
166     struct socket *asocket = (struct socket *)so;
167     struct uio u;
168 #endif
169     int i;
170     struct iovec iov[RX_MAXIOVECS];
171     struct sockaddr *sa = NULL;
172     int code;
173     size_t resid;
174
175     int haveGlock = ISAFS_GLOCK();
176     /*AFS_STATCNT(osi_NetReceive); */
177
178     if (nvecs > RX_MAXIOVECS)
179         osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
180
181     for (i = 0; i < nvecs; i++)
182         iov[i] = dvec[i];
183
184     if ((afs_termState == AFSOP_STOP_RXK_LISTENER) ||
185         (afs_termState == AFSOP_STOP_COMPLETE))
186         return -1;
187
188     if (haveGlock)
189         AFS_GUNLOCK();
190 #if defined(KERNEL_FUNNEL)
191     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
192 #endif
193 #ifdef AFS_DARWIN80_ENV
194     resid = *alength;
195     memset(&msg, 0, sizeof(struct msghdr));
196     msg.msg_name = &ss;
197     msg.msg_namelen = sizeof(struct sockaddr_storage);
198     sa =(struct sockaddr *) &ss;
199     code = sock_receivembuf(asocket, &msg, &m, 0, alength);
200     if (!code) {
201         size_t offset=0,sz;
202         resid = *alength;
203         for (i=0;i<nvecs && resid;i++) {
204             sz=MIN(resid, iov[i].iov_len);
205             code = mbuf_copydata(m, offset, sz, iov[i].iov_base);
206             if (code)
207                 break;
208             resid-=sz;
209             offset+=sz;
210         }
211     }
212     mbuf_freem(m);
213 #else
214
215     u.uio_iov = &iov[0];
216     u.uio_iovcnt = nvecs;
217     u.uio_offset = 0;
218     u.uio_resid = *alength;
219     u.uio_segflg = UIO_SYSSPACE;
220     u.uio_rw = UIO_READ;
221     u.uio_procp = NULL;
222     code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
223     resid = u.uio_resid;
224 #endif
225
226 #if defined(KERNEL_FUNNEL)
227     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
228 #endif
229     if (haveGlock)
230         AFS_GLOCK();
231
232     if (code)
233         return code;
234     *alength -= resid;
235     if (sa) {
236         if (sa->sa_family == AF_INET) {
237             if (addr)
238                 *addr = *(struct sockaddr_in *)sa;
239         } else
240             printf("Unknown socket family %d in NetReceive\n", sa->sa_family);
241 #ifndef AFS_DARWIN80_ENV
242         FREE(sa, M_SONAME);
243 #endif
244     }
245     return code;
246 }
247
248 extern int rxk_ListenerPid;
249 void
250 osi_StopListener(void)
251 {
252     struct proc *p;
253
254 #if defined(KERNEL_FUNNEL)
255     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
256 #endif
257     soclose(rx_socket);
258 #if defined(KERNEL_FUNNEL)
259     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
260 #endif
261 #ifndef AFS_DARWIN80_ENV
262     p = pfind(rxk_ListenerPid);
263     if (p)
264         psignal(p, SIGUSR1);
265 #endif
266 }
267 #else
268 #error need upcall or listener
269 #endif
270
271 int
272 osi_NetSend(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
273             int nvecs, afs_int32 alength, int istack)
274 {
275 #ifdef AFS_DARWIN80_ENV
276     socket_t asocket = (socket_t)so;
277     struct msghdr msg;
278     size_t slen;
279 #else
280     struct socket *asocket = (struct socket *)so;
281     struct uio u;
282 #endif
283     afs_int32 code;
284     int i;
285     struct iovec iov[RX_MAXIOVECS];
286     int haveGlock = ISAFS_GLOCK();
287
288     AFS_STATCNT(osi_NetSend);
289     if (nvecs > RX_MAXIOVECS)
290         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
291
292     for (i = 0; i < nvecs; i++)
293         iov[i] = dvec[i];
294
295     addr->sin_len = sizeof(struct sockaddr_in);
296
297     if ((afs_termState == AFSOP_STOP_RXK_LISTENER) ||
298         (afs_termState == AFSOP_STOP_COMPLETE))
299         return -1;
300
301     if (haveGlock)
302         AFS_GUNLOCK();
303
304 #if defined(KERNEL_FUNNEL)
305     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
306 #endif
307 #ifdef AFS_DARWIN80_ENV
308     memset(&msg, 0, sizeof(struct msghdr));
309     msg.msg_name = addr;
310     msg.msg_namelen = ((struct sockaddr *)addr)->sa_len;
311     msg.msg_iov = &iov[0];
312     msg.msg_iovlen = nvecs;
313     code = sock_send(asocket, &msg, 0, &slen);
314 #else
315     u.uio_iov = &iov[0];
316     u.uio_iovcnt = nvecs;
317     u.uio_offset = 0;
318     u.uio_resid = alength;
319     u.uio_segflg = UIO_SYSSPACE;
320     u.uio_rw = UIO_WRITE;
321     u.uio_procp = NULL;
322     code = sosend(asocket, (struct sockaddr *)addr, &u, NULL, NULL, 0);
323 #endif
324
325 #if defined(KERNEL_FUNNEL)
326     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
327 #endif
328     if (haveGlock)
329         AFS_GLOCK();
330     return code;
331 }