Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-5]: src/sys/net Pull up revisions 1.59-1.60, 1.62-1.65, 1.70 vi...



details:   https://anonhg.NetBSD.org/src/rev/6386725c3b1d
branches:  netbsd-1-5
changeset: 490458:6386725c3b1d
user:      jhawk <jhawk%NetBSD.org@localhost>
date:      Sun Dec 31 20:14:28 2000 +0000

description:
Pull up revisions 1.59-1.60, 1.62-1.65, 1.70 via patch (requested by bouyer):
        Add support for 802.1Q virtual LANs.

diffstat:

 sys/net/if_ethersubr.c |  276 ++++++++++++++++++++++++++++--------------------
 1 files changed, 158 insertions(+), 118 deletions(-)

diffs (truncated from 356 to 300 lines):

diff -r 6c2eef70d8d0 -r 6386725c3b1d sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c    Sun Dec 31 20:14:25 2000 +0000
+++ b/sys/net/if_ethersubr.c    Sun Dec 31 20:14:28 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ethersubr.c,v 1.58 2000/06/17 20:57:20 matt Exp $   */
+/*     $NetBSD: if_ethersubr.c,v 1.58.2.1 2000/12/31 20:14:28 jhawk Exp $      */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -71,6 +71,7 @@
 #include "opt_iso.h"
 #include "opt_ns.h"
 #include "opt_gateway.h"
+#include "vlan.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -93,6 +94,9 @@
 #include <net/if_types.h>
 
 #include <net/if_ether.h>
+#if NVLAN > 0
+#include <net/if_vlanvar.h>
+#endif
 
 #include <netinet/in.h>
 #ifdef INET
@@ -497,6 +501,7 @@
        u_int16_t etype;
        int s;
        struct ether_header *eh;
+       struct mbuf *n;
 #if defined (ISO) || defined (LLC) || defined(NETATALK)
        struct llc *l;
 #endif
@@ -507,6 +512,16 @@
        }
 
        eh = mtod(m, struct ether_header *);
+       etype = ntohs(eh->ether_type);
+
+       /*
+        * Determine if the packet is within its size limits.
+        */
+       if (m->m_pkthdr.len > ETHER_MAX_FRAME(etype, m->m_flags & M_HASFCS)) {
+               printf("%s: discarding oversize frame\n", ifp->if_xname);
+               m_freem(m);
+               return;
+       }
 
        ifp->if_lastchange = time;
        ifp->if_ibytes += m->m_pkthdr.len;
@@ -516,11 +531,50 @@
                        m->m_flags |= M_BCAST;
                else
                        m->m_flags |= M_MCAST;
+               ifp->if_imcasts++;
+       } else if ((ifp->if_flags & IFF_PROMISC) != 0 &&
+                  memcmp(LLADDR(ifp->if_sadl), eh->ether_dhost,
+                         ETHER_ADDR_LEN) != 0) {
+               m_freem(m);
+               return;
        }
-       if (m->m_flags & (M_BCAST|M_MCAST))
-               ifp->if_imcasts++;
+
+       /* Check if the mbuf has a VLAN tag */
+       n = m_aux_find(m, AF_LINK, ETHERTYPE_VLAN);
+       if (n) {
+#if NVLAN > 0
+               /*
+                * vlan_input() will either recursively call ether_input()
+                * or drop the packet.
+                */
+               if (((struct ethercom *)ifp)->ec_nvlans != 0)
+                       vlan_input(ifp, m);
+               else
+#endif
+                       m_freem(m);
+               return;
+       }
 
-       etype = ntohs(eh->ether_type);
+       /*
+        * Handle protocols that expect to have the Ethernet header
+        * (and possibly FCS) intact.
+        */
+       switch (etype) {
+#if NVLAN > 0
+       case ETHERTYPE_VLAN:
+               /*
+                * vlan_input() will either recursively call ether_input()
+                * or drop the packet.
+                */
+               if (((struct ethercom *)ifp)->ec_nvlans != 0)
+                       vlan_input(ifp, m);
+               else
+                       m_freem(m);
+               return;
+#endif /* NVLAN > 0 */
+       default:
+               /* Nothing. */
+       }
 
        /* Strip off the Ethernet header. */
        m_adj(m, sizeof(struct ether_header));
@@ -776,8 +830,27 @@
 void
 ether_ifdetach(struct ifnet *ifp)
 {
+       struct ethercom *ec = (void *) ifp;
+       struct sockaddr_dl *sdl = ifp->if_sadl;
+       struct ether_multi *enm;
+       int s;
 
-       /* Nothing. */
+#if NVLAN > 0
+       if (ec->ec_nvlans)
+               vlan_ifdetach(ifp);
+#endif
+
+       s = splimp();
+       while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) {
+               LIST_REMOVE(enm, enm_list);
+               free(enm, M_IFADDR);
+               ec->ec_multicnt--;
+       }
+       splx(s);
+
+       memset(LLADDR(sdl), 0, ETHER_ADDR_LEN);
+       sdl->sdl_alen = 0;
+       sdl->sdl_type = 0;
 }
 
 #if 0
