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"
16 #include "rx/rx_packet.h"
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
29 #define V4_PART_OF_V6(v6) v6.s6_addr32[3]
32 #include "inet/ip_if.h"
33 #include "netinet/udp.h"
40 #include "h/cmn_err.h"
42 #include "netinet/in.h"
46 * Function pointers for kernel socket routines
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
;
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 */
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
)
75 #define UDP_MOD_NAME "udp"
78 static afs_uint32 myNetAddrs
[ADDRSPERSITE
];
79 static int myNetMTUs
[ADDRSPERSITE
];
80 static int numMyNetAddrs
= 0;
87 #ifndef AFS_SUN510_ENV
92 int mtus
[ADDRSPERSITE
];
93 afs_uint32 addrs
[ADDRSPERSITE
];
96 memset(mtus
, 0, sizeof(mtus
));
97 memset(addrs
, 0, sizeof(addrs
));
100 (void) rw_enter(&afsifinfo_lock
, RW_READER
);
102 for (i
= 0; (afsifinfo
[i
].ipaddr
!= NULL
) && (i
< ADDRSPERSITE
); i
++) {
104 /* Ignore addresses which are down.. */
105 if (!(afsifinfo
[i
].flags
& IFF_UP
))
108 /* Compute the Rx interface MTU */
109 rxmtu
= (afsifinfo
[i
].mtu
- RX_IPUDP_SIZE
);
111 ifinaddr
= afsifinfo
[i
].ipaddr
;
112 if (myNetAddrs
[i
] != ifinaddr
)
115 /* Copy interface MTU and address; adjust maxmtu */
117 rxmtu
= rxi_AdjustIfMTU(rxmtu
);
118 maxmtu
= rxmtu
* rxi_nRecvFrags
+
119 ((rxi_nRecvFrags
- 1) * UDP_HDR_SIZE
);
120 maxmtu
= rxi_AdjustMaxMTU(rxmtu
, maxmtu
);
123 if (!rx_IsLoopbackAddr(ifinaddr
) && maxmtu
> rx_maxReceiveSize
) {
124 rx_maxReceiveSize
= MIN(RX_MAX_PACKET_SIZE
, maxmtu
);
126 MIN(rx_maxReceiveSize
, rx_maxReceiveSizeUser
);
131 (void) rw_exit(&afsifinfo_lock
);
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
);
141 for (j
= 0; j
< i
; j
++) {
142 myNetMTUs
[j
] = mtus
[j
];
143 myNetAddrs
[j
] = addrs
[j
];
151 for (ill
= ill_g_head
; ill
; ill
= ill
->ill_next
) {
152 /* Make sure this is an IPv4 ILL */
156 /* Iterate over all the addresses on this ILL */
157 for (ipif
= ill
->ill_ipif
; ipif
; ipif
= ipif
->ipif_next
) {
158 if (i
>= ADDRSPERSITE
)
161 /* Ignore addresses which are down.. */
162 if (!(ipif
->ipif_flags
& IFF_UP
))
165 /* Compute the Rx interface MTU */
166 rxmtu
= (ipif
->ipif_mtu
- RX_IPUDP_SIZE
);
168 ifinaddr
= ntohl(ipif
->ipif_local_addr
);
169 if (myNetAddrs
[i
] != ifinaddr
)
172 /* Copy interface MTU and address; adjust maxmtu */
174 rxmtu
= rxi_AdjustIfMTU(rxmtu
);
176 rxmtu
* rxi_nRecvFrags
+
177 ((rxi_nRecvFrags
- 1) * UDP_HDR_SIZE
);
178 maxmtu
= rxi_AdjustMaxMTU(rxmtu
, maxmtu
);
182 if (!rx_IsLoopbackAddr(ifinaddr
) && maxmtu
> rx_maxReceiveSize
) {
183 rx_maxReceiveSize
= MIN(RX_MAX_PACKET_SIZE
, maxmtu
);
185 MIN(rx_maxReceiveSize
, rx_maxReceiveSizeUser
);
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
);
198 for (j
= 0; j
< i
; j
++) {
199 myNetMTUs
[j
] = mtus
[j
];
200 myNetAddrs
[j
] = addrs
[j
];
209 rxi_FindIfMTU(afs_uint32 addr
)
211 afs_uint32 myAddr
, netMask
;
214 #ifdef AFS_SUN510_ENV
221 if (numMyNetAddrs
== 0)
223 myAddr
= ntohl(addr
);
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
;
234 #ifdef AFS_SUN510_ENV
235 (void) rw_enter(&afsifinfo_lock
, RW_READER
);
237 for (i
= 0; (afsifinfo
[i
].ipaddr
!= NULL
) && (i
< ADDRSPERSITE
); i
++) {
238 afs_uint32 thisAddr
, subnetMask
;
241 /* Ignore addresses which are down.. */
242 if ((afsifinfo
[i
].flags
& IFF_UP
) == 0)
245 thisAddr
= afsifinfo
[i
].ipaddr
;
246 subnetMask
= afsifinfo
[i
].netmask
;
247 thisMtu
= afsifinfo
[i
].mtu
;
249 if ((myAddr
& netMask
) == (thisAddr
& netMask
)) {
250 if ((myAddr
& subnetMask
) == (thisAddr
& subnetMask
)) {
251 if (myAddr
== thisAddr
) {
256 if (match_value
< 3) {
262 if (match_value
< 2) {
269 (void) rw_exit(&afsifinfo_lock
);
274 for (ill
= ill_g_head
; ill
; ill
= ill
->ill_next
) {
275 /* Make sure this is an IPv4 ILL */
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
;
284 thisAddr
= ipif
->ipif_local_addr
;
285 subnetMask
= ipif
->ipif_net_mask
;
286 thisMtu
= ipif
->ipif_mtu
;
288 if ((myAddr
& netMask
) == (thisAddr
& netMask
)) {
289 if ((myAddr
& subnetMask
) == (thisAddr
& subnetMask
)) {
290 if (myAddr
== thisAddr
) {
295 if (match_value
< 3) {
301 if (match_value
< 2) {
313 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
317 struct sockaddr_in rx_sockaddr
;
319 /* Allocate a new socket at specified port in network byte order. */
321 rxk_NewSocketHost(afs_uint32 ahost
, short aport
)
325 struct sockaddr_in addr
;
328 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
329 struct sockparams
*sp
;
332 AFS_STATCNT(osi_NewSocket
);
334 if (sockfs_solookup
== NULL
) {
336 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
337 (int (*)())modlookup("sockfs", "solookup");
339 (struct vnode
* (*)())modlookup("sockfs", "solookup");
341 if (sockfs_solookup
== NULL
) {
345 if (sockfs_socreate
== NULL
) {
347 (struct sonode
* (*)())modlookup("sockfs", "socreate");
348 if (sockfs_socreate
== NULL
) {
352 if (sockfs_sobind
== NULL
) {
353 sockfs_sobind
= (int (*)())modlookup("sockfs", "sobind");
354 if (sockfs_sobind
== NULL
) {
358 if (sockfs_sosetsockopt
== NULL
) {
359 sockfs_sosetsockopt
= (int (*)())modlookup("sockfs", "sosetsockopt");
360 if (sockfs_sosetsockopt
== NULL
) {
364 if (sockfs_sosendmsg
== NULL
) {
365 sockfs_sosendmsg
= (int (*)())modlookup("sockfs", "sosendmsg");
366 if (sockfs_sosendmsg
== NULL
) {
370 if (sockfs_sorecvmsg
== NULL
) {
371 sockfs_sorecvmsg
= (int (*)())modlookup("sockfs", "sorecvmsg");
372 if (sockfs_sorecvmsg
== NULL
) {
376 #ifndef AFS_SUN510_ENV
377 if (sockfs_sounbind
== NULL
) {
378 sockfs_sounbind
= (int (*)())modlookup("sockfs", "sounbind");
379 if (sockfs_sounbind
== NULL
)
382 if (sockfs_sockfree
== NULL
) {
383 sockfs_sockfree
= (void (*)())modlookup("sockfs", "sockfree");
384 if (sockfs_sockfree
== NULL
)
389 #ifdef SOLOOKUP_TAKES_SOCKPARAMS
390 error
= sockfs_solookup(AF_INET
, SOCK_DGRAM
, 0, &sp
);
395 so
= sockfs_socreate(sp
, AF_INET
, SOCK_DGRAM
, 0, SOV_STREAM
, &error
);
397 accessvp
= sockfs_solookup(AF_INET
, SOCK_DGRAM
, 0, "/dev/udp", &error
);
398 if (accessvp
== NULL
) {
402 so
= sockfs_socreate(accessvp
, AF_INET
, SOCK_DGRAM
, 0, SOV_STREAM
, NULL
,
404 #endif /* SOLOOKUP_TAKES_SOCKPARAMS */
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);
420 error
= sockfs_sosetsockopt(so
, SOL_SOCKET
, SO_SNDBUF
, &len
, sizeof(len
));
426 error
= sockfs_sosetsockopt(so
, SOL_SOCKET
, SO_RCVBUF
, &len
, sizeof(len
));
431 return (osi_socket
*)so
;
435 rxk_NewSocket(short aport
)
437 return rxk_NewSocketHost(htonl(INADDR_ANY
), aport
);
441 osi_FreeSocket(osi_socket asocket
)
443 extern int rxk_ListenerPid
;
444 struct sonode
*so
= (struct sonode
*)asocket
;
445 struct sockaddr_in taddr
;
450 AFS_STATCNT(osi_FreeSocket
);
452 taddr
.sin_family
= AF_INET
;
453 taddr
.sin_port
= rx_port
;
454 taddr
.sin_addr
.s_addr
= htonl(0x7f000001);
459 while (rxk_ListenerPid
) {
460 osi_NetSend(rx_socket
, &taddr
, &dvec
, 1, 1, 0);
461 afs_osi_Sleep(&rxk_ListenerPid
);
464 /* Was sockfs_sounbind(so, 0); sockfs_sockfree(so); That's wrong */
466 #ifdef AFS_SUN511_ENV
467 VOP_CLOSE(vp
, FREAD
|FWRITE
, 1, (offset_t
)0, CRED(), NULL
);
469 VOP_CLOSE(vp
, FREAD
|FWRITE
, 1, (offset_t
)0, CRED());
477 osi_NetSend(osi_socket asocket
, struct sockaddr_in
*addr
, struct iovec
*dvec
,
478 int nvecs
, afs_int32 asize
, int istack
)
480 struct sonode
*so
= (struct sonode
*)asocket
;
483 struct iovec iov
[RX_MAXIOVECS
];
487 memset(&uio
, 0, sizeof(uio
));
488 memset(&iov
, 0, sizeof(iov
));
490 if (nvecs
> RX_MAXIOVECS
) {
491 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs
);
494 msg
.msg_name
= (struct sockaddr
*)addr
;
495 msg
.msg_namelen
= sizeof(struct sockaddr_in
);
497 msg
.msg_iovlen
= nvecs
;
498 msg
.msg_control
= NULL
;
499 msg
.msg_controllen
= 0;
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
;
506 uio
.uio_iov
= &iov
[0];
507 uio
.uio_iovcnt
= nvecs
;
509 uio
.uio_segflg
= UIO_SYSSPACE
;
510 uio
.uio_fmode
= FREAD
| FWRITE
;
512 uio
.uio_resid
= asize
;
514 error
= sockfs_sosendmsg(so
, &msg
, &uio
);
520 osi_NetReceive(osi_socket so
, struct sockaddr_in
*addr
, struct iovec
*dvec
,
521 int nvecs
, int *alength
)
523 struct sonode
*asocket
= (struct sonode
*)so
;
526 struct iovec iov
[RX_MAXIOVECS
];
530 memset(&uio
, 0, sizeof(uio
));
531 memset(&iov
, 0, sizeof(iov
));
533 if (nvecs
> RX_MAXIOVECS
) {
534 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs
);
538 msg
.msg_namelen
= sizeof(struct sockaddr_in
);
541 msg
.msg_control
= NULL
;
542 msg
.msg_controllen
= 0;
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
;
549 uio
.uio_iov
= &iov
[0];
550 uio
.uio_iovcnt
= nvecs
;
552 uio
.uio_segflg
= UIO_SYSSPACE
;
555 uio
.uio_resid
= *alength
;
557 error
= sockfs_sorecvmsg(asocket
, &msg
, &uio
);
559 if (msg
.msg_name
== NULL
) {
562 memcpy(addr
, msg
.msg_name
, msg
.msg_namelen
);
563 kmem_free(msg
.msg_name
, msg
.msg_namelen
);
564 *alength
= *alength
- uio
.uio_resid
;
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
;
573 if (sig
== SIGKILL
) {
574 mutex_enter(&p
->p_lock
);
575 p
->p_flag
&= ~SKILLED
;
576 mutex_exit(&p
->p_lock
);
579 if (lwp
->lwp_curinfo
) {
580 siginfofree(lwp
->lwp_curinfo
);
581 lwp
->lwp_curinfo
= NULL
;
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;
593 static timeout_id_t afs_if_poller_timeout
= 0;
595 /* Global array which holds the interface info for consumers */
596 struct afs_ifinfo afsifinfo
[ADDRSPERSITE
];
599 osi_StartNetIfPoller()
601 (void) ddi_taskq_dispatch(afs_taskq
, (void(*) (void*)) osi_NetIfPoller
,
609 ldi_ident_t li
= NULL
;
610 ldi_handle_t lh
= NULL
;
614 struct lifreq
*lifrp
;
615 struct sockaddr_in
*sin4_local
;
616 struct sockaddr_in
*sin4_dst
;
618 caddr_t lifcbuf
= NULL
;
619 int i
, count
, error
, rv
;
626 /* Get our permissions */
629 /* Initialize and open /dev/udp for receiving ioctls */
630 udpmajor
= ddi_name_to_major(UDP_MOD_NAME
);
632 error
= ldi_ident_from_major(udpmajor
, &li
);
634 cmn_err(CE_WARN
, "osi_NetIfPoller: ldi_ident_from_major failed: %d",
639 error
= ldi_open_by_name(UDP_DEV_NAME
, FREAD
, cr
, &lh
, li
);
642 "osi_NetIfPoller: ldi_open_by_name failed: %d", error
);
646 /* First, how many interfaces do we have? */
647 (void) bzero((void *)&lifn
, sizeof(struct lifnum
));
648 lifn
.lifn_family
= AF_INET
;
650 error
= ldi_ioctl(lh
, SIOCGLIFNUM
, (intptr_t)&lifn
,
654 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFNUM failed: %d", error
);
657 ifcount
= lifn
.lifn_count
;
659 /* Set up some stuff for storing the results of SIOCGLIFCONF */
660 (void) bzero((void *)&lifc
, sizeof(struct lifconf
));
662 lifcbuf
= kmem_zalloc(ifcount
* sizeof(struct lifreq
), KM_SLEEP
);
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
;
669 /* Get info on each of our available interfaces. */
670 error
= ldi_ioctl(lh
, SIOCGLIFCONF
, (intptr_t)&lifc
,
674 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFCONF failed: %d", error
);
677 lifrp
= lifc
.lifc_req
;
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
++) {
685 if (count
>= ADDRSPERSITE
)
688 (void) bzero((void *)&lifr
, sizeof(struct lifreq
));
690 (void) strncpy(lifr
.lifr_name
, lifrp
->lifr_name
,
691 sizeof(lifr
.lifr_name
));
693 /* Get this interface's Flags */
694 error
= ldi_ioctl(lh
, SIOCGLIFFLAGS
, (intptr_t)&lifr
,
698 "osi_NetIfPoller: ldi_ioctl: SIOCGLIFFLAGS failed: %d",
703 /* Ignore plumbed but down interfaces. */
704 if ((lifr
.lifr_flags
& IFF_UP
) == 0)
707 flags
= lifr
.lifr_flags
;
709 /* Get this interface's MTU */
710 error
= ldi_ioctl(lh
, SIOCGLIFMTU
, (intptr_t)&lifr
,
716 mtu
= lifr
.lifr_metric
;
719 /* Get this interface's Metric */
720 error
= ldi_ioctl(lh
, SIOCGLIFMETRIC
, (intptr_t)&lifr
,
726 metric
= lifr
.lifr_metric
;
729 sin4_local
= (struct sockaddr_in
*) &lifrp
->lifr_addr
;
730 sin4_dst
= (struct sockaddr_in
*) &lifrp
->lifr_dstaddr
;
732 /* Acquire global array write lock */
733 (void) rw_enter(&afsifinfo_lock
, RW_WRITER
);
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
);
745 /* Release global array write lock */
746 (void) rw_exit(&afsifinfo_lock
);
750 } /* Bottom of loop: for each interface ... */
753 /* End of thread. Time to clean up */
755 kmem_free(lifcbuf
, ifcount
* sizeof(struct lifreq
));
757 (void) ldi_close(lh
, FREAD
, cr
);
759 (void) ldi_ident_release(li
);
761 if (afs_shuttingdown
!= AFS_RUNNING
) {
762 /* do not schedule to run again if we're shutting down */
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
));
772 osi_StopNetIfPoller(void)
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
);
780 /* if NetIfPoller is queued or running, ddi_taskq_destroy will not
781 * return until it is done */
782 ddi_taskq_destroy(afs_taskq
);
784 rw_destroy(&afsifinfo_lock
);
786 if (afs_termState
== AFSOP_STOP_NETIF
) {
787 afs_termState
= AFSOP_STOP_COMPLETE
;
788 osi_rxWakeup(&afs_termState
);
791 #endif /* AFS_SUN510_ENV */
794 shutdown_rxkernel(void)
799 osi_StopListener(void)
801 osi_FreeSocket(rx_socket
);
804 #endif /* AFS_SUN5_ENV */