#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;
}
怎么修改
最新发布