探究linux下c语言与ARP协议的实现 (linux c arp)

探究Linux下C语言与ARP协议的实现

随着计算机网络的迅猛发展,网络通信协议也越来越成熟和复杂,ARP(Address Resolution Protocol)协议是用于将IP地址转换为物理地址的一种网络协议。在Linux系统下,ARP协议的实现是由C语言编写的。本文将探究Linux下C语言与ARP协议的实现。

一、ARP协议的概述

ARP协议是指Address Resolution Protocol,即地址解析协议,它在互联网协议(IP)中被用来将IPv4地址转换成物理硬件地址,例如MAC地址。通俗的理解,ARP协议实现了IP地址到MAC地址的映射,当我们想要与其他设备通信时,首先需要知道目标设备的MAC地址,而ARP协议就是用来完成这个任务的。

当一个网络设备(网卡、路由器、交换机等)需要发送网络数据包时,它会尝试去获取目标IP地址对应的MAC地址,步骤如下:

1. 在ARP缓存中查找对应的IP地址的MAC地址,如果存在,则直接发送数据包到目标设备的MAC地址。

2. 如果ARP缓存中不存在对应的MAC地址,则网卡需要发送一个ARP请求数据包广播到整个网络中,请求目标设备回应自己的MAC地址。广播的数据包的源MAC地址为发送方的MAC地址,目标MAC地址为广播地址FF:FF:FF:FF:FF:FF,目标IP地址为目标设备的IP地址,发送方的IP地址为发送方IP地址。

3. 目标设备接收到ARP请求数据包后,如果发现请求中目标IP与自己的IP地址相同,则回复一个ARP应答数据包,表明自己的MAC地址是什么,此时源设备可以获取到目标设备的MAC地址,并在以后的网络通信中使用该地址。

二、 Linux C语言下的ARP实现

在Linux下,ARP协议的实现主要由C语言编写。下面将介绍Linux C语言下ARP协议实现的主要代码框架。

1. ARP协议数据结构

在Linux中,ARP请求数据包与应答数据包的结构是一致的。下面是ARP数据包的数据结构定义。

“`c

struct arphdr {

__be16 ar_hrd; //硬件地址类型

__be16 ar_pro; //协议地址类型

unsigned char ar_hln; //硬件地址长度

unsigned char ar_pln; //协议地址长度

__be16 ar_op; //ARP操作码

unsigned char ar_sha[ETH_ALEN]; //源MAC地址

__be32 ar_sip; //源IP地址

unsigned char ar_tha[ETH_ALEN]; //目标MAC地址

__be32 ar_tip; //目标IP地址

};

“`

其中,ar_hrd表示硬件地址类型,ar_pro表示协议地址类型,ar_hln表示硬件地址长度,ar_pln表示协议地址长度,ar_op表示ARP操作码,ar_sha表示源MAC地址,ar_sip表示源IP地址,ar_tha表示目标MAC地址,ar_tip表示目标IP地址。

2. ARP协议接口程序

ARP协议的实现主要由arp.c程序实现,下面是该程序的主要代码框架。

“`c

#include

#include

#include

#include

void arp_rcv(struct sk_buff *skb) {

//接收ARP数据包并进行处理

}

int arp_send(unsigned int type, struct net_device *dev,

unsigned long dest_ip, const unsigned char *dest_hw,

unsigned long src_ip, const unsigned char *src_hw,

const unsigned char *target_hw) {

//发送ARP数据包

}

void arp_create(struct net_device *dev) {

//创建ARP缓存

}

void arp_destroy(struct net_device *dev) {

//销毁ARP缓存

}

void arp_timer(unsigned long data) {

//处理ARP缓存中的超时数据

}

static struct neigh_parms * arp_parms_alloc(struct net_device *dev) {

//分配neigh_parms结构体

}

static void arp_parms_free(struct neigh_parms *parms) {

//释放neigh_parms结构体

}

static struct neigh_parms_template arp_parms_template = {

.parmsize = sizeof(struct arp_parms),

.neigh_priv_size = sizeof(struct arp_neigh),

.neigh_setup = arp_neigh_setup,

.neigh_cleanup = arp_neigh_cleanup,

};

void __init arp_init(void) {

//注册ARP协议到内核

}

“`

