solaris-udp-modname-20080707
[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 #ifdef AFS_SUN510_ENV
40 #include "h/ddi.h"
41 #include "h/ksynch.h"
42 #include "h/sunddi.h"
43 #include "h/sunldi.h"
44 #include "h/sockio.h"
45 #include "h/cmn_err.h"
46 #include "h/socket.h"
47 #include "netinet/in.h"
48 #endif
49
50 /*
51  * Function pointers for kernel socket routines
52  */
53 struct sonode *(*sockfs_socreate)
54   (vnode_t *, int, int, int, int, struct sonode *, int *) = NULL;
55 struct vnode *(*sockfs_solookup)
56   (int, int, int, char *, int *) = NULL;
57 int (*sockfs_sobind)
58   (struct sonode *, struct sockaddr *, int, int, int) = NULL;
59 int (*sockfs_sorecvmsg)
60   (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
61 int (*sockfs_sosendmsg)
62   (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
63 int (*sockfs_sosetsockopt)
64   (struct sonode *, int, int, void *, int) = NULL;
65 #ifndef AFS_SUN510_ENV
66 int (*sockfs_sounbind)
67   (struct sonode *, int);
68 void (*sockfs_sockfree)
69   (struct sonode *);
70 #endif
71
72 #ifndef UDP_MOD_NAME
73 #define UDP_MOD_NAME "udp"
74 #endif
75
76 static afs_uint32 myNetAddrs[ADDRSPERSITE];
77 static int myNetMTUs[ADDRSPERSITE];
78 static int numMyNetAddrs = 0;
79
80 int
81 rxi_GetIFInfo()
82 {
83     int i = 0;
84     int different = 0;
85 #ifndef AFS_SUN510_ENV
86     ill_t *ill;
87     ipif_t *ipif;
88 #endif
89     int rxmtu, maxmtu;
90     int mtus[ADDRSPERSITE];
91     afs_uint32 addrs[ADDRSPERSITE];
92     afs_uint32 ifinaddr;
93
94     memset(mtus, 0, sizeof(mtus));
95     memset(addrs, 0, sizeof(addrs));
96
97 #ifdef AFS_SUN510_ENV
98     (void) rw_enter(&afsifinfo_lock, RW_READER);
99
100     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
101
102              /* Ignore addresses which are down.. */
103             if (!(afsifinfo[i].flags & IFF_UP))
104                 continue;
105
106             /* Compute the Rx interface MTU */
107             rxmtu = (afsifinfo[i].mtu - RX_IPUDP_SIZE);
108
109             ifinaddr = afsifinfo[i].ipaddr;
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 = rxmtu * rxi_nRecvFrags +
117                 ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
118             maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
119             addrs[i] = ifinaddr;
120
121             if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
122                 rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
123                 rx_maxReceiveSize =
124                     MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
125             }
126             
127     }
128     
129     (void) rw_exit(&afsifinfo_lock);
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 #else
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)
153             continue;
154 #endif
155
156         /* Iterate over all the addresses on this ILL */
157         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
158             if (i >= ADDRSPERSITE)
159                 break;
160
161             /* Ignore addresses which are down.. */
162             if (!(ipif->ipif_flags & IFF_UP))
163                 continue;
164
165             /* Compute the Rx interface MTU */
166             rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
167
168             ifinaddr = ntohl(ipif->ipif_local_addr);
169             if (myNetAddrs[i] != ifinaddr)
170                 different++;
171
172             /* Copy interface MTU and address; adjust maxmtu */
173             mtus[i] = rxmtu;
174             rxmtu = rxi_AdjustIfMTU(rxmtu);
175             maxmtu =
176                 rxmtu * rxi_nRecvFrags +
177                 ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
178             maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
179             addrs[i] = ifinaddr;
180             i++;
181
182             if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
183                 rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
184                 rx_maxReceiveSize =
185                     MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
186             }
187         }
188     }
189
190     rx_maxJumboRecvSize =
191         RX_HEADER_SIZE + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
192         (rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE;
193     rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
194
195     if (different) {
196         int j;
197
198         for (j = 0; j < i; j++) {
199             myNetMTUs[j] = mtus[j];
200             myNetAddrs[j] = addrs[j];
201         }
202     }
203
204     return different;
205 }
206 #endif
207
208 int
209 rxi_FindIfMTU(afs_uint32 addr)
210 {
211     afs_uint32 myAddr, netMask;
212     int match_value = 0;
213     int mtu = -1;
214 #ifdef AFS_SUN510_ENV
215     int i = 0;
216 #else
217     ill_t *ill;
218     ipif_t *ipif;
219 #endif
220
221     if (numMyNetAddrs == 0)
222         rxi_GetIFInfo();
223     myAddr = ntohl(addr);
224
225     if (IN_CLASSA(myAddr))
226         netMask = IN_CLASSA_NET;
227     else if (IN_CLASSB(myAddr))
228         netMask = IN_CLASSB_NET;
229     else if (IN_CLASSC(myAddr))
230         netMask = IN_CLASSC_NET;
231     else
232         netMask = 0;
233
234 #ifdef AFS_SUN510_ENV
235     (void) rw_enter(&afsifinfo_lock, RW_READER);
236
237     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
238         afs_uint32 thisAddr, subnetMask;
239         int thisMtu;
240
241         /* Ignore addresses which are down.. */
242         if ((afsifinfo[i].flags & IFF_UP) == 0)
243             continue;
244
245         thisAddr = afsifinfo[i].ipaddr;
246         subnetMask = afsifinfo[i].netmask;
247         thisMtu = afsifinfo[i].mtu;
248
249         if ((myAddr & netMask) == (thisAddr & netMask)) {
250            if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
251                 if (myAddr == thisAddr) {
252                     match_value = 4;
253                     mtu = thisMtu;
254                 }
255
256                 if (match_value < 3) {
257                     match_value = 3;
258                     mtu = thisMtu;
259                 }
260            }
261
262            if (match_value < 2) {
263                 match_value = 2;
264                 mtu = thisMtu;
265            }
266         }
267      }
268      
269      (void) rw_exit(&afsifinfo_lock);
270
271      return mtu;
272 }
273 #else
274     for (ill = ill_g_head; ill; ill = ill->ill_next) {
275 #ifdef AFS_SUN58_ENV
276         /* Make sure this is an IPv4 ILL */
277         if (ill->ill_isv6)
278             continue;
279 #endif
280
281         /* Iterate over all the addresses on this ILL */
282         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
283             afs_uint32 thisAddr, subnetMask;
284             int thisMtu;
285
286             thisAddr = ipif->ipif_local_addr;
287             subnetMask = ipif->ipif_net_mask;
288             thisMtu = ipif->ipif_mtu;
289
290             if ((myAddr & netMask) == (thisAddr & netMask)) {
291                 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
292                     if (myAddr == thisAddr) {
293                         match_value = 4;
294                         mtu = thisMtu;
295                     }
296
297                     if (match_value < 3) {
298                         match_value = 3;
299                         mtu = thisMtu;
300                     }
301                 }
302
303                 if (match_value < 2) {
304                     match_value = 2;
305                     mtu = thisMtu;
306                 }
307             }
308         }
309     }
310
311     return mtu;
312 }
313 #endif
314
315 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
316  * afs_osinet.c. 
317  */
318
319 struct sockaddr_in rx_sockaddr;
320
321 /* Allocate a new socket at specified port in network byte order. */
322 osi_socket *
323 rxk_NewSocketHost(afs_uint32 ahost, short aport)
324 {
325     vnode_t *accessvp;
326     struct sonode *so;
327     struct sockaddr_in addr;
328     int error;
329     int len;
330
331     AFS_STATCNT(osi_NewSocket);
332
333     if (sockfs_solookup == NULL) {
334         sockfs_solookup =
335             (struct vnode * (*)())modlookup("sockfs", "solookup");
336         if (sockfs_solookup == NULL) {
337             return NULL;
338         }
339     }
340     if (sockfs_socreate == NULL) {
341         sockfs_socreate =
342             (struct sonode * (*)())modlookup("sockfs", "socreate");
343         if (sockfs_socreate == NULL) {
344             return NULL;
345         }
346     }
347     if (sockfs_sobind == NULL) {
348         sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
349         if (sockfs_sobind == NULL) {
350             return NULL;
351         }
352     }
353     if (sockfs_sosetsockopt == NULL) {
354         sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
355         if (sockfs_sosetsockopt == NULL) {
356             return NULL;
357         }
358     }
359     if (sockfs_sosendmsg == NULL) {
360         sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
361         if (sockfs_sosendmsg == NULL) {
362             return NULL;
363         }
364     }
365     if (sockfs_sorecvmsg == NULL) {
366         sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
367         if (sockfs_sorecvmsg == NULL) {
368             return NULL;
369         }
370     }
371 #ifndef AFS_SUN510_ENV
372     if (sockfs_sounbind == NULL) {
373         sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
374         if (sockfs_sounbind == NULL)
375             return NULL;
376     }
377     if (sockfs_sockfree == NULL) {
378         sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
379         if (sockfs_sockfree == NULL)
380             return NULL;
381     }
382 #endif
383
384     accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
385     if (accessvp == NULL) {
386         return NULL;
387     }
388
389     so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, NULL,
390                          &error);
391     if (so == NULL) {
392         return NULL;
393     }
394
395     addr.sin_family = AF_INET;
396     addr.sin_port = aport;
397     addr.sin_addr.s_addr = ahost; /* I wonder what the odds are on
398                                      needing to unbyteswap this */
399     error = sockfs_sobind(so, (struct sockaddr *)&addr, sizeof(addr), 0, 0);
400     if (error != 0) {
401         return NULL;
402     }
403
404     len = rx_UdpBufSize;
405     error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
406     if (error != 0) {
407         return NULL;
408     }
409
410     len = rx_UdpBufSize;
411     error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
412     if (error != 0) {
413         return NULL;
414     }
415
416     return (osi_socket *)so;
417 }
418
419 osi_socket *
420 rxk_NewSocket(short aport)
421 {
422     return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
423 }
424
425 int
426 osi_FreeSocket(register osi_socket *asocket)
427 {
428     extern int rxk_ListenerPid;
429     struct sonode *so = (struct sonode *)asocket;
430     struct sockaddr_in taddr;
431     struct iovec dvec;
432     char c;
433     vnode_t *vp;
434
435     AFS_STATCNT(osi_FreeSocket);
436
437     taddr.sin_family = AF_INET;
438     taddr.sin_port = rx_port;
439     taddr.sin_addr.s_addr = htonl(0x7f000001);
440
441     dvec.iov_base = &c;
442     dvec.iov_len = 1;
443
444     while (rxk_ListenerPid) {
445         osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
446         afs_osi_Sleep(&rxk_ListenerPid);
447     }
448
449     /* Was sockfs_sounbind(so, 0); sockfs_sockfree(so); That's wrong */
450     vp = SOTOV(so);
451  #ifdef AFS_SUN511_ENV
452     VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED(), NULL);
453  #else
454     VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED());
455  #endif
456     VN_RELE(vp);
457
458     return 0;
459 }
460
461 int
462 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
463             int nvecs, afs_int32 asize, int istack)
464 {
465     struct sonode *so = (struct sonode *)asocket;
466     struct nmsghdr msg;
467     struct uio uio;
468     struct iovec iov[RX_MAXIOVECS];
469     int error;
470     int i;
471
472     if (nvecs > RX_MAXIOVECS) {
473         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
474     }
475
476     msg.msg_name = (struct sockaddr *)addr;
477     msg.msg_namelen = sizeof(struct sockaddr_in);
478     msg.msg_iov = dvec;
479     msg.msg_iovlen = nvecs;
480     msg.msg_control = NULL;
481     msg.msg_controllen = 0;
482     msg.msg_flags = 0;
483
484     for (i = 0; i < nvecs; i++) {
485         iov[i].iov_base = dvec[i].iov_base;
486         iov[i].iov_len = dvec[i].iov_len;
487     }
488     uio.uio_iov = &iov[0];
489     uio.uio_iovcnt = nvecs;
490     uio.uio_loffset = 0;
491     uio.uio_segflg = UIO_SYSSPACE;
492     uio.uio_fmode = FREAD | FWRITE;
493     uio.uio_limit = 0;
494     uio.uio_resid = asize;
495
496     error = sockfs_sosendmsg(so, &msg, &uio);
497
498     return error;
499 }
500
501 int
502 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
503                int nvecs, int *alength)
504 {
505     struct sonode *asocket = (struct sonode *)so;
506     struct nmsghdr msg;
507     struct uio uio;
508     struct iovec iov[RX_MAXIOVECS];
509     int error;
510     int i;
511
512     if (nvecs > RX_MAXIOVECS) {
513         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
514     }
515
516     msg.msg_name = NULL;
517     msg.msg_namelen = sizeof(struct sockaddr_in);
518     msg.msg_iov = NULL;
519     msg.msg_iovlen = 0;
520     msg.msg_control = NULL;
521     msg.msg_controllen = 0;
522     msg.msg_flags = 0;
523
524     for (i = 0; i < nvecs; i++) {
525         iov[i].iov_base = dvec[i].iov_base;
526         iov[i].iov_len = dvec[i].iov_len;
527     }
528     uio.uio_iov = &iov[0];
529     uio.uio_iovcnt = nvecs;
530     uio.uio_loffset = 0;
531     uio.uio_segflg = UIO_SYSSPACE;
532     uio.uio_fmode = 0;
533     uio.uio_limit = 0;
534     uio.uio_resid = *alength;
535
536     error = sockfs_sorecvmsg(asocket, &msg, &uio);
537     if (error == 0) {
538         if (msg.msg_name == NULL) {
539             error = -1;
540         } else {
541             memcpy(addr, msg.msg_name, msg.msg_namelen);
542             kmem_free(msg.msg_name, msg.msg_namelen);
543             *alength = *alength - uio.uio_resid;
544         }
545     }
546
547     if (error == EINTR && ISSIG(curthread, FORREAL)) {
548         klwp_t *lwp = ttolwp(curthread);
549         proc_t *p = ttoproc(curthread);
550         int sig = lwp->lwp_cursig;
551
552         if (sig == SIGKILL) {
553             mutex_enter(&p->p_lock);
554             p->p_flag &= ~SKILLED;
555             mutex_exit(&p->p_lock);
556         }
557         lwp->lwp_cursig = 0;
558         if (lwp->lwp_curinfo) {
559             siginfofree(lwp->lwp_curinfo);
560             lwp->lwp_curinfo = NULL;
561         }
562     }
563
564     return error;
565 }
566
567 #if defined(AFS_SUN510_ENV)
568 /* How often afs collects interface info. Tunable via /etc/system:      */
569 /* set afs:afs_if_poll_interval = integer (value is in seconds)         */
570 static int afs_if_poll_interval = 30;
571
572 /* Global array which holds the interface info for consumers            */
573 struct afs_ifinfo afsifinfo[ADDRSPERSITE];
574
575 void
576 osi_StartNetIfPoller()
577 {
578     (void) ddi_taskq_dispatch(afs_taskq, (void(*) (void*)) osi_NetIfPoller,
579             NULL, DDI_SLEEP);
580 }
581
582 void
583 osi_NetIfPoller()
584 {
585     cred_t *cr;
586     ldi_ident_t li;
587     ldi_handle_t lh;
588     struct lifnum lifn;
589     struct lifconf lifc;
590     struct lifreq lifr;
591     struct lifreq *lifrp;
592     struct sockaddr_in *sin4_local;
593     struct sockaddr_in *sin4_dst;
594     major_t udpmajor;
595     caddr_t lifcbuf;
596     int i, count, error, rv;
597     int ifcount;
598     int metric;
599     int index;
600     uint_t mtu;
601     uint64_t flags;
602
603     if (afs_termState == AFSOP_STOP_NETIF) {
604         afs_warn("NetIfPoller... ");
605         rw_destroy(&afsifinfo_lock);
606         ddi_taskq_destroy(afs_taskq);
607         afs_termState = AFSOP_STOP_COMPLETE;
608         osi_rxWakeup(&afs_termState);
609         return;
610     }
611     /* Get our permissions */
612     cr = CRED();
613
614     /* Initialize and open /dev/udp for receiving ioctls */
615     udpmajor = ddi_name_to_major(UDP_MOD_NAME);
616
617     error = ldi_ident_from_major(udpmajor, &li);
618     if (error)
619         cmn_err(CE_PANIC, "osi_NetIfPoller: ldi_ident_from_major failed: %d",
620             error);
621
622     error = ldi_open_by_name(UDP_DEV_NAME, FREAD, cr, &lh, li);
623     if (error)
624         cmn_err(CE_PANIC,
625             "osi_NetIfPoller: ldi_open_by_name failed: %d", error);
626
627
628     /* First, how many interfaces do we have? */
629     (void) bzero((void *)&lifn, sizeof(struct lifnum));
630     lifn.lifn_family   = AF_INET;
631
632     error = ldi_ioctl(lh, SIOCGLIFNUM, (intptr_t)&lifn,
633         FKIOCTL, cr, &rv);
634     if (error)
635      cmn_err(CE_PANIC,
636          "osi_NetIfPoller: ldi_ioctl: SIOCGLIFNUM failed: %d", error);
637
638     ifcount = lifn.lifn_count;
639
640     /* Set up some stuff for storing the results of SIOCGLIFCONF */
641     (void) bzero((void *)&lifc, sizeof(struct lifconf));
642
643     lifcbuf = kmem_zalloc(ifcount * sizeof(struct lifreq), KM_SLEEP);
644
645     lifc.lifc_family  = AF_INET;
646     lifc.lifc_flags   = IFF_UP;
647     lifc.lifc_len     = ifcount * sizeof(struct lifreq);
648     lifc.lifc_buf     = lifcbuf;
649
650     /* Get info on each of our available interfaces. */
651     error = ldi_ioctl(lh, SIOCGLIFCONF, (intptr_t)&lifc,
652         FKIOCTL, cr, &rv);
653     if (error)
654         cmn_err(CE_PANIC,
655             "osi_NetIfPoller: ldi_ioctl: SIOCGLIFCONF failed: %d", error);
656
657     lifrp = lifc.lifc_req;
658
659     count = 0;
660
661     /* Loop through our interfaces and pick out the info we want */
662     for (i = lifc.lifc_len / sizeof(struct lifreq);
663         i > 0; i--, lifrp++) {
664                 
665         if (count >= ADDRSPERSITE)
666                 break;
667
668         (void) bzero((void *)&lifr, sizeof(struct lifreq));
669
670         (void) strncpy(lifr.lifr_name, lifrp->lifr_name,
671             sizeof(lifr.lifr_name));
672
673         /* Get this interface's Flags */
674         error = ldi_ioctl(lh, SIOCGLIFFLAGS, (intptr_t)&lifr,
675             FKIOCTL, cr, &rv);
676         if (error)
677             cmn_err(CE_PANIC,
678                 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFFLAGS failed: %d",
679                     error);
680
681         /* Ignore plumbed but down interfaces. */
682         if ((lifr.lifr_flags & IFF_UP) == 0)
683             continue;
684
685         flags = lifr.lifr_flags;
686
687         /* Get this interface's MTU */
688         error = ldi_ioctl(lh, SIOCGLIFMTU, (intptr_t)&lifr,
689             FKIOCTL, cr, &rv);
690
691         if (error) {
692             mtu = 1125;
693         } else {
694             mtu = lifr.lifr_metric;
695         }
696
697         /* Get this interface's Metric */
698         error = ldi_ioctl(lh, SIOCGLIFMETRIC, (intptr_t)&lifr,
699             FKIOCTL, cr, &rv);
700
701         if (error) {
702             metric = 0;
703         } else {
704             metric = lifr.lifr_metric;
705         }
706
707         sin4_local = (struct sockaddr_in *) &lifrp->lifr_addr;
708         sin4_dst = (struct sockaddr_in *) &lifrp->lifr_dstaddr;
709
710         /* Acquire global array write lock */
711         (void) rw_enter(&afsifinfo_lock, RW_WRITER);
712
713         /* Copy our collected data into the global array */
714         (void) strncpy(afsifinfo[count].ifname, lifrp->lifr_name,
715             sizeof(afsifinfo[count].ifname));
716         afsifinfo[count].ipaddr     = ntohl(sin4_local->sin_addr.s_addr);
717         afsifinfo[count].mtu        = mtu;
718         afsifinfo[count].netmask    = lifrp->lifr_addrlen;
719         afsifinfo[count].flags      = flags;
720         afsifinfo[count].metric     = metric;
721         afsifinfo[count].dstaddr    = ntohl(sin4_dst->sin_addr.s_addr);
722
723         /* Release global array write lock */
724         (void) rw_exit(&afsifinfo_lock);
725
726         count++;
727
728     } /* Bottom of loop: for each interface ... */
729
730     kmem_free(lifcbuf, ifcount * sizeof(struct lifreq));
731
732     /* End of thread. Time to clean up */
733     (void) ldi_close(lh, FREAD, cr);
734     (void) ldi_ident_release(li);
735
736     /* Schedule this to run again after afs_if_poll_interval seconds */
737     (void) timeout((void(*) (void *)) osi_StartNetIfPoller, NULL,
738         drv_usectohz((clock_t)afs_if_poll_interval * MICROSEC));
739
740 }
741 #endif /* AFS_SUN510_ENV */
742
743 void
744 shutdown_rxkernel(void)
745 {
746 }
747
748 void
749 osi_StopListener(void)
750 {
751     osi_FreeSocket(rx_socket);
752 }
753
754 #else /* AFS_SUN56_ENV */
755
756 #include "inet/common.h"
757 #include "sys/tiuser.h"
758 #include "sys/t_kuser.h"
759 #include "sys/ioctl.h"
760 #include "sys/stropts.h"
761 #include "sys/stream.h"
762 #include "sys/strsubr.h"
763 #include "sys/vnode.h"
764 #include "sys/stropts.h"
765 #include "sys/tihdr.h"
766 #include "sys/timod.h"
767 #include "sys/fcntl.h"
768 #include "sys/debug.h"
769 #include "inet/common.h"
770 #include "inet/mi.h"
771 #include "netinet/udp.h"
772
773 extern dev_t afs_udp_rdev;
774
775
776 int
777 rxi_GetIFInfo()
778 {
779     return 0;
780 }
781
782
783 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
784  * afs_osinet.c. 
785  */
786
787 dev_t afs_udp_rdev = (dev_t) 0;
788
789 /* Allocate a new socket at specified port in network byte order. */
790 osi_socket *
791 rxk_NewSocketHost(afs_uint32 ahost, short aport)
792 {
793     TIUSER *udp_tiptr;
794     struct t_bind *reqp, *rspp;
795     afs_int32 code;
796     struct sockaddr_in *myaddrp;
797     struct stdata *stp;
798     struct queue *q;
799
800     AFS_STATCNT(osi_NewSocket);
801     afs_udp_rdev = makedevice(11 /*CLONE*/, ddi_name_to_major("udp"));
802     code = t_kopen(NULL, afs_udp_rdev, FREAD | FWRITE, &udp_tiptr, CRED());
803     if (code) {
804         return (osi_socket *)0;
805     }
806
807     code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&reqp);
808     if (code) {
809         t_kclose(udp_tiptr, 0);
810     }
811     code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&rspp);
812     if (code) {
813         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
814         t_kclose(udp_tiptr, 0);
815         return (osi_socket *)0;
816     }
817
818     reqp->addr.len = sizeof(struct sockaddr_in);
819     myaddrp = (struct sockaddr_in *)reqp->addr.buf;
820     myaddrp->sin_family = AF_INET;
821     myaddrp->sin_port = aport;
822     myaddrp->sin_addr.s_addr = ahost;   /* byteswap? */
823
824     code = t_kbind(udp_tiptr, reqp, rspp);
825     if (code) {
826         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
827         t_kfree(udp_tiptr, (char *)rspp, T_BIND);
828         t_kclose(udp_tiptr, 0);
829         return (osi_socket *)0;
830     }
831     if (memcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
832         t_kfree(udp_tiptr, (char *)reqp, T_BIND);
833         t_kfree(udp_tiptr, (char *)rspp, T_BIND);
834         t_kclose(udp_tiptr, 0);
835         return (osi_socket *)0;
836     }
837     t_kfree(udp_tiptr, (char *)reqp, T_BIND);
838     t_kfree(udp_tiptr, (char *)rspp, T_BIND);
839
840     /*
841      * Set the send and receive buffer sizes.
842      */
843     stp = udp_tiptr->fp->f_vnode->v_stream;
844     q = stp->sd_wrq;
845     q->q_hiwat = rx_UdpBufSize;
846     q->q_next->q_hiwat = rx_UdpBufSize;
847     RD(q)->q_hiwat = rx_UdpBufSize;
848
849     return (osi_socket *)udp_tiptr;
850 }
851
852 osi_socket *
853 rxk_NewSocket(short aport)
854 {
855     return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
856 }
857
858 int
859 osi_FreeSocket(register osi_socket *asocket)
860 {
861     extern int rxk_ListenerPid;
862     TIUSER *udp_tiptr = (TIUSER *) asocket;
863     AFS_STATCNT(osi_FreeSocket);
864
865     if (rxk_ListenerPid) {
866         kill(rxk_ListenerPid, SIGUSR1);
867         afs_osi_Sleep(&rxk_ListenerPid);
868     }
869     return 0;
870 }
871
872
873 int
874 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
875             int nvecs, afs_int32 asize, int istack)
876 {
877     int i;
878     int code;
879     TIUSER *udp_tiptr = (TIUSER *) asocket;
880     struct t_kunitdata *udreq;
881     struct sockaddr_in sin;
882     mblk_t *bp;
883     mblk_t *dbp;
884
885     /*
886      * XXX We don't do any checking on the family since it's assumed to be
887      * AF_INET XXX
888      */
889     sin.sin_family = AF_INET;
890     sin.sin_addr.s_addr = addr->sin_addr.s_addr;
891     sin.sin_port = addr->sin_port;
892
893     /*
894      * Get a buffer for the RX header
895      */
896     if (nvecs < 1) {
897         osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
898     }
899     while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
900         if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
901             return (ENOSR);
902         }
903     }
904
905     /* Copy the data into the buffer */
906     memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
907     bp->b_datap->db_type = M_DATA;
908     bp->b_wptr += dvec[0].iov_len;
909
910     /*
911      * Append each element in the iovec to the buffer
912      */
913     for (i = 1; i < nvecs; i++) {
914         /* Get a buffer for the next chunk */
915         while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
916             if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
917                 freeb(bp);
918                 return (ENOSR);
919             }
920         }
921
922         /* Copy the data into the buffer */
923         memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base,
924                dvec[i].iov_len);
925         dbp->b_datap->db_type = M_DATA;
926         dbp->b_wptr += dvec[i].iov_len;
927
928         /* Append it to the message buffer */
929         linkb(bp, dbp);
930     }
931
932     /*
933      * Allocate and format the unitdata structure.
934      */
935     code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
936     if (code) {
937         freeb(bp);
938         printf("osi_NetSend: t_kalloc failed %d\n", code);
939         return code;
940     }
941     udreq->addr.len = sizeof(struct sockaddr_in);
942     udreq->addr.maxlen = sizeof(struct sockaddr_in);
943     udreq->addr.buf =
944         (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
945     udreq->opt.len = 0;
946     udreq->opt.maxlen = 0;
947     memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
948     udreq->udata.udata_mp = bp;
949     udreq->udata.len = asize;
950
951     code = t_ksndudata(udp_tiptr, udreq, NULL);
952     if (code) {
953         printf("osi_NetSend: t_ksndudata failed %d\n", code);
954     }
955
956     t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
957     return code;
958 }
959
960
961 int
962 osi_NetReceive(osi_socket *asocket, struct sockaddr_in *addr,
963                struct iovec *dvec, int nvecs, int *alength)
964 {
965     int i;
966     TIUSER *udp_tiptr = (TIUSER *) asocket;
967     struct t_kunitdata *udreq;
968     mblk_t *dbp;
969     char *phandle;
970     short sport;
971     int code = 0;
972     int length;
973     int tlen;
974     int blen;
975     char *tbase;
976     int type;
977     int error;
978     int events;
979
980     /*
981      * Allocate the unitdata structure.
982      */
983     code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
984     if (code) {
985         printf("osi_NetReceive: t_kalloc failed %d\n", code);
986         return code;
987     }
988     udreq->addr.len = sizeof(struct sockaddr_in);
989     udreq->addr.maxlen = sizeof(struct sockaddr_in);
990     udreq->addr.buf =
991         (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
992     udreq->opt.len = 0;
993     udreq->opt.maxlen = 0;
994
995     /*
996      * Loop until we get an error or receive some data.
997      */
998     while (1) {
999         /*
1000          * Wait until there is something to do
1001          */
1002         code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
1003         if (events == 0) {
1004             osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
1005         }
1006         /*
1007          * If there is a message then read it in
1008          */
1009         if (code == 0) {
1010             code = t_krcvudata(udp_tiptr, udreq, &type, &error);
1011         }
1012
1013         /*
1014          * Block attempts to kill this thread
1015          */
1016         if (code == EINTR && ISSIG(curthread, FORREAL)) {
1017             klwp_t *lwp = ttolwp(curthread);
1018             proc_t *p = ttoproc(curthread);
1019             int sig = lwp->lwp_cursig;
1020
1021             if (sig == SIGKILL) {
1022                 mutex_enter(&p->p_lock);
1023                 p->p_flag &= ~SKILLED;
1024                 mutex_exit(&p->p_lock);
1025             }
1026             lwp->lwp_cursig = 0;
1027             if (lwp->lwp_curinfo) {
1028                 kmem_free((caddr_t) lwp->lwp_curinfo,
1029                           sizeof(*lwp->lwp_curinfo));
1030                 lwp->lwp_curinfo = NULL;
1031             }
1032         }
1033
1034         if (code) {
1035             break;
1036         }
1037
1038         /*
1039          * Ignore non-data message types
1040          */
1041         if (type != T_DATA) {
1042             continue;
1043         }
1044
1045         /*
1046          * Save the source address
1047          */
1048         memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
1049
1050         /*
1051          * Copy out the message buffers, take care not to overflow
1052          * the I/O vector.
1053          */
1054         dbp = udreq->udata.udata_mp;
1055         length = *alength;
1056         for (i = 0; dbp != NULL && length > 0 && i < nvecs; i++) {
1057             tlen = dvec[i].iov_len;
1058             tbase = dvec[i].iov_base;
1059             if (tlen > length) {
1060                 tlen = length;
1061             }
1062             while (dbp != NULL && tlen > 0) {
1063                 blen = dbp->b_wptr - dbp->b_rptr;
1064                 if (blen > tlen) {
1065                     memcpy(tbase, (char *)dbp->b_rptr, tlen);
1066                     length -= tlen;
1067                     dbp->b_rptr += tlen;
1068                     tlen = 0;
1069                 } else {
1070                     memcpy(tbase, (char *)dbp->b_rptr, blen);
1071                     length -= blen;
1072                     tlen -= blen;
1073                     tbase += blen;
1074                     dbp = dbp->b_cont;
1075                 }
1076             }
1077         }
1078         *alength = *alength - length;
1079         break;
1080     }
1081
1082     t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
1083     return code;
1084 }
1085
1086
1087 void
1088 osi_StopListener(void)
1089 {
1090     osi_FreeSocket(rx_socket);
1091 }
1092
1093
1094 void
1095 shutdown_rxkernel(void)
1096 {
1097 }
1098
1099
1100 #endif /* AFS_SUN56_ENV */
1101 #endif /* AFS_SUN5_ENV */