内核arp请求

Linux 内核 网络地址转换函数 in_aton、 in4_pton 和 in6_pton

#ifndef _LINUX_INET_H
#define _LINUX_INET_H
 
#include <linux/types.h>
 
/*
 * These mimic similar macros defined in user-space for inet_ntop(3).
 * See /usr/include/netinet/in.h .
 */
#define INET_ADDRSTRLEN        (16)
#define INET6_ADDRSTRLEN    (48)
 
extern __be32 in_aton(const char *str);
extern int in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
extern int in6_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
#endif    /* _LINUX_INET_H */
/**
 * in4_pton - convert an IPv4 address from literal to binary representation
 * @src: the start of the IPv4 address string ,地址字符串
 * @srclen: the length of the string, -1 means strlen(src),字符串长度,可以填写-1
 * @dst: the binary (u8[4] array) representation of the IPv4 address,地址缓存
 * @delim: the delimiter of the IPv4 address in @src, -1 means no delimiter,分隔符
 * @end: A pointer to the end of the parsed string will be placed here,可以填写NULL
 *
 * Return one on success, return zero when any error occurs
 * and @end will point to the end of the parsed string.
 *
 * 成功返回1,出错返回0
 */
int in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
 
用例:
    __be32 saddr;
    ret = in4_pton("192.168.1.1", strlen("192.168.1.1"), &addr, -1, NULL);

三个函数头文件都是<linux/inet.h>.,使用是只要包含该头文件就可以了。

arp_send_dst(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
             dst_hw, dev->dev_addr, NULL, dst);

dev_hard_header

dev->header_ops         = &eth_header_ops

static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
                  unsigned short type,
                  const void *daddr, const void *saddr,
                  unsigned int len)
{
    if (!dev->header_ops || !dev->header_ops->create)
        return 0;

    return dev->header_ops->create(skb, dev, type, daddr, saddr, len);
}
/**
 * eth_header - create the Ethernet header
 * @skb:    buffer to alter
 * @dev:    source device
 * @type:    Ethernet type field
 * @daddr: destination address (NULL leave destination address)
 * @saddr: source address (NULL use device source address)
 * @len:   packet length (<= skb->len)
 *
 *
 * Set the protocol type. For a packet of type ETH_P_802_3/2 we put the length
 * in here instead.
 */
int eth_header(struct sk_buff *skb, struct net_device *dev,
           unsigned short type,
           const void *daddr, const void *saddr, unsigned int len)
{
    struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
    if (type != ETH_P_802_3 && type != ETH_P_802_2)
        eth->h_proto = htons(type);
    else
        eth->h_proto = htons(len);
    /*
     *      Set the source hardware address.
     */
    if (!saddr)
        saddr = dev->dev_addr;
    memcpy(eth->h_source, saddr, ETH_ALEN);
    if (daddr) {
        memcpy(eth->h_dest, daddr, ETH_ALEN);
        return ETH_HLEN;
    }
    /*
     *      Anyway, the loopback-device should never use this function...
     */
    if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
        memset(eth->h_dest, 0, ETH_ALEN);
        return ETH_HLEN;
    }
    return -ETH_HLEN;
}

arp_create


     dev_kfree_skb_any(skb);
     //struct sk_buff *skb;
     __be32 src_addr, dst_addr;
     in4_pton("10.10.10.8", strlen(DEST_IP),(u8 *)&dst_addr, '\0', NULL);
     in4_pton("10.10.10.7", strlen(SRC_IP), (u8 *)&src_addr, '\0', NULL);
     skb = arp_create(ARPOP_REQUEST, ETH_P_ARP,  dst_addr, dev, src_addr,NULL, dev->dev_addr, NULL);
start_xmit(skb,dev);
/* Create and send an arp packet. */
static void arp_send_dst(int type, int ptype, __be32 dest_ip,
             struct net_device *dev, __be32 src_ip,
             const unsigned char *dest_hw,
             const unsigned char *src_hw,
             const unsigned char *target_hw,
             struct dst_entry *dst)
{
    struct sk_buff *skb;

    /* arp on this interface. */
    if (dev->flags & IFF_NOARP)
        return;

    skb = arp_create(type, ptype, dest_ip, dev, src_ip,
             dest_hw, src_hw, target_hw);
    if (!skb)
        return;

    skb_dst_set(skb, dst_clone(dst));
    arp_xmit(skb);
}

static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst)
{
        skb->_skb_refdst = (unsigned long)dst;
}
我们常见的IP地址都是以点分十进制格式表示,例如“172.18.1.231”。而在程序中基本是以如下的结构表示一个IP:

struct in_addr {
         __be32     s_addr; //其实就是一个32bit的数字
};


   它和点分十进制格式的IP地址可以通过一组API实现相互转换:

int inet_aton(const char *cp,struct in_addr *inp) 无效的地址cp则返回0;否则返回非0
char *inet_ntoa(struct in_addr in) 将一个32位的IP地址转换成点分十进制字符串。
原文地址:https://www.cnblogs.com/dream397/p/15598802.html