icmp works with tcp and friends
[unix-history] / usr / src / sys / net / if.c
index 6d12908..ee6ef4f 100644 (file)
@@ -1,20 +1,39 @@
-/*     if.c    4.7     82/02/03        */
+/*     if.c    4.14    82/04/24        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
+#include "../h/socket.h"
+#include "../h/protosw.h"
 #include "../net/in.h"
 #include "../net/in_systm.h"
 #include "../net/if.h"
 #include "../net/in.h"
 #include "../net/in_systm.h"
 #include "../net/if.h"
+#include "../net/af.h"
+
+int    ifqmaxlen = IFQ_MAXLEN;
+
+/*
+ * Network interface utility routines.
+ *
+ * Routines with if_ifwith* names take sockaddr *'s as
+ * parameters.  Other routines take value parameters,
+ * e.g. if_ifwithnet takes the network number.
+ */
 
 ifinit()
 {
        register struct ifnet *ifp;
 
        for (ifp = ifnet; ifp; ifp = ifp->if_next)
 
 ifinit()
 {
        register struct ifnet *ifp;
 
        for (ifp = ifnet; ifp; ifp = ifp->if_next)
-               if (ifp->if_init)
-                       (*ifp->if_init)();
+               if (ifp->if_init) {
+                       (*ifp->if_init)(ifp->if_unit);
+                       if (ifp->if_snd.ifq_maxlen == 0)
+                               ifp->if_snd.ifq_maxlen = ifqmaxlen;
+               }
 }
 
 }
 
+/*
+ * Call each interface on a Unibus reset.
+ */
 ifubareset(uban)
        int uban;
 {
 ifubareset(uban)
        int uban;
 {
@@ -25,55 +44,112 @@ ifubareset(uban)
                        (*ifp->if_ubareset)(uban);
 }
 
                        (*ifp->if_ubareset)(uban);
 }
 
+/*
+ * Attach an interface to the
+ * list of "active" interfaces.
+ */
 if_attach(ifp)
        struct ifnet *ifp;
 {
 if_attach(ifp)
        struct ifnet *ifp;
 {
+       register struct ifnet **p = &ifnet;
 
 COUNT(IF_ATTACH);
 
 COUNT(IF_ATTACH);
-       ifp->if_next = ifnet;
-       ifnet = ifp;
+       while (*p)
+               p = &((*p)->if_next);
+       *p = ifp;
 }
 
 }
 
+/*
+ * Locate an interface based on a complete address.
+ */
 /*ARGSUSED*/
 struct ifnet *
 /*ARGSUSED*/
 struct ifnet *
-if_ifwithaddr(in)
-       struct in_addr in;
+if_ifwithaddr(addr)
+       struct sockaddr *addr;
 {
        register struct ifnet *ifp;
 
 COUNT(IF_IFWITHADDR);
 {
        register struct ifnet *ifp;
 
 COUNT(IF_IFWITHADDR);
-       for (ifp = ifnet; ifp; ifp = ifp->if_next)
-               if (ifp->if_addr.s_addr == in.s_addr)
+#define        equal(a1, a2) \
+       (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0)
+       for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+               if (ifp->if_addr.sa_family != addr->sa_family)
+                       continue;
+               if (equal(&ifp->if_addr, addr))
+                       break;
+               if ((ifp->if_flags & IFF_BROADCAST) &&
+                   equal(&ifp->if_broadaddr, addr))
                        break;
                        break;
+       }
        return (ifp);
 }
 
        return (ifp);
 }
 
-/*ARGSUSED*/
+/*
+ * Find an interface on a specific network.  If many, choice
+ * is first found.
+ */
+struct ifnet *
+if_ifwithnet(addr)
+       register struct sockaddr *addr;
+{
+       register struct ifnet *ifp;
+       register int af = addr->sa_family;
+       register int (*netmatch)() = afswitch[af].af_netmatch;
+
+       for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+               if (af != ifp->if_addr.sa_family)
+                       continue;
+               if ((*netmatch)(addr, &ifp->if_addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * As above, but parameter is network number.
+ */
 struct ifnet *
 struct ifnet *
-if_ifonnetof(in)
-       struct in_addr in;
+if_ifonnetof(net)
+       register int net;
 {
        register struct ifnet *ifp;
 {
        register struct ifnet *ifp;
-       int net;
 
 
-COUNT(IF_IFONNETOF);
-       net = in.s_net;                 /* XXX */
        for (ifp = ifnet; ifp; ifp = ifp->if_next)
                if (ifp->if_net == net)
                        break;
        return (ifp);
 }
 
        for (ifp = ifnet; ifp; ifp = ifp->if_next)
                if (ifp->if_net == net)
                        break;
        return (ifp);
 }
 
-/*ARGSUSED*/
+/*
+ * Find an interface using a specific address family
+ */
 struct ifnet *
 struct ifnet *
-if_gatewayfor(addr)
-       struct in_addr addr;
+if_ifwithaf(af)
+       register int af;
 {
 {
+       register struct ifnet *ifp;
 
 
-COUNT(IF_GATEWAYFOR);
-       return (0);
+       for (ifp = ifnet; ifp; ifp = ifp->if_next)
+               if (ifp->if_addr.sa_family == af)
+                       break;
+       return (ifp);
 }
 
 }
 
+/*
+ * Mark an interface down and notify protocols of
+ * the transition.
+ */
+if_down(ifp)
+       register struct ifnet *ifp;
+{
+       ifp->if_flags &= ~IFF_UP;
+       pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr);
+}
+
+/*
+ * Formulate an Internet address from network + host.  Used in
+ * building addresses stored in the ifnet structure.
+ */
 struct in_addr
 if_makeaddr(net, host)
        int net, host;
 struct in_addr
 if_makeaddr(net, host)
        int net, host;
@@ -91,3 +167,22 @@ if_makeaddr(net, host)
 #endif
        return (*(struct in_addr *)&addr);
 }
 #endif
        return (*(struct in_addr *)&addr);
 }
+
+/*
+ * Initialize an interface's routing
+ * table entry according to the network.
+ * INTERNET SPECIFIC.
+ */
+if_rtinit(ifp, flags)
+       register struct ifnet *ifp;
+       int flags;
+{
+       struct sockaddr_in sin;
+
+       if (ifp->if_flags & IFF_ROUTE)
+               return;
+       bzero((caddr_t)&sin, sizeof (sin));
+       sin.sin_family = AF_INET;
+       sin.sin_addr = if_makeaddr(ifp->if_net, 0);
+       rtinit(&sin, &ifp->if_addr, flags);
+}