@@ -862,6 +935,73 @@
 u_char ether_ip6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
 u_char ether_ip6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
 #endif
+
+/*
+ * Convert a sockaddr into an Ethernet address or range of Ethernet
+ * addresses.
+ */
+int
+ether_multiaddr(struct sockaddr *sa, u_int8_t addrlo[ETHER_ADDR_LEN],
+    u_int8_t addrhi[ETHER_ADDR_LEN])
+{
+#ifdef INET
+       struct sockaddr_in *sin;
+#endif /* INET */
+#ifdef INET6
+       struct sockaddr_in6 *sin6;
+#endif /* INET6 */
+
+       switch (sa->sa_family) {
+
+       case AF_UNSPEC:
+               bcopy(sa->sa_data, addrlo, ETHER_ADDR_LEN);
+               bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
+               break;
+
+#ifdef INET
+       case AF_INET:
+               sin = satosin(sa);
+               if (sin->sin_addr.s_addr == INADDR_ANY) {
+                       /*
+                        * An IP address of INADDR_ANY means listen to
+                        * or stop listening to all of the Ethernet
+                        * multicast addresses used for IP.
+                        * (This is for the sake of IP multicast routers.)
+                        */
+                       bcopy(ether_ipmulticast_min, addrlo, ETHER_ADDR_LEN);
+                       bcopy(ether_ipmulticast_max, addrhi, ETHER_ADDR_LEN);
+               }
+               else {
+                       ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
+                       bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
+               }
+               break;
+#endif
+#ifdef INET6
+       case AF_INET6:
+               sin6 = satosin6(sa);
+               if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+                       /*
+                        * An IP6 address of 0 means listen to or stop
+                        * listening to all of the Ethernet multicast
+                        * address used for IP6.
+                        * (This is used for multicast routers.)
+                        */
+                       bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
+                       bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
+               } else {
+                       ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
+                       bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
+               }
+               break;
+#endif
+
+       default:
+               return (EAFNOSUPPORT);
+       }
+       return (0);
+}
+
 /*
  * Add an Ethernet multicast address or range of addresses to the list for a
  * given interface.
@@ -870,66 +1010,14 @@
 ether_addmulti(struct ifreq *ifr, struct ethercom *ec)
 {
        struct ether_multi *enm;
-#ifdef INET
-       struct sockaddr_in *sin;
-#endif /* INET */
-#ifdef INET6
-       struct sockaddr_in6 *sin6;
-#endif /* INET6 */
-       u_char addrlo[6];
-       u_char addrhi[6];
-       int s = splimp();
-
-       switch (ifr->ifr_addr.sa_family) {
-
-       case AF_UNSPEC:
-               bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
-               bcopy(addrlo, addrhi, 6);
-               break;
+       u_char addrlo[ETHER_ADDR_LEN];
+       u_char addrhi[ETHER_ADDR_LEN];
+       int s = splimp(), error;
 
-#ifdef INET
-       case AF_INET:
-               sin = (struct sockaddr_in *)&(ifr->ifr_addr);
-               if (sin->sin_addr.s_addr == INADDR_ANY) {
-                       /*
-                        * An IP address of INADDR_ANY means listen to all
-                        * of the Ethernet multicast addresses used for IP.
-                        * (This is for the sake of IP multicast routers.)
-                        */
-                       bcopy(ether_ipmulticast_min, addrlo, 6);
-                       bcopy(ether_ipmulticast_max, addrhi, 6);
-               }
-               else {
-                       ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
-                       bcopy(addrlo, addrhi, 6);
-               }
-               break;
-#endif
-#ifdef INET6
-       case AF_INET6:
-               sin6 = (struct sockaddr_in6 *)
-                       &(((struct in6_ifreq *)ifr)->ifr_addr);
-               if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
-                       /*
-                        * An IP6 address of 0 means listen to all
-                        * of the Ethernet multicast address used for IP6.
-                        * (This is used for multicast routers.)
-                        */
-                       bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
-                       bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
-#if 0
-                       set_allmulti = 1;
-#endif
-               } else {
-                       ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
-                       bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
-               }
-               break;
-#endif
-
-       default:
+       error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
+       if (error != 0) {
                splx(s);
-               return (EAFNOSUPPORT);
+               return (error);
        }
 
        /*
@@ -981,66 +1069,18 @@
 ether_delmulti(struct ifreq *ifr, struct ethercom *ec)
 {
        struct ether_multi *enm;
-#ifdef INET
-       struct sockaddr_in *sin;
-#endif /* INET */
-#ifdef INET6
-       struct sockaddr_in6 *sin6;
-#endif /* INET6 */
-       u_char addrlo[6];
-       u_char addrhi[6];
-       int s = splimp();
-
-       switch (ifr->ifr_addr.sa_family) {
-
-       case AF_UNSPEC:
-               bcopy(ifr->ifr_addr.sa_data, addrlo, 6);



Home | Main Index | Thread Index | Old Index