栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

arp、ethernet、icmp、udp、ip协议的C语言实现(计算机网络协议栈实验)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

arp、ethernet、icmp、udp、ip协议的C语言实现(计算机网络协议栈实验)

微信公众号:创享日记
发送关键词:协议实现
获取各个协议C语言实现源代码源文件



ARP协议部分代码:

#include 
#include 
#include "net.h"
#include "arp.h"
#include "ethernet.h"

static const arp_pkt_t arp_init_pkt = {
    .hw_type16 = swap16(ARP_HW_ETHER),
    .pro_type16 = swap16(NET_PROTOCOL_IP),
    .hw_len = NET_MAC_LEN,
    .pro_len = NET_IP_LEN,
    .sender_ip = NET_IF_IP,
    .sender_mac = NET_IF_MAC,
    .target_mac = {0}};


map_t arp_table;


map_t arp_buf;


void arp_entry_print(void *ip, void *mac, time_t *timestamp)
{
    printf("%s | %s | %sn", iptos(ip), mactos(mac), timetos(*timestamp));
}


void arp_print()
{
    printf("===ARP TABLE BEGIN===n");
    map_foreach(&arp_table, arp_entry_print);
    printf("===ARP TABLE  END ===n");
}


void arp_req(uint8_t *target_ip)
{
    buf_init(&txbuf, sizeof(arp_pkt_t)); //对txbuf进行初始化

    arp_pkt_t *pkt = (arp_pkt_t *)txbuf.data;
    pkt->hw_type16 = swap16(1);
    pkt->pro_type16 = swap16(NET_PROTOCOL_IP);
    pkt->hw_len = 6;
    pkt->pro_len = 4;
    pkt->opcode16 = swap16(ARP_REQUEST);
    // for (int i = 0; i < 6; i++)
    // {
    //     pkt->sender_mac[i] = net_if_mac[i];
    //     pkt->target_mac[i] = 0x00;
    // }
    // for (int i = 0; i < 4; i++)
    // {
    //     pkt->sender_ip[i] = net_if_ip[i];
    //     pkt->target_ip[i] = *(target_ip + i);
    // }
    memcpy(pkt->sender_mac, net_if_mac, NET_MAC_LEN);
    memcpy(pkt->sender_ip, net_if_ip, NET_IP_LEN);
    memset(pkt->target_mac, 0, NET_MAC_LEN);
    memcpy(pkt->target_ip, target_ip, NET_IP_LEN);

    ethernet_out(&txbuf, ether_broadcast_mac, NET_PROTOCOL_ARP); //发送ARP报文
}



ETH协议全部代码:

#include "ethernet.h"
#include "utils.h"
#include "driver.h"
#include "arp.h"
#include "ip.h"

void ethernet_in(buf_t *buf)
{
    if(buf->len < sizeof(ether_hdr_t))   //判断数据长度,小于以太网头部长度的话丢弃不处理
    {
        return;
    }

    ether_hdr_t *hdr = (ether_hdr_t *)buf->data;
    buf_remove_header(buf,sizeof(ether_hdr_t));  //移除以太网包头
    
    net_in(buf,swap16(hdr->protocol16),hdr->src);    //向上层传递数据包
}

void ethernet_out(buf_t *buf, const uint8_t *mac, net_protocol_t protocol)
{
    if(buf->len < 46)
    {
        buf_add_padding(buf,46 - buf->len);
    }

    buf_add_header(buf,sizeof(ether_hdr_t));   //添加以太网包头
    ether_hdr_t *hdr = (ether_hdr_t *)buf->data;
    
    // for(int i = 0; i < 6; i++)   //填写目的MAC地址
    // {
    //     hdr->dst[i] = *(mac+i);
    // }

    // for(int i = 0; i < 6; i++)   //填写源MAC地址
    // {
    //     hdr->src[i] = net_if_mac[i]; //net_if_mac 得到本机的mac地址
    // }
    memcpy(hdr->dst, mac, NET_MAC_LEN);
    memcpy(hdr->src, net_if_mac, NET_MAC_LEN);
    
    hdr->protocol16 = swap16(protocol);
    
    driver_send(buf);   //将添加了以太网包头的数据帧发送到驱动层
}

void ethernet_init()
{
    buf_init(&rxbuf, ETHERNET_MAX_TRANSPORT_UNIT + sizeof(ether_hdr_t));
}


void ethernet_poll()
{
    if (driver_recv(&rxbuf) > 0)
        ethernet_in(&rxbuf);
}

ICMP协议部分代码:

#include "net.h"
#include "icmp.h"
#include "ip.h"


static void icmp_resp(buf_t *req_buf, uint8_t *src_ip)
{
    buf_t *buf = &txbuf;
    buf_init(buf, req_buf->len );
    memcpy(buf->data,req_buf->data,req_buf->len); 
    icmp_hdr_t *hdr1 = (icmp_hdr_t *)req_buf->data;
    icmp_hdr_t hdr2 = {
    .code = hdr1->code,
    .checksum16 = 0,
    .id16 = hdr1->id16,
    .seq16 = hdr1->seq16,
    .type = ICMP_TYPE_ECHO_REPLY};
    memcpy(buf->data, &hdr2, sizeof(icmp_hdr_t));
    hdr2.checksum16 = checksum16((uint16_t *)buf->data, buf->len);
    memcpy(buf->data, &hdr2, sizeof(icmp_hdr_t));
    ip_out(buf, src_ip, NET_PROTOCOL_ICMP);
}


void icmp_in(buf_t *buf, uint8_t *src_ip)
{
    if (buf->len < sizeof(icmp_hdr_t))
    {
        return;
    }

    icmp_hdr_t *hdr = (icmp_hdr_t *)buf->data;
    if (hdr->type == ICMP_TYPE_ECHO_REQUEST)
    {
        icmp_resp(buf, src_ip);
    }
    else
    {
        return;
    }
    
}



