2017年1月20日 星期五

libpcap - List data-link type(15)


一個device可以支援不同種data-link類型,目前為止只看到Ethernet這類,libpcap可以列出該裝置所有支援的data-link類型,也可以切換類型。




那來列出預設device所支援的data-link類型。
    char errbuf[PCAP_ERRBUF_SIZE];
    char *device = NULL;

    //get default interface name
    device = pcap_lookupdev(errbuf);
    if(!device) {
        fprintf(stderr, "pcap_lookupdev(): %s\n", errbuf);
        exit(1);
    }//end if
    
    printf("Device: %s\n", device);

    //open handle
    pcap_t *handle = pcap_open_live(device, 65535, 1, 1, errbuf);
    if(!handle) {
        fprintf(stderr, "pcap_open_live(): %s\n", errbuf);
        exit(1);
    }//end if
先取得預設的device名稱,然後開啟它。


函數pcap_datalink()可以取得該裝置預設的data-link類型。
    //get defalt data-link type
    int default_dlt = pcap_datalink(handle);

函數pcap_datalink()原型:
int pcap_datalink(pcap_t *p);
  • 返回值:傳回p的data-link類型。
  • 參數:p一個libpcap handle。
  • 功能:取得p的data-link類型。


接著利用函數pcap_list_datalinks()來取得支援的data-link類型。
    //get data-link list
    int *dlts = NULL;
    int dlt_len = 0;
    if((dlt_len = pcap_list_datalinks(handle, &dlts)) == -1) {
        fprintf(stderr, "pcap_list_datalinks(): %s\n", pcap_geterr(handle));
        pcap_close(handle);
        exit(1);
    }//end if

函數pcap_list_datalinks()原型:
int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
  • 返回值:傳回p的data-link支援類型數量,失敗傳回-1。
  • 參數:p一個libpcap handle。dlt_buf結果陣列指標。
  • 功能:取得p所支援的data-link所有類型。

data-link層的類型都被marcos成保留字,都是DLT_開頭,乙太網路保留字為DLT_EN10MB,其他libpcap的保留字還有:
#define DLT_CHOICE(code, description) { #code, description, code }
#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }

