solaris10-20040624
[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 struct osi_socket *
225 rxk_NewSocket(short aport)
226 {
227     vnode_t *accessvp;
228     struct sonode *so;
229     struct sockaddr_in addr;
230     int error;
231     int len;
232
233     AFS_STATCNT(osi_NewSocket);
234
235     if (sockfs_solookup == NULL) {
236         sockfs_solookup =
237             (struct vnode * (*)())modlookup("sockfs", "solookup");
238         if (sockfs_solookup == NULL) {
239             return NULL;
240         }
241     }
242     if (sockfs_socreate == NULL) {
243         sockfs_socreate =
244             (struct sonode * (*)())modlookup("sockfs", "socreate");
245         if (sockfs_socreate == NULL) {
246             return NULL;
247         }
248     }
249     if (sockfs_sobind == NULL) {
250         sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
251         if (sockfs_sobind == NULL) {
252             return NULL;
253         }
254     }
255     if (sockfs_sosetsockopt == NULL) {
256         sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
257         if (sockfs_sosetsockopt == NULL) {
258             return NULL;
259         }
260     }
261     if (sockfs_sosendmsg == NULL) {
262         sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
263         if (sockfs_sosendmsg == NULL) {
264             return NULL;
265         }
266     }
267     if (sockfs_sorecvmsg == NULL) {
268         sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
269         if (sockfs_sorecvmsg == NULL) {
270             return NULL;
271         }
272     }
273 #ifndef AFS_SUN510_ENV
274     if (sockfs_sounbind == NULL) {
275         sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
276         if (sockfs_sounbind == NULL)
277             return NULL;
278     }
279     if (sockfs_sockfree == NULL) {
280         sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
281         if (sockfs_sockfree == NULL)
282             return NULL;
283     }
284 #endif
285
286     accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
287     if (accessvp == NULL) {
288         return NULL;
289     }
290
291     so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, NULL,
292                          &error);
293     if (so == NULL) {
294         return NULL;
295     }
296
297     addr.sin_family = AF_INET;
298     addr.sin_port = aport;
299     addr.sin_addr.s_addr = INADDR_ANY;
300     error = sockfs_sobind(so, (struct sockaddr *)&addr, sizeof(addr), 0, 0);
301     if (error != 0) {
302         return NULL;
303     }
304
305     len = rx_UdpBufSize;
306     error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
307     if (error != 0) {
308         return NULL;
309     }
310
311     len = rx_UdpBufSize;
312     error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
313     if (error != 0) {
314         return NULL;
315     }
316
317     return (struct osi_socket *)so;
318 }
319
320 int
321 osi_FreeSocket(register struct osi_socket *asocket)
322 {
323     extern int rxk_ListenerPid;
324     struct sonode *so = (struct sonode *)asocket;
325     struct sockaddr_in taddr;
326     struct iovec dvec;
327     char c;
328     vnode_t *vp;
329
330     AFS_STATCNT(osi_FreeSocket);
331
332     taddr.sin_family = AF_INET;
333     taddr.sin_port = rx_port;
334     taddr.sin_addr.s_addr = htonl(0x7f000001);
335
336     dvec.iov_base = &c;
337     dvec.iov_len = 1;
338
339     while (rxk_ListenerPid) {
340         osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
341         afs_osi_Sleep(&rxk_ListenerPid);
342     }
343
344     /* Was sockfs_sounbind(so, 0); sockfs_sockfree(so); That's wrong */
345     vp = SOTOV(so);
346     VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED());
347     VN_RELE(vp);
348
349     return 0;
350 }
351
352 int
353 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
354             int nvecs, afs_int32 asize, int istack)
355 {
356     struct sonode *so = (struct sonode *)asocket;
357     struct nmsghdr msg;
358     struct uio uio;
359     struct iovec iov[RX_MAXIOVECS];
360     int error;
361     int i;
362
363     if (nvecs > RX_MAXIOVECS) {
364         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
365     }
366
367     msg.msg_name = (struct sockaddr *)addr;
368     msg.msg_namelen = sizeof(struct sockaddr_in);
369     msg.msg_iov = dvec;
370     msg.msg_iovlen = nvecs;
371     msg.msg_control = NULL;
372     msg.msg_controllen = 0;
373     msg.msg_flags = 0;
374
375     for (i = 0; i < nvecs; i++) {
376         iov[i].iov_base = dvec[i].iov_base;
377         iov[i].iov_len = dvec[i].iov_len;
378     }
379     uio.uio_iov = &iov[0];
380     uio.uio_iovcnt = nvecs;
381     uio.uio_loffset = 0;
382     uio.uio_segflg = UIO_SYSSPACE;
383     uio.uio_fmode = FREAD | FWRITE;
384     uio.uio_limit = 0;
385     uio.uio_resid = asize;
386
387     error = sockfs_sosendmsg(so, &msg, &uio);
388
389     return error;
390 }
391
392 int
393 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
394                int nvecs, int *alength)
395 {
396     struct sonode *asocket = (struct sonode *)so;
397     struct nmsghdr msg;
398     struct uio uio;
399     struct iovec iov[RX_MAXIOVECS];
400     int error;
401     int i;
402
403     if (nvecs > RX_MAXIOVECS) {
404         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
405     }
406
407     msg.msg_name = NULL;
408     msg.msg_namelen = sizeof(struct sockaddr_in);
409     msg.msg_iov = NULL;
410     msg.msg_iovlen = 0;
411     msg.msg_control = NULL;
412     msg.msg_controllen = 0;
413     msg.msg_flags = 0;
414
415     for (i = 0; i < nvecs; i++) {
416         iov[i].iov_base = dvec[i].iov_base;
417         iov[i].iov_len = dvec[i].iov_len;
418     }
419     uio.uio_iov = &iov[0];
420     uio.uio_iovcnt = nvecs;
421     uio.uio_loffset = 0;
422     uio.uio_segflg = UIO_SYSSPACE;
423     uio.uio_fmode = 0;
424     uio.uio_limit = 0;
425     uio.uio_resid = *alength;
426
427     error = sockfs_sorecvmsg(asocket, &msg, &uio);
428     if (error == 0) {
429         if (msg.msg_name == NULL) {
430             error = -1;
431         } else {
432             memcpy(addr, msg.msg_name, msg.msg_namelen);
433             kmem_free(msg.msg_name, msg.msg_namelen);
434             *alength = *alength - uio.uio_resid;
435         }
436     }
437
438     if (error == EINTR && ISSIG(curthread, FORREAL)) {
439         klwp_t *lwp = ttolwp(curthread);
440         proc_t *p = ttoproc(curthread);
441         int sig = lwp->lwp_cursig;
442
443         if (sig == SIGKILL) {
444             mutex_enter(&p->p_lock);
445             p->p_flag &= ~SKILLED;
446             mutex_exit(&p->p_lock);
447         }
448         lwp->lwp_cursig = 0;
449         if (lwp->lwp_curinfo) {
450             siginfofree(lwp->lwp_curinfo);
451             lwp->lwp_curinfo = NULL;
452         }
453     }
454
455     return error;
456 }
457
458 void
459 shutdown_rxkernel(void)
460 {
461 }
462
463 void
464 osi_StopListener(void)
465 {
466     osi_FreeSocket(rx_socket);
467 }
468
469 #else /* AFS_SUN56_ENV */
470
471 #include "inet/common.h"
472 #include "sys/tiuser.h"
473 #include "sys/t_kuser.h"
474 #include "sys/ioctl.h"
475 #include "sys/stropts.h"
476 #include "sys/stream.h"
477 #include "sys/strsubr.h"
478 #include "sys/vnode.h"
479 #include "sys/stropts.h"
480 #include "sys/tihdr.h"
481 #include "sys/timod.h"
482 #include "sys/fcntl.h"
483 #include "sys/debug.h"
484 #include "inet/common.h"
485 #include "inet/mi.h"
486 #include "netinet/udp.h"
487
488 extern dev_t afs_udp_rdev;
489
490
491 int
492 rxi_GetIFInfo()
493 {
494     return 0;
495 }
496
497
498 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
499  * afs_osinet.c. 
500  */
501
502 dev_t afs_udp_rdev = (dev_t) 0;
503
504 /* Allocate a new socket at specified port in network byte order. */
505 struct osi_socket *
506 rxk_NewSocket(short aport)
507 {
508     TIUSER *udp_tiptr;
509     struct t_bind *reqp, *rspp;
510     afs_int32 code;
511     struct sockaddr_in *myaddrp;
512     struct stdata *stp;
513     struct queue *q;
514
515     AFS_STATCNT(osi_NewSocket);
516     afs_udp_rdev = makedevice(11 /*CLONE*/, ddi_name_to_major("udp"));
517     code = t_kopen(NULL, afs_udp_rdev, FREAD | FWRITE, &udp_tiptr, CRED());
518     if (code) {
519         return (struct osi_socket *)0;
520     }
521
522     code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&reqp);
523     if (code) {
524         t_kclose(udp_tiptr, 0);
525     }
526     code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&rspp);
527     if (code) {
528         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
529         t_kclose(udp_tiptr, 0);
530         return (struct osi_socket *)0;
531     }
532
533     reqp->addr.len = sizeof(struct sockaddr_in);
534     myaddrp = (struct sockaddr_in *)reqp->addr.buf;
535     myaddrp->sin_family = AF_INET;
536     myaddrp->sin_port = aport;
537     myaddrp->sin_addr.s_addr = INADDR_ANY;      /* XXX Was 0 XXX */
538
539     code = t_kbind(udp_tiptr, reqp, rspp);
540     if (code) {
541         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
542         t_kfree(udp_tiptr, (char *)rspp, T_BIND);
543         t_kclose(udp_tiptr, 0);
544         return (struct osi_socket *)0;
545     }
546     if (memcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
547         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
548         t_kfree(udp_tiptr, (char *)rspp, T_BIND);
549         t_kclose(udp_tiptr, 0);
550         return (struct osi_socket *)0;
551     }
552     t_kfree(udp_tiptr, (char *)reqp, T_BIND);
553     t_kfree(udp_tiptr, (char *)rspp, T_BIND);
554
555     /*
556      * Set the send and receive buffer sizes.
557      */
558     stp = udp_tiptr->fp->f_vnode->v_stream;
559     q = stp->sd_wrq;
560     q->q_hiwat = rx_UdpBufSize;
561     q->q_next->q_hiwat = rx_UdpBufSize;
562     RD(q)->q_hiwat = rx_UdpBufSize;
563
564     return (struct osi_socket *)udp_tiptr;
565 }
566
567
568 int
569 osi_FreeSocket(register struct osi_socket *asocket)
570 {
571     extern int rxk_ListenerPid;
572     TIUSER *udp_tiptr = (TIUSER *) asocket;
573     AFS_STATCNT(osi_FreeSocket);
574
575     if (rxk_ListenerPid) {
576         kill(rxk_ListenerPid, SIGUSR1);
577         afs_osi_Sleep(&rxk_ListenerPid);
578     }
579     return 0;
580 }
581
582
583 int
584 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
585             int nvecs, afs_int32 asize, int istack)
586 {
587     int i;
588     int code;
589     TIUSER *udp_tiptr = (TIUSER *) asocket;
590     struct t_kunitdata *udreq;
591     struct sockaddr_in sin;
592     mblk_t *bp;
593     mblk_t *dbp;
594
595     /*
596      * XXX We don't do any checking on the family since it's assumed to be
597      * AF_INET XXX
598      */
599     sin.sin_family = AF_INET;
600     sin.sin_addr.s_addr = addr->sin_addr.s_addr;
601     sin.sin_port = addr->sin_port;
602
603     /*
604      * Get a buffer for the RX header
605      */
606     if (nvecs < 1) {
607         osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
608     }
609     while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
610         if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
611             return (ENOSR);
612         }
613     }
614
615     /* Copy the data into the buffer */
616     memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
617     bp->b_datap->db_type = M_DATA;
618     bp->b_wptr += dvec[0].iov_len;
619
620     /*
621      * Append each element in the iovec to the buffer
622      */
623     for (i = 1; i < nvecs; i++) {
624         /* Get a buffer for the next chunk */
625         while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
626             if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
627                 freeb(bp);
628                 return (ENOSR);
629             }
630         }
631
632         /* Copy the data into the buffer */
633         memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base,
634                dvec[i].iov_len);
635         dbp->b_datap->db_type = M_DATA;
636         dbp->b_wptr += dvec[i].iov_len;
637
638         /* Append it to the message buffer */
639         linkb(bp, dbp);
640     }
641
642     /*
643      * Allocate and format the unitdata structure.
644      */
645     code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
646     if (code) {
647         freeb(bp);
648         printf("osi_NetSend: t_kalloc failed %d\n", code);
649         return code;
650     }
651     udreq->addr.len = sizeof(struct sockaddr_in);
652     udreq->addr.maxlen = sizeof(struct sockaddr_in);
653     udreq->addr.buf =
654         (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
655     udreq->opt.len = 0;
656     udreq->opt.maxlen = 0;
657     memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
658     udreq->udata.udata_mp = bp;
659     udreq->udata.len = asize;
660
661     code = t_ksndudata(udp_tiptr, udreq, NULL);
662     if (code) {
663         printf("osi_NetSend: t_ksndudata failed %d\n", code);
664     }
665
666     t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
667     return code;
668 }
669
670
671 int
672 osi_NetReceive(struct osi_socket *asocket, struct sockaddr_in *addr,
673                struct iovec *dvec, int nvecs, int *alength)
674 {
675     int i;
676     TIUSER *udp_tiptr = (TIUSER *) asocket;
677     struct t_kunitdata *udreq;
678     mblk_t *dbp;
679     char *phandle;
680     short sport;
681     int code = 0;
682     int length;
683     int tlen;
684     int blen;
685     char *tbase;
686     int type;
687     int error;
688     int events;
689
690     /*
691      * Allocate the unitdata structure.
692      */
693     code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
694     if (code) {
695         printf("osi_NetReceive: t_kalloc failed %d\n", code);
696         return code;
697     }
698     udreq->addr.len = sizeof(struct sockaddr_in);
699     udreq->addr.maxlen = sizeof(struct sockaddr_in);
700     udreq->addr.buf =
701         (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
702     udreq->opt.len = 0;
703     udreq->opt.maxlen = 0;
704
705     /*
706      * Loop until we get an error or receive some data.
707      */
708     while (1) {
709         /*
710          * Wait until there is something to do
711          */
712         code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
713         if (events == 0) {
714             osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
715         }
716         /*
717          * If there is a message then read it in
718          */
719         if (code == 0) {
720             code = t_krcvudata(udp_tiptr, udreq, &type, &error);
721         }
722
723         /*
724          * Block attempts to kill this thread
725          */
726         if (code == EINTR && ISSIG(curthread, FORREAL)) {
727             klwp_t *lwp = ttolwp(curthread);
728             proc_t *p = ttoproc(curthread);
729             int sig = lwp->lwp_cursig;
730
731             if (sig == SIGKILL) {
732                 mutex_enter(&p->p_lock);
733                 p->p_flag &= ~SKILLED;
734                 mutex_exit(&p->p_lock);
735             }
736             lwp->lwp_cursig = 0;
737             if (lwp->lwp_curinfo) {
738                 kmem_free((caddr_t) lwp->lwp_curinfo,
739                           sizeof(*lwp->lwp_curinfo));
740                 lwp->lwp_curinfo = NULL;
741             }
742         }
743
744         if (code) {
745             break;
746         }
747
748         /*
749          * Ignore non-data message types
750          */
751         if (type != T_DATA) {
752             continue;
753         }
754
755         /*
756          * Save the source address
757          */
758         memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
759
760         /*
761          * Copy out the message buffers, take care not to overflow
762          * the I/O vector.
763          */
764         dbp = udreq->udata.udata_mp;
765         length = *alength;
766         for (i = 0; dbp != NULL && length > 0 && i < nvecs; i++) {
767             tlen = dvec[i].iov_len;
768             tbase = dvec[i].iov_base;
769             if (tlen > length) {
770                 tlen = length;
771             }
772             while (dbp != NULL && tlen > 0) {
773                 blen = dbp->b_wptr - dbp->b_rptr;
774                 if (blen > tlen) {
775                     memcpy(tbase, (char *)dbp->b_rptr, tlen);
776                     length -= tlen;
777                     dbp->b_rptr += tlen;
778                     tlen = 0;
779                 } else {
780                     memcpy(tbase, (char *)dbp->b_rptr, blen);
781                     length -= blen;
782                     tlen -= blen;
783                     tbase += blen;
784                     dbp = dbp->b_cont;
785                 }
786             }
787         }
788         *alength = *alength - length;
789         break;
790     }
791
792     t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
793     return code;
794 }
795
796
797 void
798 osi_StopListener(void)
799 {
800     osi_FreeSocket(rx_socket);
801 }
802
803
804 void
805 shutdown_rxkernel(void)
806 {
807 }
808
809
810 #endif /* AFS_SUN56_ENV */
811 #endif /* AFS_SUN5_ENV */