博客地址: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 '