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"
17 #include "rx/rx_kcommon.h"
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"
30 #include "netinet/ip6.h"
31 #define ipif_local_addr ipif_lcl_addr
33 #define V4_PART_OF_V6(v6) v6.s6_addr32[3]
37 #include "inet/ip_if.h"
38 #include "netinet/udp.h"
41 * Function pointers for kernel socket routines
43 struct sonode *(*sockfs_socreate)
44 (vnode_t *, int, int, int, int, struct sonode *, int *) = NULL;
45 struct vnode *(*sockfs_solookup)
46 (int, int, int, char *, int *) = NULL;
48 (struct sonode *, struct sockaddr *, int, int, int) = NULL;
49 int (*sockfs_sorecvmsg)
50 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
51 int (*sockfs_sosendmsg)
52 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
53 int (*sockfs_sosetsockopt)
54 (struct sonode *, int, int, void *, int) = NULL;
55 int (*sockfs_sounbind)
56 (struct sonode *, int);
57 void (*sockfs_sockfree)
60 static afs_uint32 myNetAddrs[ADDRSPERSITE];
61 static int myNetMTUs[ADDRSPERSITE];
62 static int numMyNetAddrs = 0;
74 int mtus[ADDRSPERSITE];
75 afs_uint32 addrs[ADDRSPERSITE];
78 memset(mtus, 0, sizeof(mtus));
79 memset(addrs, 0, sizeof(addrs));
81 for (ill = ill_g_head; ill; ill = ill->ill_next) {
83 /* Make sure this is an IPv4 ILL */
88 /* Iterate over all the addresses on this ILL */
89 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
90 if (i >= ADDRSPERSITE)
93 /* Ignore addresses which are down.. */
94 if (!(ipif->ipif_flags & IFF_UP))
97 /* Compute the Rx interface MTU */
98 rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
100 ifinaddr = ntohl(ipif->ipif_local_addr);
101 if (myNetAddrs[i] != ifinaddr)
104 /* Copy interface MTU and address; adjust maxmtu */
106 rxmtu = rxi_AdjustIfMTU(rxmtu);
108 rxmtu * rxi_nRecvFrags +
109 ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
110 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
114 if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
115 rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
117 MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
122 rx_maxJumboRecvSize =
123 RX_HEADER_SIZE + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
124 (rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE;
125 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
130 for (j = 0; j < i; j++) {
131 myNetMTUs[j] = mtus[j];
132 myNetAddrs[j] = addrs[j];
140 rxi_FindIfMTU(afs_uint32 addr)
144 afs_uint32 myAddr, netMask;
148 if (numMyNetAddrs == 0)
150 myAddr = ntohl(addr);
152 if (IN_CLASSA(myAddr))
153 netMask = IN_CLASSA_NET;
154 else if (IN_CLASSB(myAddr))
155 netMask = IN_CLASSB_NET;
156 else if (IN_CLASSC(myAddr))
157 netMask = IN_CLASSC_NET;
161 for (ill = ill_g_head; ill; ill = ill->ill_next) {
163 /* Make sure this is an IPv4 ILL */
168 /* Iterate over all the addresses on this ILL */
169 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
170 afs_uint32 thisAddr, subnetMask;
173 thisAddr = ipif->ipif_local_addr;
174 subnetMask = ipif->ipif_net_mask;
175 thisMtu = ipif->ipif_mtu;
177 if ((myAddr & netMask) == (thisAddr & netMask)) {
178 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
179 if (myAddr == thisAddr) {
184 if (match_value < 3) {
190 if (match_value < 2) {
201 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
205 struct sockaddr_in rx_sockaddr;
207 /* Allocate a new socket at specified port in network byte order. */
209 rxk_NewSocket(short aport)
213 struct sockaddr_in addr;
217 AFS_STATCNT(osi_NewSocket);
219 if (sockfs_solookup == NULL) {
221 (struct vnode * (*)())modlookup("sockfs", "solookup");
222 if (sockfs_solookup == NULL) {
226 if (sockfs_socreate == NULL) {
228 (struct sonode * (*)())modlookup("sockfs", "socreate");
229 if (sockfs_socreate == NULL) {
233 if (sockfs_sobind == NULL) {
234 sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
235 if (sockfs_sobind == NULL) {
239 if (sockfs_sosetsockopt == NULL) {
240 sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
241 if (sockfs_sosetsockopt == NULL) {
245 if (sockfs_sosendmsg == NULL) {
246 sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
247 if (sockfs_sosendmsg == NULL) {
251 if (sockfs_sorecvmsg == NULL) {
252 sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
253 if (sockfs_sorecvmsg == NULL) {
257 if (sockfs_sounbind == NULL) {
258 sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
259 if (sockfs_sounbind == NULL)
262 if (sockfs_sockfree == NULL) {
263 sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
264 if (sockfs_sockfree == NULL)
268 accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
269 if (accessvp == NULL) {
273 so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, NULL,
279 addr.sin_family = AF_INET;
280 addr.sin_port = aport;
281 addr.sin_addr.s_addr = INADDR_ANY;
282 error = sockfs_sobind(so, (struct sockaddr *)&addr, sizeof(addr), 0, 0);
288 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
294 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
299 return (struct osi_socket *)so;
303 osi_FreeSocket(register struct osi_socket *asocket)
305 extern int rxk_ListenerPid;
306 struct sonode *so = (struct sonode *)asocket;
307 struct sockaddr_in taddr;
311 AFS_STATCNT(osi_FreeSocket);
313 taddr.sin_family = AF_INET;
314 taddr.sin_port = rx_port;
315 taddr.sin_addr.s_addr = htonl(0x7f000001);
320 while (rxk_ListenerPid) {
321 osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
322 afs_osi_Sleep(&rxk_ListenerPid);
325 sockfs_sounbind(so, 0);
331 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
332 int nvecs, afs_int32 asize, int istack)
334 struct sonode *so = (struct sonode *)asocket;
337 struct iovec iov[RX_MAXIOVECS];
341 if (nvecs > RX_MAXIOVECS) {
342 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
345 msg.msg_name = (struct sockaddr *)addr;
346 msg.msg_namelen = sizeof(struct sockaddr_in);
348 msg.msg_iovlen = nvecs;
349 msg.msg_control = NULL;
350 msg.msg_controllen = 0;
353 for (i = 0; i < nvecs; i++) {
354 iov[i].iov_base = dvec[i].iov_base;
355 iov[i].iov_len = dvec[i].iov_len;
357 uio.uio_iov = &iov[0];
358 uio.uio_iovcnt = nvecs;
360 uio.uio_segflg = UIO_SYSSPACE;
361 uio.uio_fmode = FREAD | FWRITE;
363 uio.uio_resid = asize;
365 error = sockfs_sosendmsg(so, &msg, &uio);
371 osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
372 int nvecs, int *alength)
374 struct sonode *asocket = (struct sonode *)so;
377 struct iovec iov[RX_MAXIOVECS];
381 if (nvecs > RX_MAXIOVECS) {
382 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
386 msg.msg_namelen = sizeof(struct sockaddr_in);
389 msg.msg_control = NULL;
390 msg.msg_controllen = 0;
393 for (i = 0; i < nvecs; i++) {
394 iov[i].iov_base = dvec[i].iov_base;
395 iov[i].iov_len = dvec[i].iov_len;
397 uio.uio_iov = &iov[0];
398 uio.uio_iovcnt = nvecs;
400 uio.uio_segflg = UIO_SYSSPACE;
403 uio.uio_resid = *alength;
405 error = sockfs_sorecvmsg(asocket, &msg, &uio);
407 if (msg.msg_name == NULL) {
410 memcpy(addr, msg.msg_name, msg.msg_namelen);
411 kmem_free(msg.msg_name, msg.msg_namelen);
412 *alength = *alength - uio.uio_resid;
416 if (error == EINTR && ISSIG(curthread, FORREAL)) {
417 klwp_t *lwp = ttolwp(curthread);
418 proc_t *p = ttoproc(curthread);
419 int sig = lwp->lwp_cursig;
421 if (sig == SIGKILL) {
422 mutex_enter(&p->p_lock);
423 p->p_flag &= ~SKILLED;
424 mutex_exit(&p->p_lock);
427 if (lwp->lwp_curinfo) {
428 siginfofree(lwp->lwp_curinfo);
429 lwp->lwp_curinfo = NULL;
437 shutdown_rxkernel(void)
442 osi_StopListener(void)
444 osi_FreeSocket(rx_socket);
447 #else /* AFS_SUN56_ENV */
449 #include "inet/common.h"
450 #include "sys/tiuser.h"
451 #include "sys/t_kuser.h"
452 #include "sys/ioctl.h"
453 #include "sys/stropts.h"
454 #include "sys/stream.h"
455 #include "sys/strsubr.h"
456 #include "sys/vnode.h"
457 #include "sys/stropts.h"
458 #include "sys/tihdr.h"
459 #include "sys/timod.h"
460 #include "sys/fcntl.h"
461 #include "sys/debug.h"
462 #include "inet/common.h"
464 #include "netinet/udp.h"
466 extern dev_t afs_udp_rdev;
476 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
480 dev_t afs_udp_rdev = (dev_t) 0;
482 /* Allocate a new socket at specified port in network byte order. */
484 rxk_NewSocket(short aport)
487 struct t_bind *reqp, *rspp;
489 struct sockaddr_in *myaddrp;
493 AFS_STATCNT(osi_NewSocket);
494 afs_udp_rdev = makedevice(11 /*CLONE*/, ddi_name_to_major("udp"));
495 code = t_kopen(NULL, afs_udp_rdev, FREAD | FWRITE, &udp_tiptr, CRED());
497 return (struct osi_socket *)0;
500 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&reqp);
502 t_kclose(udp_tiptr, 0);
504 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&rspp);
506 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
507 t_kclose(udp_tiptr, 0);
508 return (struct osi_socket *)0;
511 reqp->addr.len = sizeof(struct sockaddr_in);
512 myaddrp = (struct sockaddr_in *)reqp->addr.buf;
513 myaddrp->sin_family = AF_INET;
514 myaddrp->sin_port = aport;
515 myaddrp->sin_addr.s_addr = INADDR_ANY; /* XXX Was 0 XXX */
517 code = t_kbind(udp_tiptr, reqp, rspp);
519 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
520 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
521 t_kclose(udp_tiptr, 0);
522 return (struct osi_socket *)0;
524 if (memcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
525 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
526 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
527 t_kclose(udp_tiptr, 0);
528 return (struct osi_socket *)0;
530 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
531 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
534 * Set the send and receive buffer sizes.
536 stp = udp_tiptr->fp->f_vnode->v_stream;
538 q->q_hiwat = rx_UdpBufSize;
539 q->q_next->q_hiwat = rx_UdpBufSize;
540 RD(q)->q_hiwat = rx_UdpBufSize;
542 return (struct osi_socket *)udp_tiptr;
547 osi_FreeSocket(register struct osi_socket *asocket)
549 extern int rxk_ListenerPid;
550 TIUSER *udp_tiptr = (TIUSER *) asocket;
551 AFS_STATCNT(osi_FreeSocket);
553 if (rxk_ListenerPid) {
554 kill(rxk_ListenerPid, SIGUSR1);
555 afs_osi_Sleep(&rxk_ListenerPid);
562 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
563 int nvecs, afs_int32 asize, int istack)
567 TIUSER *udp_tiptr = (TIUSER *) asocket;
568 struct t_kunitdata *udreq;
569 struct sockaddr_in sin;
574 * XXX We don't do any checking on the family since it's assumed to be
577 sin.sin_family = AF_INET;
578 sin.sin_addr.s_addr = addr->sin_addr.s_addr;
579 sin.sin_port = addr->sin_port;
582 * Get a buffer for the RX header
585 osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
587 while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
588 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
593 /* Copy the data into the buffer */
594 memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
595 bp->b_datap->db_type = M_DATA;
596 bp->b_wptr += dvec[0].iov_len;
599 * Append each element in the iovec to the buffer
601 for (i = 1; i < nvecs; i++) {
602 /* Get a buffer for the next chunk */
603 while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
604 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
610 /* Copy the data into the buffer */
611 memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base,
613 dbp->b_datap->db_type = M_DATA;
614 dbp->b_wptr += dvec[i].iov_len;
616 /* Append it to the message buffer */
621 * Allocate and format the unitdata structure.
623 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
626 printf("osi_NetSend: t_kalloc failed %d\n", code);
629 udreq->addr.len = sizeof(struct sockaddr_in);
630 udreq->addr.maxlen = sizeof(struct sockaddr_in);
632 (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
634 udreq->opt.maxlen = 0;
635 memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
636 udreq->udata.udata_mp = bp;
637 udreq->udata.len = asize;
639 code = t_ksndudata(udp_tiptr, udreq, NULL);
641 printf("osi_NetSend: t_ksndudata failed %d\n", code);
644 t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
650 osi_NetReceive(struct osi_socket *asocket, struct sockaddr_in *addr,
651 struct iovec *dvec, int nvecs, int *alength)
654 TIUSER *udp_tiptr = (TIUSER *) asocket;
655 struct t_kunitdata *udreq;
669 * Allocate the unitdata structure.
671 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
673 printf("osi_NetReceive: t_kalloc failed %d\n", code);
676 udreq->addr.len = sizeof(struct sockaddr_in);
677 udreq->addr.maxlen = sizeof(struct sockaddr_in);
679 (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
681 udreq->opt.maxlen = 0;
684 * Loop until we get an error or receive some data.
688 * Wait until there is something to do
690 code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
692 osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
695 * If there is a message then read it in
698 code = t_krcvudata(udp_tiptr, udreq, &type, &error);
702 * Block attempts to kill this thread
704 if (code == EINTR && ISSIG(curthread, FORREAL)) {
705 klwp_t *lwp = ttolwp(curthread);
706 proc_t *p = ttoproc(curthread);
707 int sig = lwp->lwp_cursig;
709 if (sig == SIGKILL) {
710 mutex_enter(&p->p_lock);
711 p->p_flag &= ~SKILLED;
712 mutex_exit(&p->p_lock);
715 if (lwp->lwp_curinfo) {
716 kmem_free((caddr_t) lwp->lwp_curinfo,
717 sizeof(*lwp->lwp_curinfo));
718 lwp->lwp_curinfo = NULL;
727 * Ignore non-data message types
729 if (type != T_DATA) {
734 * Save the source address
736 memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
739 * Copy out the message buffers, take care not to overflow
742 dbp = udreq->udata.udata_mp;
744 for (i = 0; dbp != NULL && length > 0 && i < nvecs; i++) {
745 tlen = dvec[i].iov_len;
746 tbase = dvec[i].iov_base;
750 while (dbp != NULL && tlen > 0) {
751 blen = dbp->b_wptr - dbp->b_rptr;
753 memcpy(tbase, (char *)dbp->b_rptr, tlen);
758 memcpy(tbase, (char *)dbp->b_rptr, blen);
766 *alength = *alength - length;
770 t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
776 osi_StopListener(void)
778 osi_FreeSocket(rx_socket);
783 shutdown_rxkernel(void)
788 #endif /* AFS_SUN56_ENV */
789 #endif /* AFS_SUN5_ENV */