solaris-x86-port-already-htons-20030414
[openafs.git] / src / rx / SOLARIS / rx_knet.c
index ef60c4f..a553d55 100644 (file)
@@ -1,40 +1,40 @@
 /*
-****************************************************************************
-*        Copyright IBM Corporation 1988, 1989 - All Rights Reserved        *
-*        Copyright Transarc Corporation 1989 - All Rights Reserved         *
-*                                                                          *
-* Permission to use, copy, modify, and distribute this software and its    *
-* documentation for any purpose and without fee is hereby granted,         *
-* provided that the above copyright notice appear in all copies and        *
-* that both that copyright notice and this permission notice appear in     *
-* supporting documentation, and that the name of IBM not be used in        *
-* advertising or publicity pertaining to distribution of the software      *
-* without specific, written prior permission.                              *
-*                                                                          *
-* IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
-* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY      *
-* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER  *
-* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING   *
-* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.    *
-****************************************************************************
-*/
-#include "../afs/param.h"
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afsconfig.h>
+#include "afs/param.h"
+
+RCSID("$Header$");
+
 #ifdef AFS_SUN5_ENV
-#include "../rx/rx_kcommon.h"
+#include "rx/rx_kcommon.h"
 
 
 #ifdef AFS_SUN56_ENV
 
