43314c1c00bc29f8d7f6639f525c1f7b9f0e009b
[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 #ifdef AFS_SUN510_ENV
345     vp = SOTOV(so);
346     VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED());
347     VN_RELE(vp);
348 #else
349     sockfs_sounbind(so, 0);
350     sockfs_sockfree(so);
351 #endif
352     return 0;
353 }
354
355 int
356 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
357             int nvecs, afs_int32 asize, int istack)
358 {
359     struct sonode *so = (struct sonode *)asocket;
360     struct nmsghdr msg;
361     struct uio uio;
362     struct iovec iov[RX_MAXIOVECS];
363     int error;
364     int i;
365
366     if (nvecs > RX_MAXIOVECS) {
367         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
368     }
369
370     msg.msg_name = (struct sockaddr *)addr;
371     msg.msg_namelen = sizeof(struct sockaddr_in);
372     msg.msg_iov = dvec;
373     msg.msg_iovlen = nvecs;
374     msg.msg_control = NULL;
375     msg.msg_controllen = 0;
376     msg.msg_flags = 0;
377
378     for (i = 0; i < nvecs; i++) {
379         iov[i].iov_base = dvec[i].iov_base;
380         iov[i].iov_len = dvec[i].iov_len;
381     }
382     uio.uio_iov = &iov[0];
383     uio.uio_iovcnt = nvecs;
384     uio.uio_loffset = 0;
385     uio.uio_segflg = UIO_SYSSPACE;
386     uio.uio_fmode = FREAD | FWRITE;
387     uio.uio_limit = 0;
388     uio.uio_resid = asize;
389
390     error = sockfs_sosendmsg(so, &msg, &uio);
391
392     return error;
393 }
394
395 int
396 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
397                int nvecs, int *alength)
398 {
399     struct sonode *asocket = (struct sonode *)so;
400     struct nmsghdr msg;
401     struct uio uio;
402     struct iovec iov[RX_MAXIOVECS];
403     int error;
404     int i;
405
406     if (nvecs > RX_MAXIOVECS) {
407         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
408     }
409
410     msg.msg_name = NULL;
411     msg.msg_namelen = sizeof(struct sockaddr_in);
412     msg.msg_iov = NULL;
413     msg.msg_iovlen = 0;
414     msg.msg_control = NULL;
415     msg.msg_controllen = 0;
416     msg.msg_flags = 0;
417
418     for (i = 0; i < nvecs; i++) {
419         iov[i].iov_base = dvec[i].iov_base;
420         iov[i].iov_len = dvec[i].iov_len;
421     }
422     uio.uio_iov = &iov[0];
423     uio.uio_iovcnt = nvecs;
424     uio.uio_loffset = 0;
425     uio.uio_segflg = UIO_SYSSPACE;
426     uio.uio_fmode = 0;
427     uio.uio_limit = 0;
428     uio.uio_resid = *alength;
429
430     error = sockfs_sorecvmsg(asocket, &msg, &uio);
431     if (error == 0) {
432         if (msg.msg_name == NULL) {
433             error = -1;
434         } else {
435             memcpy(addr, msg.msg_name, 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 struct osi_socket *
509 rxk_NewSocket(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 (struct 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 (struct 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 = INADDR_ANY;      /* XXX Was 0 XXX */
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 (struct 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 (struct 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 (struct osi_socket *)udp_tiptr;
568 }
569
570
571 int
572 osi_FreeSocket(register struct osi_socket *asocket)
573 {
574     extern int rxk_ListenerPid;
575     TIUSER *udp_tiptr = (TIUSER *) asocket;
576     AFS_STATCNT(osi_FreeSocket);
577
578     if (rxk_ListenerPid) {
579         kill(rxk_ListenerPid, SIGUSR1);
580         afs_osi_Sleep(&rxk_ListenerPid);
581     }
582     return 0;
583 }
584
585
586 int
587 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
588             int nvecs, afs_int32 asize, int istack)
589 {
590     int i;
591     int code;
592     TIUSER *udp_tiptr = (TIUSER *) asocket;
593     struct t_kunitdata *udreq;
594     struct sockaddr_in sin;
595     mblk_t *bp;
596     mblk_t *dbp;
597
598     /*
599      * XXX We don't do any checking on the family since it's assumed to be
600      * AF_INET XXX
601      */
602     sin.sin_family = AF_INET;
603     sin.sin_addr.s_addr = addr->sin_addr.s_addr;
604     sin.sin_port = addr->sin_port;
605
606     /*
607      * Get a buffer for the RX header
608      */
609     if (nvecs < 1) {
610         osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
611     }
612     while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
613         if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
614             return (ENOSR);
615         }
616     }
617
618     /* Copy the data into the buffer */
619     memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
620     bp->b_datap->db_type = M_DATA;
621     bp->b_wptr += dvec[0].iov_len;
622
623     /*
624      * Append each element in the iovec to the buffer
625      */
626     for (i = 1; i < nvecs; i++) {
627         /* Get a buffer for the next chunk */
628         while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
629             if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
630                 freeb(bp);
631                 return (ENOSR);
632             }
633         }
634
635         /* Copy the data into the buffer */
636         memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base,
637                dvec[i].iov_len);
638         dbp->b_datap->db_type = M_DATA;
639         dbp->b_wptr += dvec[i].iov_len;
640
641         /* Append it to the message buffer */
642         linkb(bp, dbp);
643     }
644
645     /*
646      * Allocate and format the unitdata structure.
647      */
648     code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
649     if (code) {
650         freeb(bp);
651         printf("osi_NetSend: t_kalloc failed %d\n", code);
652         return code;
653     }
654     udreq->addr.len = sizeof(struct sockaddr_in);
655     udreq->addr.maxlen = sizeof(struct sockaddr_in);
656     udreq->addr.buf =
657         (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
658     udreq->opt.len = 0;
659     udreq->opt.maxlen = 0;
660     memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
661     udreq->udata.udata_mp = bp;
662     udreq->udata.len = asize;
663
664     code = t_ksndudata(udp_tiptr, udreq, NULL);
665     if (code) {
666         printf("osi_NetSend: t_ksndudata failed %d\n", code);
667     }
668
669     t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
670     return code;
671 }
672
673
674 int
675 osi_NetReceive(struct osi_socket *asocket, struct sockaddr_in *addr,
676                struct iovec *dvec, int nvecs, int *alength)
677 {
678     int i;
679     TIUSER *udp_tiptr = (TIUSER *) asocket;
680     struct t_kunitdata *udreq;
681     mblk_t *dbp;
682     char *phandle;
683     short sport;
684     int code = 0;
685     int length;
686     int tlen;
687     int blen;
688     char *tbase;
689     int type;
690     int error;
691     int events;
692
693     /*
694      * Allocate the unitdata structure.
695      */
696     code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
697     if (code) {
698         printf("osi_NetReceive: t_kalloc failed %d\n", code);
699         return code;
700     }
701     udreq->addr.len = sizeof(struct sockaddr_in);
702     udreq->addr.maxlen = sizeof(struct sockaddr_in);
703     udreq->addr.buf =
704         (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
705     udreq->opt.len = 0;
706     udreq->opt.maxlen = 0;
707
708     /*
709      * Loop until we get an error or receive some data.
710      */
711     while (1) {
712         /*
713          * Wait until there is something to do
714          */
715         code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
716         if (events == 0) {
717             osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
718         }
719         /*
720          * If there is a message then read it in
721          */
722         if (code == 0) {
723             code = t_krcvudata(udp_tiptr, udreq, &type, &error);
724         }
725
726         /*
727          * Block attempts to kill this thread
728          */
729         if (code == EINTR && ISSIG(curthread, FORREAL)) {
730             klwp_t *lwp = ttolwp(curthread);
731             proc_t *p = ttoproc(curthread);
732             int sig = lwp->lwp_cursig;
733
734             if (sig == SIGKILL) {
735                 mutex_enter(&p->p_lock);
736                 p->p_flag &= ~SKILLED;
737                 mutex_exit(&p->p_lock);
738             }
739             lwp->lwp_cursig = 0;
740             if (lwp->lwp_curinfo) {
741                 kmem_free((caddr_t) lwp->lwp_curinfo,
742                           sizeof(*lwp->lwp_curinfo));
743                 lwp->lwp_curinfo = NULL;
744             }
745         }
746
747         if (code) {
748             break;
749         }
750
751         /*
752          * Ignore non-data message types
753          */
754         if (type != T_DATA) {
755             continue;
756         }
757
758         /*
759          * Save the source address
760          */
761         memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
762
763         /*
764          * Copy out the message buffers, take care not to overflow
765          * the I/O vector.
766          */
767         dbp = udreq->udata.udata_mp;
768         length = *alength;
769         for (i = 0; dbp != NULL && length > 0 && i < nvecs; i++) {
770             tlen = dvec[i].iov_len;
771             tbase = dvec[i].iov_base;
772             if (tlen > length) {
773                 tlen = length;
774             }
775             while (dbp != NULL && tlen > 0) {
776                 blen = dbp->b_wptr - dbp->b_rptr;
777                 if (blen > tlen) {
778                     memcpy(tbase, (char *)dbp->b_rptr, tlen);
779                     length -= tlen;
780                     dbp->b_rptr += tlen;
781                     tlen = 0;
782                 } else {
783                     memcpy(tbase, (char *)dbp->b_rptr, blen);
784                     length -= blen;
785                     tlen -= blen;
786                     tbase += blen;
787                     dbp = dbp->b_cont;
788                 }
789             }
790         }
791         *alength = *alength - length;
792         break;
793     }
794
795     t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
796     return code;
797 }
798
799
800 void
801 osi_StopListener(void)
802 {
803     osi_FreeSocket(rx_socket);
804 }
805
806
807 void
808 shutdown_rxkernel(void)
809 {
810 }
811
812
813 #endif /* AFS_SUN56_ENV */
814 #endif /* AFS_SUN5_ENV */