static struct dlt_choice dlt_choices[] = {
    DLT_CHOICE(DLT_NULL, "BSD loopback"),
    DLT_CHOICE(DLT_EN10MB, "Ethernet"),
    DLT_CHOICE(DLT_IEEE802, "Token ring"),
    DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"),
    DLT_CHOICE(DLT_SLIP, "SLIP"),
    DLT_CHOICE(DLT_PPP, "PPP"),
    DLT_CHOICE(DLT_FDDI, "FDDI"),
    DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
    DLT_CHOICE(DLT_RAW, "Raw IP"),
    DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
    DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
    DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
    DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
    DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
    DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
    DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
    DLT_CHOICE(DLT_IEEE802_11, "802.11"),
    DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
    DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
    DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
    DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
    DLT_CHOICE(DLT_LTALK, "Localtalk"),
    DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
    DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"),
    DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
    DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
    DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
    DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"),
    DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
    DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
    DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
    DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"),
    DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"),
    DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
    DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
    DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
    DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
    DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
    DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
    DLT_CHOICE(DLT_MTP2, "SS7 MTP2"),
    DLT_CHOICE(DLT_MTP3, "SS7 MTP3"),
    DLT_CHOICE(DLT_SCCP, "SS7 SCCP"),
    DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
    DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
    DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
    DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
    DLT_CHOICE(DLT_BACNET_MS_TP, "BACnet MS/TP"),
    DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
    DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
    DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
    DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"),
    DLT_CHOICE(DLT_GPF_T, "GPF-T"),
    DLT_CHOICE(DLT_GPF_F, "GPF-F"),
    DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"),
    DLT_CHOICE(DLT_ERF_ETH,    "Ethernet with Endace ERF header"),
    DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"),
    DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"),
    DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"),
    DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"),
    DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"),
    DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"),
    DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"),
    DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"),
    DLT_CHOICE(DLT_A429, "Arinc 429"),
    DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"),
    DLT_CHOICE(DLT_USB, "USB"),
    DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
    DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
    DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"),
    DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"),
    DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
    DLT_CHOICE(DLT_PPI, "Per-Packet Information"),
    DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
    DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"),
    DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4 with FCS"),
    DLT_CHOICE(DLT_SITA, "SITA pseudo-header"),
    DLT_CHOICE(DLT_ERF, "Endace ERF header"),
    DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"),
    DLT_CHOICE(DLT_IPMB, "IPMB"),
    DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"),
    DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
    DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"),
    DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
    DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"),
    DLT_CHOICE(DLT_LINUX_EVDEV, "Linux evdev events"),
    DLT_CHOICE(DLT_USB_LINUX_MMAPPED, "USB with padded Linux header"),
    DLT_CHOICE(DLT_DECT, "DECT"),
    DLT_CHOICE(DLT_AOS, "AOS Space Data Link protocol"),
    DLT_CHOICE(DLT_WIHART, "Wireless HART"),
    DLT_CHOICE(DLT_FC_2, "Fibre Channel FC-2"),
    DLT_CHOICE(DLT_FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
    DLT_CHOICE(DLT_IPNET, "Solaris ipnet"),
    DLT_CHOICE(DLT_CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
    DLT_CHOICE(DLT_IPV4, "Raw IPv4"),
    DLT_CHOICE(DLT_IPV6, "Raw IPv6"),
    DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
    DLT_CHOICE(DLT_DBUS, "D-Bus"),
    DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"),
    DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"),
    DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
    DLT_CHOICE(DLT_DVB_CI, "DVB-CI"),
    DLT_CHOICE(DLT_MUX27010, "MUX27010"),
    DLT_CHOICE(DLT_STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
    DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
    DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"),
    DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
    DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
    DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"),
    DLT_CHOICE(DLT_MPEG_2_TS, "MPEG-2 transport stream"),
    DLT_CHOICE(DLT_NG40, "ng40 protocol tester Iub/Iur"),
    DLT_CHOICE(DLT_NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
    DLT_CHOICE(DLT_INFINIBAND, "InfiniBand"),
    DLT_CHOICE(DLT_SCTP, "SCTP"),
    DLT_CHOICE(DLT_USBPCAP, "USB with USBPcap header"),
    DLT_CHOICE(DLT_RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
    DLT_CHOICE(DLT_BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
    DLT_CHOICE(DLT_NETLINK, "Linux netlink"),
    DLT_CHOICE(DLT_BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
    DLT_CHOICE(DLT_BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
    DLT_CHOICE(DLT_BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
    DLT_CHOICE(DLT_PROFIBUS_DL, "PROFIBUS data link layer"),
    DLT_CHOICE(DLT_PKTAP, "Apple DLT_PKTAP"),
    DLT_CHOICE(DLT_EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
    DLT_CHOICE_SENTINEL
};


接著把它列印出來,函數pcap_datalink_val_to_name()可以把類型轉成名稱;函數pcap_datalink_val_to_description()可以把類型轉成詳細的描述;另外當data-link類型為預設的類型再另外標示出來。
    for(int i = 0 ; i < dlt_len ; i++) {
        printf("%d", i + 1);
        printf(": %s(%s)",
            pcap_datalink_val_to_name(dlts[i]),
            pcap_datalink_val_to_description(dlts[i]));

        if(default_dlt == dlts[i]) {
            printf(" [default]");
        }//end if data-link type is default
        printf("\n");
    }//end for

函數pcap_datalink_val_to_name()原型:
const char *pcap_datalink_val_to_name(int dlt);
  • 返回值:傳回dlt的字串名稱。
  • 參數:dlt要取得字串名稱的data-link類型。
  • 功能:取得dlt的字串名稱。

函數pcap_datalink_val_to_description()原型:
const char *pcap_datalink_val_to_description(int dlt);
  • 返回值:傳回dlt的字串描述。
  • 參數:dlt要取得字串描述的data-link類型。
  • 功能:取得dlt的字串描述。


最後記得data-link類型的陣列是需要被釋放的。
    //free
    pcap_free_datalinks(dlts);
    pcap_close(handle);

函數pcap_free_datalinks()原型:
void pcap_free_datalinks(int *dlt_buf);
  • 參數:dlt_buf要釋放的指標。
  • 功能:釋放從pcap_list_datalinks()取得的指標。


編譯:
libpcap % gcc -I/usr/local/opt/libpcap/include -Wall -std=gnu99 -L/usr/local/opt/libpcap/lib -lpcap  list-data-link-type.c -o list-data-link-type


執行結果:
libpcap % ./list-data-link-type   
Device: en0
1: EN10MB(Ethernet) [default]
2: PPI(Per-Packet Information)
3: IEEE802_11_RADIO(802.11 plus radiotap header)
4: IEEE802_11(802.11)
5: IEEE802_11_RADIO_AVS(802.11 plus AVS radio information header)
6: RAW(Raw IP)


另外關於修改data-link類型,可以使用函數pcap_set_datalink()來達成,這邊就不多介紹了(修改後第二層解析方式就不一定是Ethernet了)。

函數pcap_set_datalink()原型:
int pcap_set_datalink(pcap_t *p, int dlt);
  • 返回值:成功傳回0,失敗傳回-1,錯誤訊息從pcap_geterr()取得。
  • 參數:p一個libpcap handle。dlt要修改得類型。
  • 功能:修改打開handle的data-link類型,會因為類型不同所抓到的封包完全不同方式解析。

Source code on Github


沒有留言:

張貼留言