zoukankan      html  css  js  c++  java
  • ARP输入 之 arp_process

    概述

    arp_process为ARP输入包的核心处理流程;

    若输入为ARP请求且查路由成功,则进行如下判断:输入到本地,则进行应答;否则,允许转发,则转发,本文代码不包含转发流程;

    若输入为ARP应答或者查路由失败,则更新邻居项;

    源码分析
      1 static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
      2 {
      3     struct net_device *dev = skb->dev;
      4     struct in_device *in_dev = __in_dev_get_rcu(dev);
      5     struct arphdr *arp;
      6     unsigned char *arp_ptr;
      7     struct rtable *rt;
      8     unsigned char *sha;
      9     unsigned char *tha = NULL;
     10     __be32 sip, tip;
     11     u16 dev_type = dev->type;
     12     int addr_type;
     13     struct neighbour *n;
     14     struct dst_entry *reply_dst = NULL;
     15     bool is_garp = false;
     16 
     17     /* arp_rcv below verifies the ARP header and verifies the device
     18      * is ARP'able.
     19      */
     20     /* 获取ip配置块 */
     21     if (!in_dev)
     22         goto out_free_skb;
     23 
     24     /* 获取arp头 */
     25     arp = arp_hdr(skb);
     26 
     27     /* 根据设备类型做检查 */
     28     switch (dev_type) {
     29     default:
     30         if (arp->ar_pro != htons(ETH_P_IP) ||
     31             htons(dev_type) != arp->ar_hrd)
     32             goto out_free_skb;
     33         break;
     34     case ARPHRD_ETHER:
     35     case ARPHRD_FDDI:
     36     case ARPHRD_IEEE802:
     37         /*
     38          * ETHERNET, and Fibre Channel (which are IEEE 802
     39          * devices, according to RFC 2625) devices will accept ARP
     40          * hardware types of either 1 (Ethernet) or 6 (IEEE 802.2).
     41          * This is the case also of FDDI, where the RFC 1390 says that
     42          * FDDI devices should accept ARP hardware of (1) Ethernet,
     43          * however, to be more robust, we'll accept both 1 (Ethernet)
     44          * or 6 (IEEE 802.2)
     45          */
     46         if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
     47              arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
     48             arp->ar_pro != htons(ETH_P_IP))
     49             goto out_free_skb;
     50         break;
     51     case ARPHRD_AX25:
     52         if (arp->ar_pro != htons(AX25_P_IP) ||
     53             arp->ar_hrd != htons(ARPHRD_AX25))
     54             goto out_free_skb;
     55         break;
     56     case ARPHRD_NETROM:
     57         if (arp->ar_pro != htons(AX25_P_IP) ||
     58             arp->ar_hrd != htons(ARPHRD_NETROM))
     59             goto out_free_skb;
     60         break;
     61     }
     62 
     63     /* Understand only these message types */
     64     
     65     /* 操作码不是应答也不是请求 */
     66     if (arp->ar_op != htons(ARPOP_REPLY) &&
     67         arp->ar_op != htons(ARPOP_REQUEST))
     68         goto out_free_skb;
     69 
     70 /*
     71  *    Extract fields
     72  */
     73     /* 获取arp指针 */
     74     arp_ptr = (unsigned char *)(arp + 1);
     75     /* 源mac */
     76     sha    = arp_ptr;
     77     /* 源ip */
     78     arp_ptr += dev->addr_len;
     79     memcpy(&sip, arp_ptr, 4);
     80     arp_ptr += 4;
     81 
     82     /* 设备类型 */
     83     switch (dev_type) {
     84 #if IS_ENABLED(CONFIG_FIREWIRE_NET)
     85     case ARPHRD_IEEE1394:
     86         break;
     87 #endif
     88     default:
     89         /* 目的mac */
     90         tha = arp_ptr;
     91         arp_ptr += dev->addr_len;
     92     }
     93     /* 目的ip */
     94     memcpy(&tip, arp_ptr, 4);
     95 /*
     96  *    Check for bad requests for 127.x.x.x and requests for multicast
     97  *    addresses.  If this is one such, delete it.
     98  */
     99     /* 目的ip是组播||回环地址但是没有启用route_localnet */
    100     if (ipv4_is_multicast(tip) ||
    101         (!IN_DEV_ROUTE_LOCALNET(in_dev) && ipv4_is_loopback(tip)))
    102         goto out_free_skb;
    103 
    104  /*
    105   *    For some 802.11 wireless deployments (and possibly other networks),
    106   *    there will be an ARP proxy and gratuitous ARP frames are attacks
    107   *    and thus should not be accepted.
    108   */
    109     /* 源ip和目的ip相同,设置了免费arp丢包 */
    110     if (sip == tip && IN_DEV_ORCONF(in_dev, DROP_GRATUITOUS_ARP))
    111         goto out_free_skb;
    112 
    113 /*
    114  *     Special case: We must set Frame Relay source Q.922 address
    115  */
    116     /* 设备类型为q.922,则设置源地址为广播地址 */
    117     if (dev_type == ARPHRD_DLCI)
    118         sha = dev->broadcast;
    119 
    120 /*
    121  *  Process entry.  The idea here is we want to send a reply if it is a
    122  *  request for us or if it is a request for someone else that we hold
    123  *  a proxy for.  We want to add an entry to our cache if it is a reply
    124  *  to us or if it is a request for our address.
    125  *  (The assumption for this last is that if someone is requesting our
    126  *  address, they are probably intending to talk to us, so it saves time
    127  *  if we cache their address.  Their address is also probably not in
    128  *  our cache, since ours is not in their cache.)
    129  *
    130  *  Putting this another way, we only care about replies if they are to
    131  *  us, in which case we add them to the cache.  For requests, we care
    132  *  about those for us and those for our proxies.  We reply to both,
    133  *  and in the case of requests for us we add the requester to the arp
    134  *  cache.
    135  */
    136 
    137     if (arp->ar_op == htons(ARPOP_REQUEST) && skb_metadata_dst(skb))
    138         reply_dst = (struct dst_entry *)
    139                 iptunnel_metadata_reply(skb_metadata_dst(skb),
    140                             GFP_ATOMIC);
    141 
    142     /* Special case: IPv4 duplicate address detection packet (RFC2131) */
    143     /* 源ip为0,用于检测地址冲突 */
    144     if (sip == 0) {
    145         /* ARP请求 && 地址是本地地址 && 不忽略该ARP请求,则发送ARP应答 */
    146         if (arp->ar_op == htons(ARPOP_REQUEST) &&
    147             inet_addr_type_dev_table(net, dev, tip) == RTN_LOCAL &&
    148             !arp_ignore(in_dev, sip, tip))
    149             arp_send_dst(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip,
    150                      sha, dev->dev_addr, sha, reply_dst);
    151         goto out_consume_skb;
    152     }
    153 
    154     /* ARP请求 && 查路由成功 */
    155     if (arp->ar_op == htons(ARPOP_REQUEST) &&
    156         ip_route_input_noref(skb, tip, sip, 0, dev) == 0) {
    157 
    158         /* 获取路由缓存 */
    159         rt = skb_rtable(skb);
    160         addr_type = rt->rt_type;
    161 
    162         /* 输入到本地 */
    163         if (addr_type == RTN_LOCAL) {
    164             int dont_send;
    165 
    166             /* 忽略检查 */
    167             dont_send = arp_ignore(in_dev, sip, tip);
    168 
    169             /* 不忽略,配置了过滤,则判断过滤 */
    170             if (!dont_send && IN_DEV_ARPFILTER(in_dev))
    171                 dont_send = arp_filter(sip, tip, dev);
    172             /* 允许输入 */
    173             if (!dont_send) {
    174                 /* 查找邻居项,更新状态 */
    175                 n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
    176 
    177                 /* 邻居项存在,则回复ARP应答 */
    178                 if (n) {
    179                     arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
    180                              sip, dev, tip, sha,
    181                              dev->dev_addr, sha,
    182                              reply_dst);
    183                     neigh_release(n);
    184                 }
    185             }
    186             goto out_consume_skb;
    187         } else if (IN_DEV_FORWARD(in_dev)) {
    188             /* ARP代理 */
    189         }
    190     }
    191 
    192    /* ARP应答或者查路由失败 */
    193 
    194     /* Update our ARP tables */
    195     /* 查找邻居项 */
    196     n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
    197 
    198     addr_type = -1;
    199     /* 邻居项存在,或者启用了接收非请求应答 */
    200     if (n || IN_DEV_ARP_ACCEPT(in_dev)) {
    201         /* 检查是否为免费ARP */
    202         is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
    203                       sip, tip, sha, tha);
    204     }
    205 
    206     /* 启用了接收非请求应答 */
    207     if (IN_DEV_ARP_ACCEPT(in_dev)) {
    208         /* Unsolicited ARP is not accepted by default.
    209            It is possible, that this option should be enabled for some
    210            devices (strip is candidate)
    211          */
    212         /*
    213           邻居项不存在,免费ARP || 邻居项不存在,不是免费ARP,则类型为应答,且为单播
    214           创建邻居项
    215         */
    216         if (!n &&
    217             (is_garp ||
    218              (arp->ar_op == htons(ARPOP_REPLY) &&
    219               (addr_type == RTN_UNICAST ||
    220                (addr_type < 0 &&
    221             /* postpone calculation to as late as possible */
    222             inet_addr_type_dev_table(net, dev, sip) ==
    223                 RTN_UNICAST)))))
    224             n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
    225     }
    226 
    227     /* 存在邻居表项 */
    228     if (n) {
    229         int state = NUD_REACHABLE;
    230         int override;
    231 
    232         /* If several different ARP replies follows back-to-back,
    233            use the FIRST one. It is possible, if several proxy
    234            agents are active. Taking the first reply prevents
    235            arp trashing and chooses the fastest router.
    236          */
    237         /* 当前时间超过了下次更新时间 或者 为免费ARP */
    238         override = time_after(jiffies,
    239                       n->updated +
    240                       NEIGH_VAR(n->parms, LOCKTIME)) ||
    241                is_garp;
    242 
    243         /* Broadcast replies and request packets
    244            do not assert neighbour reachability.
    245          */
    246         /* 不是ARP应答,或者不是本机包,设置状态为STALE */
    247         if (arp->ar_op != htons(ARPOP_REPLY) ||
    248             skb->pkt_type != PACKET_HOST)
    249             state = NUD_STALE;
    250         /* 更新邻居项 */
    251         neigh_update(n, sha, state,
    252                  override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0);
    253         neigh_release(n);
    254     }
    255 
    256 out_consume_skb:
    257     consume_skb(skb);
    258 
    259 out_free_dst:
    260     dst_release(reply_dst);
    261     return NET_RX_SUCCESS;
    262 
    263 out_free_skb:
    264     kfree_skb(skb);
    265     return NET_RX_DROP;
    266 }
  • 相关阅读:
    HDU 5273 Dylans loves sequence 暴力递推
    HDU 5285 wyh2000 and pupil 判二分图+贪心
    HDU 5281 Senior's Gun 贪心
    HDU 5651 xiaoxin juju needs help 逆元
    HDU 5646 DZY Loves Partition
    HDU 5366 The mook jong
    HDU 5391Z ball in Tina Town 数论
    HDU 5418 Victor and World 允许多次经过的TSP
    HDU 5642 King's Order dp
    抽屉原理
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11755428.html
Copyright © 2011-2022 走看看