116 lines
4.2 KiB
C
116 lines
4.2 KiB
C
|
/*拆解UDP数据报*/
|
||
|
#include <netinet/ether.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <arpa/inet.h>
|
||
|
#include <stdio.h>
|
||
|
#include <unistd.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
int main(int argc, char const *argv[])
|
||
|
{
|
||
|
// 创建原始套接字
|
||
|
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||
|
if (sock_fd < 0)
|
||
|
{
|
||
|
perror("raw socket");
|
||
|
return -1;
|
||
|
}
|
||
|
printf("原始套接字创建成功\n");
|
||
|
|
||
|
// 多次接收数据
|
||
|
while (1)
|
||
|
{
|
||
|
// 接链路层的数据报文(MAC报文)
|
||
|
unsigned char buf[1518] = ""; // 记得使用无符号类型
|
||
|
int len = recvfrom(sock_fd, buf, sizeof(buf), 0, NULL, NULL);
|
||
|
if (len < 18)
|
||
|
{
|
||
|
perror("recvfrom");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// 拆解 MAC 数据报文
|
||
|
unsigned char dst_mac[18] = ""; // 目的MAC地址
|
||
|
unsigned char src_mac[18] = ""; // 源MAC地址
|
||
|
unsigned short mac_type = ntohs(*((unsigned short *)(buf + 12)));
|
||
|
|
||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
|
||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
|
||
|
|
||
|
if (strncmp(src_mac, "00:00:00", 8) != 0)
|
||
|
printf("src_mac %s -> dst_mac %s type(%#x)\n", src_mac, dst_mac, mac_type);
|
||
|
|
||
|
// sleep(1);
|
||
|
// usleep(5);
|
||
|
|
||
|
switch (mac_type)
|
||
|
{
|
||
|
case 0x0800:
|
||
|
printf("-----ip 数据包-----\n");
|
||
|
// 拆解IP数据报
|
||
|
unsigned char *ip_buf = buf + 14;
|
||
|
// 读取IP首部长度: 单位是 4 字节
|
||
|
unsigned char ip_head_len = (ip_buf[0] & 0x0f) * 4;
|
||
|
printf("IP数据报的首部长度: %d\n", ip_head_len);
|
||
|
|
||
|
unsigned char ip_type = ip_buf[9]; // 协议类型
|
||
|
// 读取源IP和目的IP
|
||
|
unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源IP
|
||
|
unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的IP
|
||
|
inet_ntop(AF_INET, (unsigned int *)(ip_buf + 12), src_ip, INET_ADDRSTRLEN);
|
||
|
inet_ntop(AF_INET, (unsigned int *)(ip_buf + 16), dst_ip, INET_ADDRSTRLEN);
|
||
|
printf("src_ip: %s -> dst_ip: %s \n", src_ip, dst_ip);
|
||
|
|
||
|
if (ip_type == 1)
|
||
|
{
|
||
|
printf("\t------ICMP 数据报-----\n");
|
||
|
}
|
||
|
else if (ip_type == 2)
|
||
|
{
|
||
|
printf("\t------IGMP 数据报-----\n");
|
||
|
}
|
||
|
else if (ip_type == 6)
|
||
|
{
|
||
|
printf("\t------TCP 数据报-----\n");
|
||
|
// 拆解TCP的数据报
|
||
|
unsigned char *tcp_buf = ip_buf + ip_head_len; // 取出TCP的报文
|
||
|
unsigned short src_port = ntohs(*((unsigned short *)(tcp_buf))); // 源端口
|
||
|
unsigned short dst_port = ntohs(*((unsigned short *)(tcp_buf + 2))); // 目的端口
|
||
|
printf("\tsrc_port: %d -> dst_port: %d\n", src_port, dst_port);
|
||
|
|
||
|
// TCP 的数据报
|
||
|
}
|
||
|
else if (ip_type == 17)
|
||
|
{
|
||
|
printf("\t------UDP 数据报-----\n");
|
||
|
// 拆解UDP的数据报
|
||
|
unsigned char *udp_buf = ip_buf + ip_head_len; // 取出UDP的报文
|
||
|
unsigned short src_port = ntohs(*((unsigned short *)udp_buf));
|
||
|
unsigned short dst_port = ntohs(*((unsigned short *)(udp_buf + 2)));
|
||
|
|
||
|
printf("\tsrc_port: %d -> dst_port: %d\n", src_port, dst_port);
|
||
|
|
||
|
// UDP 的数据报长度: 由首部+数据长度(偶数)组成
|
||
|
unsigned short udp_buf_len = ntohs(*((unsigned short *)(udp_buf + 4))); // ntohs 用于大端转小端
|
||
|
int udp_date_size = udp_buf_len - 8;
|
||
|
char udp_date[128] = ""; // UDP 数据部分
|
||
|
strncpy(udp_date, udp_buf + 8, udp_buf_len - 8);
|
||
|
printf("\t\t %d -> %d data: %s\n", src_port, dst_port, udp_date);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
case 0x0806:
|
||
|
printf("-----ARP 数据包-----\n");
|
||
|
break;
|
||
|
case 0x8035:
|
||
|
printf("-----RARP 数据包-----\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
close(sock_fd);
|
||
|
|
||
|
return 0;
|
||
|
}
|