2013-01-09 28 views
0

我正在写一个隧道内核模块,我想为自己的处理程序注册一个特定的UDP端口。什么是最好的方式来做到这一点?这个想法是注册该处理程序,以便当该端口上的流量到达时,linux堆栈将调用我的处理程序。Linux内核:为特定的UDP端口流量注册处理程序?

[EDIT1]

通过套接字API的方法是结合于插座这样

sin.sin_family = AF_INET; 
sin.sin_addr.s_addr = htonl(INADDR_ANY); 
sin.sin_port = htons(my_port); 

err = kernel_bind(rcv_socket, (struct sockaddr *)&sin, 
     sizeof(struct sockaddr_in)); 

udp_sk(rcv_socket->sk)->encap_rcv = my_handler; 

的问题是,该插座与INADDR_ANY相关联,其对应于任何主机IP的在机器上。我想为数据包中的任何IP执行此操作?这怎么能实现?

插座不能在这种情况下使用我认为,因为任何IP意味着在堆栈中数据包通过ip_forward路径而不是ip_local_delivery。将不会有这样的数据包套接字。如何在这种情况下实现它?

+0

为什么你需要在内核模式下做到这一点?您所描述的要求似乎对于使用套接字API执行的用户模式应用程序来说是完全正常的事情... –

+0

@ChrisStratton我理解您的担忧,但此需求是需要在内部构建的更大图片的一部分内核。 – auny

+0

我不是一个超级专家,但我认为你无法获得需要使用侦听传输层数据的套接字转发的数据包。在以太网级别工作的原始套接字怎么样?我知道这可能是一个痛苦=( –

回答

-1

我不知道相关的内核级别的功能,但我建议绑定到侦听第2层帧的RAW SOCKET,并使用ip包的进一步过滤器。

像这样:

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));

那么它是由你来剖析框架和提取您只需要UDP数据包。

在第2层工作应该会授予您100%通过主机传输的IP数据包。

0

向下投票:请评论为什么你投下了这个经过测试的答案?

以下示例很有帮助。根据需要,您可以通过添加过滤器来修改示例。

对于UDP以下变化需要存在在下面的例子中

sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_UDP);

http://www.binarytides.com/packet-sniffer-code-in-c-using-linux-sockets-bsd/ http://www.binarytides.com/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/ [相关性]

我列出的代码FYI

#include<netinet/in.h> 
#include<errno.h> 
#include<netdb.h> 
#include<stdio.h> //For standard things 
#include<stdlib.h> //malloc 
#include<string.h> //strlen 

#include<netinet/ip_icmp.h> //Provides declarations for icmp header 
#include<netinet/udp.h> //Provides declarations for udp header 
#include<netinet/tcp.h> //Provides declarations for tcp header 
#include<netinet/ip.h> //Provides declarations for ip header 
#include<netinet/if_ether.h> //For ETH_P_ALL 
#include<net/ethernet.h> //For ether_header 
#include<sys/socket.h> 
#include<arpa/inet.h> 
#include<sys/ioctl.h> 
#include<sys/time.h> 
#include<sys/types.h> 
#include<unistd.h> 

void ProcessPacket(unsigned char* , int); 
void print_ip_header(unsigned char* , int); 
void print_tcp_packet(unsigned char * , int); 
void print_udp_packet(unsigned char * , int); 
void print_icmp_packet(unsigned char* , int); 
void PrintData (unsigned char* , int); 

FILE *logfile; 
struct sockaddr_in source,dest; 
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j; 

