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

前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料)


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


在这里插入图片描述


ARP协议部分代码:

#include <string.h>
#include <stdio.h>
#include "net.h"
#include "arp.h"
#include "ethernet.h"
/*** @brief 初始的arp包**/
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}};/*** @brief arp地址转换表,<ip,mac>的容器**/
map_t arp_table;/*** @brief arp buffer,<ip,buf_t>的容器**/
map_t arp_buf;/*** @brief 打印一条arp表项** @param ip 表项的ip地址* @param mac 表项的mac地址* @param timestamp 表项的更新时间*/
void arp_entry_print(void *ip, void *mac, time_t *timestamp)
{printf("%s | %s | %s\n", iptos(ip), mactos(mac), timetos(*timestamp));
}/*** @brief 打印整个arp表**/
void arp_print()
{printf("===ARP TABLE BEGIN===\n");map_foreach(&arp_table, arp_entry_print);printf("===ARP TABLE  END ===\n");
}/*** @brief 发送一个arp请求** @param target_ip 想要知道的目标的ip地址*/
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报文
}/*** @brief 发送一个arp响应** @param target_ip 目标ip地址* @param target_mac 目标mac地址*/

ETH协议全部代码:

#include "ethernet.h"
#include "utils.h"
#include "driver.h"
#include "arp.h"
#include "ip.h"
/*** @brief 处理一个收到的数据包* * @param buf 要处理的数据包*/
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);    //向上层传递数据包
}
/*** @brief 处理一个要发送的数据包* * @param buf 要处理的数据包* @param mac 目标MAC地址* @param protocol 上层协议*/
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);   //将添加了以太网包头的数据帧发送到驱动层
}
/*** @brief 初始化以太网协议* */
void ethernet_init()
{buf_init(&rxbuf, ETHERNET_MAX_TRANSPORT_UNIT + sizeof(ether_hdr_t));
}/*** @brief 一次以太网轮询* */
void ethernet_poll()
{if (driver_recv(&rxbuf) > 0)ethernet_in(&rxbuf);
}

ICMP协议部分代码:

#include "net.h"
#include "icmp.h"
#include "ip.h"/*** @brief 发送icmp响应* * @param req_buf 收到的icmp请求包* @param src_ip 源ip地址*/
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);
}/*** @brief 处理一个收到的数据包* * @param buf 要处理的数据包* @param src_ip 源ip地址*/
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;}}/*** @brief 发送icmp不可达* * @param recv_buf 收到的ip数据包* @param src_ip 源ip地址* @param code icmp code,协议不可达或端口不可达*/

UDP协议部分代码:

#include "udp.h"
#include "ip.h"
#include "icmp.h"/*** @brief udp处理程序表* */
map_t udp_table;/*** @brief udp伪校验和计算* * @param buf 要计算的包* @param src_ip 源ip地址* @param dst_ip 目的ip地址* @return uint16_t 伪校验和*/
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);
}/*** @brief 处理一个收到的udp数据包* * @param buf 要处理的包* @param src_ip 源ip地址*/
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);}
}/*** @brief 处理一个要发送的数据包* * @param buf 要处理的包* @param src_port 源端口号* @param dst_ip 目的ip地址* @param dst_port 目的端口号*/

IP协议部分代码:

#include "net.h"
#include "ip.h"
#include "ethernet.h"
#include "arp.h"
#include "icmp.h"/*** @brief 处理一个收到的数据包* * @param buf 要处理的数据包* @param src_mac 源mac地址*/
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);}
}/*** @brief 处理一个要发送的ip分片* * @param buf 要发送的分片* @param ip 目标ip地址* @param protocol 上层协议* @param id 数据包id* @param offset 分片offset,必须被8整除* @param mf 分片mf标志,是否有下一个分片*/
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);
}/*** @brief 处理一个要发送的ip数据包* * @param buf 要处理的包* @param ip 目标ip地址* @param protocol 上层协议*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/347200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CPU设计(单周期和流水线)

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送关键词&#xff1a;cpu …

前馈-反馈控制系统设计(过程控制课程设计matlab/simulink)

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送关键词&#xff1a;前馈…

感应电机直接转矩控制系统的设计与仿真(运动控制matlab/simulink)

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送关键词&#xff1a;直接…

双容水箱液位模糊PID控制系统设计与仿真(Matlab/Simulink)

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;双容模糊 获…

基于单片机步进电机控制器设计(正转反转指示灯挡位)

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;单片机步进…

基于单片机的交通灯控制系统设计

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;单片机交通…

36个精美完整网站网页完整源码HTML+CSS+JS

以下列举前9个效果图&#xff0c;源码详见微信公众号下载 ①效果图 ②效果图 ③效果图 ④效果图 ⑤效果图 ⑥效果图 ⑦效果图 ⑧效果图 ⑨效果图 微信公众号&#xff1a;创享日记 发送&#xff1a;36 获取全部完整源码&#xff08;打开.html文件均即可用&…

公司产品移动端网页-前端网页设计技术精美网站源码HTML+CSS+JS

微信公众号&#xff1a;创享日记 发送&#xff1a;产品网页 获取完整源码&#xff08;打开即可用&#xff09; 效果①主页首页 /*页面重置*/ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,f…

