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