• 通过IP获取MAC地址例子(内核层)


      博客地址:http://home.cnblogs.com/u/zengjianrong/

      在内核处理此流程,反而更加简单些,代码如下:

    #include <net/arp.h>
    #include <net/neighbour.h>
    #include "linux/ctype.h"
    
    #define MAC_BCAST_ADDR        (unsigned char *)"xffxffxffxffxffxff"
    
    /******************************************************************************
     * nArpTblCtl - find mac from arp_tbl by ip
     * DESCRIPTION: -  
     * Input: 
     * Output: 
     * Returns: -EAGAIN -- find nothing, but had send arp request.try again.
     *          -ENXIO  -- find nothing, and create error.
     *          0       -- find ok.
     * modification history
     * --------------------
     * 2.00, 2014-12-18 , zengjianrong written
     * --------------------
     ******************************************************************************/
    static int nArpTblCtl(struct net_device *dev, const __be32 s_addr_remote, const __be32 s_addr_local, const unsigned char *pucMac)
    {
        struct arpreq       arpreq;
        struct sockaddr_in  *sin = NULL;
        struct neighbour    *neigh = NULL;
        unsigned char       *hw_addr = NULL;  
        int                 err = -ENXIO; /* NO such device or address */
        
        if ((0 == s_addr_remote)
            || (NULL == pucMac)
            || (NULL == dev))
        {
            err = -EINVAL;/* INVALID ARGUMENT */
            return err;
        }
            
        memset(&arpreq, 0, sizeof(struct arpreq));    
        sin = (struct sockaddr_in *) &(arpreq.arp_pa);
        sin->sin_family = AF_INET;
        memcpy(&(sin->sin_addr.s_addr), &s_addr_remote, sizeof(__be32));
        strcpy(arpreq.arp_dev, dev->name);
        
        rtnl_lock();         
        if (neigh = neigh_lookup(&arp_tbl, &s_addr_remote, dev)) 
        {
            read_lock_bh(&neigh->lock);
            memcpy(arpreq.arp_ha.sa_data, neigh->ha, dev->addr_len);
            read_unlock_bh(&neigh->lock);
            neigh_release(neigh);
            
            hw_addr = (unsigned char *) arpreq.arp_ha.sa_data;
            memcpy(pucMac, hw_addr, 6);
            if (!(0 == pucMac[0] && 0 == pucMac[1] && 0 == pucMac[2] 
                  && 0== pucMac[3] && 0 == pucMac[4] && 0 == pucMac[5]))
            {
                err = 0;
            }
        }
        else
        { 
            if (neigh = neigh_create(&arp_tbl, &s_addr_remote, dev))
            {                       
                arp_send(ARPOP_REQUEST, ETH_P_ARP, s_addr_remote, netdev_eth1, s_addr_local,
                     MAC_BCAST_ADDR, netdev_eth1->dev_addr, NULL);     
                err = -EAGAIN;  /* try again */
            }
        }
        rtnl_unlock();
        
        return err;
    }
    static int inet_aton(cp, addr) const char *cp; struct in_addr *addr; { u_long parts[4]; uint32_t val; const char *c; char *endptr; int gotend, n; c = (const char *)cp; n = 0; /* * Run through the string, grabbing numbers until * the end of the string, or some error */ gotend = 0; while (!gotend) { unsigned long l; l = simple_strtoul(c, &endptr, 0); if (l == ULONG_MAX || (l == 0 && endptr == c)) return (0); val = (uint32_t)l; /* * If the whole string is invalid, endptr will equal * c.. this way we can make sure someone hasn't * gone '.12' or something which would get past * the next check. */ if (endptr == c) return (0); parts[n] = val; c = endptr; /* Check the next character past the previous number's end */ switch (*c) { case '.' : /* Make sure we only do 3 dots .. */ if (n == 3) /* Whoops. Quit. */ return (0); n++; c++; break; case '': gotend = 1; break; default: if (isspace((unsigned char)*c)) { gotend = 1; break; } else return (0); /* Invalid character, so fail */ } } /* * Concoct the address according to * the number of parts specified. */ switch (n) { case 0: /* a -- 32 bits */ /* * Nothing is necessary here. Overflow checking was * already done in strtoul(). */ break; case 1: /* a.b -- 8.24 bits */ if (val > 0xffffff || parts[0] > 0xff) return (0); val |= parts[0] << 24; break; case 2: /* a.b.c -- 8.8.16 bits */ if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff) return (0); val |= (parts[0] << 24) | (parts[1] << 16); break; case 3: /* a.b.c.d -- 8.8.8.8 bits */ if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xff) return (0); val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); break; } if (addr != NULL) addr->s_addr = htonl(val); return (1); } int nArpTestByZjr(void) { struct in_addr sin_local_addr; struct in_addr sin_remote_addr; unsigned char aucMac[6]; memset(aucMac, 0, 6); memset(&sin_remote_addr, 0, sizeof(struct in_addr)); if (0 == (inet_aton("200.31.96.225", &sin_remote_addr))) { printk("%s: IP address '200.31.96.225' not valid ", __FUNCTION__); return -1; } memset(&sin_local_addr, 0, sizeof(struct in_addr)); if (0 == (inet_aton("200.31.96.1", &sin_local_addr))) { printk("%s: IP address '200.31.96.1' not valid ", __FUNCTION__); return -1; } if (0 > nArpTblCtl(netdev_eth1, sin_remote_addr.s_addr, sin_local_addr.s_addr, &aucMac)) { printk("func:%s,line:%d, find nothing... ", __FUNCTION__, __LINE__); } else { printk("200.31.96.225-->%02x:%02x:%02x:%02x:%02x:%02x ", aucMac[0], aucMac[1], aucMac[2], aucMac[3], aucMac[4], aucMac[5]); } } EXPORT_SYMBOL(nArpTestByZjr);
  • 相关阅读:
    精细化python 类的内置属性
    python操作excel
    ghost linux
    Linux dd 命令
    Ubantu 使用root登陆的方法
    NSIS Error: "Error writing temporary file. Make sure your temp folder is valid
    error writing temporary file。make sure your temp folder is valid 问题已解决
    安卓电池状态监听
    Android源码下载
    vim插件详细安装过程
  • 原文地址:https://www.cnblogs.com/zengjianrong/p/4185454.html
Copyright © 2020-2023  润新知