-#include "../inet/common.h"
-#include "../sys/tiuser.h"
-#include "../sys/t_kuser.h"
-#include "../sys/stropts.h"
-#include "../sys/stream.h"
-#include "../sys/tihdr.h"
-#include "../sys/fcntl.h"
-#include "../inet/ip.h"
-#include "../netinet/udp.h"
+#include "inet/common.h"
+#include "sys/tiuser.h"
+#include "sys/t_kuser.h"
+#include "sys/stropts.h"
+#include "sys/stream.h"
+#include "sys/tihdr.h"
+#include "sys/fcntl.h"
+#ifdef AFS_SUN58_ENV
+#include "netinet/ip6.h"
+#define ipif_local_addr ipif_lcl_addr
+#ifndef V4_PART_OF_V6
+#define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
+#endif
+#endif
+#include "inet/ip.h"
+#include "inet/ip_if.h"
+#include "netinet/udp.h"
 
 /*
  * Function pointers for kernel socket routines
@@ -51,10 +51,140 @@ int (*sockfs_sosendmsg)
     (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
 int (*sockfs_sosetsockopt)
     (struct sonode *, int, int, void *, int) = NULL;
+int (*sockfs_sounbind)
+    (struct sonode *, int);
+void (*sockfs_sockfree)
+    (struct sonode *);
 
-int rxi_GetIFInfo()
+static afs_uint32 myNetAddrs[ADDRSPERSITE];
+static int myNetMTUs[ADDRSPERSITE];
+static int numMyNetAddrs = 0;
+
+int
+rxi_GetIFInfo()
 {
-    return 0;
+    int i = 0;
+    int different = 0;
+
+    ill_t *ill;
+    ipif_t *ipif;
+    int rxmtu, maxmtu;
+
+    int mtus[ADDRSPERSITE];
+    afs_uint32 addrs[ADDRSPERSITE];
+    afs_uint32 ifinaddr;
+
+    memset(mtus, 0, sizeof(mtus));
+    memset(addrs, 0, sizeof(addrs));
+
+    for (ill = ill_g_head; ill; ill = ill->ill_next) {
+#ifdef AFS_SUN58_ENV
+       /* Make sure this is an IPv4 ILL */
+       if (ill->ill_isv6) continue;
+#endif
+
+       /* Iterate over all the addresses on this ILL */
+       for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
+           if (i >= ADDRSPERSITE) break;
+
+           /* Ignore addresses which are down.. */
+           if (!(ipif->ipif_flags & IFF_UP)) continue;
+
+           /* Compute the Rx interface MTU */
+           rxmtu = (ipif->ipif_mtu - RX_IPUDP_SIZE);
+
+           ifinaddr = ntohl(ipif->ipif_local_addr);
+           if (myNetAddrs[i] != ifinaddr)
+               different++;
+
+           /* Copy interface MTU and address; adjust maxmtu */
+           mtus[i] = rxmtu;
+           rxmtu = rxi_AdjustIfMTU(rxmtu);
+           maxmtu = rxmtu * rxi_nRecvFrags + ((rxi_nRecvFrags-1) *
+                                              UDP_HDR_SIZE);
+           maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
+           addrs[i] = ifinaddr;
+           i++;
+
+           if (ifinaddr != 0x7f000001 && maxmtu > rx_maxReceiveSize) {
+               rx_maxReceiveSize = MIN( RX_MAX_PACKET_SIZE, maxmtu);
+               rx_maxReceiveSize = MIN( rx_maxReceiveSize,
+                                        rx_maxReceiveSizeUser);
+           }
+       }
+    }
+
+    rx_maxJumboRecvSize = RX_HEADER_SIZE +
+                         rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
+                         (rxi_nDgramPackets-1) * RX_JUMBOHEADERSIZE;
+    rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
+
+    if (different) {
+       int j;
+
+       for (j = 0; j < i; j++) {
+           myNetMTUs[j] = mtus[j];
+           myNetAddrs[j] = addrs[j];
+       }
+    }
+
+    return different;
+}
+
+int rxi_FindIfMTU(afs_uint32 addr)
+{
+    ill_t *ill;
+    ipif_t *ipif;
+    afs_uint32 myAddr, netMask;
+    int match_value = 0;
+    int mtu = -1;
+
+    if (numMyNetAddrs == 0)
+       rxi_GetIFInfo();
+    myAddr = ntohl(addr);
+
+    if      (IN_CLASSA(myAddr)) netMask = IN_CLASSA_NET;
+    else if (IN_CLASSB(myAddr)) netMask = IN_CLASSB_NET;
+    else if (IN_CLASSC(myAddr)) netMask = IN_CLASSC_NET;
+    else                       netMask = 0;
+
+    for (ill = ill_g_head; ill; ill = ill->ill_next) {
+#ifdef AFS_SUN58_ENV
+       /* Make sure this is an IPv4 ILL */
+       if (ill->ill_isv6) continue;
+#endif
+
+       /* Iterate over all the addresses on this ILL */
+       for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
+           afs_uint32 thisAddr, subnetMask;
+           int thisMtu;
+
+           thisAddr   = ipif->ipif_local_addr;
+           subnetMask = ipif->ipif_net_mask;
+           thisMtu    = ipif->ipif_mtu;
+
+           if ((myAddr & netMask) == (thisAddr & netMask)) {
+               if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
+                   if (myAddr == thisAddr) {
+                       match_value = 4;
+                       mtu = thisMtu;
+                   }
+
+                   if (match_value < 3) {
+                       match_value = 3;
+                       mtu = thisMtu;
+                   }
+               }
+
+               if (match_value < 2) {
+                   match_value = 2;
+                   mtu = thisMtu;
+               }
+           }
+       }
+    }
+
+    return mtu;
 }
 
 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
@@ -110,6 +240,16 @@ struct osi_socket *rxk_NewSocket(short aport)
            return NULL;
        }
     }
+    if (sockfs_sounbind == NULL) {
+       sockfs_sounbind = (int (*)())modlookup("sockfs", "sounbind");
+       if (sockfs_sounbind == NULL)
+           return NULL;
+    }
+    if (sockfs_sockfree == NULL) {
+       sockfs_sockfree = (void (*)())modlookup("sockfs", "sockfree");
+       if (sockfs_sockfree == NULL)
+           return NULL;
+    }
 
     accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
     if (accessvp == NULL) {
@@ -145,26 +285,35 @@ struct osi_socket *rxk_NewSocket(short aport)
     return (struct osi_socket *)so;
 }
 