int main() 
{ 
    int saddr_size , data_size; 
    struct sockaddr saddr; 

    unsigned char *buffer = (unsigned char *) malloc(65536); //Its Big! 

    logfile=fopen("log.txt","w"); 
    if(logfile==NULL) 
    { 
     printf("Unable to create log.txt file."); 
    } 
    printf("Starting...\n"); 

    int sock_raw = socket(AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ; 
    //setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , "eth0" , strlen("eth0")+ 1); 

    if(sock_raw < 0) 
    { 
     //Print the error with proper message 
     perror("Socket Error"); 
     return 1; 
    } 
    while(1) 
    { 
     saddr_size = sizeof saddr; 
     //Receive a packet 
     data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size); 
     if(data_size <0) 
     { 
      printf("Recvfrom error , failed to get packets\n"); 
      return 1; 
     } 
     //Now process the packet 
     ProcessPacket(buffer , data_size); 
    } 
    close(sock_raw); 
    printf("Finished"); 
    return 0; 
} 

void ProcessPacket(unsigned char* buffer, int size) 
{ 
    //Get the IP Header part of this packet , excluding the ethernet header 
    struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr)); 
    ++total; 
    switch (iph->protocol) //Check the Protocol and do accordingly... 
    { 
     case 1: //ICMP Protocol 
      ++icmp; 
      print_icmp_packet(buffer , size); 
      break; 

     case 2: //IGMP Protocol 
      ++igmp; 
      break; 

     case 6: //TCP Protocol 
      ++tcp; 
      print_tcp_packet(buffer , size); 
      break; 

     case 17: //UDP Protocol 
      ++udp; 
      print_udp_packet(buffer , size); 
      break; 

     default: //Some Other Protocol like ARP etc. 
      ++others; 
      break; 
    } 
    printf("TCP : %d UDP : %d ICMP : %d IGMP : %d Others : %d Total : %d\r", tcp , udp , icmp , igmp , others , total); 
} 

void print_ethernet_header(unsigned char* Buffer, int Size) 
{ 
    struct ethhdr *eth = (struct ethhdr *)Buffer; 

    fprintf(logfile , "\n"); 
    fprintf(logfile , "Ethernet Header\n"); 
    fprintf(logfile , " |-Destination Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n", eth->h_dest[0] , eth->h_dest[1] , eth->h_dest[2] , eth->h_dest[3] , eth->h_dest[4] , eth->h_dest[5]); 
    fprintf(logfile , " |-Source Address  : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n", eth->h_source[0] , eth->h_source[1] , eth->h_source[2] , eth->h_source[3] , eth->h_source[4] , eth->h_source[5]); 
    fprintf(logfile , " |-Protocol   : %u \n",(unsigned short)eth->h_proto); 
} 

void print_ip_header(unsigned char* Buffer, int Size) 
{ 
    print_ethernet_header(Buffer , Size); 

    unsigned short iphdrlen; 

    struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr)); 
    iphdrlen =iph->ihl*4; 

    memset(&source, 0, sizeof(source)); 
    source.sin_addr.s_addr = iph->saddr; 

    memset(&dest, 0, sizeof(dest)); 
    dest.sin_addr.s_addr = iph->daddr; 

    fprintf(logfile , "\n"); 
    fprintf(logfile , "IP Header\n"); 
    fprintf(logfile , " |-IP Version  : %d\n",(unsigned int)iph->version); 
    fprintf(logfile , " |-IP Header Length : %d DWORDS or %d Bytes\n",(unsigned int)iph->ihl,((unsigned int)(iph->ihl))*4); 
    fprintf(logfile , " |-Type Of Service : %d\n",(unsigned int)iph->tos); 
    fprintf(logfile , " |-IP Total Length : %d Bytes(Size of Packet)\n",ntohs(iph->tot_len)); 
    fprintf(logfile , " |-Identification : %d\n",ntohs(iph->id)); 
    //fprintf(logfile , " |-Reserved ZERO Field : %d\n",(unsigned int)iphdr->ip_reserved_zero); 
    //fprintf(logfile , " |-Dont Fragment Field : %d\n",(unsigned int)iphdr->ip_dont_fragment); 
    //fprintf(logfile , " |-More Fragment Field : %d\n",(unsigned int)iphdr->ip_more_fragment); 
    fprintf(logfile , " |-TTL  : %d\n",(unsigned int)iph->ttl); 
    fprintf(logfile , " |-Protocol : %d\n",(unsigned int)iph->protocol); 
    fprintf(logfile , " |-Checksum : %d\n",ntohs(iph->check)); 
    fprintf(logfile , " |-Source IP  : %s\n",inet_ntoa(source.sin_addr)); 
    fprintf(logfile , " |-Destination IP : %s\n",inet_ntoa(dest.sin_addr)); 
} 