UDP协议部分代码:

#include "udp.h"
#include "ip.h"
#include "icmp.h"


map_t udp_table;


static uint16_t udp_checksum(buf_t *buf, uint8_t *src_ip, uint8_t *dst_ip)
{
    uint8_t src[4];
    uint8_t dst[4];
    memcpy(src, src_ip, 4);
    memcpy(dst, dst_ip, 4);

    buf_add_header(buf, sizeof(udp_peso_hdr_t));
    udp_peso_hdr_t *peso_hdr = (udp_peso_hdr_t *)buf->data;
    memcpy(peso_hdr->src_ip, src, 4);
    memcpy(peso_hdr->dst_ip, dst, 4);
    peso_hdr->protocol = NET_PROTOCOL_UDP;
    peso_hdr->total_len16 = swap16(buf->len - sizeof(udp_peso_hdr_t));
    peso_hdr->placeholder = 0;

    uint16_t *p;
    p = (uint16_t *)peso_hdr;
    int n = buf->len / 2;
    int i = 0;
    uint32_t checksum = 0;
    while (i < n)
    {
        checksum += swap16(*p);
        p++;
        i++;
    }
    if (buf->len % 2 != 0)
    {
        checksum += swap16(*p) & 0xFF00;
    }
    while ((checksum >> 16) != 0)
    {
        checksum = (checksum >> 16) + (checksum & 0xFFFF);
    }
    buf_remove_header(buf, sizeof(udp_peso_hdr_t));
    memcpy(src_ip, src, 4);
    memcpy(dst_ip, dst, 4);

    return (uint16_t)(~checksum);
}


void udp_in(buf_t *buf, uint8_t *src_ip)
{
    if (buf->len < sizeof(udp_hdr_t))
    {
        return;
    }

    udp_hdr_t *hdr = (udp_hdr_t *)buf->data;
    if (buf->len < swap16(hdr->total_len16))
    {
        return;
    }

    uint16_t temp = swap16(hdr->checksum16);
    hdr->checksum16 = 0;
    hdr->checksum16 = udp_checksum(buf, src_ip, net_if_ip);
    if (temp != hdr->checksum16)
    {
        return;
    }
    uint16_t dst_port16 = swap16(hdr->dst_port16);
    uint16_t src_port16 = swap16(hdr->src_port16);
    if (!(map_get(&udp_table, &dst_port16)))
    {
        buf_add_header(buf, sizeof(ip_hdr_t));
        icmp_unreachable(buf, src_ip, ICMP_CODE_PORT_UNREACH);
    }
    else
    {
        udp_handler_t *handler = map_get(&udp_table, &dst_port16);
        buf_remove_header(buf, sizeof(udp_hdr_t));
        (*handler)(buf->data, buf->len, src_ip, src_port16);
    }
}



IP协议部分代码:

#include "net.h"
#include "ip.h"
#include "ethernet.h"
#include "arp.h"
#include "icmp.h"



void ip_in(buf_t *buf, uint8_t *src_mac)
{
    if(buf->len < sizeof(ip_hdr_t))
    {
        return;
    }
    ip_hdr_t *hdr = (ip_hdr_t *)buf->data;
    if(hdr->version != 4 || swap16(hdr->total_len16) > buf->len)
    {
        return;
    }
    uint16_t hdr_checksum_temp = hdr->hdr_checksum16;
    hdr->hdr_checksum16 = 0;
    uint16_t checksum = checksum16((uint16_t *)hdr, sizeof(ip_hdr_t));
    hdr->hdr_checksum16 = swap16(checksum);
    if(checksum != hdr_checksum_temp)
    {
        return;
    }
    else
    {
        hdr->hdr_checksum16 = hdr_checksum_temp;
    }
    for (size_t i = 0; i < NET_IP_LEN; i++)
    {
        if(hdr->dst_ip[i] != net_if_ip[i])
        {
            return;
        }
    }
    if(buf->len > swap16(hdr->total_len16))
    {
        buf_remove_padding(buf, buf->len - swap16(hdr->total_len16));
    }
    if(hdr->protocol != NET_PROTOCOL_ICMP && hdr->protocol != NET_PROTOCOL_UDP)
    {
        icmp_unreachable(buf, hdr->src_ip, ICMP_CODE_PROTOCOL_UNREACH);
    }
    else 
    {
        buf_remove_header(buf, sizeof(ip_hdr_t));
        net_in(buf, hdr->protocol, hdr->src_ip);
    }
}


void ip_fragment_out(buf_t *buf, uint8_t *ip, net_protocol_t protocol, int id, uint16_t offset, int mf)
{
    buf_add_header(buf, sizeof(ip_hdr_t));

    ip_hdr_t *hdr = (ip_hdr_t *)buf->data;
    hdr->hdr_len = 5;
    hdr->version = 4;
    hdr->tos = 0;
    hdr->total_len16 = swap16(buf->len);
    hdr->id16 = swap16(id);
    hdr->protocol = protocol;
    hdr->ttl = 64;
    if (mf == 1)
    {
        hdr->flags_fragment16 = swap16((offset >> 3) + IP_MORE_FRAGMENT);
    }
    else
    {
        hdr->flags_fragment16 = swap16(offset >> 3);
    }

    memcpy(hdr->src_ip, net_if_ip, NET_IP_LEN);
    memcpy(hdr->dst_ip, ip, NET_IP_LEN);
    
    hdr->hdr_checksum16 = 0;
    hdr->hdr_checksum16 = checksum16((uint16_t *)hdr, sizeof(ip_hdr_t));

    arp_out(buf, ip);
}



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/989543.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号