内核arp请求
Linux 内核 网络地址转换函数 in_aton、 in4_pton 和 in6_pton
#ifndef _LINUX_INET_H #define _LINUX_INET_H #include/* * 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);
三个函数头文件都是
arp_send_dst(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
dst_hw, dev->dev_addr, NULL, dst);
dev_hard_header
dev->header_ops = ð_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地址转换成点分十进制字符串。 |