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