Import Upstream version 1.8.5
[hcoop/debian/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 #include "rx/rx_packet.h"
17
18
19 #include "inet/common.h"
20 #include "sys/tiuser.h"
21 #include "sys/t_kuser.h"
22 #include "sys/stropts.h"
23 #include "sys/stream.h"
24 #include "sys/tihdr.h"
25 #include "sys/fcntl.h"
26 #include "netinet/ip6.h"
27 #define ipif_local_addr ipif_lcl_addr
28 #ifndef V4_PART_OF_V6
29 #define V4_PART_OF_V6(v6) v6.s6_addr32[3]
30 #endif
31 #include "inet/ip.h"
32 #include "inet/ip_if.h"
33 #include "netinet/udp.h"
34 #ifdef AFS_SUN510_ENV
35 #include "h/ddi.h"
36 #include "h/ksynch.h"
37 #include "h/sunddi.h"
38 #include "h/sunldi.h"
39 #include "h/sockio.h"
40 #include "h/cmn_err.h"
41 #include "h/socket.h"
42 #include "netinet/in.h"
43 #endif
44
45 /*
46 * Function pointers for kernel socket routines
47 */
48 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
49 struct sonode *(*sockfs_socreate)
50 (struct sockparams *, int, int, int, int, int *) = NULL;
51 int (*sockfs_solookup)
52 (int, int, int, struct sockparams **) = NULL;
53 #else
54 struct sonode *(*sockfs_socreate)
55 (vnode_t *, int, int, int, int, struct sonode *, int *) = NULL;
56 struct vnode *(*sockfs_solookup)
57 (int, int, int, char *, int *) = NULL;
58 #endif /* SOLOOKUP_TAKES_SOCKPARAMS */
59 int (*sockfs_sobind)
60 (struct sonode *, struct sockaddr *, int, int, int) = NULL;
61 int (*sockfs_sorecvmsg)
62 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
63 int (*sockfs_sosendmsg)
64 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
65 int (*sockfs_sosetsockopt)
66 (struct sonode *, int, int, void *, int) = NULL;
67 #ifndef AFS_SUN510_ENV
68 int (*sockfs_sounbind)
69 (struct sonode *, int);
70 void (*sockfs_sockfree)
71 (struct sonode *);
72 #endif
73
74 #ifndef UDP_MOD_NAME
75 #define UDP_MOD_NAME "udp"
76 #endif
77
78 static afs_uint32 myNetAddrs[ADDRSPERSITE];
79 static int myNetMTUs[ADDRSPERSITE];
80 static int numMyNetAddrs = 0;
81
82 int
83 rxi_GetIFInfo()
84 {
85 int i = 0;
86 int different = 0;
87 #ifndef AFS_SUN510_ENV
88 ill_t *ill;
89 ipif_t *ipif;
90 #endif
91 int rxmtu, maxmtu;
92 int mtus[ADDRSPERSITE];
93 afs_uint32 addrs[ADDRSPERSITE];
94 afs_uint32 ifinaddr;
95
96 memset(mtus, 0, sizeof(mtus));
97 memset(addrs, 0, sizeof(addrs));
98
99 #ifdef AFS_SUN510_ENV
100 (void) rw_enter(&afsifinfo_lock, RW_READER);
101
102 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
103
104 /* Ignore addresses which are down.. */
105 if (!(afsifinfo[i].flags & IFF_UP))
106 continue;
107
108 /* Compute the Rx interface MTU */
109 rxmtu = (afsifinfo[i].mtu - RX_IPUDP_SIZE);
110
111 ifinaddr = afsifinfo[i].ipaddr;
112 if (myNetAddrs[i] != ifinaddr)
113 different++;
114
115 /* Copy interface MTU and address; adjust maxmtu */
116 mtus[i] = rxmtu;
117 rxmtu = rxi_AdjustIfMTU(rxmtu);
118 maxmtu = rxmtu * rxi_nRecvFrags +
119 ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
120 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
121 addrs[i] = ifinaddr;
122
123 if (!rx_IsLoopbackAddr(ifinaddr) && maxmtu > rx_maxReceiveSize) {
124 rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
125 rx_maxReceiveSize =
126 MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
127 }
128
129 }
130
131 (void) rw_exit(&afsifinfo_lock);
132
133 rx_maxJumboRecvSize =
134 RX_HEADER_SIZE + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
135 (rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE;
136 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
137
138 if (different) {
139 int j;
140
141 for (j = 0; j < i; j++) {
142 myNetMTUs[j] = mtus[j];
143 myNetAddrs[j] = addrs[j];
144 }
145 }
146
147 return different;
148 }
149
150 #else
151 for (ill = ill_g_head; ill; ill = ill->ill_next) {
152 /* Make sure this is an IPv4 ILL */
153 if (ill->ill_isv6)
154 continue;
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 (!rx_IsLoopbackAddr(ifinaddr) && 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 /* Make sure this is an IPv4 ILL */
276 if (ill->ill_isv6)
277 continue;
278
279 /* Iterate over all the addresses on this ILL */
280 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
281 afs_uint32 thisAddr, subnetMask;
282 int thisMtu;
283
284 thisAddr = ipif->ipif_local_addr;
285 subnetMask = ipif->ipif_net_mask;
286 thisMtu = ipif->ipif_mtu;
287
288 if ((myAddr & netMask) == (thisAddr & netMask)) {
289 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
290 if (myAddr == thisAddr) {
291 match_value = 4;
292 mtu = thisMtu;
293 }
294
295 if (match_value < 3) {
296 match_value = 3;
297 mtu = thisMtu;
298 }
299 }
300
301 if (match_value < 2) {
302 match_value = 2;
303 mtu = thisMtu;
304 }
305 }
306 }
307 }
308
309 return mtu;
310 }
311 #endif
312
313 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
314 * afs_osinet.c.
315 */
316
317 struct sockaddr_in rx_sockaddr;
318
319 /* Allocate a new socket at specified port in network byte order. */
320 osi_socket *
321 rxk_NewSocketHost(afs_uint32 ahost, short aport)
322 {
323 vnode_t *accessvp;
324 struct sonode *so;
325 struct sockaddr_in addr;
326 int error;
327 int len;
328 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
329 struct sockparams *sp;
330 #endif
331
332 AFS_STATCNT(osi_NewSocket);
333
334 if (sockfs_solookup == NULL) {
335 sockfs_solookup =
336 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
337 (int (*)())modlookup("sockfs", "solookup");
338 #else
339 (struct vnode * (*)())modlookup("sockfs", "solookup");
340 #endif
341 if (sockfs_solookup == NULL) {
342 return NULL;
343 }
344 }
345 if (sockfs_socreate == NULL) {
346 sockfs_socreate =
347 (struct sonode * (*)())modlookup("sockfs", "socreate");
348 if (sockfs_socreate == NULL) {
349 return NULL;
350 }
351 }
352 if (sockfs_sobind == NULL) {
353 sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
354 if (sockfs_sobind == NULL) {
355 return NULL;
356 }
357 }
358 if (sockfs_sosetsockopt == NULL) {
359 sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
360 if (sockfs_sosetsockopt == NULL) {
361 return NULL;
362 }
363 }
364 if (sockfs_sosendmsg == NULL) {
365 sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
366 if (sockfs_sosendmsg == NULL) {
367 return NULL;
368 }
369 }
370 if (sockfs_sorecvmsg == NULL) {
371 sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
372 if (sockfs_sorecvmsg == NULL) {
373 return NULL;
374 }
375 }
376 #ifndef AFS_SUN510_ENV
377 if (sockfs_sounbind == NULL) {
378 sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
379 if (sockfs_sounbind == NULL)
380 return NULL;
381 }
382 if (sockfs_sockfree == NULL) {
383 sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
384 if (sockfs_sockfree == NULL)
385 return NULL;
386 }
387 #endif
388
389 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
390 error = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, &sp);
391 if (error != 0) {
392 return NULL;
393 }
394
395 so = sockfs_socreate(sp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, &error);
396 #else
397 accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
398 if (accessvp == NULL) {
399 return NULL;
400 }
401
402 so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, NULL,
403 &error);
404 #endif /* SOLOOKUP_TAKES_SOCKPARAMS */
405
406 if (so == NULL) {
407 return NULL;
408 }
409
410 addr.sin_family = AF_INET;
411 addr.sin_port = aport;
412 addr.sin_addr.s_addr = ahost; /* I wonder what the odds are on
413 needing to unbyteswap this */
414 error = sockfs_sobind(so, (struct sockaddr *)&addr, sizeof(addr), 0, 0);
415 if (error != 0) {
416 return NULL;
417 }
418
419 len = rx_UdpBufSize;
420 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
421 if (error != 0) {
422 return NULL;
423 }
424
425 len = rx_UdpBufSize;
426 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
427 if (error != 0) {
428 return NULL;
429 }
430
431 return (osi_socket *)so;
432 }
433
434 osi_socket *
435 rxk_NewSocket(short aport)
436 {
437 return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
438 }
439
440 int
441 osi_FreeSocket(osi_socket asocket)
442 {
443 extern int rxk_ListenerPid;
444 struct sonode *so = (struct sonode *)asocket;
445 struct sockaddr_in taddr;
446 struct iovec dvec;
447 char c;
448 vnode_t *vp;
449
450 AFS_STATCNT(osi_FreeSocket);
451
452 taddr.sin_family = AF_INET;
453 taddr.sin_port = rx_port;
454 taddr.sin_addr.s_addr = htonl(0x7f000001);
455
456 dvec.iov_base = &c;
457 dvec.iov_len = 1;
458
459 while (rxk_ListenerPid) {
460 osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
461 afs_osi_Sleep(&rxk_ListenerPid);
462 }
463
464 /* Was sockfs_sounbind(so, 0); sockfs_sockfree(so); That's wrong */
465 vp = SOTOV(so);
466 #ifdef AFS_SUN511_ENV
467 VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED(), NULL);
468 #else
469 VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED());
470 #endif
471 VN_RELE(vp);
472
473 return 0;
474 }
475
476 int
477 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
478 int nvecs, afs_int32 asize, int istack)
479 {
480 struct sonode *so = (struct sonode *)asocket;
481 struct nmsghdr msg;
482 struct uio uio;
483 struct iovec iov[RX_MAXIOVECS];
484 int error;
485 int i;
486
487 memset(&uio, 0, sizeof(uio));
488 memset(&iov, 0, sizeof(iov));
489
490 if (nvecs > RX_MAXIOVECS) {
491 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
492 }
493
494 msg.msg_name = (struct sockaddr *)addr;
495 msg.msg_namelen = sizeof(struct sockaddr_in);
496 msg.msg_iov = dvec;
497 msg.msg_iovlen = nvecs;
498 msg.msg_control = NULL;
499 msg.msg_controllen = 0;
500 msg.msg_flags = 0;
501
502 for (i = 0; i < nvecs; i++) {
503 iov[i].iov_base = dvec[i].iov_base;
504 iov[i].iov_len = dvec[i].iov_len;
505 }
506 uio.uio_iov = &iov[0];
507 uio.uio_iovcnt = nvecs;
508 uio.uio_loffset = 0;
509 uio.uio_segflg = UIO_SYSSPACE;
510 uio.uio_fmode = FREAD | FWRITE;
511 uio.uio_limit = 0;
512 uio.uio_resid = asize;
513
514 error = sockfs_sosendmsg(so, &msg, &uio);
515
516 return error;
517 }
518
519 int
520 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
521 int nvecs, int *alength)
522 {
523 struct sonode *asocket = (struct sonode *)so;
524 struct nmsghdr msg;
525 struct uio uio;
526 struct iovec iov[RX_MAXIOVECS];
527 int error;
528 int i;
529
530 memset(&uio, 0, sizeof(uio));
531 memset(&iov, 0, sizeof(iov));
532
533 if (nvecs > RX_MAXIOVECS) {
534 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
535 }
536
537 msg.msg_name = NULL;
538 msg.msg_namelen = sizeof(struct sockaddr_in);
539 msg.msg_iov = NULL;
540 msg.msg_iovlen = 0;
541 msg.msg_control = NULL;
542 msg.msg_controllen = 0;
543 msg.msg_flags = 0;
544
545 for (i = 0; i < nvecs; i++) {
546 iov[i].iov_base = dvec[i].iov_base;
547 iov[i].iov_len = dvec[i].iov_len;
548 }
549 uio.uio_iov = &iov[0];
550 uio.uio_iovcnt = nvecs;
551 uio.uio_loffset = 0;
552 uio.uio_segflg = UIO_SYSSPACE;
553 uio.uio_fmode = 0;
554 uio.uio_limit = 0;
555 uio.uio_resid = *alength;
556
557 error = sockfs_sorecvmsg(asocket, &msg, &uio);
558 if (error == 0) {
559 if (msg.msg_name == NULL) {
560 error = -1;
561 } else {
562 memcpy(addr, msg.msg_name, msg.msg_namelen);
563 kmem_free(msg.msg_name, msg.msg_namelen);
564 *alength = *alength - uio.uio_resid;
565 }
566 }
567
568 if (error == EINTR && ISSIG(curthread, FORREAL)) {
569 klwp_t *lwp = ttolwp(curthread);
570 proc_t *p = ttoproc(curthread);
571 int sig = lwp->lwp_cursig;
572
573 if (sig == SIGKILL) {
574 mutex_enter(&p->p_lock);
575 p->p_flag &= ~SKILLED;
576 mutex_exit(&p->p_lock);
577 }
578 lwp->lwp_cursig = 0;
579 if (lwp->lwp_curinfo) {
580 siginfofree(lwp->lwp_curinfo);
581 lwp->lwp_curinfo = NULL;
582 }
583 }
584
585 return error;
586 }
587
588 #if defined(AFS_SUN510_ENV)
589 /* How often afs collects interface info. Tunable via /etc/system: */
590 /* set afs:afs_if_poll_interval = integer (value is in seconds) */
591 static int afs_if_poll_interval = 30;
592
593 static timeout_id_t afs_if_poller_timeout = 0;
594
595 /* Global array which holds the interface info for consumers */
596 struct afs_ifinfo afsifinfo[ADDRSPERSITE];
597
598 void
599 osi_StartNetIfPoller()
600 {
601 (void) ddi_taskq_dispatch(afs_taskq, (void(*) (void*)) osi_NetIfPoller,
602 NULL, DDI_SLEEP);
603 }
604
605 void
606 osi_NetIfPoller()
607 {
608 cred_t *cr;
609 ldi_ident_t li = NULL;
610 ldi_handle_t lh = NULL;
611 struct lifnum lifn;
612 struct lifconf lifc;
613 struct lifreq lifr;
614 struct lifreq *lifrp;
615 struct sockaddr_in *sin4_local;
616 struct sockaddr_in *sin4_dst;
617 major_t udpmajor;
618 caddr_t lifcbuf = NULL;
619 int i, count, error, rv;
620 int ifcount;
621 int metric;
622 int index;
623 uint_t mtu;
624 uint64_t flags;
625
626 /* Get our permissions */
627 cr = CRED();
628
629 /* Initialize and open /dev/udp for receiving ioctls */
630 udpmajor = ddi_name_to_major(UDP_MOD_NAME);
631
632 error = ldi_ident_from_major(udpmajor, &li);
633 if (error) {
634 cmn_err(CE_WARN, "osi_NetIfPoller: ldi_ident_from_major failed: %d",
635 error);
636 goto cleanup;
637 }
638
639 error = ldi_open_by_name(UDP_DEV_NAME, FREAD, cr, &lh, li);
640 if (error) {
641 cmn_err(CE_WARN,
642 "osi_NetIfPoller: ldi_open_by_name failed: %d", error);
643 goto cleanup;
644 }
645
646 /* First, how many interfaces do we have? */
647 (void) bzero((void *)&lifn, sizeof(struct lifnum));
648 lifn.lifn_family = AF_INET;
649
650 error = ldi_ioctl(lh, SIOCGLIFNUM, (intptr_t)&lifn,
651 FKIOCTL, cr, &rv);
652 if (error) {
653 cmn_err(CE_WARN,
654 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFNUM failed: %d", error);
655 goto cleanup;
656 }
657 ifcount = lifn.lifn_count;
658
659 /* Set up some stuff for storing the results of SIOCGLIFCONF */
660 (void) bzero((void *)&lifc, sizeof(struct lifconf));
661
662 lifcbuf = kmem_zalloc(ifcount * sizeof(struct lifreq), KM_SLEEP);
663
664 lifc.lifc_family = AF_INET;
665 lifc.lifc_flags = IFF_UP;
666 lifc.lifc_len = ifcount * sizeof(struct lifreq);
667 lifc.lifc_buf = lifcbuf;
668
669 /* Get info on each of our available interfaces. */
670 error = ldi_ioctl(lh, SIOCGLIFCONF, (intptr_t)&lifc,
671 FKIOCTL, cr, &rv);
672 if (error) {
673 cmn_err(CE_WARN,
674 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFCONF failed: %d", error);
675 goto cleanup;
676 }
677 lifrp = lifc.lifc_req;
678
679 count = 0;
680
681 /* Loop through our interfaces and pick out the info we want */
682 for (i = lifc.lifc_len / sizeof(struct lifreq);
683 i > 0; i--, lifrp++) {
684
685 if (count >= ADDRSPERSITE)
686 break;
687
688 (void) bzero((void *)&lifr, sizeof(struct lifreq));
689
690 (void) strncpy(lifr.lifr_name, lifrp->lifr_name,
691 sizeof(lifr.lifr_name));
692
693 /* Get this interface's Flags */
694 error = ldi_ioctl(lh, SIOCGLIFFLAGS, (intptr_t)&lifr,
695 FKIOCTL, cr, &rv);
696 if (error) {
697 cmn_err(CE_WARN,
698 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFFLAGS failed: %d",
699 error);
700 goto cleanup;
701 }
702
703 /* Ignore plumbed but down interfaces. */
704 if ((lifr.lifr_flags & IFF_UP) == 0)
705 continue;
706
707 flags = lifr.lifr_flags;
708
709 /* Get this interface's MTU */
710 error = ldi_ioctl(lh, SIOCGLIFMTU, (intptr_t)&lifr,
711 FKIOCTL, cr, &rv);
712
713 if (error) {
714 mtu = 1125;
715 } else {
716 mtu = lifr.lifr_metric;
717 }
718
719 /* Get this interface's Metric */
720 error = ldi_ioctl(lh, SIOCGLIFMETRIC, (intptr_t)&lifr,
721 FKIOCTL, cr, &rv);
722
723 if (error) {
724 metric = 0;
725 } else {
726 metric = lifr.lifr_metric;
727 }
728
729 sin4_local = (struct sockaddr_in *) &lifrp->lifr_addr;
730 sin4_dst = (struct sockaddr_in *) &lifrp->lifr_dstaddr;
731
732 /* Acquire global array write lock */
733 (void) rw_enter(&afsifinfo_lock, RW_WRITER);
734
735 /* Copy our collected data into the global array */
736 (void) strncpy(afsifinfo[count].ifname, lifrp->lifr_name,
737 sizeof(afsifinfo[count].ifname));
738 afsifinfo[count].ipaddr = ntohl(sin4_local->sin_addr.s_addr);
739 afsifinfo[count].mtu = mtu;
740 afsifinfo[count].netmask = lifrp->lifr_addrlen;
741 afsifinfo[count].flags = flags;
742 afsifinfo[count].metric = metric;
743 afsifinfo[count].dstaddr = ntohl(sin4_dst->sin_addr.s_addr);
744
745 /* Release global array write lock */
746 (void) rw_exit(&afsifinfo_lock);
747
748 count++;
749
750 } /* Bottom of loop: for each interface ... */
751
752 cleanup:
753 /* End of thread. Time to clean up */
754 if (lifcbuf)
755 kmem_free(lifcbuf, ifcount * sizeof(struct lifreq));
756 if (lh)
757 (void) ldi_close(lh, FREAD, cr);
758 if (li)
759 (void) ldi_ident_release(li);
760
761 if (afs_shuttingdown != AFS_RUNNING) {
762 /* do not schedule to run again if we're shutting down */
763 return;
764 }
765
766 /* Schedule this to run again after afs_if_poll_interval seconds */
767 afs_if_poller_timeout = timeout((void(*) (void *)) osi_StartNetIfPoller,
768 NULL, drv_usectohz((clock_t)afs_if_poll_interval * MICROSEC));
769 }
770
771 void
772 osi_StopNetIfPoller(void)
773 {
774 /* it's okay if untimeout races with StartNetIfPoller/NetIfPoller;
775 * it can handle being passed invalid ids. If StartNetIfPoller is
776 * in the middle of running, untimeout will not return until
777 * StartNetIfPoller is done */
778 untimeout(afs_if_poller_timeout);
779
780 /* if NetIfPoller is queued or running, ddi_taskq_destroy will not
781 * return until it is done */
782 ddi_taskq_destroy(afs_taskq);
783
784 rw_destroy(&afsifinfo_lock);
785
786 if (afs_termState == AFSOP_STOP_NETIF) {
787 afs_termState = AFSOP_STOP_COMPLETE;
788 osi_rxWakeup(&afs_termState);
789 }
790 }
791 #endif /* AFS_SUN510_ENV */
792
793 void
794 shutdown_rxkernel(void)
795 {
796 }
797
798 void
799 osi_StopListener(void)
800 {
801 osi_FreeSocket(rx_socket);
802 }
803
804 #endif /* AFS_SUN5_ENV */