抓取udp广播包

#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, &ethreq) != -1) {
        ethreq.ifr_flags &= ~IFF_PROMISC;
        ioctl(sock, SIOCSIFFLAGS, &ethreq);
    }
    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, &ethreq) == -1) {
        perror("ioctl");
        close(sock);
        exit(1);
    }

    ethreq.ifr_flags |= IFF_PROMISC;
    if (ioctl(sock, SIOCSIFFLAGS, &ethreq) == -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;
}

 

转载于:https://www.cnblogs.com/hacqing/archive/2012/08/13/2636158.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值