void print_tcp_packet(unsigned char* Buffer, int Size) 
{ 
    unsigned short iphdrlen; 

    struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr)); 
    iphdrlen = iph->ihl*4; 

    struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr)); 

    int header_size = sizeof(struct ethhdr) + iphdrlen + tcph->doff*4; 

    fprintf(logfile , "\n\n***********************TCP Packet*************************\n"); 

    print_ip_header(Buffer,Size); 

    fprintf(logfile , "\n"); 
    fprintf(logfile , "TCP Header\n"); 
    fprintf(logfile , " |-Source Port  : %u\n",ntohs(tcph->source)); 
    fprintf(logfile , " |-Destination Port : %u\n",ntohs(tcph->dest)); 
    fprintf(logfile , " |-Sequence Number : %u\n",ntohl(tcph->seq)); 
    fprintf(logfile , " |-Acknowledge Number : %u\n",ntohl(tcph->ack_seq)); 
    fprintf(logfile , " |-Header Length  : %d DWORDS or %d BYTES\n" ,(unsigned int)tcph->doff,(unsigned int)tcph->doff*4); 
    //fprintf(logfile , " |-CWR Flag : %d\n",(unsigned int)tcph->cwr); 
    //fprintf(logfile , " |-ECN Flag : %d\n",(unsigned int)tcph->ece); 
    fprintf(logfile , " |-Urgent Flag   : %d\n",(unsigned int)tcph->urg); 
    fprintf(logfile , " |-Acknowledgement Flag : %d\n",(unsigned int)tcph->ack); 
    fprintf(logfile , " |-Push Flag   : %d\n",(unsigned int)tcph->psh); 
    fprintf(logfile , " |-Reset Flag   : %d\n",(unsigned int)tcph->rst); 
    fprintf(logfile , " |-Synchronise Flag  : %d\n",(unsigned int)tcph->syn); 
    fprintf(logfile , " |-Finish Flag   : %d\n",(unsigned int)tcph->fin); 
    fprintf(logfile , " |-Window   : %d\n",ntohs(tcph->window)); 
    fprintf(logfile , " |-Checksum  : %d\n",ntohs(tcph->check)); 
    fprintf(logfile , " |-Urgent Pointer : %d\n",tcph->urg_ptr); 
    fprintf(logfile , "\n"); 
    fprintf(logfile , "      DATA Dump       "); 
    fprintf(logfile , "\n"); 

    fprintf(logfile , "IP Header\n"); 
    PrintData(Buffer,iphdrlen); 

    fprintf(logfile , "TCP Header\n"); 
    PrintData(Buffer+iphdrlen,tcph->doff*4); 

    fprintf(logfile , "Data Payload\n");  
    PrintData(Buffer + header_size , Size - header_size); 

    fprintf(logfile , "\n###########################################################"); 
} 

void print_udp_packet(unsigned char *Buffer , int Size) 
{ 

    unsigned short iphdrlen; 

    struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr)); 
    iphdrlen = iph->ihl*4; 

    struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr)); 

    int header_size = sizeof(struct ethhdr) + iphdrlen + sizeof udph; 

    fprintf(logfile , "\n\n***********************UDP Packet*************************\n"); 

    print_ip_header(Buffer,Size);   

    fprintf(logfile , "\nUDP Header\n"); 
    fprintf(logfile , " |-Source Port  : %d\n" , ntohs(udph->source)); 
    fprintf(logfile , " |-Destination Port : %d\n" , ntohs(udph->dest)); 
    fprintf(logfile , " |-UDP Length  : %d\n" , ntohs(udph->len)); 
    fprintf(logfile , " |-UDP Checksum  : %d\n" , ntohs(udph->check)); 

    fprintf(logfile , "\n"); 
    fprintf(logfile , "IP Header\n"); 
    PrintData(Buffer , iphdrlen); 

    fprintf(logfile , "UDP Header\n"); 
    PrintData(Buffer+iphdrlen , sizeof udph); 

    fprintf(logfile , "Data Payload\n");  

    //Move the pointer ahead and reduce the size of string 
    PrintData(Buffer + header_size , Size - header_size); 

    fprintf(logfile , "\n###########################################################"); 
} 

