在linux系统中,使用struct ethhdr结构体表示以太网帧的头部。这个struct ethhdr结构体位于linx内核include\linux\if_ether.h中。
struct ethhdr结构体原型如下所示:
<span style="font-family:FangSong_GB2312;font-size:18px;">struct ethhdr
{
unsigned char h_dest[ETH_ALEN]; //目的MAC地址
unsigned char h_source[ETH_ALEN]; //源MAC地址
__u16 h_proto ; //网络层所使用的协议类型
}__attribute__((packed)) //用于告诉编译器不要对这个结构体中的缝隙部分进行填充操作;</span>
strcut ethhdr常见的操作
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="white-space:pre"> </span>int eth_header(struct sk_buff *skb, struct net_device *dev,
u16 type, void *daddr, void *saddr, unsigned len)
<span style="white-space:pre"> </span>EXPORT_SYMBOL(eth_header);</span>
int eth_header(struct sk_buff *skb, struct net_device *dev,
<span style="white-space:pre"> </span> u16 type, void *daddr, void *saddr, int len)
{
//将skb->data = skb->data + ETH_ALEN;
struct ethhdr *eth = (struct ethhdr*)skb_push(skb, ETH_ALEN);
if(type != ETH_P_802_3)
eth->proto = htons(type); // htons()将本地类型转换为网络类型
else
eth->proto = htons(len);
//如果 saddr = NULL的话,以太网帧头中的源MAC地址为dev的MAC地址
if(!saddr)
saddr = dev->dev_addr;
memcpy(eth->saddr, saddr, ETH_ALEN);
if(daddr)
{
memcpy(eth->daddr, daddr, ETH_ALEN);
return ETH_HLEN ; //返回值为14
}
return -ETH_HLEN;
}
__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev);
__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct ethhdr *eth;
skb->dev = dev;
eth = eth_hdr(skb);
if(netdev_uses_dsa_tags(dev))
return htons(ETH_P_DSA);
if(netdev_uses_trailer_tags(dev))
return htons(ETH_P_TRAILER);
if( ntohs(eth->h_proto) >= 1536 )
return eth->h_proto;
int eth_header_parse(struct sk_buff *skb, u8 *haddr)
{
struct ethhdr *eth = eth_hdr(skb);
memcpy(haddr, eth->h_source, ETH_ALEN); //可知haddr中存放的是源MAC地址;
return ETH_ALEN;
}
char *print_mac(char *buffer, const unsigned char *addr);
EXPORT_SYMBOL(print_mac);
char *print_mac(char *buffer, const unsigned char *addr)
{
// MAC_BUF_SIZE = 18
// ETH_ALEN = 6
_format_mac_addr(buffer, MAC_BUF_SIZE, addr, ETH_ALEN);
return buffer;
}