2014-10-09 4 views
2

Я пытаюсь создать программу для чтения, учитывая IP-адрес и порт (в данном случае на localhost), UDP-пакетов в Mac OS X (текущая версия 10.9.5).Как читать и отправлять UDP-пакеты в Mac OS X?

Единственный, который дал мне полезные данные, - tcpdump и nc (netcat), но он работал только 1 раз. Это то, что я сделал:

1 ° терминальное окно

$ sudo tcpdump -i en0 -X -v 'udp port 60000' 
tcpdump: listening on en0, link-type EN10MB (Ethernet), capture size 65535 bytes 
* new packet with the string 'Hello' at the end * 

2 ° терминальное окно

$ nc -u 192.168.1.67 60000 
Hello 
$ 

У меня нет много знаний по этому аргументу, поэтому окончательное вопрос:

Если мне нужно создать программу, которая должна прочитать любой UDP-пакет с указанием номера порта и отправить UDP-пакеты через один и тот же порт на любой IP-адрес, что самый простой подход? Я пытался использовать libpcap через C, но безуспешно.

+0

I.e., вы хотите получать все UDP-пакеты, отправленные на определенный порт на вашем компьютере, и отвечать на эти UDP-пакеты? И нет необходимости видеть какие-либо пакеты * другие *, чем те пакеты, то есть, если они отправляются на другую машину или отправляются на ваш компьютер, но не являются пакетом UDP, или если это пакет UDP, отправленный на ваша машина, но не этот порт, вам не нужно это видеть? Если это так, вам не нужно использовать libpcap, вы можете просто использовать обычные UDP-сокеты. –

ответ

4

Я решил проблему с Libpcap использования библиотеки C:

main.c

#include <pcap.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netinet/if_ether.h> 
#include <netinet/ip.h> 
#include <string.h> 

void my_callback(u_char *user, const struct pcap_pkthdr *pkthdr, const u_char *packet) { 

    int i = 0; 
    int k = 0; 

    for (i = 0; i < pkthdr->len; i++) { 
     if ((i % 16) == 0) { 
      fprintf(stdout, "\n%03x0\t", k); 
      k++; 
     } 
     fprintf(stdout, "%02x ", packet[i]); 
    } 

    fprintf(stdout, "\n*******************************************************\n"); 

    u_char ethernet_packet[14]; 
    u_char ip_header[24]; 
    u_char udp_header[8]; 
    int udp_header_start = 34; 
    int data_length; 

    for (i = 0; i < 14; i++) { 
     ethernet_packet[i] = packet[0 + i]; 
    } 

    fprintf(stdout, "Destination Address\t\t%02X:%02X:%02X:%02X:%02X:%02X\n", ethernet_packet[0], ethernet_packet[1], ethernet_packet[2], ethernet_packet[3], ethernet_packet[4], ethernet_packet[5]); 
    fprintf(stdout, "Source Address\t\t\t%02X:%02X:%02X:%02X:%02X:%02X\n", ethernet_packet[6], ethernet_packet[7], ethernet_packet[8], ethernet_packet[9], ethernet_packet[10], ethernet_packet[11]); 

    if (ethernet_packet[12] == 0x08 && 
     ethernet_packet[13] == 0x00) { 

     fprintf(stdout, "Ethertype\t\t\t\tIP Packet\n"); 

     for (i = 0; i < 20; i++) { 
      ip_header[i] = packet[14 + i]; 
     } 

     fprintf(stdout, "Version\t\t\t\t\t%d\n", (ip_header[0] >> 4)); 
     fprintf(stdout, "IHL\t\t\t\t\t\t%d\n", (ip_header[0] & 0x0F)); 
     fprintf(stdout, "Type of Service\t\t\t%d\n", ip_header[1]); 
     fprintf(stdout, "Total Length\t\t\t%d\n", ip_header[2]); 
     fprintf(stdout, "Identification\t\t\t0x%02x 0x%02x\n", ip_header[3], ip_header[4]); 
     fprintf(stdout, "Flags\t\t\t\t\t%d\n", ip_header[5] >> 5); 
     fprintf(stdout, "Fragment Offset\t\t\t%d\n", (((ip_header[5] & 0x1F) << 8) + ip_header[6])); 
     fprintf(stdout, "Time To Live\t\t\t%d\n", ip_header[7]); 
     if (ip_header[9] == 0x11) { 

      fprintf(stdout, "Protocol\t\t\t\tUDP\n"); 
     } 
     else { 
      fprintf(stdout, "Protocol\t\t\t\t%d\n", ip_header[9]); 
     } 
     fprintf(stdout, "Header Checksum\t\t\t0x%02x 0x%02x\n", ip_header[10], ip_header[11]); 
     fprintf(stdout, "Source Address\t\t\t%d.%d.%d.%d\n", ip_header[12], ip_header[13], ip_header[14], ip_header[15]); 
     fprintf(stdout, "Destination Address\t\t%d.%d.%d.%d\n", ip_header[16], ip_header[17], ip_header[18], ip_header[19]); 
     if ((ip_header[0] & 0x0F) > 5) { 
      udp_header_start = 48; 
      fprintf(stdout, "Options\t\t\t\t\t0x%02x 0x%02x 0x%02x 0x%02x\n", ip_header[20], ip_header[21], ip_header[22], ip_header[23]); 
     } 

     if (ip_header[9] == 0x11) { 

      fprintf(stdout, "\t\t\t\tUDP HEADER\n"); 

      for (i = 0; i < 8; i++) { 
       udp_header[i] = packet[udp_header_start + i]; 
      } 

      fprintf(stdout, "Source Port\t\t\t\t%d\n", (udp_header[0] << 8) + udp_header[1]); 
      fprintf(stdout, "Destination Port\t\t%d\n", (udp_header[2] << 8) + udp_header[3]); 
      fprintf(stdout, "Length\t\t\t\t\t%d\n", (udp_header[4] << 8) + udp_header[5]); 
      fprintf(stdout, "Checksum\t\t\t\t0x%02x 0x%02x\n", udp_header[6], udp_header[7]); 

      data_length = pkthdr->len - (udp_header_start + 8); 

      fprintf(stdout, "Data\n"); 
      for (i = 0; i < data_length; i++) { 

       fprintf(stdout, "%02x ", packet[udp_header_start + 8 + i]); 
      } 
      fprintf(stdout, "\n"); 
     } 
    } 
    else { 
     fprintf(stdout, "Ethertype\t\t\t\tUnknow\n"); 
    } 
} 

