Import Upstream version 1.8.5
[hcoop/debian/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_atomic.h"
16 #include "rx/rx_internal.h"
17 #include "rx/rx_packet.h"
18 #include "rx/rx_stats.h"
19
20 #ifdef AFS_DARWIN80_ENV
21 #define soclose sock_close
22 #endif
23
24 #ifdef RXK_UPCALL_ENV
25 void
26 rx_upcall(socket_t so, void *arg, __unused int waitflag)
27 {
28 mbuf_t m;
29 int error = 0;
30 int i, flags = 0;
31 struct msghdr msg;
32 struct sockaddr_storage ss;
33 struct sockaddr *sa = NULL;
34 struct sockaddr_in from;
35 struct rx_packet *p;
36 afs_int32 rlen;
37 afs_int32 tlen;
38 afs_int32 savelen; /* was using rlen but had aliasing problems */
39 size_t nbytes, resid, noffset;
40
41 /* we stopped rx but the socket isn't closed yet */
42 if (!rxi_IsRunning())
43 return;
44
45 /* See if a check for additional packets was issued */
46 rx_CheckPackets();
47
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. */
54 tlen = rlen - tlen;
55 if (tlen > 0) {
56 tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_RECV_CBUF);
57 if (tlen > 0) {
58 tlen = rlen - tlen;
59 } else
60 tlen = rlen;
61 } else
62 tlen = rlen;
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;
68
69 resid = nbytes = tlen + sizeof(afs_int32);
70
71 memset(&msg, 0, sizeof(struct msghdr));
72 msg.msg_name = &ss;
73 msg.msg_namelen = sizeof(struct sockaddr_storage);
74 sa =(struct sockaddr *) &ss;
75
76 do {
77 m = NULL;
78 error = sock_receivembuf(so, &msg, &m, MSG_DONTWAIT, &nbytes);
79 if (!error) {
80 size_t sz, offset = 0;
81 noffset = 0;
82 resid = nbytes;
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);
86 if (error)
87 break;
88 resid-=sz;
89 offset+=sz;
90 noffset += sz;
91 }
92 }
93 } while (0);
94
95 mbuf_freem(m);
96
97 /* restore the vec to its correct state */
98 p->wirevec[p->niovecs - 1].iov_len = savelen;
99
100 if (error == EWOULDBLOCK && noffset > 0)
101 error = 0;
102
103 if (!error) {
104 int host, port;
105
106 nbytes -= resid;
107
108 if (sa->sa_family == AF_INET)
109 from = *(struct sockaddr_in *)sa;
110
111 p->length = nbytes - RX_HEADER_SIZE;;
112 if ((nbytes > tlen) || (p->length & 0x8000)) { /* Bogus packet */
113 if (nbytes <= 0) {
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);
119 }
120 dpf(("B: bogus packet from [%x,%d] nb=%d",
121 from.sin_addr.s_addr, from.sin_port, nbytes));
122 }
123 return;
124 } else {
125 /* Extract packet header. */
126 rxi_DecodePacketHeader(p);
127
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]);
133 }
134 }
135
136 #ifdef RX_TRIMDATABUFS
137 /* Free any empty packet buffers at the end of this packet */
138 rxi_TrimDataBufs(p, 1);
139 #endif
140 /* receive pcket */
141 p = rxi_ReceivePacket(p, so, host, port, 0, 0);
142 }
143 }
144 /* free packet? */
145 if (p)
146 rxi_FreePacket(p);
147
148 return;
149 }
150
151 /* in listener env, the listener shutdown does this. we have no listener */
152 void
153 osi_StopNetIfPoller(void)
154 {
155 shutdown_rx();
156 soclose(rx_socket);
157 if (afs_termState == AFSOP_STOP_NETIF) {
158 afs_termState = AFSOP_STOP_COMPLETE;
159 osi_rxWakeup(&afs_termState);
160 }
161 }
162 #elif defined(RXK_LISTENER_ENV)
163 int
164 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
165 int nvecs, int *alength)
166 {
167 int i;
168 struct iovec iov[RX_MAXIOVECS];
169 struct sockaddr *sa = NULL;
170 int code;
171 size_t resid;
172
173 int haveGlock = ISAFS_GLOCK();
174
175 #ifdef AFS_DARWIN80_ENV
176 socket_t asocket = (socket_t)so;
177 struct msghdr msg;
178 struct sockaddr_storage ss;
179 int rlen;
180 mbuf_t m;
181 #else
182 struct socket *asocket = (struct socket *)so;
183 struct uio u;
184 memset(&u, 0, sizeof(u));
185 #endif
186 memset(&iov, 0, sizeof(iov));
187 /*AFS_STATCNT(osi_NetReceive); */
188
189 if (nvecs > RX_MAXIOVECS)
190 osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
191
192 for (i = 0; i < nvecs; i++)
193 iov[i] = dvec[i];
194
195 if ((afs_termState == AFSOP_STOP_RXK_LISTENER) ||
196 (afs_termState == AFSOP_STOP_COMPLETE))
197 return -1;
198
199 if (haveGlock)
200 AFS_GUNLOCK();
201 #if defined(KERNEL_FUNNEL)
202 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
203 #endif
204 #ifdef AFS_DARWIN80_ENV
205 resid = *alength;
206 memset(&msg, 0, sizeof(struct msghdr));
207 msg.msg_name = &ss;
208 msg.msg_namelen = sizeof(struct sockaddr_storage);
209 sa =(struct sockaddr *) &ss;
210 code = sock_receivembuf(asocket, &msg, &m, 0, alength);
211 if (!code) {
212 size_t offset=0,sz;
213 resid = *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);
217 if (code)
218 break;
219 resid-=sz;
220 offset+=sz;
221 }
222 }
223 mbuf_freem(m);
224 #else
225
226 u.uio_iov = &iov[0];
227 u.uio_iovcnt = nvecs;
228 u.uio_offset = 0;
229 u.uio_resid = *alength;
230 u.uio_segflg = UIO_SYSSPACE;
231 u.uio_rw = UIO_READ;
232 u.uio_procp = NULL;
233 code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
234 resid = u.uio_resid;
235 #endif
236
237 #if defined(KERNEL_FUNNEL)
238 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
239 #endif
240 if (haveGlock)
241 AFS_GLOCK();
242
243 if (code)
244 return code;
245 *alength -= resid;
246 if (sa) {
247 if (sa->sa_family == AF_INET) {
248 if (addr)
249 *addr = *(struct sockaddr_in *)sa;
250 } else
251 printf("Unknown socket family %d in NetReceive\n", sa->sa_family);
252 #ifndef AFS_DARWIN80_ENV
253 FREE(sa, M_SONAME);
254 #endif
255 }
256 return code;
257 }
258
259 extern int rxk_ListenerPid;
260 void
261 osi_StopListener(void)
262 {
263 struct proc *p;
264
265 #if defined(KERNEL_FUNNEL)
266 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
267 #endif
268 soclose(rx_socket);
269 #if defined(KERNEL_FUNNEL)
270 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
271 #endif
272 #ifndef AFS_DARWIN80_ENV
273 p = pfind(rxk_ListenerPid);
274 if (p)
275 psignal(p, SIGUSR1);
276 #endif
277 }
278 #else
279 #error need upcall or listener
280 #endif
281
282 int
283 osi_NetSend(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
284 int nvecs, afs_int32 alength, int istack)
285 {
286 afs_int32 code;
287 int i;
288 struct iovec iov[RX_MAXIOVECS];
289 int haveGlock = ISAFS_GLOCK();
290 #ifdef AFS_DARWIN80_ENV
291 socket_t asocket = (socket_t)so;
292 struct msghdr msg;
293 size_t slen;
294 #else
295 struct socket *asocket = (struct socket *)so;
296 struct uio u;
297 memset(&u, 0, sizeof(u));
298 #endif
299 memset(&iov, 0, sizeof(iov));
300
301 AFS_STATCNT(osi_NetSend);
302 if (nvecs > RX_MAXIOVECS)
303 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
304
305 for (i = 0; i < nvecs; i++)
306 iov[i] = dvec[i];
307
308 addr->sin_len = sizeof(struct sockaddr_in);
309
310 if ((afs_termState == AFSOP_STOP_RXK_LISTENER) ||
311 (afs_termState == AFSOP_STOP_COMPLETE))
312 return -1;
313
314 if (haveGlock)
315 AFS_GUNLOCK();
316
317 #if defined(KERNEL_FUNNEL)
318 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
319 #endif
320 #ifdef AFS_DARWIN80_ENV
321 memset(&msg, 0, sizeof(struct msghdr));
322 msg.msg_name = addr;
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);
327 #else
328 u.uio_iov = &iov[0];
329 u.uio_iovcnt = nvecs;
330 u.uio_offset = 0;
331 u.uio_resid = alength;
332 u.uio_segflg = UIO_SYSSPACE;
333 u.uio_rw = UIO_WRITE;
334 u.uio_procp = NULL;
335 code = sosend(asocket, (struct sockaddr *)addr, &u, NULL, NULL, 0);
336 #endif
337
338 #if defined(KERNEL_FUNNEL)
339 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
340 #endif
341 if (haveGlock)
342 AFS_GLOCK();
343 return code;
344 }