udphdr

本文详细解释了UDP头部结构,包括源端口号、目的端口号、数据报长度和校验和的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/usr/src/linux/include/linux/udp.h

struct udphdr {

        __u16   source;

        __u16   dest;

        __u16   len;

        __u16   check;

};

     |----------------|----------------|-------------
     |     source     |     dest       |
     |----------------|----------------|
     |     len        |    check   |
     |---------------------------------|

                    UDP头




udphdr->source
    16位源端口号

udphdr ->dest
    16位目的端口号

udphdr ->len
    表示此次发送的数据报的长度,16位。

udphdr ->check
    校验和。

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <net/ethernet.h> #include <netinet/ip.h> #include <netinet/udp.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <time.h> #include <netpacket/packet.h> // 添加这个头文件 #include <linux/if_ether.h> // 添加这个头文件 // TFTP 操作码 #define TFTP_RRQ 1 #define TFTP_WRQ 2 #define TFTP_DATA 3 #define TFTP_ACK 4 #define TFTP_ERROR 5 // TFTP 错误码 const char *tftp_errors[] = { "未定义错误", "文件未找到", "访问违规", "磁盘满或分配超过", "非法操作", "未知传输ID", "文件已存在", "无此用户" }; // 打印时间戳 void print_timestamp() { time_t now = time(NULL); struct tm *t = localtime(&now); printf("[%02d:%02d:%02d] ", t->tm_hour, t->tm_min, t->tm_sec); } // 解析 TFTP 数据包 void parse_tftp_packet(const unsigned char *data, int len, const char *src_ip, const char *dst_ip, uint16_t src_port, uint16_t dst_port) { if (len < 4) return; // 最小TFTP包长度检查 // 提取操作码 (大端序) uint16_t opcode = ntohs(*(uint16_t *)data); print_timestamp(); printf("%s:%d -> %s:%d | ", src_ip, src_port, dst_ip, dst_port); switch (opcode) { case TFTP_RRQ: printf("TFTP Read Request: "); // 文件名从第3字节开始,以null结束 printf("File: '%s' Mode: '%s'", data + 2, data + 2 + strlen((char *)data + 2) + 1); break; case TFTP_WRQ: printf("TFTP Write Request: "); printf("File: '%s' Mode: '%s'", data + 2, data + 2 + strlen((char *)data + 2) + 1); break; case TFTP_DATA: { uint16_t block_num = ntohs(*(uint16_t *)(data + 2)); int data_len = len - 4; // 减去操作码和块号 printf("TFTP Data: Block #%d, Size: %d bytes", block_num, data_len); break; } case TFTP_ACK: { uint16_t block_num = ntohs(*(uint16_t *)(data + 2)); printf("TFTP ACK: Block #%d", block_num); break; } case TFTP_ERROR: { uint16_t error_code = ntohs(*(uint16_t *)(data + 2)); const char *error_msg = (error_code < 8) ? tftp_errors[error_code] : "未知错误"; printf("TFTP Error: Code %d - %s", error_code, error_msg); if (len > 4) printf(" | Msg: '%s'", data + 4); break; } default: printf("Unknown TFTP Opcode: %d", opcode); } printf("\n"); } int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "Usage: sudo %s <interface>\n", argv[0]); fprintf(stderr, "Example: sudo %s eth0\n", argv[0]); exit(EXIT_FAILURE); } char *interface = argv[1]; // 创建原始套接字 int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sockfd < 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } // 绑定到指定接口 struct sockaddr_ll sll; memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_protocol = htons(ETH_P_ALL); sll.sll_ifindex = if_nametoindex(interface); if (sll.sll_ifindex == 0) { perror("Interface not found"); close(sockfd); exit(EXIT_FAILURE); } if (bind(sockfd, (struct sockaddr *)&sll, sizeof(sll)) < 0) { perror("Bind failed"); close(sockfd); exit(EXIT_FAILURE); } printf("Monitoring TFTP traffic on interface %s...\n", interface); // 设置缓冲区 unsigned char buffer[65536]; struct sockaddr_in source, src_addr, dst_addr; char src_ip[INET_ADDRSTRLEN], dst_ip[INET_ADDRSTRLEN]; while (1) { // 接收数据包 ssize_t data_size = recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL); if (data_size < 0) { perror("Packet receive error"); continue; } // 解析以太网帧头 struct ethhdr *eth = (struct ethhdr *)buffer; // 只处理IPv4包 (0x0800) if (ntohs(eth->h_proto) != ETH_P_IP) continue; // 解析IP头 struct iphdr *ip = (struct iphdr *)(buffer + sizeof(struct ethhdr)); unsigned short iphdr_len = ip->ihl * 4; // 只处理UDP包 (协议号17) if (ip->protocol != IPPROTO_UDP) continue; // 解析UDP头 struct udphdr *udp = (struct udphdr *)(buffer + sizeof(struct ethhdr) + iphdr_len); unsigned short udp_len = ntohs(udp->len); // 转换IP地址为字符串 inet_ntop(AF_INET, &(ip->saddr), src_ip, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(ip->daddr), dst_ip, INET_ADDRSTRLEN); uint16_t src_port = ntohs(udp->source); uint16_t dst_port = ntohs(udp->dest); // 只处理TFTP相关端口 (69或客户端端口) if (!(dst_port == 69 || src_port == 69 || (dst_port > 1024 && src_port > 1024))) continue; // 获取TFTP数据负载 (跳过UDP头) unsigned char *tftp_data = (unsigned char *)udp + sizeof(struct udphdr); int tftp_len = udp_len - sizeof(struct udphdr); // 解析TFTP数据包 parse_tftp_packet(tftp_data, tftp_len, src_ip, dst_ip, src_port, dst_port); } close(sockfd); return 0; } 怎么修改
最新发布
08-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值