创建一个坚固的备份系统

在Foreach&#xff0c;我们拥有Synology RS815 来存储所有备份。 这些备份来自我们网络中的不同来源&#xff0c;例如路由器&#xff0c;交换机&#xff0c;数据库服务器&#xff0c;Web服务器&#xff0c;应用程序日志文件&#xff0c;邮件服务器等等。 Synology NAS使配置这…

班级网站-前端网页技术精美完整源码HTML+CSS+JS

微信公众号&#xff1a;创享日记 发送&#xff1a;班级网站 获取完整源码&#xff08;打开即可用&#xff09; 效果图①首页主页 效果图②关于页面 效果图③联系方式及留言 效果图④我们的画廊展示 其余及源码详见微信公众号下载&#xff01; <!DOCTYPE html> <html…

医药协会网站-前端网页技术设计HTML+CSS精美完整网页网站源码

微信公众号&#xff1a;创享日记 发送&#xff1a;医药协会网站 获取完整源码 效果图预览①主页首页 效果图预览②资源下载中心 效果图预览③登录/注册 效果图预览④文章资讯详情 效果图预览⑤文章资讯列表 效果图预览⑥留言板 效果图预览⑦图文列表 效果图预览⑧图文详情 源码…

数字通信系统仿真的MATLAB实现(QPSK)

关注公号【逆向通信猿】更精彩!!! 仿真结果 本文以QPSK为调制体制进行仿真,以下结果为比特信噪比Eb/N0=10dB(此时符号信噪比Es/N0=13dB,SNR信噪比=3.98dB,换算关系在代码中为第44行)时的各步骤结果图

动漫网站-前端网页技术精美网站源码HTML+CSS+JS

微信公众号&#xff1a;创享日记 发送&#xff1a;动漫网站 获取完整源码&#xff08;打开即可用&#xff09; 效果图①主页首页 效果图②作品列表展示页 效果图③作品详情展示页 效果图④联系我们 效果图⑤博客列表 效果图⑥博客详情 效果图⑦其它 其它及源码详见微信公众号下…

【2021.02.09更新】数学常用基本公式

泰勒级数 条件不多说了&#xff0c;函数f(x)f(x)f(x)在点xx0x {x_0}xx0​出展开为 f(x0)f′(x0)(x−x0)f′′(x0)2!(x−x0)2⋯f(n)(x0)n!(x−x0)n⋯f({x_0}) f({x_0})(x - {x_0}) \frac{{f({x_0})}}{{2!}}{(x - {x_0})^2} \cdots \frac{{{f^{(n)}}({x_0})}}{{n!}}{(x - {…

服装商城电商-前端网页技术精美完整源码HTML+CSS+JS

微信公众号&#xff1a;创享日记 发送&#xff1a;服装电商 获取完整源码&#xff08;打开即可用&#xff09; 效果①主页首页 效果②登录页 效果③注册页 效果④结算结账页 效果⑤联系页 效果⑥找不到资源页 效果⑦商品列表页 效果⑧商品详情页 效果⑨心愿清单页 其余及源码详…

【2021.02.09更新】数字信号处理公式推导

卷积 h(t)⊗x(t)∫−∞∞h(τ)x(t−τ)dτh(t) \otimes x(t) \int_{ - \infty }^{ \infty } {h(\tau )x(t - \tau )d\tau }h(t)⊗x(t)∫−∞∞​h(τ)x(t−τ)dτ 令τut2\tau u \frac{t}{2}τu2t​&#xff0c;则 h(t)⊗x(t)∫−∞∞h(ut2)x(−ut2)duh(t) \otimes x(t) …

旅游展示网站-前端网页设计技术完整精美源码HTML+CSS+JS

微信公众号&#xff1a;创享日记 发送&#xff1a;旅游网站 获取完整源码&#xff08;打开即可用&#xff09; 效果①首页主页 效果②关于我们页 效果③提供的服务页 效果④我们的能力页 /*页面重置*/ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote…

【2021.01.01】人生中很重要的一个十年,差强人意

回顾整个2020年&#xff0c;是疯狂的一年&#xff0c;也是令人难忘的一年&#xff0c;对于我也是比较励志的一年&#xff0c;绝对是自己人生中的一个里程碑。完成了人生中最重要的一件大事&#xff0c;感谢有你一直陪着我&#xff0c;愿天下有情人终成眷属&#xff0c;最终走到…

数字信号处理实验一 系统响应及系统稳定性

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;响应及稳定…

数字信号处理实验二 IIR数字滤波器设计及软件实现

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;iir滤波器 …