The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/net/if_ethersubr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * Copyright (c) 1982, 1989, 1993
   27  *      The Regents of the University of California.  All rights reserved.
   28  *
   29  * Redistribution and use in source and binary forms, with or without
   30  * modification, are permitted provided that the following conditions
   31  * are met:
   32  * 1. Redistributions of source code must retain the above copyright
   33  *    notice, this list of conditions and the following disclaimer.
   34  * 2. Redistributions in binary form must reproduce the above copyright
   35  *    notice, this list of conditions and the following disclaimer in the
   36  *    documentation and/or other materials provided with the distribution.
   37  * 3. All advertising materials mentioning features or use of this software
   38  *    must display the following acknowledgement:
   39  *      This product includes software developed by the University of
   40  *      California, Berkeley and its contributors.
   41  * 4. Neither the name of the University nor the names of its contributors
   42  *    may be used to endorse or promote products derived from this software
   43  *    without specific prior written permission.
   44  *
   45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   55  * SUCH DAMAGE.
   56  *
   57  *      @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
   58  * $FreeBSD: src/sys/net/if_ethersubr.c,v 1.70.2.17 2001/08/01 00:47:49 fenner Exp $
   59  */
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/kernel.h>
   64 #include <sys/malloc.h>
   65 #include <sys/mbuf.h>
   66 #include <sys/socket.h>
   67 #include <sys/sockio.h>
   68 #include <sys/sysctl.h>
   69 
   70 #include <net/if.h>
   71 #include <net/netisr.h>
   72 #include <net/route.h>
   73 #include <net/if_llc.h>
   74 #include <net/if_dl.h>
   75 #include <net/if_types.h>
   76 
   77 #if INET || INET6
   78 #include <netinet/in.h>
   79 #include <netinet/in_var.h>
   80 #include <netinet/if_ether.h>
   81 #include <netinet/in_systm.h>
   82 #include <netinet/ip.h>
   83 #endif
   84 
   85 #if IPX
   86 #include <netipx/ipx.h>
   87 #include <netipx/ipx_if.h>
   88 #endif
   89 
   90 #include <sys/socketvar.h>
   91 
   92 #if LLC && CCITT
   93 extern struct ifqueue pkintrq;
   94 #endif
   95 
   96 #if BRIDGE
   97 #include <net/bridge.h>
   98 #endif
   99 
  100 /* #include "vlan.h" */
  101 #if NVLAN > 0
  102 #include <net/if_vlan_var.h>
  103 #endif /* NVLAN > 0 */
  104 
  105 extern u_char   etherbroadcastaddr[];
  106 #define senderr(e) do { error = (e); goto bad;} while (0)
  107 #define IFP2AC(IFP) ((struct arpcom *)IFP)
  108 
  109 /*
  110  * Perform common duties while attaching to interface list
  111  */
  112 
  113 
  114 /* 
  115     IONetworkingFamily should call dlil_if_attach
  116     ether_ifattach becomes obsolete, but remains for
  117     temporary compatibility with third parties extensions
  118 */
  119 void
  120 ether_ifattach(ifp)
  121         register struct ifnet *ifp;
  122 {
  123         boolean_t funnel_state;
  124 
  125         funnel_state = thread_funnel_set(network_flock, TRUE);
  126 
  127         ifp->if_name = "en";
  128         ifp->if_family = APPLE_IF_FAM_ETHERNET;
  129         ifp->if_type = IFT_ETHER;
  130         ifp->if_addrlen = 6;
  131         ifp->if_hdrlen = 14;
  132         ifp->if_mtu = ETHERMTU;
  133         if (ifp->if_baudrate == 0)
  134             ifp->if_baudrate = 10000000;
  135 
  136         dlil_if_attach(ifp);
  137         (void) thread_funnel_set(network_flock, funnel_state);
  138 }
  139 
  140 SYSCTL_DECL(_net_link);
  141 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
  142 
  143 int
  144 ether_resolvemulti(ifp, llsa, sa)
  145         struct ifnet *ifp;
  146         struct sockaddr **llsa;
  147         struct sockaddr *sa;
  148 {
  149         struct sockaddr_dl *sdl;
  150         struct sockaddr_in *sin;
  151         u_char *e_addr;
  152 #if INET6
  153         struct sockaddr_in6 *sin6;
  154 #endif
  155 
  156 
  157         switch(sa->sa_family) {
  158         case AF_UNSPEC:
  159                 /* AppleTalk uses AF_UNSPEC for multicast registration.
  160                  * No mapping needed. Just check that it's a valid MC address.
  161                  */
  162                 e_addr = &sa->sa_data[0];
  163                 if ((e_addr[0] & 1) != 1)
  164                         return EADDRNOTAVAIL;
  165                 *llsa = 0;
  166                 return 0;
  167 
  168         case AF_LINK:
  169                 /* 
  170                  * No mapping needed. Just check that it's a valid MC address.
  171                  */
  172                 sdl = (struct sockaddr_dl *)sa;
  173                 e_addr = LLADDR(sdl);
  174                 if ((e_addr[0] & 1) != 1)
  175                         return EADDRNOTAVAIL;
  176                 *llsa = 0;
  177                 return 0;
  178 
  179 #if INET
  180         case AF_INET:
  181                 sin = (struct sockaddr_in *)sa;
  182                 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
  183                         return EADDRNOTAVAIL;
  184                 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
  185                        M_WAITOK);
  186                 sdl->sdl_len = sizeof *sdl;
  187                 sdl->sdl_family = AF_LINK;
  188                 sdl->sdl_index = ifp->if_index;
  189                 sdl->sdl_type = IFT_ETHER;
  190                 sdl->sdl_nlen = 0;
  191                 sdl->sdl_alen = ETHER_ADDR_LEN;
  192                 sdl->sdl_slen = 0;
  193                 e_addr = LLADDR(sdl);
  194                 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
  195                 *llsa = (struct sockaddr *)sdl;
  196                 return 0;
  197 #endif
  198 #if INET6
  199         case AF_INET6:
  200                 sin6 = (struct sockaddr_in6 *)sa;
  201                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  202                         /*
  203                          * An IP6 address of 0 means listen to all
  204                          * of the Ethernet multicast address used for IP6.
  205                          * (This is used for multicast routers.)
  206                          */
  207                         ifp->if_flags |= IFF_ALLMULTI;
  208                         *llsa = 0;
  209                         return 0;
  210                 }
  211                 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
  212                        M_WAITOK);
  213                 sdl->sdl_len = sizeof *sdl;
  214                 sdl->sdl_family = AF_LINK;
  215                 sdl->sdl_index = ifp->if_index;
  216                 sdl->sdl_type = IFT_ETHER;
  217                 sdl->sdl_nlen = 0;
  218                 sdl->sdl_alen = ETHER_ADDR_LEN;
  219                 sdl->sdl_slen = 0;
  220                 e_addr = LLADDR(sdl);
  221                 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
  222                 kprintf("ether_resolvemulti Adding %x:%x:%x:%x:%x:%x\n",
  223                                 e_addr[0], e_addr[1], e_addr[2], e_addr[3], e_addr[4], e_addr[5]);
  224                 *llsa = (struct sockaddr *)sdl;
  225                 return 0;
  226 #endif
  227 
  228         default:
  229                 /* 
  230                  * Well, the text isn't quite right, but it's the name
  231                  * that counts...
  232                  */
  233                 return EAFNOSUPPORT;
  234         }
  235 }
  236 
  237 
  238 
  239 
  240 
  241 u_char  ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
  242 u_char  ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
  243 /*
  244  * Add an Ethernet multicast address or range of addresses to the list for a
  245  * given interface.
  246  */
  247 int
  248 ether_addmulti(ifr, ac)
  249         struct ifreq *ifr;
  250         register struct arpcom *ac;
  251 {
  252         register struct ether_multi *enm;
  253         struct sockaddr_in *sin;
  254         u_char addrlo[6];
  255         u_char addrhi[6];
  256         int s = splimp();
  257 
  258         switch (ifr->ifr_addr.sa_family) {
  259 
  260         case AF_UNSPEC:
  261                 bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
  262                 bcopy(addrlo, addrhi, 6);
  263                 break;
  264 
  265 #if INET
  266         case AF_INET:
  267                 sin = (struct sockaddr_in *)&(ifr->ifr_addr);
  268                 if (sin->sin_addr.s_addr == INADDR_ANY) {
  269                         /*
  270                          * An IP address of INADDR_ANY means listen to all
  271                          * of the Ethernet multicast addresses used for IP.
  272                          * (This is for the sake of IP multicast routers.)
  273                          */
  274                         bcopy(ether_ipmulticast_min, addrlo, 6);
  275                         bcopy(ether_ipmulticast_max, addrhi, 6);
  276                 }
  277                 else {
  278                         ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
  279                         bcopy(addrlo, addrhi, 6);
  280                 }
  281                 break;
  282 #endif
  283 
  284         default:
  285                 splx(s);
  286                 return (EAFNOSUPPORT);
  287         }
  288 
  289         /*
  290          * Verify that we have valid Ethernet multicast addresses.
  291          */
  292         if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
  293                 splx(s);
  294                 return (EINVAL);
  295         }
  296         /*
  297          * See if the address range is already in the list.
  298          */
  299         ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
  300         if (enm != NULL) {
  301                 /*
  302                  * Found it; just increment the reference count.
  303                  */
  304                 ++enm->enm_refcount;
  305                 splx(s);
  306                 return (0);
  307         }
  308         /*
  309          * New address or range; malloc a new multicast record
  310          * and link it into the interface's multicast list.
  311          */
  312         enm = (struct ether_multi *)_MALLOC(sizeof(*enm), M_IFMADDR, M_WAITOK);
  313         if (enm == NULL) {
  314                 splx(s);
  315                 return (ENOBUFS);
  316         }
  317         bcopy(addrlo, enm->enm_addrlo, 6);
  318         bcopy(addrhi, enm->enm_addrhi, 6);
  319         enm->enm_ac = ac;
  320         enm->enm_refcount = 1;
  321         enm->enm_next = ac->ac_multiaddrs;
  322         ac->ac_multiaddrs = enm;
  323         splx(s);
  324         /*
  325          * Return ENETRESET to inform the driver that the list has changed
  326          * and its reception filter should be adjusted accordingly.
  327          */
  328         return (ENETRESET);
  329 }
  330 
  331 /*
  332  * Delete a multicast address record.
  333  */
  334 int
  335 ether_delmulti(ifr, ac, ret_mca)
  336         struct ifreq *ifr;
  337         register struct arpcom *ac;
  338         struct ether_addr * ret_mca;
  339 {
  340         register struct ether_multi *enm;
  341         register struct ether_multi **p;
  342         struct sockaddr_in *sin;
  343         u_char addrlo[6];
  344         u_char addrhi[6];
  345         int s = splimp();
  346 
  347         switch (ifr->ifr_addr.sa_family) {
  348 
  349         case AF_UNSPEC:
  350                 bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
  351                 bcopy(addrlo, addrhi, 6);
  352                 break;
  353 
  354 #if INET
  355         case AF_INET:
  356                 sin = (struct sockaddr_in *)&(ifr->ifr_addr);
  357                 if (sin->sin_addr.s_addr == INADDR_ANY) {
  358                         /*
  359                          * An IP address of INADDR_ANY means stop listening
  360                          * to the range of Ethernet multicast addresses used
  361                          * for IP.
  362                          */
  363                         bcopy(ether_ipmulticast_min, addrlo, 6);
  364                         bcopy(ether_ipmulticast_max, addrhi, 6);
  365                 }
  366                 else {
  367                         ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
  368                         bcopy(addrlo, addrhi, 6);
  369                 }
  370                 break;
  371 #endif
  372 
  373         default:
  374                 splx(s);
  375                 return (EAFNOSUPPORT);
  376         }
  377 
  378         /*
  379          * Look up the address in our list.
  380          */
  381         ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
  382         if (enm == NULL) {
  383                 splx(s);
  384                 return (ENXIO);
  385         }
  386         if (--enm->enm_refcount != 0) {
  387                 /*
  388                  * Still some claims to this record.
  389                  */
  390                 splx(s);
  391                 return (0);
  392         }
  393 
  394         /* save the low and high address of the range before deletion */
  395         if (ret_mca) {
  396                 *ret_mca        = *((struct ether_addr *)addrlo);
  397                 *(ret_mca + 1)  = *((struct ether_addr *)addrhi);
  398         }
  399 
  400         /*
  401          * No remaining claims to this record; unlink and free it.
  402          */
  403         for (p = &enm->enm_ac->ac_multiaddrs;
  404              *p != enm;
  405              p = &(*p)->enm_next)
  406                 continue;
  407         *p = (*p)->enm_next;
  408         FREE(enm, M_IFMADDR);
  409         splx(s);
  410         /*
  411          * Return ENETRESET to inform the driver that the list has changed
  412          * and its reception filter should be adjusted accordingly.
  413          */
  414         return (ENETRESET);
  415 }
  416 
  417 /*
  418  * Convert Ethernet address to printable (loggable) representation.
  419  */
  420 static u_char digits[] = "0123456789abcdef";
  421 char *
  422 ether_sprintf(p, ap)
  423         register u_char *p;
  424         register u_char *ap;
  425 {       register char *cp;
  426         register i;
  427 
  428         for (cp = p, i = 0; i < 6; i++) {
  429                 *cp++ = digits[*ap >> 4];
  430                 *cp++ = digits[*ap++ & 0xf];
  431                 *cp++ = ':';
  432         }
  433         *--cp = 0;
  434         return (p);
  435 }

Cache object: a43dd7bdc903d4ad11d2e8f3cbd8fb64


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.