其中,arp_rcv函数用于接收ARP数据包,并进行处理;arp_send函数用于发送ARP数据包;arp_create函数用于创建ARP缓存;arp_destroy函数用于销毁ARP缓存;arp_timer函数用于处理ARP缓存中的超时数据。此外,arp_parms_alloc函数和arp_parms_free函数用于分配和释放neigh_parms结构体,而arp_parms_template结构体则定义了ARP协议相关的参数模板。

3. ARP协议的实现流程

ARP协议的实现流程主要包含以下几个步骤。

1. 接收ARP数据包

当一个ARP数据包到达时,首先需要通过arp_rcv函数接收数据包。

“`c

void arp_rcv(struct sk_buff *skb) {

struct arphdr *arp;

struct neighbour *neigh;

//检查数据包的长度是否正确

if (/* !数据包长度正确 */) {

kfree_skb(skb);

return;

}

//获取ARP协议头

arp = arp_hdr(skb);

//分配缓存结构体

neigh = neighbour_alloc(&arp_tbl, &arp->saddr, arp->ar_hln, 0, skb->dev);

if (neigh) {

//缓存数据包

neighbour_update(neigh, skb);

neighbour_release(neigh);

}

//释放缓存

kfree_skb(skb);

}

“`

在接收到数据包后,首先需要检查数据包的长度是否正确,然后通过arp_hdr函数获取ARP协议头。接下来需要分配缓存结构体,这里使用neighbour_alloc函数完成,该函数可以分配一个neighbour结构体并将其插入到neighbour表中。当缓存数据包后,使用neighbour_update函数更新缓存,并通过neighbour_release函数将缓存的neigh结构释放。最后将skb数据包指针释放。

2. 发送ARP数据包

当需要发送ARP数据包时,需要调用arp_send函数。

“`c

int arp_send(unsigned int type, struct net_device *dev,

unsigned long dest_ip, const unsigned char *dest_hw,

unsigned long src_ip, const unsigned char *src_hw,

const unsigned char *target_hw) {

struct sk_buff *skb;

struct arphdr *arp;

//分配skb缓存结构体

skb = alloc_skb(/* 指定缓存长度 */, GFP_ATOMIC);

if (!skb) {

return -ENOMEM;

}

//填充ARP头部

arp = (struct arphdr *) skb_put(skb, sizeof(struct arphdr));

//设置各个字段值

arp->ar_hrd = htons(ARPHRD_ETHER);

arp->ar_pro = htons(ETH_P_IP);

arp->ar_hln = ETH_ALEN;

arp->ar_pln = 4;

arp->ar_op = htons(type);

memcpy(arp->ar_sha, src_hw, ETH_ALEN);

arp->ar_sip = htonl(src_ip);

memset(arp->ar_tha, 0, ETH_ALEN);

arp->ar_tip= htonl(dest_ip);

if (target_hw) {

memcpy(arp->ar_tha, target_hw, ETH_ALEN);

}

//填充数据链路头

//调用dev_hard_start_xmit函数发送数据包

//释放skb缓存结构体

return 0;

}

“`

发送ARP数据包时,首先需要分配一个skb缓存结构体,然后填充ARP头部,设置各个字段值。最后将数据链路头填充,调用dev_hard_start_xmit函数发送数据包,发送完成后释放skb缓存结构体。

3. 创建和销毁ARP缓存

在ARP协议的实现中,需要创建一个缓存表用于存储ARP请求的响应数据。当缓存中的数据超时后,需要将其从缓存表中释放。

“`c

void arp_create(struct net_device *dev) {

//创建ARP缓存

}

void arp_destroy(struct net_device *dev) {

//销毁ARP缓存

}

“`

这里的arp_create和arp_destroy函数用于创建和销毁ARP缓存表。

4. ARP定时器

在ARP协议的实现中,由于网络环境可能会发生变化,ARP缓存中的数据可能会失效。因此,需要使用ARP定时器定期检查ARP缓存中的数据是否已经超时,如果已经超时,则需要将其释放。

“`c

void arp_timer(unsigned long data) {

//处理ARP缓存中的超时数据

}

“`

在定时器中,需要遍历缓存表,检查缓存中每个元素的时间戳是否已经超时,如果已经超时,则需要将其从缓存表中释放。

三、结论


数据运维技术 » 探究linux下c语言与ARP协议的实现 (linux c arp)