void print_icmp_packet(unsigned char* Buffer , int Size) 
{ 
    unsigned short iphdrlen; 

    struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr)); 
    iphdrlen = iph->ihl * 4; 

    struct icmphdr *icmph = (struct icmphdr *)(Buffer + iphdrlen + sizeof(struct ethhdr)); 

    int header_size = sizeof(struct ethhdr) + iphdrlen + sizeof icmph; 

    fprintf(logfile , "\n\n***********************ICMP Packet*************************\n"); 

    print_ip_header(Buffer , Size); 

    fprintf(logfile , "\n"); 

    fprintf(logfile , "ICMP Header\n"); 
    fprintf(logfile , " |-Type : %d",(unsigned int)(icmph->type)); 

    if((unsigned int)(icmph->type) == 11) 
    { 
     fprintf(logfile , " (TTL Expired)\n"); 
    } 
    else if((unsigned int)(icmph->type) == ICMP_ECHOREPLY) 
    { 
     fprintf(logfile , " (ICMP Echo Reply)\n"); 
    } 

    fprintf(logfile , " |-Code : %d\n",(unsigned int)(icmph->code)); 
    fprintf(logfile , " |-Checksum : %d\n",ntohs(icmph->checksum)); 
    //fprintf(logfile , " |-ID  : %d\n",ntohs(icmph->id)); 
    //fprintf(logfile , " |-Sequence : %d\n",ntohs(icmph->sequence)); 
    fprintf(logfile , "\n"); 

    fprintf(logfile , "IP Header\n"); 
    PrintData(Buffer,iphdrlen); 

    fprintf(logfile , "UDP Header\n"); 
    PrintData(Buffer + iphdrlen , sizeof icmph); 

    fprintf(logfile , "Data Payload\n");  

    //Move the pointer ahead and reduce the size of string 
    PrintData(Buffer + header_size , (Size - header_size)); 

    fprintf(logfile , "\n###########################################################"); 
} 

void PrintData (unsigned char* data , int Size) 
{ 
    int i , j; 
    for(i=0 ; i < Size ; i++) 
    { 
     if(i!=0 && i%16==0) //if one line of hex printing is complete... 
     { 
      fprintf(logfile , "   "); 
      for(j=i-16 ; j<i ; j++) 
      { 
       if(data[j]>=32 && data[j]<=128) 
        fprintf(logfile , "%c",(unsigned char)data[j]); //if its a number or alphabet 

       else fprintf(logfile , "."); //otherwise print a dot 
      } 
      fprintf(logfile , "\n"); 
     } 

     if(i%16==0) fprintf(logfile , " "); 
      fprintf(logfile , " %02X",(unsigned int)data[i]); 

     if(i==Size-1) //print the last spaces 
     { 
      for(j=0;j<15-i%16;j++) 
      { 
       fprintf(logfile , " "); //extra spaces 
      } 

      fprintf(logfile , "   "); 

      for(j=i-i%16 ; j<=i ; j++) 
      { 
       if(data[j]>=32 && data[j]<=128) 
       { 
        fprintf(logfile , "%c",(unsigned char)data[j]); 
       } 
       else 
       { 
        fprintf(logfile , "."); 
       } 
      } 

      fprintf(logfile , "\n"); 
     } 
    } 
} 

在Linux运行带有前缀“sudo”的代码。 :)

相关问题