-int osi_FreeSocket(asocket)
-    register struct osi_socket *asocket; 
+int osi_FreeSocket(register struct osi_socket *asocket)
 {
     extern int rxk_ListenerPid;
     struct sonode *so = (struct sonode *)asocket;
-    vnode_t *vp = SOTOV(so);
+    struct sockaddr_in taddr;
+    struct iovec dvec;
+    char c;
 
     AFS_STATCNT(osi_FreeSocket);
-    if (rxk_ListenerPid)
-       kill(rxk_ListenerPid, SIGUSR1);
+
+    taddr.sin_family = AF_INET;
+    taddr.sin_port = rx_port;
+    taddr.sin_addr.s_addr = htonl(0x7f000001);
+
+    dvec.iov_base = &c;
+    dvec.iov_len = 1;
+
+    while (rxk_ListenerPid) {
+       osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
+       afs_osi_Sleep(&rxk_ListenerPid);
+    }
+
+    sockfs_sounbind(so, 0);
+    sockfs_sockfree(so);
     return 0;
 }
 
-int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack) 
-    struct osi_socket *asocket;
-    struct sockaddr_in *addr; 
-    struct iovec dvec[];
-    int nvecs;
-    afs_int32 asize;
-    int istack;
+int osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, 
+       struct iovec *dvec, int nvecs, afs_int32 asize, int istack) 
 {
     struct sonode *so = (struct sonode *)asocket;
     struct nmsghdr msg;
@@ -202,14 +351,10 @@ int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
     return error;
 }
 
-int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
-    struct osi_socket *asocket;
-    struct sockaddr_in *addr;
-    struct iovec *dvec;
-    int nvecs;
-    int *alength;
-{
-    struct sonode *so = (struct sonode *)asocket;
+int osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
+        int nvecs, int *alength)
+{  
+    struct sonode *asocket = (struct sonode *)so;
     struct nmsghdr msg;
     struct uio uio;
     struct iovec iov[RX_MAXIOVECS];
@@ -240,12 +385,12 @@ int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
     uio.uio_limit = 0;
     uio.uio_resid = *alength;
 
-    error = sockfs_sorecvmsg(so, &msg, &uio);
+    error = sockfs_sorecvmsg(asocket, &msg, &uio);
     if (error == 0) {
        if (msg.msg_name == NULL) {
            error = -1;
        } else {
-           bcopy(msg.msg_name, addr, msg.msg_namelen);
+           memcpy(addr, msg.msg_name, msg.msg_namelen);
            kmem_free(msg.msg_name, msg.msg_namelen);
            *alength = *alength - uio.uio_resid;
        }
@@ -282,22 +427,22 @@ void osi_StopListener(void)
 
 #else /* AFS_SUN56_ENV */
 
-#include "../inet/common.h"
-#include "../sys/tiuser.h"
-#include "../sys/t_kuser.h"
-#include "../sys/ioctl.h"
-#include "../sys/stropts.h"
-#include "../sys/stream.h"
-#include "../sys/strsubr.h"
-#include "../sys/vnode.h"
-#include "../sys/stropts.h"
-#include "../sys/tihdr.h"
-#include "../sys/timod.h"
-#include "../sys/fcntl.h"
-#include "../sys/debug.h"
-#include "../inet/common.h"
-#include "../inet/mi.h"
-#include "../netinet/udp.h"
+#include "inet/common.h"
+#include "sys/tiuser.h"
+#include "sys/t_kuser.h"
+#include "sys/ioctl.h"
+#include "sys/stropts.h"
+#include "sys/stream.h"
+#include "sys/strsubr.h"
+#include "sys/vnode.h"
+#include "sys/stropts.h"
+#include "sys/tihdr.h"
+#include "sys/timod.h"
+#include "sys/fcntl.h"
+#include "sys/debug.h"
+#include "inet/common.h"
+#include "inet/mi.h"
+#include "netinet/udp.h"
 
 extern dev_t afs_udp_rdev;
 
@@ -355,7 +500,7 @@ struct osi_socket *rxk_NewSocket(short aport)
        t_kclose(udp_tiptr, 0);
        return (struct osi_socket *)0;
     }
-    if (bcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
+    if (memcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
        t_kfree(udp_tiptr, (char *)reqp, T_BIND);
        t_kfree(udp_tiptr, (char *)rspp, T_BIND);
        t_kclose(udp_tiptr, 0);
@@ -377,26 +522,22 @@ struct osi_socket *rxk_NewSocket(short aport)
 }
 
 
-int osi_FreeSocket(asocket)
-    register struct osi_socket *asocket; 
+int osi_FreeSocket(register struct osi_socket *asocket)
 {
     extern int rxk_ListenerPid;
     TIUSER *udp_tiptr = (TIUSER *) asocket;    
     AFS_STATCNT(osi_FreeSocket);
 
-    if (rxk_ListenerPid)
+    if (rxk_ListenerPid) {
        kill(rxk_ListenerPid, SIGUSR1);
+       afs_osi_Sleep(&rxk_ListenerPid);
+    }
     return 0;
 }
 
 
-int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack) 
-    register struct osi_socket *asocket;
-    struct iovec dvec[];
-    int nvecs;
-    register afs_int32 asize;
-    struct sockaddr_in *addr; 
-    int istack;
+int osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, 
+               struct iovec *dvec, int nvecs, afs_int32 asize, int istack) 
 {
     int i;
     int code;
@@ -427,7 +568,7 @@ int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
     }
 
     /* Copy the data into the buffer */
