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