分析Linux网络模块Arp源代码

1. 简介

Arp(Address Resolution Protocol,地址解析协议)是一种用于获取网络层地址和物理层地址的协议,它用于在互联网中将IP地址转换为MAC地址。本文将分析Linux内核中的Arp模块的源代码,探讨其实现原理和关键函数。

2. Arp模块结构

Linux内核中的Arp模块由多个文件组成,其中最重要的文件是`arp.c`和`arp.h`。

2.1 `arp.h`文件

`arp.h`文件定义了Arp模块的数据结构、常量和函数声明。其中包括:

struct arpreq {

struct sockaddr_in arp_pa; /* protocol address */

struct sockaddr_in arp_ha; /* hardware address */

int arp_flags;

struct sockaddr_in arp_netmask; /* netmask */

char arp_dev[16];

};

struct neighbour {

struct hh_cache *hh;

int nud_state;

__u8 ha[ETH_ALEN];

struct sk_buff_head arp_queue;

struct rcu_head rcu;

int arp_count;

__u32 primary_key;

unsigned long confirmed:1,

updated:1,

noref:1,

failcount:8;

int parms_cookie;

struct neighbour *proxy_redir;

__be32 saddr;

};

struct neightbl_config {

int entries;

unsigned int gc_thresh1;

unsigned int gc_thresh2;

unsigned int gc_thresh3;

struct neigh_table *tbl;

};

2.2 `arp.c`文件

`arp.c`文件是Arp模块的核心代码文件,实现了Arp协议的功能。其中包括了一系列实现Arp协议的函数,如:

3. Arp协议的实现原理

在Linux内核中,Arp模块首先会通过`arp_ioctl()`函数接收用户空间的Arp请求。

static int arp_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd)

{ ... }

然后,Arp模块会调用`arp_send()`函数向目标主机发送Arp请求,并等待目标主机的回复。

static void arp_send(int type, int ptype, int code, struct neighbour *neigh, struct sk_buff *skb)

{ ... }

当目标主机的Arp回复到达后,Arp模块会调用`arp_rcv()`函数进行处理。

static int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)

{ ... }

最后,Arp模块将Arp缓存存储在neighbour数据结构中,并通过`neigh_event_send()`函数通知其他模块。

static inline void neigh_event_send(struct neighbour *n, struct sk_buff *skb)

{ ... }

4. 关键函数解析

4.1 `arp_send()`函数

函数原型:`static void arp_send(int type, int ptype, int code, struct neighbour *neigh, struct sk_buff *skb)`

重要部分:

if (neigh_hh_init(skb, &neigh_hh_arg) == NULL)

goto out;

通过`neigh_hh_init()`函数初始化ARP缓存,存储目标主机的MAC地址。

4.2 `arp_rcv()`函数

函数原型:`static int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)`

重要部分:

for (p = &rcu_dereference_bh(arp_tbl[thash].arp_list[hh->hh_type]);

p != NULL;

p = pnext) {

pnext = p->next;

if (hh->hh_data.res.dst_lsb == p->ha[hh->hh_type]) {

ndo_appfunc(skb, ND_NET_ARP_IP);

if (!atomic_read(&skb->users))

kfree_skb(skb);

rcu_read_unlock_bh();

return skb->len;

}

}

通过遍历ARP缓存链表,查找并比对目标主机的MAC地址。

5. 总结

本文分析了Linux内核中的Arp模块的源代码,探讨了其实现原理和关键函数。Arp模块通过发送Arp请求并接收回复来获取目标主机的MAC地址,然后将其存储在Arp缓存中,以供后续使用。

在实际应用中,Arp模块对于网络通信起到了至关重要的作用,能够实现网络层地址和物理层地址之间的转换,提高了网络通信的效率和可靠性。同时,深入理解Arp模块的源代码对于Linux内核网络协议栈的学习和理解也具有重要意义。

操作系统标签