2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include "afs/param.h"
15 #include "rx/rx_kcommon.h"
18 #include "inet/common.h"
19 #include "sys/tiuser.h"
20 #include "sys/t_kuser.h"
21 #include "sys/stropts.h"
22 #include "sys/stream.h"
23 #include "sys/tihdr.h"
24 #include "sys/fcntl.h"
25 #include "netinet/ip6.h"
26 #define ipif_local_addr ipif_lcl_addr
28 #define V4_PART_OF_V6(v6) v6.s6_addr32[3]
31 #include "inet/ip_if.h"
32 #include "netinet/udp.h"
39 #include "h/cmn_err.h"
41 #include "netinet/in.h"
45 * Function pointers for kernel socket routines
47 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
48 struct sonode *(*sockfs_socreate)
49 (struct sockparams *, int, int, int, int, int *) = NULL;
50 int (*sockfs_solookup)
51 (int, int, int, struct sockparams **) = NULL;
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 #endif /* SOLOOKUP_TAKES_SOCKPARAMS */
59 (struct sonode *, struct sockaddr *, int, int, int) = NULL;
60 int (*sockfs_sorecvmsg)
61 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
62 int (*sockfs_sosendmsg)
63 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
64 int (*sockfs_sosetsockopt)
65 (struct sonode *, int, int, void *, int) = NULL;
66 #ifndef AFS_SUN510_ENV
67 int (*sockfs_sounbind)
68 (struct sonode *, int);
69 void (*sockfs_sockfree)
74 #define UDP_MOD_NAME "udp"
77 static afs_uint32 myNetAddrs[ADDRSPERSITE];
78 static int myNetMTUs[ADDRSPERSITE];
79 static int numMyNetAddrs = 0;
86 #ifndef AFS_SUN510_ENV
91 int mtus[ADDRSPERSITE];
92 afs_uint32 addrs[ADDRSPERSITE];
95 memset(mtus, 0, sizeof(mtus));
96 memset(addrs, 0, sizeof(addrs));
99 (void) rw_enter(&afsifinfo_lock, RW_READER);
101 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
103 /* Ignore addresses which are down.. */
104 if (!(afsifinfo[i].flags & IFF_UP))
107 /* Compute the Rx interface MTU */
108 rxmtu = (afsifinfo[i].mtu - RX_IPUDP_SIZE);
110 ifinaddr = afsifinfo[i].ipaddr;
111 if (myNetAddrs[i] != ifinaddr)
114 /* Copy interface MTU and address; adjust maxmtu */
116 rxmtu = rxi_AdjustIfMTU(rxmtu);
117 maxmtu = rxmtu * rxi_nRecvFrags +
118 ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
119 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
122 if (!rx_IsLoopbackAddr(ifinaddr) && maxmtu > rx_maxReceiveSize) {
123 rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
125 MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
130 (void) rw_exit(&afsifinfo_lock);
132 rx_maxJumboRecvSize =
133 RX_HEADER_SIZE + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
134 (rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE;
135 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
140 for (j = 0; j < i; j++) {
141 myNetMTUs[j] = mtus[j];
142 myNetAddrs[j] = addrs[j];
150 for (ill = ill_g_head; ill; ill = ill->ill_next) {
151 /* Make sure this is an IPv4 ILL */
155 /* Iterate over all the addresses on this ILL */
156 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
157 if (i >= ADDRSPERSITE)
160 /* Ignore addresses which are down.. */
161 if (!(ipif->ipif_flags & IFF_UP))
164 /* Compute the Rx interface MTU */
165 rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
167 ifinaddr = ntohl(ipif->ipif_local_addr);
168 if (myNetAddrs[i] != ifinaddr)
171 /* Copy interface MTU and address; adjust maxmtu */
173 rxmtu = rxi_AdjustIfMTU(rxmtu);
175 rxmtu * rxi_nRecvFrags +
176 ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
177 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
181 if (!rx_IsLoopbackAddr(ifinaddr) && maxmtu > rx_maxReceiveSize) {
182 rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
184 MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
189 rx_maxJumboRecvSize =
190 RX_HEADER_SIZE + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
191 (rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE;
192 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
197 for (j = 0; j < i; j++) {
198 myNetMTUs[j] = mtus[j];
199 myNetAddrs[j] = addrs[j];
208 rxi_FindIfMTU(afs_uint32 addr)
210 afs_uint32 myAddr, netMask;
213 #ifdef AFS_SUN510_ENV
220 if (numMyNetAddrs == 0)
222 myAddr = ntohl(addr);
224 if (IN_CLASSA(myAddr))
225 netMask = IN_CLASSA_NET;
226 else if (IN_CLASSB(myAddr))
227 netMask = IN_CLASSB_NET;
228 else if (IN_CLASSC(myAddr))
229 netMask = IN_CLASSC_NET;
233 #ifdef AFS_SUN510_ENV
234 (void) rw_enter(&afsifinfo_lock, RW_READER);
236 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
237 afs_uint32 thisAddr, subnetMask;
240 /* Ignore addresses which are down.. */
241 if ((afsifinfo[i].flags & IFF_UP) == 0)
244 thisAddr = afsifinfo[i].ipaddr;
245 subnetMask = afsifinfo[i].netmask;
246 thisMtu = afsifinfo[i].mtu;
248 if ((myAddr & netMask) == (thisAddr & netMask)) {
249 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
250 if (myAddr == thisAddr) {
255 if (match_value < 3) {
261 if (match_value < 2) {
268 (void) rw_exit(&afsifinfo_lock);
273 for (ill = ill_g_head; ill; ill = ill->ill_next) {
274 /* Make sure this is an IPv4 ILL */
278 /* Iterate over all the addresses on this ILL */
279 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
280 afs_uint32 thisAddr, subnetMask;
283 thisAddr = ipif->ipif_local_addr;
284 subnetMask = ipif->ipif_net_mask;
285 thisMtu = ipif->ipif_mtu;
287 if ((myAddr & netMask) == (thisAddr & netMask)) {
288 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
289 if (myAddr == thisAddr) {
294 if (match_value < 3) {
300 if (match_value < 2) {
312 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
316 struct sockaddr_in rx_sockaddr;
318 /* Allocate a new socket at specified port in network byte order. */
320 rxk_NewSocketHost(afs_uint32 ahost, short aport)
324 struct sockaddr_in addr;
327 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
328 struct sockparams *sp;
331 AFS_STATCNT(osi_NewSocket);
333 if (sockfs_solookup == NULL) {
335 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
336 (int (*)())modlookup("sockfs", "solookup");
338 (struct vnode * (*)())modlookup("sockfs", "solookup");
340 if (sockfs_solookup == NULL) {
344 if (sockfs_socreate == NULL) {
346 (struct sonode * (*)())modlookup("sockfs", "socreate");
347 if (sockfs_socreate == NULL) {
351 if (sockfs_sobind == NULL) {
352 sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
353 if (sockfs_sobind == NULL) {
357 if (sockfs_sosetsockopt == NULL) {
358 sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
359 if (sockfs_sosetsockopt == NULL) {
363 if (sockfs_sosendmsg == NULL) {
364 sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
365 if (sockfs_sosendmsg == NULL) {
369 if (sockfs_sorecvmsg == NULL) {
370 sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
371 if (sockfs_sorecvmsg == NULL) {
375 #ifndef AFS_SUN510_ENV
376 if (sockfs_sounbind == NULL) {
377 sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
378 if (sockfs_sounbind == NULL)
381 if (sockfs_sockfree == NULL) {
382 sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
383 if (sockfs_sockfree == NULL)
388 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
389 error = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, &sp);
394 so = sockfs_socreate(sp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, &error);
396 accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
397 if (accessvp == NULL) {
401 so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, NULL,
403 #endif /* SOLOOKUP_TAKES_SOCKPARAMS */
409 addr.sin_family = AF_INET;
410 addr.sin_port = aport;
411 addr.sin_addr.s_addr = ahost; /* I wonder what the odds are on
412 needing to unbyteswap this */
413 error = sockfs_sobind(so, (struct sockaddr *)&addr, sizeof(addr), 0, 0);
419 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
425 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
430 return (osi_socket *)so;
434 rxk_NewSocket(short aport)
436 return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
440 osi_FreeSocket(osi_socket asocket)
442 extern int rxk_ListenerPid;
443 struct sonode *so = (struct sonode *)asocket;
444 struct sockaddr_in taddr;
449 AFS_STATCNT(osi_FreeSocket);
451 taddr.sin_family = AF_INET;
452 taddr.sin_port = rx_port;
453 taddr.sin_addr.s_addr = htonl(0x7f000001);
458 while (rxk_ListenerPid) {
459 osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
460 afs_osi_Sleep(&rxk_ListenerPid);
463 /* Was sockfs_sounbind(so, 0); sockfs_sockfree(so); That's wrong */
465 #ifdef AFS_SUN511_ENV
466 VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED(), NULL);
468 VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED());
476 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
477 int nvecs, afs_int32 asize, int istack)
479 struct sonode *so = (struct sonode *)asocket;
482 struct iovec iov[RX_MAXIOVECS];
486 if (nvecs > RX_MAXIOVECS) {
487 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
490 msg.msg_name = (struct sockaddr *)addr;
491 msg.msg_namelen = sizeof(struct sockaddr_in);
493 msg.msg_iovlen = nvecs;
494 msg.msg_control = NULL;
495 msg.msg_controllen = 0;
498 for (i = 0; i < nvecs; i++) {
499 iov[i].iov_base = dvec[i].iov_base;
500 iov[i].iov_len = dvec[i].iov_len;
502 uio.uio_iov = &iov[0];
503 uio.uio_iovcnt = nvecs;
505 uio.uio_segflg = UIO_SYSSPACE;
506 uio.uio_fmode = FREAD | FWRITE;
508 uio.uio_resid = asize;
510 error = sockfs_sosendmsg(so, &msg, &uio);
516 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
517 int nvecs, int *alength)
519 struct sonode *asocket = (struct sonode *)so;
522 struct iovec iov[RX_MAXIOVECS];
526 if (nvecs > RX_MAXIOVECS) {
527 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
531 msg.msg_namelen = sizeof(struct sockaddr_in);
534 msg.msg_control = NULL;
535 msg.msg_controllen = 0;
538 for (i = 0; i < nvecs; i++) {
539 iov[i].iov_base = dvec[i].iov_base;
540 iov[i].iov_len = dvec[i].iov_len;
542 uio.uio_iov = &iov[0];
543 uio.uio_iovcnt = nvecs;
545 uio.uio_segflg = UIO_SYSSPACE;
548 uio.uio_resid = *alength;
550 error = sockfs_sorecvmsg(asocket, &msg, &uio);
552 if (msg.msg_name == NULL) {
555 memcpy(addr, msg.msg_name, msg.msg_namelen);
556 kmem_free(msg.msg_name, msg.msg_namelen);
557 *alength = *alength - uio.uio_resid;
561 if (error == EINTR && ISSIG(curthread, FORREAL)) {
562 klwp_t *lwp = ttolwp(curthread);
563 proc_t *p = ttoproc(curthread);
564 int sig = lwp->lwp_cursig;
566 if (sig == SIGKILL) {
567 mutex_enter(&p->p_lock);
568 p->p_flag &= ~SKILLED;
569 mutex_exit(&p->p_lock);
572 if (lwp->lwp_curinfo) {
573 siginfofree(lwp->lwp_curinfo);
574 lwp->lwp_curinfo = NULL;
581 #if defined(AFS_SUN510_ENV)
582 /* How often afs collects interface info. Tunable via /etc/system: */
583 /* set afs:afs_if_poll_interval = integer (value is in seconds) */
584 static int afs_if_poll_interval = 30;
586 static timeout_id_t afs_if_poller_timeout = 0;
588 /* Global array which holds the interface info for consumers */
589 struct afs_ifinfo afsifinfo[ADDRSPERSITE];
592 osi_StartNetIfPoller()
594 (void) ddi_taskq_dispatch(afs_taskq, (void(*) (void*)) osi_NetIfPoller,
602 ldi_ident_t li = NULL;
603 ldi_handle_t lh = NULL;
607 struct lifreq *lifrp;
608 struct sockaddr_in *sin4_local;
609 struct sockaddr_in *sin4_dst;
611 caddr_t lifcbuf = NULL;
612 int i, count, error, rv;
619 /* Get our permissions */
622 /* Initialize and open /dev/udp for receiving ioctls */
623 udpmajor = ddi_name_to_major(UDP_MOD_NAME);
625 error = ldi_ident_from_major(udpmajor, &li);
627 cmn_err(CE_WARN, "osi_NetIfPoller: ldi_ident_from_major failed: %d",
632 error = ldi_open_by_name(UDP_DEV_NAME, FREAD, cr, &lh, li);
635 "osi_NetIfPoller: ldi_open_by_name failed: %d", error);
639 /* First, how many interfaces do we have? */
640 (void) bzero((void *)&lifn, sizeof(struct lifnum));
641 lifn.lifn_family = AF_INET;
643 error = ldi_ioctl(lh, SIOCGLIFNUM, (intptr_t)&lifn,
647 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFNUM failed: %d", error);
650 ifcount = lifn.lifn_count;
652 /* Set up some stuff for storing the results of SIOCGLIFCONF */
653 (void) bzero((void *)&lifc, sizeof(struct lifconf));
655 lifcbuf = kmem_zalloc(ifcount * sizeof(struct lifreq), KM_SLEEP);
657 lifc.lifc_family = AF_INET;
658 lifc.lifc_flags = IFF_UP;
659 lifc.lifc_len = ifcount * sizeof(struct lifreq);
660 lifc.lifc_buf = lifcbuf;
662 /* Get info on each of our available interfaces. */
663 error = ldi_ioctl(lh, SIOCGLIFCONF, (intptr_t)&lifc,
667 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFCONF failed: %d", error);
670 lifrp = lifc.lifc_req;
674 /* Loop through our interfaces and pick out the info we want */
675 for (i = lifc.lifc_len / sizeof(struct lifreq);
676 i > 0; i--, lifrp++) {
678 if (count >= ADDRSPERSITE)
681 (void) bzero((void *)&lifr, sizeof(struct lifreq));
683 (void) strncpy(lifr.lifr_name, lifrp->lifr_name,
684 sizeof(lifr.lifr_name));
686 /* Get this interface's Flags */
687 error = ldi_ioctl(lh, SIOCGLIFFLAGS, (intptr_t)&lifr,
691 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFFLAGS failed: %d",
696 /* Ignore plumbed but down interfaces. */
697 if ((lifr.lifr_flags & IFF_UP) == 0)
700 flags = lifr.lifr_flags;
702 /* Get this interface's MTU */
703 error = ldi_ioctl(lh, SIOCGLIFMTU, (intptr_t)&lifr,
709 mtu = lifr.lifr_metric;
712 /* Get this interface's Metric */
713 error = ldi_ioctl(lh, SIOCGLIFMETRIC, (intptr_t)&lifr,
719 metric = lifr.lifr_metric;
722 sin4_local = (struct sockaddr_in *) &lifrp->lifr_addr;
723 sin4_dst = (struct sockaddr_in *) &lifrp->lifr_dstaddr;
725 /* Acquire global array write lock */
726 (void) rw_enter(&afsifinfo_lock, RW_WRITER);
728 /* Copy our collected data into the global array */
729 (void) strncpy(afsifinfo[count].ifname, lifrp->lifr_name,
730 sizeof(afsifinfo[count].ifname));
731 afsifinfo[count].ipaddr = ntohl(sin4_local->sin_addr.s_addr);
732 afsifinfo[count].mtu = mtu;
733 afsifinfo[count].netmask = lifrp->lifr_addrlen;
734 afsifinfo[count].flags = flags;
735 afsifinfo[count].metric = metric;
736 afsifinfo[count].dstaddr = ntohl(sin4_dst->sin_addr.s_addr);
738 /* Release global array write lock */
739 (void) rw_exit(&afsifinfo_lock);
743 } /* Bottom of loop: for each interface ... */
746 /* End of thread. Time to clean up */
748 kmem_free(lifcbuf, ifcount * sizeof(struct lifreq));
750 (void) ldi_close(lh, FREAD, cr);
752 (void) ldi_ident_release(li);
754 if (afs_shuttingdown) {
755 /* do not schedule to run again if we're shutting down */
759 /* Schedule this to run again after afs_if_poll_interval seconds */
760 afs_if_poller_timeout = timeout((void(*) (void *)) osi_StartNetIfPoller,
761 NULL, drv_usectohz((clock_t)afs_if_poll_interval * MICROSEC));
765 osi_StopNetIfPoller(void)
767 /* it's okay if untimeout races with StartNetIfPoller/NetIfPoller;
768 * it can handle being passed invalid ids. If StartNetIfPoller is
769 * in the middle of running, untimeout will not return until
770 * StartNetIfPoller is done */
771 untimeout(afs_if_poller_timeout);
773 /* if NetIfPoller is queued or running, ddi_taskq_destroy will not
774 * return until it is done */
775 ddi_taskq_destroy(afs_taskq);
777 rw_destroy(&afsifinfo_lock);
779 if (afs_termState == AFSOP_STOP_NETIF) {
780 afs_termState = AFSOP_STOP_COMPLETE;
781 osi_rxWakeup(&afs_termState);
784 #endif /* AFS_SUN510_ENV */
787 shutdown_rxkernel(void)
792 osi_StopListener(void)
794 osi_FreeSocket(rx_socket);
797 #endif /* AFS_SUN5_ENV */