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]
35 #include "../inet/ip.h"
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;
55 static afs_uint32 myNetAddrs[ADDRSPERSITE];
56 static int myNetMTUs[ADDRSPERSITE];
57 static int numMyNetAddrs = 0;
69 int mtus[ADDRSPERSITE];
70 afs_uint32 addrs[ADDRSPERSITE];
73 memset(mtus, 0, sizeof(mtus));
74 memset(addrs, 0, sizeof(addrs));
76 for (ill = ill_g_head; ill; ill = ill->ill_next) {
78 /* Make sure this is an IPv4 ILL */
79 if (ill->ill_isv6) continue;
82 /* Iterate over all the addresses on this ILL */
83 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
84 if (i >= ADDRSPERSITE) break;
86 /* Ignore addresses which are down.. */
87 if (!(ipif->ipif_flags & IFF_UP)) continue;
89 /* Compute the Rx interface MTU */
90 rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
92 ifinaddr = ntohl(ipif->ipif_local_addr);
93 if (myNetAddrs[i] != ifinaddr)
96 /* Copy interface MTU and address; adjust maxmtu */
98 rxmtu = rxi_AdjustIfMTU(rxmtu);
99 maxmtu = rxmtu * rxi_nRecvFrags + ((rxi_nRecvFrags-1) *
101 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
105 if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
106 rx_maxReceiveSize = MIN( RX_MAX_PACKET_SIZE, maxmtu);
107 rx_maxReceiveSize = MIN( rx_maxReceiveSize,
108 rx_maxReceiveSizeUser);
113 rx_maxJumboRecvSize = RX_HEADER_SIZE +
114 rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
115 (rxi_nDgramPackets-1) * RX_JUMBOHEADERSIZE;
116 rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
121 for (j = 0; j < i; j++) {
122 myNetMTUs[j] = mtus[j];
123 myNetAddrs[j] = addrs[j];
136 afs_uint32 myAddr, netMask;
140 if (numMyNetAddrs == 0)
142 myAddr = ntohl(addr);
144 if (IN_CLASSA(myAddr)) netMask = IN_CLASSA_NET;
145 else if (IN_CLASSB(myAddr)) netMask = IN_CLASSB_NET;
146 else if (IN_CLASSC(myAddr)) netMask = IN_CLASSC_NET;
149 for (ill = ill_g_head; ill; ill = ill->ill_next) {
151 /* Make sure this is an IPv4 ILL */
152 if (ill->ill_isv6) continue;
155 /* Iterate over all the addresses on this ILL */
156 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
157 afs_uint32 thisAddr, subnetMask;
160 thisAddr = ipif->ipif_local_addr;
161 subnetMask = ipif->ipif_net_mask;
162 thisMtu = ipif->ipif_mtu;
164 if ((myAddr & netMask) == (thisAddr & netMask)) {
165 if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
166 if (myAddr == thisAddr) {
171 if (match_value < 3) {
177 if (match_value < 2) {
188 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
192 struct sockaddr_in rx_sockaddr;
194 /* Allocate a new socket at specified port in network byte order. */
195 struct osi_socket *rxk_NewSocket(short aport)
199 struct sockaddr_in addr;
203 AFS_STATCNT(osi_NewSocket);
205 if (sockfs_solookup == NULL) {
206 sockfs_solookup = (struct vnode *(*)())modlookup("sockfs", "solookup");
207 if (sockfs_solookup == NULL) {
211 if (sockfs_socreate == NULL) {
212 sockfs_socreate = (struct sonode *(*)())modlookup("sockfs", "socreate");
213 if (sockfs_socreate == NULL) {
217 if (sockfs_sobind == NULL) {
218 sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
219 if (sockfs_sobind == NULL) {
223 if (sockfs_sosetsockopt == NULL) {
224 sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
225 if (sockfs_sosetsockopt == NULL) {
229 if (sockfs_sosendmsg == NULL) {
230 sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
231 if (sockfs_sosendmsg == NULL) {
235 if (sockfs_sorecvmsg == NULL) {
236 sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
237 if (sockfs_sorecvmsg == NULL) {
242 accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
243 if (accessvp == NULL) {
247 so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0,
248 SOV_STREAM, NULL, &error);
253 addr.sin_family = AF_INET;
254 addr.sin_port = aport;
255 addr.sin_addr.s_addr = INADDR_ANY;
256 error = sockfs_sobind(so, (struct sockaddr *)&addr, sizeof(addr), 0, 0);
262 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
268 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
273 return (struct osi_socket *)so;
276 int osi_FreeSocket(asocket)
277 register struct osi_socket *asocket;
279 extern int rxk_ListenerPid;
280 struct sonode *so = (struct sonode *)asocket;
281 vnode_t *vp = SOTOV(so);
283 AFS_STATCNT(osi_FreeSocket);
284 while (rxk_ListenerPid) {
285 kill(rxk_ListenerPid, SIGUSR1);
286 afs_osi_Sleep(&rxk_ListenerPid);
291 int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
292 struct osi_socket *asocket;
293 struct sockaddr_in *addr;
299 struct sonode *so = (struct sonode *)asocket;
302 struct iovec iov[RX_MAXIOVECS];
306 if (nvecs > RX_MAXIOVECS) {
307 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
310 msg.msg_name = (struct sockaddr *)addr;
311 msg.msg_namelen = sizeof(struct sockaddr_in);
313 msg.msg_iovlen = nvecs;
314 msg.msg_control = NULL;
315 msg.msg_controllen = 0;
318 for (i = 0 ; i < nvecs ; i++) {
319 iov[i].iov_base = dvec[i].iov_base;
320 iov[i].iov_len = dvec[i].iov_len;
322 uio.uio_iov = &iov[0];
323 uio.uio_iovcnt = nvecs;
325 uio.uio_segflg = UIO_SYSSPACE;
326 uio.uio_fmode = FREAD|FWRITE;
328 uio.uio_resid = asize;
330 error = sockfs_sosendmsg(so, &msg, &uio);
335 int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
336 struct osi_socket *asocket;
337 struct sockaddr_in *addr;
342 struct sonode *so = (struct sonode *)asocket;
345 struct iovec iov[RX_MAXIOVECS];
349 if (nvecs > RX_MAXIOVECS) {
350 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
354 msg.msg_namelen = sizeof(struct sockaddr_in);
357 msg.msg_control = NULL;
358 msg.msg_controllen = 0;
361 for (i = 0 ; i < nvecs ; i++) {
362 iov[i].iov_base = dvec[i].iov_base;
363 iov[i].iov_len = dvec[i].iov_len;
365 uio.uio_iov = &iov[0];
366 uio.uio_iovcnt = nvecs;
368 uio.uio_segflg = UIO_SYSSPACE;
371 uio.uio_resid = *alength;
373 error = sockfs_sorecvmsg(so, &msg, &uio);
375 if (msg.msg_name == NULL) {
378 memcpy(addr, msg.msg_name, msg.msg_namelen);
379 kmem_free(msg.msg_name, msg.msg_namelen);
380 *alength = *alength - uio.uio_resid;
384 if (error == EINTR && ISSIG(curthread, FORREAL)) {
385 klwp_t *lwp = ttolwp(curthread);
386 proc_t *p = ttoproc(curthread);
387 int sig = lwp->lwp_cursig;
389 if (sig == SIGKILL) {
390 mutex_enter(&p->p_lock);
391 p->p_flag &= ~SKILLED;
392 mutex_exit(&p->p_lock);
395 if (lwp->lwp_curinfo) {
396 siginfofree(lwp->lwp_curinfo);
397 lwp->lwp_curinfo = NULL;
404 void shutdown_rxkernel(void)
408 void osi_StopListener(void)
410 osi_FreeSocket(rx_socket);
413 #else /* AFS_SUN56_ENV */
415 #include "../inet/common.h"
416 #include "../sys/tiuser.h"
417 #include "../sys/t_kuser.h"
418 #include "../sys/ioctl.h"
419 #include "../sys/stropts.h"
420 #include "../sys/stream.h"
421 #include "../sys/strsubr.h"
422 #include "../sys/vnode.h"
423 #include "../sys/stropts.h"
424 #include "../sys/tihdr.h"
425 #include "../sys/timod.h"
426 #include "../sys/fcntl.h"
427 #include "../sys/debug.h"
428 #include "../inet/common.h"
429 #include "../inet/mi.h"
430 #include "../netinet/udp.h"
432 extern dev_t afs_udp_rdev;
441 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
445 dev_t afs_udp_rdev = (dev_t)0;
447 /* Allocate a new socket at specified port in network byte order. */
448 struct osi_socket *rxk_NewSocket(short aport)
451 struct t_bind *reqp, *rspp;
453 struct sockaddr_in *myaddrp;
457 AFS_STATCNT(osi_NewSocket);
458 afs_udp_rdev = makedevice(11 /*CLONE*/, ddi_name_to_major("udp"));
459 code = t_kopen(NULL, afs_udp_rdev, FREAD|FWRITE, &udp_tiptr, CRED());
461 return (struct osi_socket *)0;
464 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&reqp);
466 t_kclose(udp_tiptr, 0);
468 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&rspp);
470 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
471 t_kclose(udp_tiptr, 0);
472 return (struct osi_socket *)0;
475 reqp->addr.len = sizeof(struct sockaddr_in);
476 myaddrp = (struct sockaddr_in *) reqp->addr.buf;
477 myaddrp->sin_family = AF_INET;
478 myaddrp->sin_port = aport;
479 myaddrp->sin_addr.s_addr = INADDR_ANY; /* XXX Was 0 XXX */
481 code = t_kbind(udp_tiptr, reqp, rspp);
483 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
484 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
485 t_kclose(udp_tiptr, 0);
486 return (struct osi_socket *)0;
488 if (memcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
489 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
490 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
491 t_kclose(udp_tiptr, 0);
492 return (struct osi_socket *)0;
494 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
495 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
498 * Set the send and receive buffer sizes.
500 stp = udp_tiptr->fp->f_vnode->v_stream;
502 q->q_hiwat = rx_UdpBufSize;
503 q->q_next->q_hiwat = rx_UdpBufSize;
504 RD(q)->q_hiwat = rx_UdpBufSize;
506 return (struct osi_socket *) udp_tiptr;
510 int osi_FreeSocket(asocket)
511 register struct osi_socket *asocket;
513 extern int rxk_ListenerPid;
514 TIUSER *udp_tiptr = (TIUSER *) asocket;
515 AFS_STATCNT(osi_FreeSocket);
517 if (rxk_ListenerPid) {
518 kill(rxk_ListenerPid, SIGUSR1);
519 afs_osi_Sleep(&rxk_ListenerPid);
525 int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
526 register struct osi_socket *asocket;
529 register afs_int32 asize;
530 struct sockaddr_in *addr;
535 TIUSER *udp_tiptr = (TIUSER *) asocket;
536 struct t_kunitdata *udreq;
537 struct sockaddr_in sin;
542 * XXX We don't do any checking on the family since it's assumed to be
545 sin.sin_family = AF_INET;
546 sin.sin_addr.s_addr = addr->sin_addr.s_addr;
547 sin.sin_port = addr->sin_port;
550 * Get a buffer for the RX header
553 osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
555 while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
556 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
561 /* Copy the data into the buffer */
562 memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
563 bp->b_datap->db_type = M_DATA;
564 bp->b_wptr += dvec[0].iov_len;
567 * Append each element in the iovec to the buffer
569 for (i = 1 ; i < nvecs ; i++) {
570 /* Get a buffer for the next chunk */
571 while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
572 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
578 /* Copy the data into the buffer */
579 memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base, dvec[i].iov_len);
580 dbp->b_datap->db_type = M_DATA;
581 dbp->b_wptr += dvec[i].iov_len;
583 /* Append it to the message buffer */
588 * Allocate and format the unitdata structure.
590 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
593 printf("osi_NetSend: t_kalloc failed %d\n", code);
596 udreq->addr.len = sizeof(struct sockaddr_in);
597 udreq->addr.maxlen = sizeof(struct sockaddr_in);
598 udreq->addr.buf = (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
600 udreq->opt.maxlen = 0;
601 memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
602 udreq->udata.udata_mp = bp;
603 udreq->udata.len = asize;
605 code = t_ksndudata(udp_tiptr, udreq, NULL);
607 printf("osi_NetSend: t_ksndudata failed %d\n", code);
610 t_kfree(udp_tiptr, (caddr_t)udreq, T_UNITDATA);
615 int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
616 struct osi_socket *asocket;
617 struct sockaddr_in *addr;
623 TIUSER *udp_tiptr = (TIUSER *) asocket;
624 struct t_kunitdata *udreq;
638 * Allocate the unitdata structure.
640 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
642 printf("osi_NetReceive: t_kalloc failed %d\n", code);
645 udreq->addr.len = sizeof(struct sockaddr_in);
646 udreq->addr.maxlen = sizeof(struct sockaddr_in);
647 udreq->addr.buf = (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
649 udreq->opt.maxlen = 0;
652 * Loop until we get an error or receive some data.
656 * Wait until there is something to do
658 code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
660 osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
663 * If there is a message then read it in
666 code = t_krcvudata(udp_tiptr, udreq, &type, &error);
670 * Block attempts to kill this thread
672 if (code == EINTR && ISSIG(curthread, FORREAL)) {
673 klwp_t *lwp = ttolwp(curthread);
674 proc_t *p = ttoproc(curthread);
675 int sig = lwp->lwp_cursig;
677 if (sig == SIGKILL) {
678 mutex_enter(&p->p_lock);
679 p->p_flag &= ~SKILLED;
680 mutex_exit(&p->p_lock);
683 if (lwp->lwp_curinfo) {
684 kmem_free((caddr_t)lwp->lwp_curinfo, sizeof(*lwp->lwp_curinfo));
685 lwp->lwp_curinfo = NULL;
694 * Ignore non-data message types
696 if (type != T_DATA) {
701 * Save the source address
703 memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
706 * Copy out the message buffers, take care not to overflow
709 dbp = udreq->udata.udata_mp;
711 for (i = 0 ; dbp != NULL && length > 0 && i < nvecs ; i++) {
712 tlen = dvec[i].iov_len;
713 tbase = dvec[i].iov_base;
717 while (dbp != NULL && tlen > 0) {
718 blen = dbp->b_wptr - dbp->b_rptr;
720 memcpy(tbase, (char *)dbp->b_rptr, tlen);
725 memcpy(tbase, (char *)dbp->b_rptr, blen);
733 *alength = *alength - length;
737 t_kfree(udp_tiptr, (caddr_t)udreq, T_UNITDATA);
742 void osi_StopListener(void)
744 osi_FreeSocket(rx_socket);
748 void shutdown_rxkernel(void)
753 #endif /* AFS_SUN56_ENV */
754 #endif /* AFS_SUN5_ENV */