用户态协议栈设计实现udp,arp与icmp协议( 三 )

测试能否解析udp包的数据

  • 开启netmap
每次重启使用前都需要insmod netmap.ko ,然后我们查看ls /dev/netmap -l,出现下面的设备就说明开启成功了 。
root@wxf:/netmap/LINUX# insmod netmap.ko root@wxf:/netmap/LINUX# ls /dev/netmap -lcrw------- 1 root root 10, 54 Jul 18 17:28 /dev/netmap
用户态协议栈设计实现udp,arp与icmp协议

文章插图
 
  • 运行上面的udp测试代码
可以看到我们能够正常的接收udp数据
用户态协议栈设计实现udp,arp与icmp协议

文章插图
 
?但是为什么过了一会再发数据,程序就接收不到了,而且还多了这么多非udp的数据包??因为宿主机不知道虚拟机的ip和mac地址了,我们查看arp表,发现没有192.168.109.100虚拟机的记录,此时宿主机会在局域网内广播arp请求,这也就是为什么new data coming但不是udp的原因 。刚开始能正常解析数据是因为,虚拟机刚开机的时候,我用xshell连虚拟机,所以宿主机发送过arp请求,而虚拟机的内核协议栈此时还没被netmap接管,回应了arp请求,宿主机就将虚拟机的信息暂时的添加到arp表中,当动态arp记录失效,udp包不知道发给谁,就会先发arp请求 。
用户态协议栈设计实现udp,arp与icmp协议

文章插图
 

用户态协议栈设计实现udp,arp与icmp协议

文章插图
 
?解决这个问题的办法很简单,要么我们手动在宿主机上添加一条静态的arp记录,要么我们实现arp协议,下面我们来实现arp协议 。
2.实现arp协议设计思路我们知道arp协议是在网络层的,所以我们先解析ether,再解析arp即可
用户态协议栈设计实现udp,arp与icmp协议

文章插图
 

用户态协议栈设计实现udp,arp与icmp协议

文章插图
 
?代码
//// Created by 68725 on 2022/7/19.//#include <stdio.h>#include <sys/poll.h>#include <netinet/in.h>#include <arpa/inet.h>#define NETMAP_WITH_LIBS#include <net/netmap_user.h>#include <string.h>#pragma pack(1)#define ETH_ADDR_LENGTH 6#define PROTO_IP 0x0800#define PROTO_ARP 0x0806#define PROTO_RARP 0x0835#define PROTP_UPD 17struct ethhdr {unsigned char h_dst[ETH_ADDR_LENGTH];unsigned char h_src[ETH_ADDR_LENGTH];unsigned short h_proto;};struct iphdr {unsigned char hdrlen: 4,version: 4;unsigned char tos;unsigned short totlen;unsigned short id;unsigned short flag_offset;unsigned char ttl;unsigned char type;unsigned short check;unsigned int sip;unsigned int dip;};struct ippkt {struct ethhdr eh; //14struct iphdr ip; //20};struct udphdr {unsigned short sport;unsigned short dport;unsigned short length;unsigned short check;};struct udppkt {struct ethhdr eh; //14struct iphdr ip; //20struct udphdr udp;//8unsigned char data[0];};struct arphdr {unsigned short h_type;unsigned short h_proto;unsigned char h_addrlen;unsigned char h_protolen;unsigned short oper;unsigned char smac[ETH_ADDR_LENGTH];unsigned int sip;unsigned char dmac[ETH_ADDR_LENGTH];unsigned int dip;};struct arppkt {struct ethhdr eh;struct arphdr arp;};int str2mac(char *mac, char *str) {char *p = str;unsigned char value = https://www.isolves.com/it/wl/zs/2022-07-21/0x0;int i = 0;while (p != '') {if (*p == ':') {mac[i++] = value;value = 0x0;}else {unsigned char temp = *p;if (temp <= '9' && temp >= '0') {temp -= '0';}else if (temp <= 'f' && temp >= 'a') {temp -= 'a';temp += 10;}else if (temp <= 'F' && temp >= 'A') {temp -= 'A';temp += 10;}else {break;}value <<= 4;value |= temp;}p++;}mac[i] = value;return 0;}void echo_arp_pkt(struct arppkt *arp, struct arppkt *arp_rt, char *mac) {memcpy(arp_rt, arp, sizeof(struct arppkt));memcpy(arp_rt->eh.h_dst, arp->eh.h_src, ETH_ADDR_LENGTH);//以太网首部填入目的 macstr2mac(arp_rt->eh.h_src, mac);//以太网首部填入源macarp_rt->eh.h_proto = arp->eh.h_proto;//以太网协议还是arp协议arp_rt->arp.h_addrlen = 6;arp_rt->arp.h_protolen = 4;arp_rt->arp.oper = htons(2); // ARP响应str2mac(arp_rt->arp.smac, mac);//arp报文填入源macarp_rt->arp.sip = arp->arp.dip; // arp报文填入发送端 ipmemcpy(arp_rt->arp.dmac, arp->arp.smac, ETH_ADDR_LENGTH);//arp报文填入目的 macarp_rt->arp.dip = arp->arp.sip; // arp报文填入目的 ip}int main() {struct nm_pkthdr h;struct nm_desc *nmr = nm_open("netmap:ens33", NULL, 0, NULL);if (nmr == NULL) {return -1;}printf("open ens33 seccessn");struct pollfd pfd = {0};pfd.fd = nmr->fd;pfd.events = POLLIN;while (1) {printf("new data coming!n");int ret = poll(&pfd, 1, -1);if (ret < 0) {continue;}if (pfd.revents & POLLIN) {unsigned char *stream = nm_nextpkt(nmr, &h);struct ethhdr *eh = (struct ethhdr *) stream;if (ntohs(eh->h_proto) == PROTO_IP) {struct ippkt *iph=(struct ippkt *)stream;if (iph->ip.type == PROTP_UPD) {struct udppkt *udp = (struct udppkt *) stream;int udplength = ntohs(udp->udp.length);udp->data[udplength - 8] = '';printf("udp ---> %sn", udp->data);struct udppkt udp_rt;echo_udp_pkt(udp, &udp_rt);nm_inject(nmr, &udp_rt, sizeof(struct udppkt));}}else if (ntohs(eh->h_proto) == PROTO_ARP) {struct arppkt *arp = (struct arppkt *) stream;struct arppkt arp_rt;if (arp->arp.dip == inet_addr("192.168.109.100")) {echo_arp_pkt(arp, &arp_rt, "00:0c:29:1b:18:20");nm_inject(nmr, &arp_rt, sizeof(arp_rt));printf("arp retn");}}}}nm_close(nmr);}//gcc -o main main.c -I /netmap/sys///insmod netmap.ko


推荐阅读