链路层原始套接字源码
发送端
#include <stdio.h> #include <stdlib.h> #include <unistd.h>// close() #include <string.h>// strcpy, memset(), and memcpy() #include <netdb.h> // struct addrinfo #include <sys/types.h> // needed for socket(), uint8_t, uint16_t, uint32_t #include <sys/socket.h> // needed for socket() #include <netinet/in.h> // IPPROTO_ICMP, INET_ADDRSTRLEN #include <netinet/ip.h>// struct ip and IP_MAXPACKET (which is 65535) #include <netinet/ip_icmp.h> // struct icmp, ICMP_ECHO #include <arpa/inet.h> // inet_pton() and inet_ntop() #include <sys/ioctl.h> // macro ioctl is defined #include <bits/ioctls.h> // defines values for argument "request" of ioctl. #include <net/if.h> // struct ifreq #include <linux/if_ether.h> // ETH_P_IP = 0x0800, ETH_P_IPV6 = 0x86DD #include <linux/if_packet.h> // struct sockaddr_ll (see man 7 packet) #include <net/ethernet.h> #include <errno.h> // errno, perror() #define ETH_P_DEAN 0x8874 //自定义的以太网协议type int main (int argc, char **argv) { int i, datalen,frame_length, sd, bytes; char *interface="ens33";; uint8_t data[IP_MAXPACKET]; uint8_t src_mac[6]; uint8_t dst_mac[6];; uint8_t ether_frame[IP_MAXPACKET]; struct sockaddr_ll device; if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { perror ("socket() failed to get socket descriptor for using ioctl() "); exit (EXIT_FAILURE); } // Use ioctl() to look up interface name and get its MAC address. struct ifreq ifr; memset (&ifr, 0, sizeof (ifr)); snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface); if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) { perror ("ioctl() failed to get source MAC address "); return (EXIT_FAILURE); } memcpy (src_mac, ifr.ifr_hwaddr.sa_data, 6);// Copy source MAC address. memset (&device, 0, sizeof (device)); if (ioctl (sd, SIOCGIFINDEX, &ifr) < 0) { perror ("ioctl() failed to get source MAC address "); return (EXIT_FAILURE); } device.sll_ifindex = ifr.ifr_ifindex; // Set destination MAC address: you need to fill these out // 00:0c:29:38:90:56 dst_mac[0] = 0x00; dst_mac[1] = 0x0c; dst_mac[2] = 0x29; dst_mac[3] = 0x38; dst_mac[4] = 0x90; dst_mac[5] = 0x56; device.sll_family = AF_PACKET; memcpy (device.sll_addr, src_mac, 6); device.sll_halen = htons (6); // 发送的data,但是抓包时看到最小数据长度为46,以太网协议规定以太网帧数据域最小为46字节,不足的自动补零处理 sprintf(data,"%s","hello,world!"); datalen = strlen(data); // 填充以太网帧 memcpy (ether_frame, dst_mac, 6); memcpy (ether_frame + 6, src_mac, 6); ether_frame[12] = ETH_P_DEAN / 256; ether_frame[13] = ETH_P_DEAN % 256; memcpy (ether_frame + 14 , data, datalen); frame_length = 6 + 6 + 2 + datalen; if ((bytes = sendto (sd, ether_frame, frame_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0) { perror ("sendto() failed"); exit (EXIT_FAILURE); } close (sd); return (EXIT_SUCCESS); }
接收端
#include <stdio.h> #include <stdlib.h> #include <unistd.h>// close() #include <string.h>// strcpy, memset(), and memcpy() #include <netdb.h> // struct addrinfo #include <sys/types.h> // needed for socket(), uint8_t, uint16_t, uint32_t #include <sys/socket.h> // needed for socket() #include <netinet/in.h> // IPPROTO_ICMP, INET_ADDRSTRLEN #include <netinet/ip.h>// struct ip and IP_MAXPACKET (which is 65535) #include <netinet/ip_icmp.h> // struct icmp, ICMP_ECHO #include <arpa/inet.h> // inet_pton() and inet_ntop() #include <sys/ioctl.h> // macro ioctl is defined #include <bits/ioctls.h> // defines values for argument "request" of ioctl. #include <net/if.h> // struct ifreq #include <linux/if_ether.h> // ETH_P_IP = 0x0800, ETH_P_IPV6 = 0x86DD #include <linux/if_packet.h> // struct sockaddr_ll (see man 7 packet) #include <net/ethernet.h> #include <errno.h> // errno, perror() #define ETH_P_DEAN 0x8874 //自定义的以太网协议type int main (int argc, char **argv) { int sd; uint8_t data[IP_MAXPACKET]; uint8_t src_mac[32]; uint8_t dst_mac[32];; if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_DEAN))) < 0) { perror ("socket() failed to get socket descriptor for using ioctl() "); exit (EXIT_FAILURE); } while(1) { memset(src_mac, 0, sizeof(src_mac)); memset(dst_mac, 0, sizeof(dst_mac)); recvfrom(sd, data, sizeof(data), 0, NULL, NULL); sprintf(src_mac,"%02x:%02x:%02x:%02x:%02x:%02x",data[0],data[1],data[2],data[3],data[4],data[5]); sprintf(dst_mac,"%02x:%02x:%02x:%02x:%02x:%02x",data[6],data[7],data[8],data[9],data[10],data[11]); printf("%s->%s\n",src_mac,dst_mac); } close (sd); return (EXIT_SUCCESS); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了