int main(int argc,char **argv) { 

    char *dev; 
    char errbuf[PCAP_ERRBUF_SIZE]; 
    pcap_t* descr; 
    struct bpf_program fp; 
    bpf_u_int32 maskp; 
    bpf_u_int32 netp; 

    dev = pcap_lookupdev(errbuf); 
    if(dev == NULL) { 
     fprintf(stderr,"%s\n",errbuf); exit(1); 
    } 

    pcap_lookupnet(dev, &netp, &maskp, errbuf); 
    descr = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf); 

    if(descr == NULL) { 
     printf("pcap_open_live(): %s\n",errbuf); 
     exit(1); 
    } 

    char filter[] = "udp"; 
    if(pcap_compile(descr,&fp, filter,0,netp) == -1) { 
     fprintf(stderr,"Error calling pcap_compile\n"); 
     exit(1); 
    } 

    if(pcap_setfilter(descr,&fp) == -1) { 
     fprintf(stderr,"Error setting filter\n"); 
     exit(1); 

    } 

    pcap_loop(descr,-1,my_callback,NULL);  

    /* write a packet 
    //define a new packet and for each position set its values 
    u_char packet[86]; 


    // Send down the packet 
    if (pcap_sendpacket(descr, packet, 86) != 0) { 

     fprintf(stderr,"\nError sending the packet: %s\n", pcap_geterr(descr)); 
     return 2; 
    } 
    */ 
    return 0; 
} 

Идея заключается в том, что мы выбираем пакет через pcap_loop и анализируют данные, мы получаем:

В моем случае у меня есть заголовок Ethernet при запуске, я использовал Википедию, чтобы понять, как это делается Ethernet frame. EtherType установлен в 0x0800, что показывает, что следующие байты: IP HeaderIPv4 Header. здесь показывает, что это UDP PacketUDP Packet Structure.

Я скомпилировал это на OS X 10.9 через Xcode с библиотекой pcap, и он работает отлично. Единственная проблема в том, что это действительно статично, для этого требуется Ethernet и работает только для IPv4.

+0

Спасибо за ответ. Существует ли такая же реализация my_callback(), но для пакета TCP? – Sergio

+0

для TCP совершенно разные, начиная с заголовка, UDP один проще и проще https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure У меня нет реализации TCP в данный момент – genesisxyz