solaris-sockaddr-storage-20060804
[openafs.git] / src / rx / SOLARIS / 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 RCSID
14     ("$Header$");
15
16 #ifdef AFS_SUN5_ENV
17 #include "rx/rx_kcommon.h"
18
19
20 #ifdef AFS_SUN56_ENV
21
22 #include "inet/common.h"
23 #include "sys/tiuser.h"
24 #include "sys/t_kuser.h"
25 #include "sys/stropts.h"
26 #include "sys/stream.h"
27 #include "sys/tihdr.h"
28 #include "sys/fcntl.h"
29 #ifdef AFS_SUN58_ENV
30 #include "netinet/ip6.h"
31 #define ipif_local_addr ipif_lcl_addr
32 #ifndef V4_PART_OF_V6
33 #define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
34 #endif
35 #endif
36 #include "inet/ip.h"
37 #include "inet/ip_if.h"
38 #include "netinet/udp.h"
39
40 /*
41  * Function pointers for kernel socket routines
42  */
43 struct sonode *(*sockfs_socreate)
44   (vnode_t *, int, int, int, int, struct sonode *, int *) = NULL;
45 struct vnode *(*sockfs_solookup)
46   (int, int, int, char *, int *) = NULL;
47 int (*sockfs_sobind)
48   (struct sonode *, struct sockaddr *, int, int, int) = NULL;
49 int (*sockfs_sorecvmsg)
50   (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
51 int (*sockfs_sosendmsg)
52   (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
53 int (*sockfs_sosetsockopt)
54   (struct sonode *, int, int, void *, int) = NULL;
55 #ifndef AFS_SUN510_ENV
56 int (*sockfs_sounbind)
57   (struct sonode *, int);
58 void (*sockfs_sockfree)
59   (struct sonode *);
60 #endif
61
62 static afs_uint32 myNetAddrs[ADDRSPERSITE];
63 static int myNetMTUs[ADDRSPERSITE];
64 static int numMyNetAddrs = 0;
65
66 int
67 rxi_GetIFInfo()
68 {
69     int i = 0;
70     int different = 0;
71
72     ill_t *ill;
73     ipif_t *ipif;
74     int rxmtu, maxmtu;
75 #ifdef AFS_SUN510_ENV
76     ill_walk_context_t ctx;
77 #endif
78
79     int mtus[ADDRSPERSITE];
80     afs_uint32 addrs[ADDRSPERSITE];
81     afs_uint32 ifinaddr;
82
83     memset(mtus, 0, sizeof(mtus));
84     memset(addrs, 0, sizeof(addrs));
85
86 #ifdef AFS_SUN510_ENV
87     for (ill = ILL_START_WALK_ALL(&ctx) ; ill ; ill = ill_next(&ctx, ill)) {
88 #else
89     for (ill = ill_g_head; ill; ill = ill->ill_next) {
90 #endif
91 #ifdef AFS_SUN58_ENV
92         /* Make sure this is an IPv4 ILL */
93         if (ill->ill_isv6)
94             continue;
95 #endif
96
97         /* Iterate over all the addresses on this ILL */
98         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
99             if (i >= ADDRSPERSITE)
100                 break;
101
102             /* Ignore addresses which are down.. */
103             if (!(ipif->ipif_flags & IFF_UP))
104                 continue;
105
106             /* Compute the Rx interface MTU */
107             rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
108
109             ifinaddr = ntohl(ipif->ipif_local_addr);
110             if (myNetAddrs[i] != ifinaddr)
111                 different++;
112
113             /* Copy interface MTU and address; adjust maxmtu */
114             mtus[i] = rxmtu;
115             rxmtu = rxi_AdjustIfMTU(rxmtu);
116             maxmtu =
117                 rxmtu * rxi_nRecvFrags +
118                 ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
119             maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
120             addrs[i] = ifinaddr;
121             i++;
122
123             if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
124                 rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
125                 rx_maxReceiveSize =
126                     MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
127             }
128         }
129     }
130
131     rx_maxJumboRecvSize =
132         RX_HEADER_SIZE + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
133         (rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE;
134     rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
135
136     if (different) {
137         int j;
138
139         for (j = 0; j < i; j++) {
140             myNetMTUs[j] = mtus[j];
141             myNetAddrs[j] = addrs[j];
142         }
143     }
144
145     return different;
146 }
147
148 int
149 rxi_FindIfMTU(afs_uint32 addr)
150 {
151     ill_t *ill;
152     ipif_t *ipif;
153     afs_uint32 myAddr, netMask;
154     int match_value = 0;
155     int mtu = -1;
156 #ifdef AFS_SUN510_ENV
157     ill_walk_context_t ctx;
158 #endif
159
160     if (numMyNetAddrs == 0)
161         rxi_GetIFInfo();
162     myAddr = ntohl(addr);
163
164     if (IN_CLASSA(myAddr))
165         netMask = IN_CLASSA_NET;
166     else if (IN_CLASSB(myAddr))
167         netMask = IN_CLASSB_NET;
168     else if (IN_CLASSC(myAddr))
169         netMask = IN_CLASSC_NET;
170     else
171         netMask = 0;
172
173 #ifdef AFS_SUN510_ENV
174     for (ill = ILL_START_WALK_ALL(&ctx) ; ill ; ill = ill_next(&ctx, ill)) {
175 #else
176     for (ill = ill_g_head; ill; ill = ill->ill_next) {
177 #endif
178 #ifdef AFS_SUN58_ENV
179         /* Make sure this is an IPv4 ILL */
180         if (ill->ill_isv6)
181             continue;
182 #endif
183
184         /* Iterate over all the addresses on this ILL */
185         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
186             afs_uint32 thisAddr, subnetMask;
187             int thisMtu;
188
189             thisAddr = ipif->ipif_local_addr;
190             subnetMask = ipif->ipif_net_mask;
191             thisMtu = ipif->ipif_mtu;
192
193             if ((myAddr & netMask) == (thisAddr & netMask)) {
194                 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
195                     if (myAddr == thisAddr) {
196                         match_value = 4;
197                         mtu = thisMtu;
198                     }
199
200                     if (match_value < 3) {
201                         match_value = 3;
202                         mtu = thisMtu;
203                     }
204                 }
205
206                 if (match_value < 2) {
207                     match_value = 2;
208                     mtu = thisMtu;
209                 }
210             }
211         }
212     }
213
214     return mtu;
215 }
216
217 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
218  * afs_osinet.c. 
219  */
220
221 struct sockaddr_in rx_sockaddr;
222
223 /* Allocate a new socket at specified port in network byte order. */
224 osi_socket *
225 rxk_NewSocketHost(struct sockaddr_storage *addr, int salen)
226 {
227     vnode_t *accessvp;
228     struct sonode *so;
229     int error;
230     int len;
231
232     AFS_STATCNT(osi_NewSocket);
233
234     if (sockfs_solookup == NULL) {
235         sockfs_solookup =
236             (struct vnode * (*)())modlookup("sockfs", "solookup");
237         if (sockfs_solookup == NULL) {
238             return NULL;
239         }
240     }
241     if (sockfs_socreate == NULL) {
242         sockfs_socreate =
243             (struct sonode * (*)())modlookup("sockfs", "socreate");
244         if (sockfs_socreate == NULL) {
245             return NULL;
246         }
247     }
248     if (sockfs_sobind == NULL) {
249         sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
250         if (sockfs_sobind == NULL) {
251             return NULL;
252         }
253     }
254     if (sockfs_sosetsockopt == NULL) {
255         sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
256         if (sockfs_sosetsockopt == NULL) {
257             return NULL;
258         }
259     }
260     if (sockfs_sosendmsg == NULL) {
261         sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
262         if (sockfs_sosendmsg == NULL) {
263             return NULL;
264         }
265     }
266     if (sockfs_sorecvmsg == NULL) {
267         sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
268         if (sockfs_sorecvmsg == NULL) {
269             return NULL;
270         }
271     }
272 #ifndef AFS_SUN510_ENV
273     if (sockfs_sounbind == NULL) {
274         sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
275         if (sockfs_sounbind == NULL)
276             return NULL;
277     }
278     if (sockfs_sockfree == NULL) {
279         sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
280         if (sockfs_sockfree == NULL)
281             return NULL;
282     }
283 #endif
284
285     accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
286     if (accessvp == NULL) {
287         return NULL;
288     }
289
290     so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, NULL,
291                          &error);
292     if (so == NULL) {
293         return NULL;
294     }
295
296     error = sockfs_sobind(so, (struct sockaddr *)addr, salen, 0, 0);
297     if (error != 0) {
298         return NULL;
299     }
300
301     len = rx_UdpBufSize;
302     error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
303     if (error != 0) {
304         return NULL;
305     }
306
307     len = rx_UdpBufSize;
308     error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
309     if (error != 0) {
310         return NULL;
311     }
312
313     return (osi_socket *)so;
314 }
315
316 osi_socket *
317 rxk_NewSocket(short aport)
318 {
319     return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
320 }
321
322 int
323 osi_FreeSocket(register osi_socket *asocket)
324 {
325     extern int rxk_ListenerPid;
326     struct sonode *so = (struct sonode *)asocket;
327     struct sockaddr_in taddr;
328     struct iovec dvec;
329     char c;
330     vnode_t *vp;
331
332     AFS_STATCNT(osi_FreeSocket);
333
334     taddr.sin_family = AF_INET;
335     taddr.sin_port = rx_port;
336     taddr.sin_addr.s_addr = htonl(0x7f000001);
337
338     dvec.iov_base = &c;
339     dvec.iov_len = 1;
340
341     while (rxk_ListenerPid) {
342         osi_NetSend(rx_socket, &taddr, sizeof(taddr), &dvec, 1, 1, 0);
343         afs_osi_Sleep(&rxk_ListenerPid);
344     }
345
346     /* Was sockfs_sounbind(so, 0); sockfs_sockfree(so); That's wrong */
347     vp = SOTOV(so);
348     VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED());
349     VN_RELE(vp);
350
351     return 0;
352 }
353
354 int
355 osi_NetSend(osi_socket asocket, struct sockaddr_storage *saddr, int slen,
356             struct iovec *dvec, int nvecs, afs_int32 asize, int istack)
357 {
358     struct sonode *so = (struct sonode *)asocket;
359     struct nmsghdr msg;
360     struct uio uio;
361     struct iovec iov[RX_MAXIOVECS];
362     int error;
363     int i;
364
365     if (nvecs > RX_MAXIOVECS) {
366         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
367     }
368
369     msg.msg_name = (struct sockaddr *) saddr;
370     msg.msg_namelen = slen;
371     msg.msg_iov = dvec;
372     msg.msg_iovlen = nvecs;
373     msg.msg_control = NULL;
374     msg.msg_controllen = 0;
375     msg.msg_flags = 0;
376
377     for (i = 0; i < nvecs; i++) {
378         iov[i].iov_base = dvec[i].iov_base;
379         iov[i].iov_len = dvec[i].iov_len;
380     }
381     uio.uio_iov = &iov[0];
382     uio.uio_iovcnt = nvecs;
383     uio.uio_loffset = 0;
384     uio.uio_segflg = UIO_SYSSPACE;
385     uio.uio_fmode = FREAD | FWRITE;
386     uio.uio_limit = 0;
387     uio.uio_resid = asize;
388
389     error = sockfs_sosendmsg(so, &msg, &uio);
390
391     return error;
392 }
393
394 int
395 osi_NetReceive(osi_socket so, struct sockaddr_storage *saddr, int *slen,
396                struct iovec *dvec, int nvecs, int *alength)
397 {
398     struct sonode *asocket = (struct sonode *)so;
399     struct nmsghdr msg;
400     struct uio uio;
401     struct iovec iov[RX_MAXIOVECS];
402     int error;
403     int i;
404
405     if (nvecs > RX_MAXIOVECS) {
406         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
407     }
408
409     msg.msg_name = NULL;
410     msg.msg_namelen = *slen;
411     msg.msg_iov = NULL;
412     msg.msg_iovlen = 0;
413     msg.msg_control = NULL;
414     msg.msg_controllen = 0;
415     msg.msg_flags = 0;
416
417     for (i = 0; i < nvecs; i++) {
418         iov[i].iov_base = dvec[i].iov_base;
419         iov[i].iov_len = dvec[i].iov_len;
420     }
421     uio.uio_iov = &iov[0];
422     uio.uio_iovcnt = nvecs;
423     uio.uio_loffset = 0;
424     uio.uio_segflg = UIO_SYSSPACE;
425     uio.uio_fmode = 0;
426     uio.uio_limit = 0;
427     uio.uio_resid = *alength;
428
429     error = sockfs_sorecvmsg(asocket, &msg, &uio);
430     if (error == 0) {
431         if (msg.msg_name == NULL) {
432             error = -1;
433         } else {
434             memcpy(saddr, msg.msg_name, msg.msg_namelen);
435             *slen = msg.msg_namelen;
436             kmem_free(msg.msg_name, msg.msg_namelen);
437             *alength = *alength - uio.uio_resid;
438         }
439     }
440
441     if (error == EINTR && ISSIG(curthread, FORREAL)) {
442         klwp_t *lwp = ttolwp(curthread);
443         proc_t *p = ttoproc(curthread);
444         int sig = lwp->lwp_cursig;
445
446         if (sig == SIGKILL) {
447             mutex_enter(&p->p_lock);
448             p->p_flag &= ~SKILLED;
449             mutex_exit(&p->p_lock);
450         }
451         lwp->lwp_cursig = 0;
452         if (lwp->lwp_curinfo) {
453             siginfofree(lwp->lwp_curinfo);
454             lwp->lwp_curinfo = NULL;
455         }
456     }
457
458     return error;
459 }
460
461 void
462 shutdown_rxkernel(void)
463 {
464 }
465
466 void
467 osi_StopListener(void)
468 {
469     osi_FreeSocket(rx_socket);
470 }
471
472 #else /* AFS_SUN56_ENV */
473
474 #include "inet/common.h"
475 #include "sys/tiuser.h"
476 #include "sys/t_kuser.h"
477 #include "sys/ioctl.h"
478 #include "sys/stropts.h"
479 #include "sys/stream.h"
480 #include "sys/strsubr.h"
481 #include "sys/vnode.h"
482 #include "sys/stropts.h"
483 #include "sys/tihdr.h"
484 #include "sys/timod.h"
485 #include "sys/fcntl.h"
486 #include "sys/debug.h"
487 #include "inet/common.h"
488 #include "inet/mi.h"
489 #include "netinet/udp.h"
490
491 extern dev_t afs_udp_rdev;
492
493
494 int
495 rxi_GetIFInfo()
496 {
497     return 0;
498 }
499
500
501 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
502  * afs_osinet.c. 
503  */
504
505 dev_t afs_udp_rdev = (dev_t) 0;
506
507 /* Allocate a new socket at specified port in network byte order. */
508 osi_socket *
509 rxk_NewSocketHost(afs_uint32 ahost, short aport)
510 {
511     TIUSER *udp_tiptr;
512     struct t_bind *reqp, *rspp;
513     afs_int32 code;
514     struct sockaddr_in *myaddrp;
515     struct stdata *stp;
516     struct queue *q;
517
518     AFS_STATCNT(osi_NewSocket);
519     afs_udp_rdev = makedevice(11 /*CLONE*/, ddi_name_to_major("udp"));
520     code = t_kopen(NULL, afs_udp_rdev, FREAD | FWRITE, &udp_tiptr, CRED());
521     if (code) {
522         return (osi_socket *)0;
523     }
524
525     code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&reqp);
526     if (code) {
527         t_kclose(udp_tiptr, 0);
528     }
529     code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&rspp);
530     if (code) {
531         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
532         t_kclose(udp_tiptr, 0);
533         return (osi_socket *)0;
534     }
535
536     reqp->addr.len = sizeof(struct sockaddr_in);
537     myaddrp = (struct sockaddr_in *)reqp->addr.buf;
538     myaddrp->sin_family = AF_INET;
539     myaddrp->sin_port = aport;
540     myaddrp->sin_addr.s_addr = ahost;   /* byteswap? */
541
542     code = t_kbind(udp_tiptr, reqp, rspp);
543     if (code) {
544         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
545         t_kfree(udp_tiptr, (char *)rspp, T_BIND);
546         t_kclose(udp_tiptr, 0);
547         return (osi_socket *)0;
548     }
549     if (memcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
550         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
551         t_kfree(udp_tiptr, (char *)rspp, T_BIND);
552         t_kclose(udp_tiptr, 0);
553         return (osi_socket *)0;
554     }
555     t_kfree(udp_tiptr, (char *)reqp, T_BIND);
556     t_kfree(udp_tiptr, (char *)rspp, T_BIND);
557
558     /*
559      * Set the send and receive buffer sizes.
560      */
561     stp = udp_tiptr->fp->f_vnode->v_stream;
562     q = stp->sd_wrq;
563     q->q_hiwat = rx_UdpBufSize;
564     q->q_next->q_hiwat = rx_UdpBufSize;
565     RD(q)->q_hiwat = rx_UdpBufSize;
566
567     return (osi_socket *)udp_tiptr;
568 }
569
570 osi_socket *
571 rxk_NewSocket(short aport)
572 {
573     return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
574 }
575
576 int
577 osi_FreeSocket(register osi_socket *asocket)
578 {
579     extern int rxk_ListenerPid;
580     TIUSER *udp_tiptr = (TIUSER *) asocket;
581     AFS_STATCNT(osi_FreeSocket);
582
583     if (rxk_ListenerPid) {
584         kill(rxk_ListenerPid, SIGUSR1);
585         afs_osi_Sleep(&rxk_ListenerPid);
586     }
587     return 0;
588 }
589
590
591 int
592 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
593             int nvecs, afs_int32 asize, int istack)
594 {
595     int i;
596     int code;
597     TIUSER *udp_tiptr = (TIUSER *) asocket;
598     struct t_kunitdata *udreq;
599     struct sockaddr_in sin;
600     mblk_t *bp;
601     mblk_t *dbp;
602
603     /*
604      * XXX We don't do any checking on the family since it's assumed to be
605      * AF_INET XXX
606      */
607     sin.sin_family = AF_INET;
608     sin.sin_addr.s_addr = addr->sin_addr.s_addr;
609     sin.sin_port = addr->sin_port;
610
611     /*
612      * Get a buffer for the RX header
613      */
614     if (nvecs < 1) {
615         osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
616     }
617     while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
618         if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
619             return (ENOSR);
620         }
621     }
622
623     /* Copy the data into the buffer */
624     memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
625     bp->b_datap->db_type = M_DATA;
626     bp->b_wptr += dvec[0].iov_len;
627
628     /*
629      * Append each element in the iovec to the buffer
630      */
631     for (i = 1; i < nvecs; i++) {
632         /* Get a buffer for the next chunk */
633         while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
634             if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
635                 freeb(bp);
636                 return (ENOSR);
637             }
638         }
639
640         /* Copy the data into the buffer */
641         memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base,
642                dvec[i].iov_len);
643         dbp->b_datap->db_type = M_DATA;
644         dbp->b_wptr += dvec[i].iov_len;
645
646         /* Append it to the message buffer */
647         linkb(bp, dbp);
648     }
649
650     /*
651      * Allocate and format the unitdata structure.
652      */
653     code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
654     if (code) {
655         freeb(bp);
656         printf("osi_NetSend: t_kalloc failed %d\n", code);
657         return code;
658     }
659     udreq->addr.len = sizeof(struct sockaddr_in);
660     udreq->addr.maxlen = sizeof(struct sockaddr_in);
661     udreq->addr.buf =
662         (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
663     udreq->opt.len = 0;
664     udreq->opt.maxlen = 0;
665     memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
666     udreq->udata.udata_mp = bp;
667     udreq->udata.len = asize;
668
669     code = t_ksndudata(udp_tiptr, udreq, NULL);
670     if (code) {
671         printf("osi_NetSend: t_ksndudata failed %d\n", code);
672     }
673
674     t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
675     return code;
676 }
677
678
679 int
680 osi_NetReceive(osi_socket *asocket, struct sockaddr_in *addr,
681                struct iovec *dvec, int nvecs, int *alength)
682 {
683     int i;
684     TIUSER *udp_tiptr = (TIUSER *) asocket;
685     struct t_kunitdata *udreq;
686     mblk_t *dbp;
687     char *phandle;
688     short sport;
689     int code = 0;
690     int length;
691     int tlen;
692     int blen;
693     char *tbase;
694     int type;
695     int error;
696     int events;
697
698     /*
699      * Allocate the unitdata structure.
700      */
701     code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
702     if (code) {
703         printf("osi_NetReceive: t_kalloc failed %d\n", code);
704         return code;
705     }
706     udreq->addr.len = sizeof(struct sockaddr_in);
707     udreq->addr.maxlen = sizeof(struct sockaddr_in);
708     udreq->addr.buf =
709         (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
710     udreq->opt.len = 0;
711     udreq->opt.maxlen = 0;
712
713     /*
714      * Loop until we get an error or receive some data.
715      */
716     while (1) {
717         /*
718          * Wait until there is something to do
719          */
720         code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
721         if (events == 0) {
722             osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
723         }
724         /*
725          * If there is a message then read it in
726          */
727         if (code == 0) {
728             code = t_krcvudata(udp_tiptr, udreq, &type, &error);
729         }
730
731         /*
732          * Block attempts to kill this thread
733          */
734         if (code == EINTR && ISSIG(curthread, FORREAL)) {
735             klwp_t *lwp = ttolwp(curthread);
736             proc_t *p = ttoproc(curthread);
737             int sig = lwp->lwp_cursig;
738
739             if (sig == SIGKILL) {
740                 mutex_enter(&p->p_lock);
741                 p->p_flag &= ~SKILLED;
742                 mutex_exit(&p->p_lock);
743             }
744             lwp->lwp_cursig = 0;
745             if (lwp->lwp_curinfo) {
746                 kmem_free((caddr_t) lwp->lwp_curinfo,
747                           sizeof(*lwp->lwp_curinfo));
748                 lwp->lwp_curinfo = NULL;
749             }
750         }
751
752         if (code) {
753             break;
754         }
755
756         /*
757          * Ignore non-data message types
758          */
759         if (type != T_DATA) {
760             continue;
761         }
762
763         /*
764          * Save the source address
765          */
766         memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
767
768         /*
769          * Copy out the message buffers, take care not to overflow
770          * the I/O vector.
771          */
772         dbp = udreq->udata.udata_mp;
773         length = *alength;
774         for (i = 0; dbp != NULL && length > 0 && i < nvecs; i++) {
775             tlen = dvec[i].iov_len;
776             tbase = dvec[i].iov_base;
777             if (tlen > length) {
778                 tlen = length;
779             }
780             while (dbp != NULL && tlen > 0) {
781                 blen = dbp->b_wptr - dbp->b_rptr;
782                 if (blen > tlen) {
783                     memcpy(tbase, (char *)dbp->b_rptr, tlen);
784                     length -= tlen;
785                     dbp->b_rptr += tlen;
786                     tlen = 0;
787                 } else {
788                     memcpy(tbase, (char *)dbp->b_rptr, blen);
789                     length -= blen;
790                     tlen -= blen;
791                     tbase += blen;
792                     dbp = dbp->b_cont;
793                 }
794             }
795         }
796         *alength = *alength - length;
797         break;
798     }
799
800     t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
801     return code;
802 }
803
804
805 void
806 osi_StopListener(void)
807 {
808     osi_FreeSocket(rx_socket);
809 }
810
811
812 void
813 shutdown_rxkernel(void)
814 {
815 }
816
817
818 #endif /* AFS_SUN56_ENV */
819 #endif /* AFS_SUN5_ENV */