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

Cache object: 3d395fa68ea38e1f308b23977ef12f4c


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