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/netatalk/aarp.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) 2004-2005 Robert N. M. Watson
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 /*-
   27  * Copyright (c) 1990,1991,1994 Regents of The University of Michigan.
   28  * All Rights Reserved.
   29  *
   30  * Permission to use, copy, modify, and distribute this software and
   31  * its documentation for any purpose and without fee is hereby granted,
   32  * provided that the above copyright notice appears in all copies and
   33  * that both that copyright notice and this permission notice appear
   34  * in supporting documentation, and that the name of The University
   35  * of Michigan not be used in advertising or publicity pertaining to
   36  * distribution of the software without specific, written prior
   37  * permission. This software is supplied as is without expressed or
   38  * implied warranties of any kind.
   39  *
   40  * This product includes software developed by the University of
   41  * California, Berkeley and its contributors.
   42  *
   43  *      Research Systems Unix Group
   44  *      The University of Michigan
   45  *      c/o Wesley Craig
   46  *      535 W. William Street
   47  *      Ann Arbor, Michigan
   48  *      +1-313-764-2278
   49  *      netatalk@umich.edu
   50  *
   51  * $FreeBSD$
   52  */
   53 
   54 #include "opt_atalk.h"
   55 #include "opt_mac.h"
   56 
   57 #include <sys/param.h>
   58 #include <sys/systm.h>
   59 #include <sys/mac.h>
   60 #include <sys/mbuf.h>
   61 #include <sys/kernel.h>
   62 #include <sys/socket.h>
   63 #include <sys/syslog.h>
   64 
   65 #include <net/if.h>
   66 
   67 #include <netinet/in.h>
   68 #undef s_net
   69 #include <netinet/if_ether.h>
   70 
   71 #include <netatalk/at.h>
   72 #include <netatalk/at_var.h>
   73 #include <netatalk/aarp.h>
   74 #include <netatalk/phase2.h>
   75 #include <netatalk/at_extern.h>
   76 
   77 static void aarptfree(struct aarptab *aat);
   78 static void at_aarpinput(struct ifnet *ifp, struct mbuf *m);
   79 
   80 #define AARPTAB_BSIZ    9
   81 #define AARPTAB_NB      19
   82 #define AARPTAB_SIZE    (AARPTAB_BSIZ * AARPTAB_NB)
   83 static struct aarptab   aarptab[AARPTAB_SIZE];
   84 
   85 struct mtx aarptab_mtx;
   86 MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF);
   87 
   88 #define AARPTAB_HASH(a) \
   89     ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB)
   90 
   91 #define AARPTAB_LOOK(aat, addr) { \
   92     int         n; \
   93     AARPTAB_LOCK_ASSERT(); \
   94     aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
   95     for (n = 0; n < AARPTAB_BSIZ; n++, aat++) \
   96         if (aat->aat_ataddr.s_net == (addr).s_net && \
   97              aat->aat_ataddr.s_node == (addr).s_node) \
   98             break; \
   99         if (n >= AARPTAB_BSIZ) \
  100             aat = NULL; \
  101 }
  102 
  103 #define AARPT_AGE       (60 * 1)
  104 #define AARPT_KILLC     20
  105 #define AARPT_KILLI     3
  106 
  107 # if !defined(__FreeBSD__)
  108 extern u_char                   etherbroadcastaddr[6];
  109 # endif /* __FreeBSD__ */
  110 
  111 static const u_char atmulticastaddr[ 6 ] = {
  112     0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
  113 };
  114 
  115 u_char  at_org_code[ 3 ] = {
  116     0x08, 0x00, 0x07,
  117 };
  118 const u_char    aarp_org_code[ 3 ] = {
  119     0x00, 0x00, 0x00,
  120 };
  121 
  122 static struct callout_handle aarptimer_ch =
  123     CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
  124 
  125 static void
  126 aarptimer(void *ignored)
  127 {
  128     struct aarptab      *aat;
  129     int                 i;
  130 
  131     aarptimer_ch = timeout(aarptimer, (caddr_t)0, AARPT_AGE * hz);
  132     aat = aarptab;
  133     AARPTAB_LOCK();
  134     for (i = 0; i < AARPTAB_SIZE; i++, aat++) {
  135         if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM))
  136             continue;
  137         if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ?
  138                 AARPT_KILLC : AARPT_KILLI))
  139             continue;
  140         aarptfree(aat);
  141     }
  142     AARPTAB_UNLOCK();
  143 }
  144 
  145 /* 
  146  * search through the network addresses to find one that includes
  147  * the given network.. remember to take netranges into
  148  * consideration.
  149  */
  150 struct at_ifaddr *
  151 at_ifawithnet(struct sockaddr_at  *sat)
  152 {
  153     struct at_ifaddr    *aa;
  154     struct sockaddr_at  *sat2;
  155 
  156         for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
  157                 sat2 = &(aa->aa_addr);
  158                 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) {
  159                         break;
  160                 }
  161                 if((aa->aa_flags & AFA_PHASE2)
  162                 && (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net))
  163                 && (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) {
  164                         break;
  165                 }
  166         }
  167         return (aa);
  168 }
  169 
  170 static void
  171 aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat)
  172 {
  173     struct mbuf         *m;
  174     struct ether_header *eh;
  175     struct ether_aarp   *ea;
  176     struct at_ifaddr    *aa;
  177     struct llc          *llc;
  178     struct sockaddr     sa;
  179 
  180     AARPTAB_UNLOCK_ASSERT();
  181     if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
  182         return;
  183     }
  184 #ifdef MAC
  185     mac_create_mbuf_linklayer(ifp, m);
  186 #endif
  187     m->m_len = sizeof(*ea);
  188     m->m_pkthdr.len = sizeof(*ea);
  189     MH_ALIGN(m, sizeof(*ea));
  190 
  191     ea = mtod(m, struct ether_aarp *);
  192     bzero((caddr_t)ea, sizeof(*ea));
  193 
  194     ea->aarp_hrd = htons(AARPHRD_ETHER);
  195     ea->aarp_pro = htons(ETHERTYPE_AT);
  196     ea->aarp_hln = sizeof(ea->aarp_sha);
  197     ea->aarp_pln = sizeof(ea->aarp_spu);
  198     ea->aarp_op = htons(AARPOP_REQUEST);
  199     bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
  200             sizeof(ea->aarp_sha));
  201 
  202     /*
  203      * We need to check whether the output ethernet type should
  204      * be phase 1 or 2. We have the interface that we'll be sending
  205      * the aarp out. We need to find an AppleTalk network on that
  206      * interface with the same address as we're looking for. If the
  207      * net is phase 2, generate an 802.2 and SNAP header.
  208      */
  209     if ((aa = at_ifawithnet(sat)) == NULL) {
  210         m_freem(m);
  211         return;
  212     }
  213 
  214     eh = (struct ether_header *)sa.sa_data;
  215 
  216     if (aa->aa_flags & AFA_PHASE2) {
  217         bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
  218         eh->ether_type = htons(sizeof(struct llc) + sizeof(struct ether_aarp));
  219         M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
  220         if (m == NULL) {
  221             return;
  222         }
  223         llc = mtod(m, struct llc *);
  224         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  225         llc->llc_control = LLC_UI;
  226         bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
  227         llc->llc_ether_type = htons(ETHERTYPE_AARP);
  228 
  229         bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
  230                sizeof(ea->aarp_spnet));
  231         bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet,
  232                sizeof(ea->aarp_tpnet));
  233         ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node;
  234         ea->aarp_tpnode = sat->sat_addr.s_node;
  235     } else {
  236         bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
  237                 sizeof(eh->ether_dhost));
  238         eh->ether_type = htons(ETHERTYPE_AARP);
  239 
  240         ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node;
  241         ea->aarp_tpa = sat->sat_addr.s_node;
  242     }
  243 
  244 #ifdef NETATALKDEBUG
  245     printf("aarp: sending request for %u.%u\n",
  246            ntohs(AA_SAT(aa)->sat_addr.s_net),
  247            AA_SAT(aa)->sat_addr.s_node);
  248 #endif /* NETATALKDEBUG */
  249 
  250     sa.sa_len = sizeof(struct sockaddr);
  251     sa.sa_family = AF_UNSPEC;
  252     ifp->if_output(ifp, m, &sa, NULL /* route */);
  253 }
  254 
  255 int
  256 aarpresolve(ifp, m, destsat, desten)
  257     struct ifnet        *ifp;
  258     struct mbuf         *m;
  259     struct sockaddr_at  *destsat;
  260     u_char              *desten;
  261 {
  262     struct at_ifaddr    *aa;
  263     struct aarptab      *aat;
  264 
  265     if (at_broadcast(destsat)) {
  266         m->m_flags |= M_BCAST;
  267         if ((aa = at_ifawithnet(destsat)) == NULL)  {
  268             m_freem(m);
  269             return (0);
  270         }
  271         if (aa->aa_flags & AFA_PHASE2) {
  272             bcopy(atmulticastaddr, (caddr_t)desten, sizeof(atmulticastaddr));
  273         } else {
  274             bcopy(ifp->if_broadcastaddr, (caddr_t)desten,
  275                     sizeof(ifp->if_addrlen));
  276         }
  277         return (1);
  278     }
  279 
  280     AARPTAB_LOCK();
  281     AARPTAB_LOOK(aat, destsat->sat_addr);
  282     if (aat == NULL) {                  /* No entry */
  283         aat = aarptnew(&destsat->sat_addr);
  284         if (aat == NULL) { /* we should fail more gracefully! */
  285             panic("aarpresolve: no free entry");
  286         }
  287         goto done;
  288     }
  289     /* found an entry */
  290     aat->aat_timer = 0;
  291     if (aat->aat_flags & ATF_COM) {     /* entry is COMplete */
  292         bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten,
  293                 sizeof(aat->aat_enaddr));
  294         AARPTAB_UNLOCK();
  295         return (1);
  296     }
  297     /* entry has not completed */
  298     if (aat->aat_hold) {
  299         m_freem(aat->aat_hold);
  300     }
  301 done:
  302     aat->aat_hold = m;
  303     AARPTAB_UNLOCK();
  304     aarpwhohas(ifp, destsat);
  305     return (0);
  306 }
  307 
  308 void
  309 aarpintr(m)
  310     struct mbuf         *m;
  311 {
  312     struct arphdr       *ar;
  313     struct ifnet        *ifp;
  314 
  315     ifp = m->m_pkthdr.rcvif;
  316     if (ifp->if_flags & IFF_NOARP)
  317         goto out;
  318 
  319     if (m->m_len < sizeof(struct arphdr)) {
  320         goto out;
  321     }
  322 
  323     ar = mtod(m, struct arphdr *);
  324     if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) {
  325         goto out;
  326     }
  327     
  328     if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln +
  329             2 * ar->ar_pln) {
  330         goto out;
  331     }
  332     
  333     switch(ntohs(ar->ar_pro)) {
  334     case ETHERTYPE_AT :
  335         at_aarpinput(ifp, m);
  336         return;
  337 
  338     default:
  339         break;
  340     }
  341 
  342 out:
  343     m_freem(m);
  344 }
  345 
  346 static void
  347 at_aarpinput(struct ifnet *ifp, struct mbuf *m)
  348 {
  349     struct ether_aarp   *ea;
  350     struct at_ifaddr    *aa;
  351     struct aarptab      *aat;
  352     struct ether_header *eh;
  353     struct llc          *llc;
  354     struct sockaddr_at  sat;
  355     struct sockaddr     sa;
  356     struct at_addr      spa, tpa, ma;
  357     int                 op;
  358     u_short             net;
  359 
  360     ea = mtod(m, struct ether_aarp *);
  361 
  362     /* Check to see if from my hardware address */
  363     if (!bcmp((caddr_t)ea->aarp_sha, IFP2ENADDR(ifp),
  364             sizeof(IFP2ENADDR(ifp)))) {
  365         m_freem(m);
  366         return;
  367     }
  368 
  369     op = ntohs(ea->aarp_op);
  370     bcopy(ea->aarp_tpnet, &net, sizeof(net));
  371 
  372     if (net != 0) { /* should be ATADDR_ANYNET? */
  373         sat.sat_len = sizeof(struct sockaddr_at);
  374         sat.sat_family = AF_APPLETALK;
  375         sat.sat_addr.s_net = net;
  376         if ((aa = at_ifawithnet(&sat)) == NULL) {
  377             m_freem(m);
  378             return;
  379         }
  380         bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net));
  381         bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net));
  382     } else {
  383         /*
  384          * Since we don't know the net, we just look for the first
  385          * phase 1 address on the interface.
  386          */
  387         for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
  388                 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
  389             if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
  390                     (aa->aa_flags & AFA_PHASE2) == 0) {
  391                 break;
  392             }
  393         }
  394         if (aa == NULL) {
  395             m_freem(m);
  396             return;
  397         }
  398         tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
  399     }
  400 
  401     spa.s_node = ea->aarp_spnode;
  402     tpa.s_node = ea->aarp_tpnode;
  403     ma.s_net = AA_SAT(aa)->sat_addr.s_net;
  404     ma.s_node = AA_SAT(aa)->sat_addr.s_node;
  405 
  406     /*
  407      * This looks like it's from us.
  408      */
  409     if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
  410         if (aa->aa_flags & AFA_PROBING) {
  411             /*
  412              * We're probing, someone either responded to our probe, or
  413              * probed for the same address we'd like to use. Change the
  414              * address we're probing for.
  415              */
  416             callout_stop(&aa->aa_callout);
  417             wakeup(aa);
  418             m_freem(m);
  419             return;
  420         } else if (op != AARPOP_PROBE) {
  421             /*
  422              * This is not a probe, and we're not probing. This means
  423              * that someone's saying they have the same source address
  424              * as the one we're using. Get upset...
  425              */
  426             log(LOG_ERR,
  427                     "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
  428                     ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
  429                     ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
  430             m_freem(m);
  431             return;
  432         }
  433     }
  434 
  435     AARPTAB_LOCK();
  436     AARPTAB_LOOK(aat, spa);
  437     if (aat != NULL) {
  438         if (op == AARPOP_PROBE) {
  439             /*
  440              * Someone's probing for spa, dealocate the one we've got,
  441              * so that if the prober keeps the address, we'll be able
  442              * to arp for him.
  443              */
  444             aarptfree(aat);
  445             AARPTAB_UNLOCK();
  446             m_freem(m);
  447             return;
  448         }
  449 
  450         bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
  451                 sizeof(ea->aarp_sha));
  452         aat->aat_flags |= ATF_COM;
  453         if (aat->aat_hold) {
  454             struct mbuf *mhold = aat->aat_hold;
  455             aat->aat_hold = NULL;
  456             AARPTAB_UNLOCK();
  457             sat.sat_len = sizeof(struct sockaddr_at);
  458             sat.sat_family = AF_APPLETALK;
  459             sat.sat_addr = spa;
  460             (*ifp->if_output)(ifp, mhold,
  461                     (struct sockaddr *)&sat, NULL); /* XXX */
  462         } else
  463             AARPTAB_UNLOCK();
  464     } else if ((tpa.s_net == ma.s_net)
  465            && (tpa.s_node == ma.s_node)
  466            && (op != AARPOP_PROBE)
  467            && ((aat = aarptnew(&spa)) != NULL)) {
  468                 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
  469                     sizeof(ea->aarp_sha));
  470                 aat->aat_flags |= ATF_COM;
  471                 AARPTAB_UNLOCK();
  472     } else
  473         AARPTAB_UNLOCK();
  474 
  475     /*
  476      * Don't respond to responses, and never respond if we're
  477      * still probing.
  478      */
  479     if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
  480             op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
  481         m_freem(m);
  482         return;
  483     }
  484 
  485     bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha,
  486             sizeof(ea->aarp_sha));
  487     bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
  488             sizeof(ea->aarp_sha));
  489 
  490     /* XXX */
  491     eh = (struct ether_header *)sa.sa_data;
  492     bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost,
  493             sizeof(eh->ether_dhost));
  494 
  495     if (aa->aa_flags & AFA_PHASE2) {
  496         eh->ether_type = htons(sizeof(struct llc) +
  497                 sizeof(struct ether_aarp));
  498         M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
  499         if (m == NULL) {
  500             return;
  501         }
  502         llc = mtod(m, struct llc *);
  503         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  504         llc->llc_control = LLC_UI;
  505         bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
  506         llc->llc_ether_type = htons(ETHERTYPE_AARP);
  507 
  508         bcopy(ea->aarp_spnet, ea->aarp_tpnet, sizeof(ea->aarp_tpnet));
  509         bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet));
  510     } else {
  511         eh->ether_type = htons(ETHERTYPE_AARP);
  512     }
  513 
  514     ea->aarp_tpnode = ea->aarp_spnode;
  515     ea->aarp_spnode = ma.s_node;
  516     ea->aarp_op = htons(AARPOP_RESPONSE);
  517 
  518     sa.sa_len = sizeof(struct sockaddr);
  519     sa.sa_family = AF_UNSPEC;
  520     (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
  521     return;
  522 }
  523 
  524 static void
  525 aarptfree(struct aarptab *aat)
  526 {
  527 
  528     AARPTAB_LOCK_ASSERT();
  529     if (aat->aat_hold)
  530         m_freem(aat->aat_hold);
  531     aat->aat_hold = NULL;
  532     aat->aat_timer = aat->aat_flags = 0;
  533     aat->aat_ataddr.s_net = 0;
  534     aat->aat_ataddr.s_node = 0;
  535 }
  536 
  537 struct aarptab *
  538 aarptnew(addr)
  539     struct at_addr      *addr;
  540 {
  541     int                 n;
  542     int                 oldest = -1;
  543     struct aarptab      *aat, *aato = NULL;
  544     static int          first = 1;
  545 
  546     AARPTAB_LOCK_ASSERT();
  547     if (first) {
  548         first = 0;
  549         aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz);
  550     }
  551     aat = &aarptab[ AARPTAB_HASH(*addr) * AARPTAB_BSIZ ];
  552     for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
  553         if (aat->aat_flags == 0)
  554             goto out;
  555         if (aat->aat_flags & ATF_PERM)
  556             continue;
  557         if ((int) aat->aat_timer > oldest) {
  558             oldest = aat->aat_timer;
  559             aato = aat;
  560         }
  561     }
  562     if (aato == NULL)
  563         return (NULL);
  564     aat = aato;
  565     aarptfree(aat);
  566 out:
  567     aat->aat_ataddr = *addr;
  568     aat->aat_flags = ATF_INUSE;
  569     return (aat);
  570 }
  571 
  572 
  573 void
  574 aarpprobe(void *arg)
  575 {
  576     struct ifnet        *ifp = arg;
  577     struct mbuf         *m;
  578     struct ether_header *eh;
  579     struct ether_aarp   *ea;
  580     struct at_ifaddr    *aa;
  581     struct llc          *llc;
  582     struct sockaddr     sa;
  583 
  584     /*
  585      * We need to check whether the output ethernet type should
  586      * be phase 1 or 2. We have the interface that we'll be sending
  587      * the aarp out. We need to find an AppleTalk network on that
  588      * interface with the same address as we're looking for. If the
  589      * net is phase 2, generate an 802.2 and SNAP header.
  590      */
  591     AARPTAB_LOCK();
  592     for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
  593             aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
  594         if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
  595                 (aa->aa_flags & AFA_PROBING)) {
  596             break;
  597         }
  598     }
  599     if (aa == NULL) {           /* serious error XXX */
  600         AARPTAB_UNLOCK();
  601         printf("aarpprobe why did this happen?!\n");
  602         return;
  603     }
  604 
  605     if (aa->aa_probcnt <= 0) {
  606         aa->aa_flags &= ~AFA_PROBING;
  607         wakeup(aa);
  608         AARPTAB_UNLOCK();
  609         return;
  610     } else {
  611         callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp);
  612     }
  613     AARPTAB_UNLOCK();
  614 
  615     if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
  616         return;
  617     }
  618 #ifdef MAC
  619     mac_create_mbuf_linklayer(ifp, m);
  620 #endif
  621     m->m_len = sizeof(*ea);
  622     m->m_pkthdr.len = sizeof(*ea);
  623     MH_ALIGN(m, sizeof(*ea));
  624 
  625     ea = mtod(m, struct ether_aarp *);
  626     bzero((caddr_t)ea, sizeof(*ea));
  627 
  628     ea->aarp_hrd = htons(AARPHRD_ETHER);
  629     ea->aarp_pro = htons(ETHERTYPE_AT);
  630     ea->aarp_hln = sizeof(ea->aarp_sha);
  631     ea->aarp_pln = sizeof(ea->aarp_spu);
  632     ea->aarp_op = htons(AARPOP_PROBE);
  633     bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
  634             sizeof(ea->aarp_sha));
  635 
  636     eh = (struct ether_header *)sa.sa_data;
  637 
  638     if (aa->aa_flags & AFA_PHASE2) {
  639         bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
  640         eh->ether_type = htons(sizeof(struct llc) +
  641                 sizeof(struct ether_aarp));
  642         M_PREPEND(m, sizeof(struct llc), M_TRYWAIT);
  643         if (m == NULL) {
  644             return;
  645         }
  646         llc = mtod(m, struct llc *);
  647         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  648         llc->llc_control = LLC_UI;
  649         bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
  650         llc->llc_ether_type = htons(ETHERTYPE_AARP);
  651 
  652         bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
  653                 sizeof(ea->aarp_spnet));
  654         bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet,
  655                 sizeof(ea->aarp_tpnet));
  656         ea->aarp_spnode = ea->aarp_tpnode = AA_SAT(aa)->sat_addr.s_node;
  657     } else {
  658         bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
  659                 sizeof(eh->ether_dhost));
  660         eh->ether_type = htons(ETHERTYPE_AARP);
  661         ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node;
  662     }
  663 
  664 #ifdef NETATALKDEBUG
  665     printf("aarp: sending probe for %u.%u\n",
  666            ntohs(AA_SAT(aa)->sat_addr.s_net),
  667            AA_SAT(aa)->sat_addr.s_node);
  668 #endif /* NETATALKDEBUG */
  669 
  670     sa.sa_len = sizeof(struct sockaddr);
  671     sa.sa_family = AF_UNSPEC;
  672     (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
  673     aa->aa_probcnt--;
  674 }
  675 
  676 void
  677 aarp_clean(void)
  678 {
  679     struct aarptab      *aat;
  680     int                 i;
  681 
  682     untimeout(aarptimer, 0, aarptimer_ch);
  683     AARPTAB_LOCK();
  684     for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) {
  685         if (aat->aat_hold) {
  686             m_freem(aat->aat_hold);
  687             aat->aat_hold = NULL;
  688         }
  689     }
  690     AARPTAB_UNLOCK();
  691 }

Cache object: 9ed62c42adb5a1404efd59c9b6e16bc7


[ 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.