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"
16 #include "rx/rx_kcommon.h"
21 #include "inet/common.h"
22 #include "sys/tiuser.h"
23 #include "sys/t_kuser.h"
24 #include "sys/stropts.h"
25 #include "sys/stream.h"
26 #include "sys/tihdr.h"
27 #include "sys/fcntl.h"
29 #include "netinet/ip6.h"
30 #define ipif_local_addr ipif_lcl_addr
32 #define V4_PART_OF_V6(v6) v6.s6_addr32[3]
36 #include "inet/ip_if.h"
37 #include "netinet/udp.h"
40 * Function pointers for kernel socket routines
42 struct sonode *(*sockfs_socreate)
43 (vnode_t *, int, int, int, int, struct sonode *, int *) = NULL;
44 struct vnode *(*sockfs_solookup)
45 (int, int, int, char *, int *) = NULL;
47 (struct sonode *, struct sockaddr *, int, int, int) = NULL;
48 int (*sockfs_sorecvmsg)
49 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
50 int (*sockfs_sosendmsg)
51 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
52 int (*sockfs_sosetsockopt)
53 (struct sonode *, int, int, void *, int) = NULL;
54 int (*sockfs_sounbind)
55 (struct sonode *, int);
56 void (*sockfs_sockfree)
59 static afs_uint32 myNetAddrs[ADDRSPERSITE];
60 static int myNetMTUs[ADDRSPERSITE];
61 static int numMyNetAddrs = 0;
73 int mtus[ADDRSPERSITE];
74 afs_uint32 addrs[ADDRSPERSITE];
77 memset(mtus, 0, sizeof(mtus));
78 memset(addrs, 0, sizeof(addrs));
80 for (ill = ill_g_head; ill; ill = ill->ill_next) {
82 /* Make sure this is an IPv4 ILL */
83 if (ill->ill_isv6) continue;
86 /* Iterate over all the addresses on this ILL */
87 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
88 if (i >= ADDRSPERSITE) break;
90 /* Ignore addresses which are down.. */
91 if (!(ipif->ipif_flags & IFF_UP)) continue;
93 /* Compute the Rx interface MTU */
94 rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
96 ifinaddr = ntohl(ipif->ipif_local_addr);
97 if (myNetAddrs[i] != ifinaddr)
100 /* Copy interface MTU and address; adjust maxmtu */
102 rxmtu = rxi_AdjustIfMTU(rxmtu);
103 maxmtu = rxmtu * rxi_nRecvFrags + ((rxi_nRecvFrags-1) *
105 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
109 if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
110 rx_maxReceiveSize = MIN( RX_MAX_PACKET_SIZE, maxmtu);
111 rx_maxReceiveSize = MIN( rx_maxReceiveSize,
112 rx_maxReceiveSizeUser);
117 rx_maxJumboRecvSize = RX_HEADER_SIZE +
118 rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
119 (rxi_nDgramPackets-1) * RX_JUMBOHEADERSIZE;
120 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
125 for (j = 0; j < i; j++) {
126 myNetMTUs[j] = mtus[j];
127 myNetAddrs[j] = addrs[j];
134 int rxi_FindIfMTU(afs_uint32 addr)
138 afs_uint32 myAddr, netMask;
142 if (numMyNetAddrs == 0)
144 myAddr = ntohl(addr);
146 if (IN_CLASSA(myAddr)) netMask = IN_CLASSA_NET;
147 else if (IN_CLASSB(myAddr)) netMask = IN_CLASSB_NET;
148 else if (IN_CLASSC(myAddr)) netMask = IN_CLASSC_NET;
151 for (ill = ill_g_head; ill; ill = ill->ill_next) {
153 /* Make sure this is an IPv4 ILL */
154 if (ill->ill_isv6) continue;
157 /* Iterate over all the addresses on this ILL */
158 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
159 afs_uint32 thisAddr, subnetMask;
162 thisAddr = ipif->ipif_local_addr;
163 subnetMask = ipif->ipif_net_mask;
164 thisMtu = ipif->ipif_mtu;
166 if ((myAddr & netMask) == (thisAddr & netMask)) {
167 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
168 if (myAddr == thisAddr) {
173 if (match_value < 3) {
179 if (match_value < 2) {
190 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
194 struct sockaddr_in rx_sockaddr;
196 /* Allocate a new socket at specified port in network byte order. */
197 struct osi_socket *rxk_NewSocket(short aport)
201 struct sockaddr_in addr;
205 AFS_STATCNT(osi_NewSocket);
207 if (sockfs_solookup == NULL) {
208 sockfs_solookup = (struct vnode *(*)())modlookup("sockfs", "solookup");
209 if (sockfs_solookup == NULL) {
213 if (sockfs_socreate == NULL) {
214 sockfs_socreate = (struct sonode *(*)())modlookup("sockfs", "socreate");
215 if (sockfs_socreate == NULL) {
219 if (sockfs_sobind == NULL) {
220 sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
221 if (sockfs_sobind == NULL) {
225 if (sockfs_sosetsockopt == NULL) {
226 sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
227 if (sockfs_sosetsockopt == NULL) {
231 if (sockfs_sosendmsg == NULL) {
232 sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
233 if (sockfs_sosendmsg == NULL) {
237 if (sockfs_sorecvmsg == NULL) {
238 sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
239 if (sockfs_sorecvmsg == NULL) {
243 if (sockfs_sounbind == NULL) {
244 sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
245 if (sockfs_sounbind == NULL)
248 if (sockfs_sockfree == NULL) {
249 sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
250 if (sockfs_sockfree == NULL)
254 accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
255 if (accessvp == NULL) {
259 so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0,
260 SOV_STREAM, NULL, &error);
265 addr.sin_family = AF_INET;
266 addr.sin_port = aport;
267 addr.sin_addr.s_addr = INADDR_ANY;
268 error = sockfs_sobind(so, (struct sockaddr *)&addr, sizeof(addr), 0, 0);
274 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
280 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
285 return (struct osi_socket *)so;
288 int osi_FreeSocket(register struct osi_socket *asocket)
290 extern int rxk_ListenerPid;
291 struct sonode *so = (struct sonode *)asocket;
292 struct sockaddr_in taddr;
296 AFS_STATCNT(osi_FreeSocket);
298 taddr.sin_family = AF_INET;
299 taddr.sin_port = rx_port;
300 taddr.sin_addr.s_addr = htonl(0x7f000001);
305 while (rxk_ListenerPid) {
306 osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
307 afs_osi_Sleep(&rxk_ListenerPid);
310 sockfs_sounbind(so, 0);
315 int osi_NetSend(osi_socket asocket, struct sockaddr_in *addr,
316 struct iovec *dvec, int nvecs, afs_int32 asize, int istack)
318 struct sonode *so = (struct sonode *)asocket;
321 struct iovec iov[RX_MAXIOVECS];
325 if (nvecs > RX_MAXIOVECS) {
326 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
329 msg.msg_name = (struct sockaddr *)addr;
330 msg.msg_namelen = sizeof(struct sockaddr_in);
332 msg.msg_iovlen = nvecs;
333 msg.msg_control = NULL;
334 msg.msg_controllen = 0;
337 for (i = 0 ; i < nvecs ; i++) {
338 iov[i].iov_base = dvec[i].iov_base;
339 iov[i].iov_len = dvec[i].iov_len;
341 uio.uio_iov = &iov[0];
342 uio.uio_iovcnt = nvecs;
344 uio.uio_segflg = UIO_SYSSPACE;
345 uio.uio_fmode = FREAD|FWRITE;
347 uio.uio_resid = asize;
349 error = sockfs_sosendmsg(so, &msg, &uio);
354 int osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
355 int nvecs, int *alength)
357 struct sonode *asocket = (struct sonode *)so;
360 struct iovec iov[RX_MAXIOVECS];
364 if (nvecs > RX_MAXIOVECS) {
365 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
369 msg.msg_namelen = sizeof(struct sockaddr_in);
372 msg.msg_control = NULL;
373 msg.msg_controllen = 0;
376 for (i = 0 ; i < nvecs ; i++) {
377 iov[i].iov_base = dvec[i].iov_base;
378 iov[i].iov_len = dvec[i].iov_len;
380 uio.uio_iov = &iov[0];
381 uio.uio_iovcnt = nvecs;
383 uio.uio_segflg = UIO_SYSSPACE;
386 uio.uio_resid = *alength;
388 error = sockfs_sorecvmsg(asocket, &msg, &uio);
390 if (msg.msg_name == NULL) {
393 memcpy(addr, msg.msg_name, msg.msg_namelen);
394 kmem_free(msg.msg_name, msg.msg_namelen);
395 *alength = *alength - uio.uio_resid;
399 if (error == EINTR && ISSIG(curthread, FORREAL)) {
400 klwp_t *lwp = ttolwp(curthread);
401 proc_t *p = ttoproc(curthread);
402 int sig = lwp->lwp_cursig;
404 if (sig == SIGKILL) {
405 mutex_enter(&p->p_lock);
406 p->p_flag &= ~SKILLED;
407 mutex_exit(&p->p_lock);
410 if (lwp->lwp_curinfo) {
411 siginfofree(lwp->lwp_curinfo);
412 lwp->lwp_curinfo = NULL;
419 void shutdown_rxkernel(void)
423 void osi_StopListener(void)
425 osi_FreeSocket(rx_socket);
428 #else /* AFS_SUN56_ENV */
430 #include "inet/common.h"
431 #include "sys/tiuser.h"
432 #include "sys/t_kuser.h"
433 #include "sys/ioctl.h"
434 #include "sys/stropts.h"
435 #include "sys/stream.h"
436 #include "sys/strsubr.h"
437 #include "sys/vnode.h"
438 #include "sys/stropts.h"
439 #include "sys/tihdr.h"
440 #include "sys/timod.h"
441 #include "sys/fcntl.h"
442 #include "sys/debug.h"
443 #include "inet/common.h"
445 #include "netinet/udp.h"
447 extern dev_t afs_udp_rdev;
456 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
460 dev_t afs_udp_rdev = (dev_t)0;
462 /* Allocate a new socket at specified port in network byte order. */
463 struct osi_socket *rxk_NewSocket(short aport)
466 struct t_bind *reqp, *rspp;
468 struct sockaddr_in *myaddrp;
472 AFS_STATCNT(osi_NewSocket);
473 afs_udp_rdev = makedevice(11 /*CLONE*/, ddi_name_to_major("udp"));
474 code = t_kopen(NULL, afs_udp_rdev, FREAD|FWRITE, &udp_tiptr, CRED());
476 return (struct osi_socket *)0;
479 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&reqp);
481 t_kclose(udp_tiptr, 0);
483 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&rspp);
485 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
486 t_kclose(udp_tiptr, 0);
487 return (struct osi_socket *)0;
490 reqp->addr.len = sizeof(struct sockaddr_in);
491 myaddrp = (struct sockaddr_in *) reqp->addr.buf;
492 myaddrp->sin_family = AF_INET;
493 myaddrp->sin_port = aport;
494 myaddrp->sin_addr.s_addr = INADDR_ANY; /* XXX Was 0 XXX */
496 code = t_kbind(udp_tiptr, reqp, rspp);
498 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
499 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
500 t_kclose(udp_tiptr, 0);
501 return (struct osi_socket *)0;
503 if (memcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
504 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
505 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
506 t_kclose(udp_tiptr, 0);
507 return (struct osi_socket *)0;
509 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
510 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
513 * Set the send and receive buffer sizes.
515 stp = udp_tiptr->fp->f_vnode->v_stream;
517 q->q_hiwat = rx_UdpBufSize;
518 q->q_next->q_hiwat = rx_UdpBufSize;
519 RD(q)->q_hiwat = rx_UdpBufSize;
521 return (struct osi_socket *) udp_tiptr;
525 int osi_FreeSocket(register struct osi_socket *asocket)
527 extern int rxk_ListenerPid;
528 TIUSER *udp_tiptr = (TIUSER *) asocket;
529 AFS_STATCNT(osi_FreeSocket);
531 if (rxk_ListenerPid) {
532 kill(rxk_ListenerPid, SIGUSR1);
533 afs_osi_Sleep(&rxk_ListenerPid);
539 int osi_NetSend(osi_socket asocket, struct sockaddr_in *addr,
540 struct iovec *dvec, int nvecs, afs_int32 asize, int istack)
544 TIUSER *udp_tiptr = (TIUSER *) asocket;
545 struct t_kunitdata *udreq;
546 struct sockaddr_in sin;
551 * XXX We don't do any checking on the family since it's assumed to be
554 sin.sin_family = AF_INET;
555 sin.sin_addr.s_addr = addr->sin_addr.s_addr;
556 sin.sin_port = addr->sin_port;
559 * Get a buffer for the RX header
562 osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
564 while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
565 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
570 /* Copy the data into the buffer */
571 memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
572 bp->b_datap->db_type = M_DATA;
573 bp->b_wptr += dvec[0].iov_len;
576 * Append each element in the iovec to the buffer
578 for (i = 1 ; i < nvecs ; i++) {
579 /* Get a buffer for the next chunk */
580 while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
581 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
587 /* Copy the data into the buffer */
588 memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base, dvec[i].iov_len);
589 dbp->b_datap->db_type = M_DATA;
590 dbp->b_wptr += dvec[i].iov_len;
592 /* Append it to the message buffer */
597 * Allocate and format the unitdata structure.
599 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
602 printf("osi_NetSend: t_kalloc failed %d\n", code);
605 udreq->addr.len = sizeof(struct sockaddr_in);
606 udreq->addr.maxlen = sizeof(struct sockaddr_in);
607 udreq->addr.buf = (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
609 udreq->opt.maxlen = 0;
610 memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
611 udreq->udata.udata_mp = bp;
612 udreq->udata.len = asize;
614 code = t_ksndudata(udp_tiptr, udreq, NULL);
616 printf("osi_NetSend: t_ksndudata failed %d\n", code);
619 t_kfree(udp_tiptr, (caddr_t)udreq, T_UNITDATA);
624 int osi_NetReceive(struct osi_socket *asocket, struct sockaddr_in *addr,
625 struct iovec *dvec, int nvecs, int *alength)
628 TIUSER *udp_tiptr = (TIUSER *) asocket;
629 struct t_kunitdata *udreq;
643 * Allocate the unitdata structure.
645 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
647 printf("osi_NetReceive: t_kalloc failed %d\n", code);
650 udreq->addr.len = sizeof(struct sockaddr_in);
651 udreq->addr.maxlen = sizeof(struct sockaddr_in);
652 udreq->addr.buf = (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
654 udreq->opt.maxlen = 0;
657 * Loop until we get an error or receive some data.
661 * Wait until there is something to do
663 code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
665 osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
668 * If there is a message then read it in
671 code = t_krcvudata(udp_tiptr, udreq, &type, &error);
675 * Block attempts to kill this thread
677 if (code == EINTR && ISSIG(curthread, FORREAL)) {
678 klwp_t *lwp = ttolwp(curthread);
679 proc_t *p = ttoproc(curthread);
680 int sig = lwp->lwp_cursig;
682 if (sig == SIGKILL) {
683 mutex_enter(&p->p_lock);
684 p->p_flag &= ~SKILLED;
685 mutex_exit(&p->p_lock);
688 if (lwp->lwp_curinfo) {
689 kmem_free((caddr_t)lwp->lwp_curinfo, sizeof(*lwp->lwp_curinfo));
690 lwp->lwp_curinfo = NULL;
699 * Ignore non-data message types
701 if (type != T_DATA) {
706 * Save the source address
708 memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
711 * Copy out the message buffers, take care not to overflow
714 dbp = udreq->udata.udata_mp;
716 for (i = 0 ; dbp != NULL && length > 0 && i < nvecs ; i++) {
717 tlen = dvec[i].iov_len;
718 tbase = dvec[i].iov_base;
722 while (dbp != NULL && tlen > 0) {
723 blen = dbp->b_wptr - dbp->b_rptr;
725 memcpy(tbase, (char *)dbp->b_rptr, tlen);
730 memcpy(tbase, (char *)dbp->b_rptr, blen);
738 *alength = *alength - length;
742 t_kfree(udp_tiptr, (caddr_t)udreq, T_UNITDATA);
747 void osi_StopListener(void)
749 osi_FreeSocket(rx_socket);
753 void shutdown_rxkernel(void)
758 #endif /* AFS_SUN56_ENV */
759 #endif /* AFS_SUN5_ENV */