aboutsummaryrefslogtreecommitdiffstats
path: root/gg_sniff/pcap.c
diff options
context:
space:
mode:
Diffstat (limited to 'gg_sniff/pcap.c')
-rw-r--r--gg_sniff/pcap.c968
1 files changed, 484 insertions, 484 deletions
diff --git a/gg_sniff/pcap.c b/gg_sniff/pcap.c
index 6ec710b..2e31769 100644
--- a/gg_sniff/pcap.c
+++ b/gg_sniff/pcap.c
@@ -46,113 +46,113 @@
#define CONNTIMER 5 // XXX conf ?
struct phandler {
- pcap_handler f;
- int type;
+ pcap_handler f;
+ int type;
};
struct _cap_t {
- pcap_t *pcap;
- pcap_handler handler;
- struct event *ev;
- struct event *conntimer_ev;
- struct timeval conntimer_tv;
- struct gg_client *ggcli;
- struct ggnet *net;
- int pinvalid;
- int ptruncated;
+ pcap_t *pcap;
+ pcap_handler handler;
+ struct event *ev;
+ struct event *conntimer_ev;
+ struct timeval conntimer_tv;
+ struct gg_client *ggcli;
+ struct ggnet *net;
+ int pinvalid;
+ int ptruncated;
};
static pcap_t *my_pcap_open_live(const char *, int, int, int,
- char *, u_int, u_int);
+ char *, u_int, u_int);
static void ip_handle(struct ip *, const u_char *, u_int);
static void conn_del(struct ggnet_conn *);
static void ether_handle(struct ether_header *, const u_char *, u_int);
static pcap_handler lookup_phandler(int);
static void phandler_ether(u_char *,
- const struct pcap_pkthdr *, const u_char *);
+ const struct pcap_pkthdr *, const u_char *);
#if defined(__OpenBSD__)
static void phandler_loop(u_char *,
- const struct pcap_pkthdr *, const u_char *);
+ const struct pcap_pkthdr *, const u_char *);
#endif
#if defined(__linux__)
static void phandler_sll(u_char *,
- const struct pcap_pkthdr *, const u_char *);
+ const struct pcap_pkthdr *, const u_char *);
#endif
static void cb_pcap(int, short, void *);
static void cb_conntimer(int, short, void *);
static void cb_nodename(struct ggnet *, struct ggnet_node *);
static struct phandler phandlers[] = {
- { phandler_ether, DLT_EN10MB },
- { phandler_ether, DLT_IEEE802 },
+ { phandler_ether, DLT_EN10MB },
+ { phandler_ether, DLT_IEEE802 },
#if defined(__OpenBSD__)
- { phandler_loop, DLT_LOOP },
+ { phandler_loop, DLT_LOOP },
#endif
#if defined(__linux__)
- { phandler_sll, DLT_LINUX_SLL },
+ { phandler_sll, DLT_LINUX_SLL },
#endif
- { NULL, 0 },
+ { NULL, 0 },
};
static struct _cap_t _cap;
- int
+int
ggsniff_pcap_init(struct event_base *ev_base, struct gg_client *ggcli,
- struct ggnet *net, char *iface, int active, char *filter)
+ struct ggnet *net, char *iface, int active, char *filter)
{
- char errbuf[PCAP_ERRBUF_SIZE];
- struct bpf_program bprog;
- pcap_t *pcap;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ struct bpf_program bprog;
+ pcap_t *pcap;
#if defined(__OpenBSD__)
- if (!iface)
- err(1, "On OpenBSD you cannot listen on ANY interface");
+ if (!iface)
+ err(1, "On OpenBSD you cannot listen on ANY interface");
#endif
- pcap = my_pcap_open_live(iface, PCAP_SNAPLEN, 1, PCAP_TO,
- errbuf, -1, 0);
- if (pcap == NULL)
- err(1, "capture: pcap_open_live failed on interface %s\n"
- "with snaplen %d : %s",
- iface, PCAP_SNAPLEN, errbuf);
- if (!filter)
- filter = strndup(PCAP_FILTER, 256);
- if (pcap_compile(pcap, &bprog, filter, 0, 0) < 0)
- err(1, "capture: pcap_compile failed with filter %s : %s",
- filter, pcap_geterr(pcap));
- if (pcap_setfilter(pcap, &bprog) < 0)
- err(1, "capture: pcap_setfilter failed : %s",
- pcap_geterr(pcap));
-
- _cap.pcap = pcap;
- _cap.handler = lookup_phandler(pcap_datalink(pcap));
- //_cap.tv.tv_sec = 0;
- //_cap.tv.tv_usec = PCAP_TO;
- fd_nonblock(pcap_fileno(pcap));
- _cap.ev = event_new(ev_base, pcap_fileno(pcap), EV_READ|EV_PERSIST,
- cb_pcap, NULL);
- //event_add(_cap.ev, &_cap->tv);
- event_add(_cap.ev, NULL);
-
- _cap.conntimer_tv.tv_sec = CONNTIMER;
- _cap.conntimer_tv.tv_usec = 0;
- _cap.conntimer_ev = evtimer_new(ev_base, cb_conntimer, NULL);
- if (evtimer_add(_cap.conntimer_ev, &_cap.conntimer_tv) == -1)
- gg_log_fatal("user: event_add conntimer failed: %s", strerror(errno));
-
- if (active)
- ggnet_set_dns(net, 1, ev_base, cb_nodename);
-
- _cap.ggcli = ggcli;
- _cap.net = net;
-
- return 1;
+ pcap = my_pcap_open_live(iface, PCAP_SNAPLEN, 1, PCAP_TO,
+ errbuf, -1, 0);
+ if (pcap == NULL)
+ err(1, "capture: pcap_open_live failed on interface %s\n"
+ "with snaplen %d : %s",
+ iface, PCAP_SNAPLEN, errbuf);
+ if (!filter)
+ filter = strndup(PCAP_FILTER, 256);
+ if (pcap_compile(pcap, &bprog, filter, 0, 0) < 0)
+ err(1, "capture: pcap_compile failed with filter %s : %s",
+ filter, pcap_geterr(pcap));
+ if (pcap_setfilter(pcap, &bprog) < 0)
+ err(1, "capture: pcap_setfilter failed : %s",
+ pcap_geterr(pcap));
+
+ _cap.pcap = pcap;
+ _cap.handler = lookup_phandler(pcap_datalink(pcap));
+ //_cap.tv.tv_sec = 0;
+ //_cap.tv.tv_usec = PCAP_TO;
+ fd_nonblock(pcap_fileno(pcap));
+ _cap.ev = event_new(ev_base, pcap_fileno(pcap), EV_READ|EV_PERSIST,
+ cb_pcap, NULL);
+ //event_add(_cap.ev, &_cap->tv);
+ event_add(_cap.ev, NULL);
+
+ _cap.conntimer_tv.tv_sec = CONNTIMER;
+ _cap.conntimer_tv.tv_usec = 0;
+ _cap.conntimer_ev = evtimer_new(ev_base, cb_conntimer, NULL);
+ if (evtimer_add(_cap.conntimer_ev, &_cap.conntimer_tv) == -1)
+ gg_log_fatal("user: event_add conntimer failed: %s", strerror(errno));
+
+ if (active)
+ ggnet_set_dns(net, 1, ev_base, cb_nodename);
+
+ _cap.ggcli = ggcli;
+ _cap.net = net;
+
+ return 1;
}
- void
+void
ggsniff_pcap_shutdown(void)
{
- event_del(_cap.ev);
- pcap_close(_cap.pcap);
+ event_del(_cap.ev);
+ pcap_close(_cap.pcap);
}
/*
@@ -162,192 +162,192 @@ ggsniff_pcap_shutdown(void)
* based on OpenBSD tcpdump, privsep_pcap.c v1.16
*/
- static pcap_t *
+static pcap_t *
my_pcap_open_live(const char *dev, int slen, int promisc, int to_ms,
- char *ebuf, u_int dlt, u_int dirfilt)
+ char *ebuf, u_int dlt, u_int dirfilt)
{
#if defined(__OpenBSD__)
- struct bpf_version bv;
- u_int v;
- pcap_t *p;
- char bpf[sizeof "/dev/bpf0000000000"];
- int fd, n = 0;
- struct ifreq ifr;
-
- p = xmalloc(sizeof(*p));
- bzero(p, sizeof(*p));
-
- /* priv part */
-
- do {
- snprintf(bpf, sizeof(bpf), "/dev/bpf%d", n++);
- fd = open(bpf, O_RDONLY);
- } while (fd < 0 && errno == EBUSY);
- if (fd < 0)
- return NULL;
-
- v = 32768; /* XXX this should be a user-accessible hook */
- ioctl(fd, BIOCSBLEN, &v);
-
- strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
- if (ioctl(fd, BIOCSETIF, &ifr) < 0)
- return NULL;
-
- if (dlt != (u_int) -1 && ioctl(fd, BIOCSDLT, &dlt))
- return NULL;
-
- if (promisc)
- /* this is allowed to fail */
- ioctl(fd, BIOCPROMISC, NULL);
- if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0)
- return NULL;
-
- /* lock the descriptor */
- if (ioctl(fd, BIOCLOCK, NULL) < 0)
- return NULL;
-
- /* end of priv part */
-
- /* fd is locked, can only use 'safe' ioctls */
- if (ioctl(fd, BIOCVERSION, &bv) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
- pcap_strerror(errno));
- return NULL;
- }
-
- if (bv.bv_major != BPF_MAJOR_VERSION ||
- bv.bv_minor < BPF_MINOR_VERSION) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "kernel bpf filter out of date");
- return NULL;
- }
-
- p->fd = fd;
- p->snapshot = slen;
-
- /* Get the data link layer type. */
- if (ioctl(fd, BIOCGDLT, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
- pcap_strerror(errno));
- return NULL;
- }
+ struct bpf_version bv;
+ u_int v;
+ pcap_t *p;
+ char bpf[sizeof "/dev/bpf0000000000"];
+ int fd, n = 0;
+ struct ifreq ifr;
+
+ p = xmalloc(sizeof(*p));
+ bzero(p, sizeof(*p));
+
+ /* priv part */
+
+ do {
+ snprintf(bpf, sizeof(bpf), "/dev/bpf%d", n++);
+ fd = open(bpf, O_RDONLY);
+ } while (fd < 0 && errno == EBUSY);
+ if (fd < 0)
+ return NULL;
+
+ v = 32768; /* XXX this should be a user-accessible hook */
+ ioctl(fd, BIOCSBLEN, &v);
+
+ strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, &ifr) < 0)
+ return NULL;
+
+ if (dlt != (u_int) -1 && ioctl(fd, BIOCSDLT, &dlt))
+ return NULL;
+
+ if (promisc)
+ /* this is allowed to fail */
+ ioctl(fd, BIOCPROMISC, NULL);
+ if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0)
+ return NULL;
+
+ /* lock the descriptor */
+ if (ioctl(fd, BIOCLOCK, NULL) < 0)
+ return NULL;
+
+ /* end of priv part */
+
+ /* fd is locked, can only use 'safe' ioctls */
+ if (ioctl(fd, BIOCVERSION, &bv) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
+
+ if (bv.bv_major != BPF_MAJOR_VERSION ||
+ bv.bv_minor < BPF_MINOR_VERSION) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "kernel bpf filter out of date");
+ return NULL;
+ }
+
+ p->fd = fd;
+ p->snapshot = slen;
+
+ /* Get the data link layer type. */
+ if (ioctl(fd, BIOCGDLT, &v) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
#if _BSDI_VERSION - 0 >= 199510
- /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
- switch (v) {
+ /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
+ switch (v) {
- case DLT_SLIP:
- v = DLT_SLIP_BSDOS;
- break;
+ case DLT_SLIP:
+ v = DLT_SLIP_BSDOS;
+ break;
- case DLT_PPP:
- v = DLT_PPP_BSDOS;
- break;
- }
+ case DLT_PPP:
+ v = DLT_PPP_BSDOS;
+ break;
+ }
#endif
- p->linktype = v;
-
- /* XXX hack from tcpdump */
- if (p->linktype == DLT_PFLOG && p->snapshot < 160)
- p->snapshot = 160;
-
- /* set timeout */
- if (to_ms != 0) {
- struct timeval to;
- to.tv_sec = to_ms / 1000;
- to.tv_usec = (to_ms * 1000) % 1000000;
- if (ioctl(p->fd, BIOCSRTIMEOUT, &to) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
- pcap_strerror(errno));
- return NULL;
- }
- }
-
- if (ioctl(fd, BIOCGBLEN, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
- pcap_strerror(errno));
- return NULL;
- }
- p->bufsize = v;
- p->buffer = (u_char *)malloc(p->bufsize);
- if (p->buffer == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- return NULL;
- }
- return p;
+ p->linktype = v;
+
+ /* XXX hack from tcpdump */
+ if (p->linktype == DLT_PFLOG && p->snapshot < 160)
+ p->snapshot = 160;
+
+ /* set timeout */
+ if (to_ms != 0) {
+ struct timeval to;
+ to.tv_sec = to_ms / 1000;
+ to.tv_usec = (to_ms * 1000) % 1000000;
+ if (ioctl(p->fd, BIOCSRTIMEOUT, &to) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
+ }
+
+ if (ioctl(fd, BIOCGBLEN, &v) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
+ p->bufsize = v;
+ p->buffer = (u_char *)malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ return NULL;
+ }
+ return p;
#else /* defined(__OpenBSD__) */
- return pcap_open_live(dev, slen, promisc, to_ms, ebuf);
+ return pcap_open_live(dev, slen, promisc, to_ms, ebuf);
#endif
}
- static void
+static void
cb_pcap(int fd, short why, void *data)
{
- //gg_log_tmp("cb_pcap");
- pcap_dispatch(_cap.pcap, PCAP_COUNT, _cap.handler, NULL);
+ //gg_log_tmp("cb_pcap");
+ pcap_dispatch(_cap.pcap, PCAP_COUNT, _cap.handler, NULL);
- /* reschedule */
- //if (event_add(&_cap->ev, &_cap->tv) == -1)
- // gg_log_fatal("user: event_add pcap failed : %s", strerror(errno));
+ /* reschedule */
+ //if (event_add(&_cap->ev, &_cap->tv) == -1)
+ // gg_log_fatal("user: event_add pcap failed : %s", strerror(errno));
}
- static void
+static void
cb_conntimer(int fd, short why, void *data)
{
- struct ggnet_conn *c, *ctmp;
- struct ggnet_node *n, *ntmp;
- int i, to;
-
- gg_log_debug("ev_timer");
- ggnet_time_update(_cap.net, time(NULL));
-
- i = 0;
- LIST_FOREACH_SAFE(c, &_cap.net->conn_list, entry, ctmp) {
- switch (c->proto) {
- case IPPROTO_UDP:
- to = CONN_TIMEOUT_UDP;
- break;
- case IPPROTO_ICMP:
- to = CONN_TIMEOUT_ICMP;
- break;
- default:
- to = CONN_TIMEOUT;
- break;
- }
- if (_cap.net->time > c->lastseen + to)
- conn_del(c);
- else
- i++;
- }
-
- if (_cap.net->node_count > NODE_MAX_WITHOUT_TIMEOUT) {
- LIST_FOREACH_SAFE(n, &_cap.net->node_list, entry, ntmp) {
- if (n->used == 0 &&
- _cap.net->time > n->lastseen + NODE_TIMEOUT)
- ggnet_node_del(_cap.net, n);
- }
- }
-
- gg_log_debug("user: ev_timer leaving with %d active connections and %d active nodes", i, _cap.net->node_count);
- if (evtimer_add(_cap.conntimer_ev, &_cap.conntimer_tv) == -1)
- gg_log_fatal("user: event_add conntimer failed : %s", strerror(errno));
+ struct ggnet_conn *c, *ctmp;
+ struct ggnet_node *n, *ntmp;
+ int i, to;
+
+ gg_log_debug("ev_timer");
+ ggnet_time_update(_cap.net, time(NULL));
+
+ i = 0;
+ LIST_FOREACH_SAFE(c, &_cap.net->conn_list, entry, ctmp) {
+ switch (c->proto) {
+ case IPPROTO_UDP:
+ to = CONN_TIMEOUT_UDP;
+ break;
+ case IPPROTO_ICMP:
+ to = CONN_TIMEOUT_ICMP;
+ break;
+ default:
+ to = CONN_TIMEOUT;
+ break;
+ }
+ if (_cap.net->time > c->lastseen + to)
+ conn_del(c);
+ else
+ i++;
+ }
+
+ if (_cap.net->node_count > NODE_MAX_WITHOUT_TIMEOUT) {
+ LIST_FOREACH_SAFE(n, &_cap.net->node_list, entry, ntmp) {
+ if (n->used == 0 &&
+ _cap.net->time > n->lastseen + NODE_TIMEOUT)
+ ggnet_node_del(_cap.net, n);
+ }
+ }
+
+ gg_log_debug("user: ev_timer leaving with %d active connections and %d active nodes", i, _cap.net->node_count);
+ if (evtimer_add(_cap.conntimer_ev, &_cap.conntimer_tv) == -1)
+ gg_log_fatal("user: event_add conntimer failed : %s", strerror(errno));
}
- static void
+static void
cb_nodename(struct ggnet *net, struct ggnet_node *n)
{
- struct gg_packet pkt;
- int len;
-
- len = strnlen(n->fqdn, GGNET_DNSNAME_MAX);
- if (len > 0) {
- pkt.ver = PACKET_VERSION;
- pkt.type = PACKET_NAME;
- pkt.name_addr = n->addr.s_addr;
- pkt.name_len = len;
- strncpy((char *)pkt.name_fqdn, n->fqdn, sizeof(pkt.name_fqdn));
- gg_client_send(_cap.ggcli, &pkt);
- }
+ struct gg_packet pkt;
+ int len;
+
+ len = strnlen(n->fqdn, GGNET_DNSNAME_MAX);
+ if (len > 0) {
+ pkt.ver = PACKET_VERSION;
+ pkt.type = PACKET_NAME;
+ pkt.name_addr = n->addr.s_addr;
+ pkt.name_len = len;
+ strncpy((char *)pkt.name_fqdn, n->fqdn, sizeof(pkt.name_fqdn));
+ gg_client_send(_cap.ggcli, &pkt);
+ }
}
/*
@@ -359,221 +359,221 @@ cb_nodename(struct ggnet *net, struct ggnet_node *n)
#define NOTCAPTURED(v) ((u_char *)v > (u_char *)pend - sizeof(*v))
#define NOTRECEIVED(v) (wirelen < sizeof(v))
#define log_pinvalid(fmt, ...) \
- gg_log_info("ggsniff pinvalid: " fmt, ##__VA_ARGS__)
- static void
+ gg_log_info("ggsniff pinvalid: " fmt, ##__VA_ARGS__)
+static void
ip_handle(struct ip *ip, const u_char *pend, u_int wirelen)
{
- u_int len, ip_hlen, off;
- const u_char *cp;
- struct tcphdr *tcph;
- struct udphdr *udph;
- struct icmp *icmp;
- struct in_addr src, dst;
- u_int src_port, dst_port;
- u_int proto, close;
- int response;
- struct ggnet_conn *conn;
- struct gg_packet pkt;
-
- if (NOTCAPTURED(ip)) {
- log_pinvalid("user: ip truncated (ip %x pend %x sizeof(ip) %d",
- ip, pend, sizeof(ip));
- _cap.ptruncated++;
- return;
- }
-
- if (ip->ip_v != IPVERSION) {
- log_pinvalid("user: invalid ip version");
- _cap.pinvalid++;
- return;
- }
-
- len = ntohs(ip->ip_len);
- if (wirelen < len) {
- log_pinvalid("user: ip too small");
- _cap.pinvalid++;
- len = wirelen;
- }
-
- ip_hlen = ip->ip_hl * 4;
- if (ip_hlen < sizeof(struct ip) || ip_hlen > len) {
- log_pinvalid("user: ip_hlen invalid, %d", ip_hlen);
- _cap.pinvalid++;
- return;
- }
- len -= ip_hlen;
-
- src.s_addr = ntohl(ip->ip_src.s_addr);
- dst.s_addr = ntohl(ip->ip_dst.s_addr);
- src_port = 0;
- dst_port = 0;
- proto = IPPROTO_IP;
- close = 0;
-
- off = ntohs(ip->ip_off);
- if ((off & IP_OFFMASK) == 0) {
- cp = (const u_char *)ip + ip_hlen;
- switch (ip->ip_p) {
-
- case IPPROTO_TCP:
- tcph = (struct tcphdr *)cp;
- if (NOTCAPTURED(&tcph->th_flags)) {
- log_pinvalid("user: tcp truncated");
- _cap.ptruncated++;
- return;
- }
- if (NOTRECEIVED(*tcph)) {
- log_pinvalid("user: tcp too small");
- _cap.pinvalid++;
- return;
- }
- src_port = ntohs(tcph->th_sport);
- dst_port = ntohs(tcph->th_dport);
- proto = IPPROTO_TCP;
- if ((tcph->th_flags & TH_FIN) &&
- (tcph->th_flags & TH_ACK))
- close = 1;
- break;
-
- case IPPROTO_UDP:
- udph = (struct udphdr *)cp;
- if (NOTCAPTURED(&udph->uh_dport)) {
- log_pinvalid("user: udp truncated, "
- "ip %x, udph %x, uh_port %x, pend %x, ip_hlen %d",
- ip, udph, &udph->uh_dport, pend, ip_hlen);
- _cap.ptruncated++;
- return;
- }
- if (NOTRECEIVED(*udph)) {
- log_pinvalid("user: udp too small");
- _cap.pinvalid++;
- return;
- }
- src_port = ntohs(udph->uh_sport);
- dst_port = ntohs(udph->uh_dport);
- proto = IPPROTO_UDP;
- break;
-
- case IPPROTO_ICMP:
- icmp = (struct icmp *)cp;
- if (NOTRECEIVED(*icmp)) {
- log_pinvalid("user: icmp too small");
- _cap.pinvalid++;
- return;
- }
- proto = IPPROTO_ICMP;
- break;
-
- default:
- gg_log_warn("user: unknown ip protocol !");
- break;
- }
- } else {
- /*
- * if this isn't the first frag, we're missing the
- * next level protocol header.
- */
- gg_log_debug("user: got a fragmented ip packet !");
- }
-
- pkt.ver = PACKET_VERSION;
- conn = ggnet_conn_find(_cap.net, &src, src_port, &dst, dst_port,
- proto, &response);
- if (conn) {
- if (!close) {
- pkt.type = PACKET_DATA;
- pkt.data_connid = conn->id;
- GG_PKTDATA_SIZE_ENCODE(pkt.data_size, ip->ip_len, response);
- gg_client_send(_cap.ggcli, &pkt);
- ggnet_conn_data(_cap.net, conn, ip->ip_len, response);
- } else {
- conn_del(conn);
- }
- } else {
- if (!close) {
- conn = ggnet_conn_add(_cap.net, &src, src_port, &dst, dst_port, proto,
- ip->ip_len, -1);
- pkt.type = PACKET_NEWCONN;
- pkt.newconn_id = conn->id;
- pkt.newconn_src = src.s_addr;
- pkt.newconn_dst = dst.s_addr;
- pkt.newconn_proto = proto;
- GG_PKTDATA_SIZE_ENCODE(pkt.newconn_size, ip->ip_len, 0);
- gg_client_send(_cap.ggcli, &pkt);
- } else {
- gg_log_warn("user: captured connection close w/o open !");
- }
- }
+ u_int len, ip_hlen, off;
+ const u_char *cp;
+ struct tcphdr *tcph;
+ struct udphdr *udph;
+ struct icmp *icmp;
+ struct in_addr src, dst;
+ u_int src_port, dst_port;
+ u_int proto, close;
+ int response;
+ struct ggnet_conn *conn;
+ struct gg_packet pkt;
+
+ if (NOTCAPTURED(ip)) {
+ log_pinvalid("user: ip truncated (ip %x pend %x sizeof(ip) %d",
+ ip, pend, sizeof(ip));
+ _cap.ptruncated++;
+ return;
+ }
+
+ if (ip->ip_v != IPVERSION) {
+ log_pinvalid("user: invalid ip version");
+ _cap.pinvalid++;
+ return;
+ }
+
+ len = ntohs(ip->ip_len);
+ if (wirelen < len) {
+ log_pinvalid("user: ip too small");
+ _cap.pinvalid++;
+ len = wirelen;
+ }
+
+ ip_hlen = ip->ip_hl * 4;
+ if (ip_hlen < sizeof(struct ip) || ip_hlen > len) {
+ log_pinvalid("user: ip_hlen invalid, %d", ip_hlen);
+ _cap.pinvalid++;
+ return;
+ }
+ len -= ip_hlen;
+
+ src.s_addr = ntohl(ip->ip_src.s_addr);
+ dst.s_addr = ntohl(ip->ip_dst.s_addr);
+ src_port = 0;
+ dst_port = 0;
+ proto = IPPROTO_IP;
+ close = 0;
+
+ off = ntohs(ip->ip_off);
+ if ((off & IP_OFFMASK) == 0) {
+ cp = (const u_char *)ip + ip_hlen;
+ switch (ip->ip_p) {
+
+ case IPPROTO_TCP:
+ tcph = (struct tcphdr *)cp;
+ if (NOTCAPTURED(&tcph->th_flags)) {
+ log_pinvalid("user: tcp truncated");
+ _cap.ptruncated++;
+ return;
+ }
+ if (NOTRECEIVED(*tcph)) {
+ log_pinvalid("user: tcp too small");
+ _cap.pinvalid++;
+ return;
+ }
+ src_port = ntohs(tcph->th_sport);
+ dst_port = ntohs(tcph->th_dport);
+ proto = IPPROTO_TCP;
+ if ((tcph->th_flags & TH_FIN) &&
+ (tcph->th_flags & TH_ACK))
+ close = 1;
+ break;
+
+ case IPPROTO_UDP:
+ udph = (struct udphdr *)cp;
+ if (NOTCAPTURED(&udph->uh_dport)) {
+ log_pinvalid("user: udp truncated, "
+ "ip %x, udph %x, uh_port %x, pend %x, ip_hlen %d",
+ ip, udph, &udph->uh_dport, pend, ip_hlen);
+ _cap.ptruncated++;
+ return;
+ }
+ if (NOTRECEIVED(*udph)) {
+ log_pinvalid("user: udp too small");
+ _cap.pinvalid++;
+ return;
+ }
+ src_port = ntohs(udph->uh_sport);
+ dst_port = ntohs(udph->uh_dport);
+ proto = IPPROTO_UDP;
+ break;
+
+ case IPPROTO_ICMP:
+ icmp = (struct icmp *)cp;
+ if (NOTRECEIVED(*icmp)) {
+ log_pinvalid("user: icmp too small");
+ _cap.pinvalid++;
+ return;
+ }
+ proto = IPPROTO_ICMP;
+ break;
+
+ default:
+ gg_log_warn("user: unknown ip protocol !");
+ break;
+ }
+ } else {
+ /*
+ * if this isn't the first frag, we're missing the
+ * next level protocol header.
+ */
+ gg_log_debug("user: got a fragmented ip packet !");
+ }
+
+ pkt.ver = PACKET_VERSION;
+ conn = ggnet_conn_find(_cap.net, &src, src_port, &dst, dst_port,
+ proto, &response);
+ if (conn) {
+ if (!close) {
+ pkt.type = PACKET_DATA;
+ pkt.data_connid = conn->id;
+ GG_PKTDATA_SIZE_ENCODE(pkt.data_size, ip->ip_len, response);
+ gg_client_send(_cap.ggcli, &pkt);
+ ggnet_conn_data(_cap.net, conn, ip->ip_len, response);
+ } else {
+ conn_del(conn);
+ }
+ } else {
+ if (!close) {
+ conn = ggnet_conn_add(_cap.net, &src, src_port, &dst, dst_port, proto,
+ ip->ip_len, -1);
+ pkt.type = PACKET_NEWCONN;
+ pkt.newconn_id = conn->id;
+ pkt.newconn_src = src.s_addr;
+ pkt.newconn_dst = dst.s_addr;
+ pkt.newconn_proto = proto;
+ GG_PKTDATA_SIZE_ENCODE(pkt.newconn_size, ip->ip_len, 0);
+ gg_client_send(_cap.ggcli, &pkt);
+ } else {
+ gg_log_warn("user: captured connection close w/o open !");
+ }
+ }
}
- static void
+static void
conn_del(struct ggnet_conn *c)
{
- struct gg_packet pkt;
+ struct gg_packet pkt;
- pkt.ver = PACKET_VERSION;
- pkt.type = PACKET_DELCONN;
- pkt.delconn_id = c->id;
- gg_client_send(_cap.ggcli, &pkt);
- ggnet_conn_del(_cap.net, c);
+ pkt.ver = PACKET_VERSION;
+ pkt.type = PACKET_DELCONN;
+ pkt.delconn_id = c->id;
+ gg_client_send(_cap.ggcli, &pkt);
+ ggnet_conn_del(_cap.net, c);
}
- static void
+static void
ether_handle(struct ether_header *ether, const u_char *pend, u_int wirelen)
{
- struct ip *ip;
- u_short ether_type;
-
- wirelen -= sizeof(struct ether_header);
-
- ether_type = ntohs(ether->ether_type);
- if (ether_type <= ETHERMTU)
- gg_log_debug("llc packet !");
- else {
- switch (ether_type) {
- case ETHERTYPE_IP:
- gg_log_debug("loop family AF_LINK IP");
- ip = (struct ip *)((u_char *)ether + sizeof(struct ether_header));
- ip_handle(ip, pend, wirelen);
- break;
- default:
- gg_log_debug("loop non ip packet !");
- break;
- }
- }
+ struct ip *ip;
+ u_short ether_type;
+
+ wirelen -= sizeof(struct ether_header);
+
+ ether_type = ntohs(ether->ether_type);
+ if (ether_type <= ETHERMTU)
+ gg_log_debug("llc packet !");
+ else {
+ switch (ether_type) {
+ case ETHERTYPE_IP:
+ gg_log_debug("loop family AF_LINK IP");
+ ip = (struct ip *)((u_char *)ether + sizeof(struct ether_header));
+ ip_handle(ip, pend, wirelen);
+ break;
+ default:
+ gg_log_debug("loop non ip packet !");
+ break;
+ }
+ }
}
- static pcap_handler
+static pcap_handler
lookup_phandler(int type)
{
- struct phandler *p;
-
- for (p = phandlers; p->f; ++p) {
- if (type == p->type)
- return p->f;
- }
- err(1, "user: unknown data link type 0x%x", type);
- /* NOTREACHED */
- return NULL;
+ struct phandler *p;
+
+ for (p = phandlers; p->f; ++p) {
+ if (type == p->type)
+ return p->f;
+ }
+ err(1, "user: unknown data link type 0x%x", type);
+ /* NOTREACHED */
+ return NULL;
}
- static void
+static void
phandler_ether(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
- struct ether_header *ep;
- const u_char *pend;
- u_int len;
+ struct ether_header *ep;
+ const u_char *pend;
+ u_int len;
- gg_log_debug("user: pcap handler ethernet !");
+ gg_log_debug("user: pcap handler ethernet !");
- /* XXX here i assume that packets are alligned, which might not
- * be the case when using dump files, says tcpdump sources */
+ /* XXX here i assume that packets are alligned, which might not
+ * be the case when using dump files, says tcpdump sources */
- ep = (struct ether_header *)p;
- pend = p + h->caplen;
- len = h->len - sizeof(struct ether_header);
+ ep = (struct ether_header *)p;
+ pend = p + h->caplen;
+ len = h->len - sizeof(struct ether_header);
- ether_handle(ep, pend, len);
+ ether_handle(ep, pend, len);
}
/*
@@ -587,37 +587,37 @@ phandler_ether(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
#define LINUX_SLL_P_CAN 0x000C /* Controller Area Network */
#define LINUX_SLL_P_IRDA_LAP 0x0017 /* IrDA Link Access Protocol */
- static void
+static void
phandler_sll(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
- struct ip *ip;
- struct ether_header *ep;
- u_int family;
- const u_char *pend;
- u_int len;
-
- gg_log_debug("user: phandler_sll !");
-
- /* XXX here i assume that packets are alligned, which might not
- * be the case when using dump files, says tcpdump sources */
-
- pend = p + h->caplen;
- len = h->len - SLL_HDR_LEN;
-
- family = ntohs(p[14]);
- if (family < 1536) { /* linux and wireshark are good for you */
- switch (family) {
- case LINUX_SLL_P_ETHERNET:
- ep = (struct ether_header *)((u_char *)p + SLL_HDR_LEN);
- ether_handle(ep, pend, len);
- default:
- gg_log_debug("unknown family %x !", family);
- break;
- }
- } else {
- ip = (struct ip *)(p + SLL_HDR_LEN);
- ip_handle(ip, pend, len);
- }
+ struct ip *ip;
+ struct ether_header *ep;
+ u_int family;
+ const u_char *pend;
+ u_int len;
+
+ gg_log_debug("user: phandler_sll !");
+
+ /* XXX here i assume that packets are alligned, which might not
+ * be the case when using dump files, says tcpdump sources */
+
+ pend = p + h->caplen;
+ len = h->len - SLL_HDR_LEN;
+
+ family = ntohs(p[14]);
+ if (family < 1536) { /* linux and wireshark are good for you */
+ switch (family) {
+ case LINUX_SLL_P_ETHERNET:
+ ep = (struct ether_header *)((u_char *)p + SLL_HDR_LEN);
+ ether_handle(ep, pend, len);
+ default:
+ gg_log_debug("unknown family %x !", family);
+ break;
+ }
+ } else {
+ ip = (struct ip *)(p + SLL_HDR_LEN);
+ ip_handle(ip, pend, len);
+ }
}
#endif /* __linux__ */
@@ -627,38 +627,38 @@ phandler_sll(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
#if defined(__OpenBSD__)
#define NULL_HDRLEN 4
- static void
+static void
phandler_loop(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
- struct ip *ip;
- struct ether_header *ep;
- u_int family;
- const u_char *pend;
- u_int len;
-
- gg_log_debug("user: pcap handler loop !");
-
- /* XXX here i assume that packets are alligned, which might not
- * be the case when using dump files, says tcpdump sources */
-
- pend = p + h->caplen;
- len = h->len - NULL_HDRLEN;
-
- memcpy((char *)&family, (char *)p, sizeof(family));
- family = ntohl(family);
- switch (family) {
- case AF_INET:
- gg_log_debug("loop family AF_INET");
- ip = (struct ip *)(p + NULL_HDRLEN);
- ip_handle(ip, pend, len);
- break;
- case AF_LINK:
- ep = (struct ether_header *)((u_char *)p + NULL_HDRLEN);
- ether_handle(ep, pend, len);
- break;
- default:
- gg_log_debug("unknown family %x !", family);
- break;
- }
+ struct ip *ip;
+ struct ether_header *ep;
+ u_int family;
+ const u_char *pend;
+ u_int len;
+
+ gg_log_debug("user: pcap handler loop !");
+
+ /* XXX here i assume that packets are alligned, which might not
+ * be the case when using dump files, says tcpdump sources */
+
+ pend = p + h->caplen;
+ len = h->len - NULL_HDRLEN;
+
+ memcpy((char *)&family, (char *)p, sizeof(family));
+ family = ntohl(family);
+ switch (family) {
+ case AF_INET:
+ gg_log_debug("loop family AF_INET");
+ ip = (struct ip *)(p + NULL_HDRLEN);
+ ip_handle(ip, pend, len);
+ break;
+ case AF_LINK:
+ ep = (struct ether_header *)((u_char *)p + NULL_HDRLEN);
+ ether_handle(ep, pend, len);
+ break;
+ default:
+ gg_log_debug("unknown family %x !", family);
+ break;
+ }
}
#endif /* __OpenBSD__ */