123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- /*
- * SpanDSP - a series of DSP components for telephony
- *
- * pcap_parse.c
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2009 Steve Underwood
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Some code from SIPP (http://sf.net/projects/sipp) was used as a model
- * for how to work with PCAP files. That code was authored by Guillaume
- * TEISSIER from FTR&D 02/02/2006, and released under the GPL2 licence.
- */
- #if defined(HAVE_CONFIG_H)
- #include "config.h"
- #endif
- #include <inttypes.h>
- #include <stdlib.h>
- #include <stdio.h>
- #if defined(HAVE_PCAP_H)
- #include <pcap.h>
- #endif
- #include <netinet/in.h>
- #include <netinet/udp.h>
- #if defined(__HPUX) || defined(__CYGWIN__) || defined(__FreeBSD__)
- #include <netinet/in_systm.h>
- #endif
- #include <netinet/ip.h>
- #if !defined(__CYGWIN__)
- #include <netinet/ip6.h>
- #endif
- #include <string.h>
- #include <netinet/in.h>
- #include <netinet/udp.h>
- #include <time.h>
- #include "udptl.h"
- #include "spandsp.h"
- #include "pcap_parse.h"
- #if defined(__HPUX) || defined(__DARWIN) || defined(__CYGWIN__) || defined(__FreeBSD__)
- struct iphdr
- {
- #if defined(_HPUX_LI)
- unsigned int ihl:4;
- unsigned int version:4;
- #else
- unsigned int version:4;
- unsigned int ihl:4;
- #endif
- uint8_t tos;
- uint16_t tot_len;
- uint16_t id;
- uint16_t frag_off;
- uint8_t ttl;
- uint8_t protocol;
- uint16_t check;
- uint32_t saddr;
- uint32_t daddr;
- /*The options start here. */
- };
- #endif
- /* We define our own structures for Ethernet Header and IPv6 Header as they are not available on CYGWIN.
- * We only need the fields, which are necessary to determine the type of the next header.
- * we could also define our own structures for UDP and IPv4. We currently use the structures
- * made available by the platform, as we had no problems to get them on all supported platforms.
- */
- typedef struct _ether_hdr
- {
- char ether_dst[6];
- char ether_src[6];
- uint16_t ether_type;
- } ether_hdr;
- typedef struct _linux_sll_hdr
- {
- uint16_t packet_type;
- uint16_t arphrd;
- uint16_t slink_length;
- uint8_t bytes[8];
- uint16_t ether_type;
- } linux_sll_hdr;
- typedef struct _null_hdr
- {
- uint32_t pf_type;
- } null_hdr;
- #if !defined(__CYGWIN__)
- typedef struct _ipv6_hdr
- {
- char dontcare[6];
- u_int8_t nxt_header; /* we only need the next header, so we can determine, if the next header is UDP or not */
- char dontcare2[33];
- } ipv6_hdr;
- #endif
- char errbuf[PCAP_ERRBUF_SIZE];
- int pcap_scan_pkts(const char *file,
- uint32_t src_addr,
- uint16_t src_port,
- uint32_t dest_addr,
- uint16_t dest_port,
- pcap_timing_update_handler_t *timing_update_handler,
- pcap_packet_handler_t *packet_handler,
- void *user_data)
- {
- pcap_t *pcap;
- struct pcap_pkthdr *pkthdr;
- uint8_t *pktdata;
- const uint8_t *body;
- int body_len;
- int total_pkts;
- uint32_t pktlen;
- ether_hdr *ethhdr;
- linux_sll_hdr *sllhdr;
- null_hdr *nullhdr;
- struct iphdr *iphdr;
- #if !defined(__CYGWIN__)
- ipv6_hdr *ip6hdr;
- #endif
- struct udphdr *udphdr;
- int datalink;
- int packet_type;
- total_pkts = 0;
- if ((pcap = pcap_open_offline(file, errbuf)) == NULL)
- {
- fprintf(stderr, "Can't open PCAP file '%s'\n", file);
- return -1;
- }
- datalink = pcap_datalink(pcap);
- /* DLT_EN10MB seems to apply to all forms of ethernet, not just the 10MB kind. */
- switch (datalink)
- {
- case DLT_EN10MB:
- printf("Datalink type ethernet\n");
- break;
- case DLT_LINUX_SLL:
- printf("Datalink type cooked Linux socket\n");
- break;
- case DLT_NULL:
- printf("Datalink type NULL\n");
- break;
- default:
- fprintf(stderr, "Unsupported data link type %d\n", datalink);
- return -1;
- }
- pkthdr = NULL;
- pktdata = NULL;
- #if defined(HAVE_PCAP_NEXT_EX)
- while (pcap_next_ex(pcap, &pkthdr, (const uint8_t **) &pktdata) == 1)
- {
- #else
- if ((pkthdr = (struct pcap_pkthdr *) malloc(sizeof(*pkthdr))) == NULL)
- {
- fprintf(stderr, "Can't allocate memory for pcap pkthdr\n");
- return -1;
- }
- while ((pktdata = (uint8_t *) pcap_next(pcap, pkthdr)) != NULL)
- {
- #endif
- switch (datalink)
- {
- case DLT_EN10MB:
- ethhdr = (ether_hdr *) pktdata;
- packet_type = ntohs(ethhdr->ether_type);
- #if !defined(__CYGWIN__)
- if (packet_type != 0x0800 /* IPv4 */
- &&
- packet_type != 0x86DD) /* IPv6 */
- #else
- if (packet_type != 0x0800) /* IPv4 */
- #endif
- {
- continue;
- }
- iphdr = (struct iphdr *) ((uint8_t *) ethhdr + sizeof(*ethhdr));
- break;
- case DLT_LINUX_SLL:
- sllhdr = (linux_sll_hdr *) pktdata;
- packet_type = ntohs(sllhdr->ether_type);
- #if !defined(__CYGWIN__)
- if (packet_type != 0x0800 /* IPv4 */
- &&
- packet_type != 0x86DD) /* IPv6 */
- #else
- if (packet_type != 0x0800) /* IPv4 */
- #endif
- {
- continue;
- }
- iphdr = (struct iphdr *) ((uint8_t *) sllhdr + sizeof(*sllhdr));
- break;
- case DLT_NULL:
- nullhdr = (null_hdr *) pktdata;
- if (nullhdr->pf_type != PF_INET && nullhdr->pf_type != PF_INET6)
- continue;
- iphdr = (struct iphdr *) ((uint8_t *) nullhdr + sizeof(*nullhdr));
- break;
- default:
- continue;
- }
- #if 0
- {
- int i;
- printf("--- %d -", pkthdr->caplen);
- for (i = 0; i < pkthdr->caplen; i++)
- printf(" %02x", pktdata[i]);
- printf("\n");
- }
- #endif
- #if !defined(__CYGWIN__)
- if (iphdr && iphdr->version == 6)
- {
- /* ipv6 */
- pktlen = (uint32_t) pkthdr->len - sizeof(*ethhdr) - sizeof(*ip6hdr);
- ip6hdr = (ipv6_hdr *) (void *) iphdr;
- if (ip6hdr->nxt_header != IPPROTO_UDP)
- continue;
- udphdr = (struct udphdr *) ((uint8_t *) ip6hdr + sizeof(*ip6hdr));
- }
- else
- #endif
- {
- /* ipv4 */
- if (iphdr->protocol != IPPROTO_UDP)
- continue;
- #if defined(__DARWIN) || defined(__CYGWIN__) || defined(__FreeBSD__)
- udphdr = (struct udphdr *) ((uint8_t *) iphdr + (iphdr->ihl << 2) + 4);
- pktlen = (uint32_t) ntohs(udphdr->uh_ulen);
- #elif defined ( __HPUX)
- udphdr = (struct udphdr *) ((uint8_t *) iphdr + (iphdr->ihl << 2));
- pktlen = (uint32_t) pkthdr->len - sizeof(*ethhdr) - sizeof(*iphdr);
- #else
- udphdr = (struct udphdr *) ((uint8_t *) iphdr + (iphdr->ihl << 2));
- pktlen = (uint32_t) ntohs(udphdr->len);
- #endif
- }
- timing_update_handler(user_data, &pkthdr->ts);
- if (src_addr && ntohl(iphdr->saddr) != src_addr)
- continue;
- #if defined(__DARWIN) || defined(__CYGWIN__) || defined(__FreeBSD__)
- if (src_port && ntohs(udphdr->uh_sport) != src_port)
- #else
- if (src_port && ntohs(udphdr->source) != src_port)
- #endif
- continue;
- if (dest_addr && ntohl(iphdr->daddr) != dest_addr)
- continue;
- #if defined(__DARWIN) || defined(__CYGWIN__) || defined(__FreeBSD__)
- if (dest_port && ntohs(udphdr->uh_dport) != dest_port)
- #else
- if (dest_port && ntohs(udphdr->dest) != dest_port)
- #endif
- continue;
- if (pkthdr->len != pkthdr->caplen)
- {
- fprintf(stderr, "Truncated packet - total len = %d, captured len = %d\n", pkthdr->len, pkthdr->caplen);
- exit(2);
- }
- #if 0
- printf("%d:%d -> %d:%d\n", ntohl(iphdr->saddr), ntohs(udphdr->source), ntohl(iphdr->daddr), ntohs(udphdr->dest));
- #endif
- body = (const uint8_t *) udphdr;
- body += sizeof(struct udphdr);
- body_len = pktlen - sizeof(struct udphdr);
- packet_handler(user_data, body, body_len);
- total_pkts++;
- }
- fprintf(stderr, "In pcap %s there were %d accepted packets\n", file, total_pkts);
- pcap_close(pcap);
- return 0;
- }
- /*- End of function --------------------------------------------------------*/
- /*- End of file ------------------------------------------------------------*/
|