-    bcopy((char *)dvec[0].iov_base, (char *)bp->b_wptr, dvec[0].iov_len);
+    memcpy((char *)bp->b_wptr, (char *)dvec[0].iov_base, dvec[0].iov_len);
     bp->b_datap->db_type = M_DATA;
     bp->b_wptr += dvec[0].iov_len;
 
@@ -444,7 +585,7 @@ int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
        }
 
        /* Copy the data into the buffer */
-       bcopy((char *)dvec[i].iov_base, (char *)dbp->b_wptr, dvec[i].iov_len);
+       memcpy((char *)dbp->b_wptr, (char *)dvec[i].iov_base, dvec[i].iov_len);
        dbp->b_datap->db_type = M_DATA;
        dbp->b_wptr += dvec[i].iov_len;
 
@@ -466,7 +607,7 @@ int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
     udreq->addr.buf = (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
     udreq->opt.len = 0;
     udreq->opt.maxlen = 0;
-    bcopy((char *)&sin, udreq->addr.buf, sizeof(struct sockaddr_in));
+    memcpy(udreq->addr.buf, (char *)&sin, sizeof(struct sockaddr_in));
     udreq->udata.udata_mp = bp;
     udreq->udata.len = asize;
 
@@ -480,12 +621,8 @@ int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
 }
 
 
-int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
-    struct osi_socket *asocket;
-    struct sockaddr_in *addr;
-    struct iovec *dvec;
-    int nvecs;
-    int *alength;
+int osi_NetReceive(struct osi_socket *asocket, struct sockaddr_in *addr, 
+       struct iovec *dvec, int nvecs, int *alength)
 {
     int i;
     TIUSER *udp_tiptr = (TIUSER *) asocket;    
@@ -568,7 +705,7 @@ int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
        /*
         * Save the source address
         */
-       bcopy(udreq->addr.buf, (char *)addr, sizeof(struct sockaddr_in));
+       memcpy((char *)addr, udreq->addr.buf, sizeof(struct sockaddr_in));
 
        /*
         * Copy out the message buffers, take care not to overflow
@@ -585,12 +722,12 @@ int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
            while (dbp != NULL && tlen > 0) {
                blen = dbp->b_wptr - dbp->b_rptr;
                if (blen > tlen) {
-                   bcopy((char *)dbp->b_rptr, tbase, tlen);
+                   memcpy(tbase, (char *)dbp->b_rptr, tlen);
                    length -= tlen;
                    dbp->b_rptr += tlen;
                    tlen = 0;
                } else {
-                   bcopy((char *)dbp->b_rptr, tbase, blen);
+                   memcpy(tbase, (char *)dbp->b_rptr, blen);
                    length -= blen;
                    tlen -= blen;
                    tbase += blen;