赞
踩
前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料)
微信公众号:创享日记
发送关键词:协议实现
获取各个协议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 上层协议
*/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。