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 #ifndef AFS_SUN510_ENV
56 int (*sockfs_sounbind)
57 (struct sonode *, int);
58 void (*sockfs_sockfree)
62 static afs_uint32 myNetAddrs[ADDRSPERSITE];
63 static int myNetMTUs[ADDRSPERSITE];
64 static int numMyNetAddrs = 0;
76 ill_walk_context_t ctx;
79 int mtus[ADDRSPERSITE];
80 afs_uint32 addrs[ADDRSPERSITE];
83 memset(mtus, 0, sizeof(mtus));
84 memset(addrs, 0, sizeof(addrs));
87 for (ill = ILL_START_WALK_ALL(&ctx) ; ill ; ill = ill_next(&ctx, ill)) {
89 for (ill = ill_g_head; ill; ill = ill->ill_next) {
92 /* Make sure this is an IPv4 ILL */
97 /* Iterate over all the addresses on this ILL */
98 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
99 if (i >= ADDRSPERSITE)
102 /* Ignore addresses which are down.. */
103 if (!(ipif->ipif_flags & IFF_UP))
106 /* Compute the Rx interface MTU */
107 rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
109 ifinaddr = ntohl(ipif->ipif_local_addr);
110 if (myNetAddrs[i] != ifinaddr)
113 /* Copy interface MTU and address; adjust maxmtu */
115 rxmtu = rxi_AdjustIfMTU(rxmtu);
117 rxmtu * rxi_nRecvFrags +
118 ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
119 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
123 if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
124 rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
126 MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
131 rx_maxJumboRecvSize =
132 RX_HEADER_SIZE + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
133 (rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE;
134 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
139 for (j = 0; j < i; j++) {
140 myNetMTUs[j] = mtus[j];
141 myNetAddrs[j] = addrs[j];
149 rxi_FindIfMTU(afs_uint32 addr)
153 afs_uint32 myAddr, netMask;
156 #ifdef AFS_SUN510_ENV
157 ill_walk_context_t ctx;
160 if (numMyNetAddrs == 0)
162 myAddr = ntohl(addr);
164 if (IN_CLASSA(myAddr))
165 netMask = IN_CLASSA_NET;
166 else if (IN_CLASSB(myAddr))
167 netMask = IN_CLASSB_NET;
168 else if (IN_CLASSC(myAddr))
169 netMask = IN_CLASSC_NET;
173 #ifdef AFS_SUN510_ENV
174 for (ill = ILL_START_WALK_ALL(&ctx) ; ill ; ill = ill_next(&ctx, ill)) {
176 for (ill = ill_g_head; ill; ill = ill->ill_next) {
179 /* Make sure this is an IPv4 ILL */
184 /* Iterate over all the addresses on this ILL */
185 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
186 afs_uint32 thisAddr, subnetMask;
189 thisAddr = ipif->ipif_local_addr;
190 subnetMask = ipif->ipif_net_mask;
191 thisMtu = ipif->ipif_mtu;
193 if ((myAddr & netMask) == (thisAddr & netMask)) {
194 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
195 if (myAddr == thisAddr) {
200 if (match_value < 3) {
206 if (match_value < 2) {
217 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
221 struct sockaddr_in rx_sockaddr;
223 /* Allocate a new socket at specified port in network byte order. */
225 rxk_NewSocketHost(struct sockaddr_storage *addr, int salen)
232 AFS_STATCNT(osi_NewSocket);
234 if (sockfs_solookup == NULL) {
236 (struct vnode * (*)())modlookup("sockfs", "solookup");
237 if (sockfs_solookup == NULL) {
241 if (sockfs_socreate == NULL) {
243 (struct sonode * (*)())modlookup("sockfs", "socreate");
244 if (sockfs_socreate == NULL) {
248 if (sockfs_sobind == NULL) {
249 sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
250 if (sockfs_sobind == NULL) {
254 if (sockfs_sosetsockopt == NULL) {
255 sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
256 if (sockfs_sosetsockopt == NULL) {
260 if (sockfs_sosendmsg == NULL) {
261 sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
262 if (sockfs_sosendmsg == NULL) {
266 if (sockfs_sorecvmsg == NULL) {
267 sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
268 if (sockfs_sorecvmsg == NULL) {
272 #ifndef AFS_SUN510_ENV
273 if (sockfs_sounbind == NULL) {
274 sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
275 if (sockfs_sounbind == NULL)
278 if (sockfs_sockfree == NULL) {
279 sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
280 if (sockfs_sockfree == NULL)
285 accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
286 if (accessvp == NULL) {
290 so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0, SOV_STREAM, NULL,
296 error = sockfs_sobind(so, (struct sockaddr *)addr, salen, 0, 0);
302 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
308 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
313 return (osi_socket *)so;
317 rxk_NewSocket(short aport)
319 return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
323 osi_FreeSocket(register osi_socket *asocket)
325 extern int rxk_ListenerPid;
326 struct sonode *so = (struct sonode *)asocket;
327 struct sockaddr_in taddr;
332 AFS_STATCNT(osi_FreeSocket);
334 taddr.sin_family = AF_INET;
335 taddr.sin_port = rx_port;
336 taddr.sin_addr.s_addr = htonl(0x7f000001);
341 while (rxk_ListenerPid) {
342 osi_NetSend(rx_socket, &taddr, sizeof(taddr), &dvec, 1, 1, 0);
343 afs_osi_Sleep(&rxk_ListenerPid);
346 /* Was sockfs_sounbind(so, 0); sockfs_sockfree(so); That's wrong */
348 VOP_CLOSE(vp, FREAD|FWRITE, 1, (offset_t)0, CRED());
355 osi_NetSend(osi_socket asocket, struct sockaddr_storage *saddr, int slen,
356 struct iovec *dvec, int nvecs, afs_int32 asize, int istack)
358 struct sonode *so = (struct sonode *)asocket;
361 struct iovec iov[RX_MAXIOVECS];
365 if (nvecs > RX_MAXIOVECS) {
366 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
369 msg.msg_name = (struct sockaddr *) saddr;
370 msg.msg_namelen = slen;
372 msg.msg_iovlen = nvecs;
373 msg.msg_control = NULL;
374 msg.msg_controllen = 0;
377 for (i = 0; i < nvecs; i++) {
378 iov[i].iov_base = dvec[i].iov_base;
379 iov[i].iov_len = dvec[i].iov_len;
381 uio.uio_iov = &iov[0];
382 uio.uio_iovcnt = nvecs;
384 uio.uio_segflg = UIO_SYSSPACE;
385 uio.uio_fmode = FREAD | FWRITE;
387 uio.uio_resid = asize;
389 error = sockfs_sosendmsg(so, &msg, &uio);
395 osi_NetReceive(osi_socket so, struct sockaddr_storage *saddr, int *slen,
396 struct iovec *dvec, int nvecs, int *alength)
398 struct sonode *asocket = (struct sonode *)so;
401 struct iovec iov[RX_MAXIOVECS];
405 if (nvecs > RX_MAXIOVECS) {
406 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
410 msg.msg_namelen = *slen;
413 msg.msg_control = NULL;
414 msg.msg_controllen = 0;
417 for (i = 0; i < nvecs; i++) {
418 iov[i].iov_base = dvec[i].iov_base;
419 iov[i].iov_len = dvec[i].iov_len;
421 uio.uio_iov = &iov[0];
422 uio.uio_iovcnt = nvecs;
424 uio.uio_segflg = UIO_SYSSPACE;
427 uio.uio_resid = *alength;
429 error = sockfs_sorecvmsg(asocket, &msg, &uio);
431 if (msg.msg_name == NULL) {
434 memcpy(saddr, msg.msg_name, msg.msg_namelen);
435 *slen = msg.msg_namelen;
436 kmem_free(msg.msg_name, msg.msg_namelen);
437 *alength = *alength - uio.uio_resid;
441 if (error == EINTR && ISSIG(curthread, FORREAL)) {
442 klwp_t *lwp = ttolwp(curthread);
443 proc_t *p = ttoproc(curthread);
444 int sig = lwp->lwp_cursig;
446 if (sig == SIGKILL) {
447 mutex_enter(&p->p_lock);
448 p->p_flag &= ~SKILLED;
449 mutex_exit(&p->p_lock);
452 if (lwp->lwp_curinfo) {
453 siginfofree(lwp->lwp_curinfo);
454 lwp->lwp_curinfo = NULL;
462 shutdown_rxkernel(void)
467 osi_StopListener(void)
469 osi_FreeSocket(rx_socket);
472 #else /* AFS_SUN56_ENV */
474 #include "inet/common.h"
475 #include "sys/tiuser.h"
476 #include "sys/t_kuser.h"
477 #include "sys/ioctl.h"
478 #include "sys/stropts.h"
479 #include "sys/stream.h"
480 #include "sys/strsubr.h"
481 #include "sys/vnode.h"
482 #include "sys/stropts.h"
483 #include "sys/tihdr.h"
484 #include "sys/timod.h"
485 #include "sys/fcntl.h"
486 #include "sys/debug.h"
487 #include "inet/common.h"
489 #include "netinet/udp.h"
491 extern dev_t afs_udp_rdev;
501 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
505 dev_t afs_udp_rdev = (dev_t) 0;
507 /* Allocate a new socket at specified port in network byte order. */
509 rxk_NewSocketHost(afs_uint32 ahost, short aport)
512 struct t_bind *reqp, *rspp;
514 struct sockaddr_in *myaddrp;
518 AFS_STATCNT(osi_NewSocket);
519 afs_udp_rdev = makedevice(11 /*CLONE*/, ddi_name_to_major("udp"));
520 code = t_kopen(NULL, afs_udp_rdev, FREAD | FWRITE, &udp_tiptr, CRED());
522 return (osi_socket *)0;
525 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&reqp);
527 t_kclose(udp_tiptr, 0);
529 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&rspp);
531 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
532 t_kclose(udp_tiptr, 0);
533 return (osi_socket *)0;
536 reqp->addr.len = sizeof(struct sockaddr_in);
537 myaddrp = (struct sockaddr_in *)reqp->addr.buf;
538 myaddrp->sin_family = AF_INET;
539 myaddrp->sin_port = aport;
540 myaddrp->sin_addr.s_addr = ahost; /* byteswap? */
542 code = t_kbind(udp_tiptr, reqp, rspp);
544 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
545 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
546 t_kclose(udp_tiptr, 0);
547 return (osi_socket *)0;
549 if (memcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
550 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
551 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
552 t_kclose(udp_tiptr, 0);
553 return (osi_socket *)0;
555 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
556 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
559 * Set the send and receive buffer sizes.
561 stp = udp_tiptr->fp->f_vnode->v_stream;
563 q->q_hiwat = rx_UdpBufSize;
564 q->q_next->q_hiwat = rx_UdpBufSize;
565 RD(q)->q_hiwat = rx_UdpBufSize;
567 return (osi_socket *)udp_tiptr;
571 rxk_NewSocket(short aport)
573 return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
577 osi_FreeSocket(register osi_socket *asocket)
579 extern int rxk_ListenerPid;
580 TIUSER *udp_tiptr = (TIUSER *) asocket;
581 AFS_STATCNT(osi_FreeSocket);
583 if (rxk_ListenerPid) {
584 kill(rxk_ListenerPid, SIGUSR1);
585 afs_osi_Sleep(&rxk_ListenerPid);
592 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
593 int nvecs, afs_int32 asize, int istack)
597 TIUSER *udp_tiptr = (TIUSER *) asocket;
598 struct t_kunitdata *udreq;
599 struct sockaddr_in sin;
604 * XXX We don't do any checking on the family since it's assumed to be
607 sin.sin_family = AF_INET;
608 sin.sin_addr.s_addr = addr->sin_addr.s_addr;
609 sin.sin_port = addr->sin_port;
612 * Get a buffer for the RX header
615 osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
617 while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
618 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
623 /* Copy the data into the buffer */
624 memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
625 bp->b_datap->db_type = M_DATA;
626 bp->b_wptr += dvec[0].iov_len;
629 * Append each element in the iovec to the buffer
631 for (i = 1; i < nvecs; i++) {
632 /* Get a buffer for the next chunk */
633 while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
634 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
640 /* Copy the data into the buffer */
641 memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base,
643 dbp->b_datap->db_type = M_DATA;
644 dbp->b_wptr += dvec[i].iov_len;
646 /* Append it to the message buffer */
651 * Allocate and format the unitdata structure.
653 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
656 printf("osi_NetSend: t_kalloc failed %d\n", code);
659 udreq->addr.len = sizeof(struct sockaddr_in);
660 udreq->addr.maxlen = sizeof(struct sockaddr_in);
662 (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
664 udreq->opt.maxlen = 0;
665 memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
666 udreq->udata.udata_mp = bp;
667 udreq->udata.len = asize;
669 code = t_ksndudata(udp_tiptr, udreq, NULL);
671 printf("osi_NetSend: t_ksndudata failed %d\n", code);
674 t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
680 osi_NetReceive(osi_socket *asocket, struct sockaddr_in *addr,
681 struct iovec *dvec, int nvecs, int *alength)
684 TIUSER *udp_tiptr = (TIUSER *) asocket;
685 struct t_kunitdata *udreq;
699 * Allocate the unitdata structure.
701 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
703 printf("osi_NetReceive: t_kalloc failed %d\n", code);
706 udreq->addr.len = sizeof(struct sockaddr_in);
707 udreq->addr.maxlen = sizeof(struct sockaddr_in);
709 (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
711 udreq->opt.maxlen = 0;
714 * Loop until we get an error or receive some data.
718 * Wait until there is something to do
720 code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
722 osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
725 * If there is a message then read it in
728 code = t_krcvudata(udp_tiptr, udreq, &type, &error);
732 * Block attempts to kill this thread
734 if (code == EINTR && ISSIG(curthread, FORREAL)) {
735 klwp_t *lwp = ttolwp(curthread);
736 proc_t *p = ttoproc(curthread);
737 int sig = lwp->lwp_cursig;
739 if (sig == SIGKILL) {
740 mutex_enter(&p->p_lock);
741 p->p_flag &= ~SKILLED;
742 mutex_exit(&p->p_lock);
745 if (lwp->lwp_curinfo) {
746 kmem_free((caddr_t) lwp->lwp_curinfo,
747 sizeof(*lwp->lwp_curinfo));
748 lwp->lwp_curinfo = NULL;
757 * Ignore non-data message types
759 if (type != T_DATA) {
764 * Save the source address
766 memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
769 * Copy out the message buffers, take care not to overflow
772 dbp = udreq->udata.udata_mp;
774 for (i = 0; dbp != NULL && length > 0 && i < nvecs; i++) {
775 tlen = dvec[i].iov_len;
776 tbase = dvec[i].iov_base;
780 while (dbp != NULL && tlen > 0) {
781 blen = dbp->b_wptr - dbp->b_rptr;
783 memcpy(tbase, (char *)dbp->b_rptr, tlen);
788 memcpy(tbase, (char *)dbp->b_rptr, blen);
796 *alength = *alength - length;
800 t_kfree(udp_tiptr, (caddr_t) udreq, T_UNITDATA);
806 osi_StopListener(void)
808 osi_FreeSocket(rx_socket);
813 shutdown_rxkernel(void)
818 #endif /* AFS_SUN56_ENV */
819 #endif /* AFS_SUN5_ENV */