#include <sys/types.h> #include <sys/time.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <linux/types.h> #include <netinet/in.h> #include <netinet/udp.h> #include <netinet/ip.h> #include <netpacket/packet.h> #include <net/ethernet.h> #include <arpa/inet.h> #include <string.h> #include <signal.h> #include <net/if.h> #include <stdio.h> #include <sys/uio.h> #include <fcntl.h> #include <unistd.h> #include <linux/filter.h> #include <stdlib.h> #define ETH_HDR_LEN 14 #define IP_HDR_LEN 20 #define UDP_HDR_LEN 8 #define TCP_HDR_LEN 20 #define UDP_PROTOCOL_TYPE 17 #define BROADCAST_ADDRESS -1 #define BROADCAST_PORT 8878 typedef struct ip_header { #ifdef WORKS_BIGENDIAN u_int8_t ip_version:4, /*version:4*/ ip_header_length:4; /*IP协议首部长度*/ #else u_int8_t ip_header_length:4, ip_version:4; #endif u_int8_t ip_tos; /*TOS服务质量*/ u_int16_t ip_length; /*总长度*/ u_int16_t ip_id; /*标识*/ u_int16_t ip_off; /*偏移*/ u_int8_t ip_ttl; /*生存时间*/ u_int8_t ip_protocol; /*协议类型*/ u_int16_t ip_checksum; /*校验和*/ struct in_addr ip_source_address; /*源IP*/ struct in_addr ip_destination_address; /*目的IP*/ } ip_header; typedef struct udp_header { u_int16_t src_port; u_int16_t dst_port; u_int16_t lens; u_int16_t check_sum; } udp_header; static int sock; unsigned short ip_check_sum(unsigned short *addr,int len) { unsigned short cksum; unsigned int sum=0; while(len>1) { sum+=*addr++; len-=2; } if(len==1) sum+=*(unsigned char*)addr; sum=(sum>>16)+(sum&0xffff); //把高位的进位,加到低八位,其实是32位加法 sum+=(sum>>16); //add carry cksum=~sum; //取反 return (cksum); } void sig_handle(int sig) { struct ifreq ethreq; if (sig == SIGTERM) { fprintf(stderr, "SIGTERM"); } else if (sig == SIGINT) { fprintf(stderr, "SIGINT"); } else if (sig == SIGQUIT) { fprintf(stderr, "SIGQUIT"); } strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ); if (ioctl(sock, SIOCGIFFLAGS, ðreq) != -1) { ethreq.ifr_flags &= ~IFF_PROMISC; ioctl(sock, SIOCSIFFLAGS, ðreq); } close(sock); exit(0); } int main(void) { int n; char buff[1024 * 2]; unsigned char *ethhead; unsigned char *iphead; struct ifreq ethreq; struct sigaction sighandle; struct sock_filter bpf_code[] = { { 0x28, 0, 0, 0x0000000c }, { 0x15, 0, 6, 0x000086dd }, { 0x30, 0, 0, 0x00000014 }, { 0x15, 0, 15, 0x00000011 }, { 0x28, 0, 0, 0x00000036 }, { 0x15, 12, 0, 0x000022ae }, { 0x28, 0, 0, 0x00000038 }, { 0x15, 10, 11, 0x000022ae }, { 0x15, 0, 10, 0x00000800 }, { 0x30, 0, 0, 0x00000017 }, { 0x15, 0, 8, 0x00000011 }, { 0x28, 0, 0, 0x00000014 }, { 0x45, 6, 0, 0x00001fff }, { 0xb1, 0, 0, 0x0000000e }, { 0x48, 0, 0, 0x0000000e }, { 0x15, 2, 0, 0x000022ae }, { 0x48, 0, 0, 0x00000010 }, { 0x15, 0, 1, 0x000022ae }, { 0x6, 0, 0, 0x0000ffff }, { 0x6, 0, 0, 0x00000000 } }; struct sock_fprog filter; filter.len = sizeof(bpf_code) / sizeof(bpf_code[0]); filter.filter = bpf_code; sighandle.sa_flags = 0; sighandle.sa_handler = sig_handle; sigemptyset(&sighandle.sa_mask); sigaction(SIGTERM, &sighandle, NULL); sigaction(SIGINT, &sighandle, NULL); sigaction(SIGQUIT, &sighandle, NULL); if ((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP))) == -1) { // if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) { perror("socket"); exit(1); } strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ); if (ioctl(sock, SIOCGIFFLAGS, ðreq) == -1) { perror("ioctl"); close(sock); exit(1); } ethreq.ifr_flags |= IFF_PROMISC; if (ioctl(sock, SIOCSIFFLAGS, ðreq) == -1) { perror("ioctl"); close(sock); exit(1); } if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) == -1) { perror("setsockopt"); close(sock); exit(1); } ip_header *p_ip_header = (ip_header *)(buff + sizeof(struct ether_header)); udp_header *p_udp_header = 0; while (1) { n = recvfrom(sock, buff, sizeof(buff), 0, 0, 0); if (n < (ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN)) { fprintf( stderr, "invalid packet\n"); continue ; } // printf("%d bytes reieved\n", n); ethhead = buff; if (ntohs(ethhead[12] | ethhead[13] << 8) != 0x0800) { continue ; } //ip头校验 if (ip_check_sum(p_ip_header, p_ip_header->ip_header_length * 4) != 0) { continue ; } if (p_ip_header->ip_protocol != UDP_PROTOCOL_TYPE) { continue ; } if (p_ip_header->ip_destination_address.s_addr != BROADCAST_ADDRESS) { continue ; } p_udp_header = (char *)p_ip_header + p_ip_header->ip_header_length * 4; if (htons(p_udp_header->dst_port) != BROADCAST_PORT) { continue ; } // printf("ip header lens: %d \n", p_ip_header->ip_header_length); // p_udp_header = buff + ETH_HDR_LEN + IP_HDR_LEN; printf("src port: %d ", htons(p_udp_header->src_port)); printf("dst port: %d ", htons(p_udp_header->dst_port)); printf("data lens: %d ", htons(p_udp_header->lens)); printf("check sum: %d.\n", p_udp_header->check_sum); // printf("ip: head_len[%d] offset[%d] ", p_ip_header->ip_header_length, // p_ip_header->ip_off); // printf("src ip: %s ", inet_ntoa((struct in_addr)p_ip_header->ip_source_address)); // printf("dst ip: %s. ", inet_ntoa((struct in_addr)p_ip_header->ip_destination_address)); // printf("%d\n", p_ip_header->ip_destination_address); // printf("Ethernet: MAC[%02X:%02X:%02X:%02X:%02X:%02X]", ethhead[0], ethhead[1], ethhead[2], // ethhead[3], ethhead[4], ethhead[5]); // printf("->[%02X:%02X:%02X:%02X:%02X:%02X]", ethhead[6], ethhead[7], ethhead[8], // ethhead[9], ethhead[10], ethhead[11]); // printf(" type[%04x]/n", (ntohs(ethhead[12]|ethhead[13]<<8))); } close(sock); exit(0); return 0; }