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