2014-10-09 3 views
2

Mac OS X (현재 버전 10.9.5)의 UDP 패킷에 대해 IP 주소와 포트 (이 경우 localhost), 읽기 용 프로그램을 만들려고합니다.Mac OS X에서 UDP 패킷을 읽고 보내는 방법은 무엇입니까?

나에게 유용한 데이터를 준 유일한 사람은 tcpdump와 nc (netcat)이지만 한 번만 작동했습니다. 이것은 내가 무엇을했는지 있습니다 :

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 패킷을 보내야하는 프로그램을 작성해야하는 경우, 가장 쉬운 방법은? C를 통해 libpcap을 사용하려고했지만 성공하지 못했습니다.

+0

즉 컴퓨터의 특정 포트로 전송 된 모든 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 frame을 사용했다. EtherType은 0x0800로 설정되어 다음 바이트가 IP HeaderIPv4 Header임을 나타냅니다. 여기서 은 UDP PacketUDP Packet Structure입니다.

나는 pcap 라이브러리로 Xcode를 통해 OS X 10.9에서 이것을 컴파일했고, 정상적으로 작동합니다. 유일한 문제는 이것이 실제로 정적이라는 것입니다. 이더넷이 필요하며 IPv4에서만 작동합니다.

+0

답변 해 주셔서 감사합니다. my_callback()의 ​​동일한 구현이 있지만 TCP 패킷을위한 것입니까? TCP에 대한 – Sergio

+0

은 헤더와 완전히 다르다. UDP는 간단하고 간단하다. https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure 현재 TCP 구현이 준비되어 있지 않다. – genesisxyz

관련 문제