aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2013-07-06 02:27:56 +0200
committerLaurent Ghigonis <laurent@p1sec.com>2013-07-06 02:27:56 +0200
commit2b575ec093dcd84d8d5c816fe41dd5b7363228e6 (patch)
tree7f32e89871b99edb4e6556007d9515353a266b06
parentgg_map: printf use %p for pointers (diff)
downloadglouglou-2b575ec093dcd84d8d5c816fe41dd5b7363228e6.tar.xz
glouglou-2b575ec093dcd84d8d5c816fe41dd5b7363228e6.zip
WIP traceroute integration, disabled by default
gg_map is not graphing correctly the route for now
-rw-r--r--gg_map/gg_map.c74
-rw-r--r--gg_sniff/pcap.c45
-rw-r--r--libglouglou/libggnet.c68
-rw-r--r--libglouglou/libggnet.h37
-rw-r--r--libglouglou/libggnet_dns.c5
-rw-r--r--libglouglou/libglouglou.c40
-rw-r--r--libglouglou/libglouglou.h16
7 files changed, 265 insertions, 20 deletions
diff --git a/gg_map/gg_map.c b/gg_map/gg_map.c
index 221b915..511d791 100644
--- a/gg_map/gg_map.c
+++ b/gg_map/gg_map.c
@@ -73,6 +73,37 @@ _cb_ggnet_delgroup(struct ggnet *net, struct ggnet_nodegroup *group)
egraph_vertice_del(_egraph, vgroup);
}
+void
+_cb_ggnet_link(struct ggnet *net, struct ggnet_node *a, struct ggnet_node *b)
+{
+ Egraph_Edge *e;
+
+ e = egraph_edge_add(_egraph, ggnet_node_usrdata_get(a),
+ ggnet_node_usrdata_get(b), NULL);
+ if (!e) {
+ printf("gg_map: WARNING: _cb_link cannot create edge !\n");
+ return;
+ }
+ egraph_edge_type_set(_egraph, e, "edge_group");
+}
+
+void
+_cb_ggnet_unlink(struct ggnet *net, struct ggnet_node *a, struct ggnet_node *b)
+{
+ Egraph_Edge *e;
+ const char *type;
+
+ e = egraph_edge_find(_egraph, ggnet_node_usrdata_get(a), ggnet_node_usrdata_get(b));
+ if (!e) {
+ printf("gg_map: WARNING: _cb_unlink on non existing edge !\n");
+ return;
+ }
+ egraph_edge_type_get(_egraph, e, &type);
+ if (strncmp(type, "edge_group", EGRAPH_TYPE_MAXLEN))
+ return;
+ egraph_edge_del(_egraph, e);
+}
+
static Egraph_Vertice *
_node_to_vertice(struct ggnet_node *n)
{
@@ -230,6 +261,37 @@ _conn_name(u_int32_t addr, u_int8_t pktsize, u_char *fqdn) {
egraph_vertice_rename(_egraph, ggnet_node_usrdata_get(n), (char *)fqdn);
}
+static void
+_conn_trace(u_int32_t addr, u_int8_t hopcount, struct gg_packet *pkt) {
+ struct gg_packet_tracehop *h;
+ struct ggnet_node *n, *np;
+ struct in_addr ip;
+ Egraph_Vertice *v;
+ int i;
+
+ ip.s_addr = addr;
+ np = ggnet_node_find(_ggnet, &ip);
+ if (!np)
+ return;
+ for (i=0; i<hopcount; i++) {
+ h = &pkt->trace_hops[i];
+ ip.s_addr = h->addr;
+ n = ggnet_node_find(_ggnet, &ip);
+ if (!n) {
+ n = ggnet_node_add(_ggnet, &ip);
+ v = _node_to_vertice(n);
+ if (v)
+ egraph_vertice_type_set(_egraph, v,
+ "vertice_group");
+ else
+ printf("gg_map: ERROR: could not create trace vertice !\n");
+
+ }
+ ggnet_node_path_link(np, n);
+ np = n;
+ }
+}
+
static int
_cb_packet(struct gg_client *cli, struct gg_packet *pkt)
{
@@ -278,6 +340,16 @@ _cb_packet(struct gg_client *cli, struct gg_packet *pkt)
_conn_name(pkt->name_addr, pkt->name_len, pkt->name_fqdn);
break;
+
+ case PACKET_TRACE:
+ if (_loglevel >= 1) {
+ printf(" type PACKET_TRACE\n");
+ printf(" trace_addr %4x\n", pkt->trace_addr);
+ printf(" trace_hopcount %d\n", pkt->trace_hopcount);
+ }
+
+ _conn_trace(pkt->trace_addr, pkt->trace_hopcount, pkt);
+ break;
}
return 0;
@@ -482,6 +554,8 @@ elm_main(int argc, char **argv)
goto quit;
ggnet_set_grouping(_ggnet, GGNET_GROUPING_TRUE,
_cb_ggnet_addgroup, _cb_ggnet_delgroup);
+ ggnet_setcb_traceroute(_ggnet,
+ _cb_ggnet_link, _cb_ggnet_unlink);
_ev_base = event_base_new();
ggcli = gg_client_connect(_ev_base, gg_serv_ip, gg_serv_port,
diff --git a/gg_sniff/pcap.c b/gg_sniff/pcap.c
index 78c7211..d0b326a 100644
--- a/gg_sniff/pcap.c
+++ b/gg_sniff/pcap.c
@@ -80,7 +80,7 @@ static void phandler_sll(u_char *,
static void cb_pcap(int, short, void *);
static void cb_conntimer(int, short, void *);
static void cb_nodename(struct ggnet *, struct ggnet_node *);
-static void cb_nodetraceroute(struct ggnet *, struct ggnet_node *);
+static void cb_nodetraceroute(struct ggnet *, struct ggnet_traceroute_req *);
static struct phandler phandlers[] = {
{ phandler_ether, DLT_EN10MB },
@@ -140,8 +140,11 @@ ggsniff_pcap_init(struct event_base *ev_base, struct gg_client *ggcli,
gg_log_fatal("user: event_add conntimer failed: %s", strerror(errno));
if (active) {
+ gg_log_info("active mode");
ggnet_set_dns(net, 1, ev_base, cb_nodename);
- //ggnet_set_traceroute(net, 1, ev_base, cb_nodetraceroute);
+ // XXX IN PROGRESS traceroute, disabled for now, 20130705
+ // laurent
+ //ggnet_set_traceroute(net, 1, iface, ev_base, cb_nodetraceroute);
}
_cap.ggcli = ggcli;
@@ -341,6 +344,7 @@ cb_nodename(struct ggnet *net, struct ggnet_node *n)
struct gg_packet pkt;
int len;
+ gg_log_debug("cb_nodename");
len = strnlen(n->fqdn, GGNET_DNSNAME_MAX);
if (len > 0) {
pkt.ver = PACKET_VERSION;
@@ -353,21 +357,30 @@ cb_nodename(struct ggnet *net, struct ggnet_node *n)
}
static void
-cb_nodetraceroute(struct ggnet *net, struct ggnet_node *n)
+cb_nodetraceroute(struct ggnet *net, struct ggnet_traceroute_req *req)
{
+ struct ggnet_traceroute_hop *h;
struct gg_packet pkt;
- int len;
+ int i;
- len = strnlen(n->fqdn, GGNET_DNSNAME_MAX);
- if (len > 0) {
- pkt.ver = PACKET_VERSION;
- pkt.type = PACKET_TRACE;
- pkt.name_addr = n->addr.s_addr;
- // XXX IN PROGRESS
- //pkt.name_len = len;
- //strncpy((char *)pkt.name_fqdn, n->fqdn, sizeof(pkt.name_fqdn));
- gg_client_send(_cap.ggcli, &pkt);
+ if (req->hopcount_answering == 0)
+ return;
+
+ gg_log_debug("cb_nodetraceroute");
+ pkt.ver = PACKET_VERSION;
+ pkt.type = PACKET_TRACE;
+ pkt.trace_addr = req->target->ip.addr_ip;
+ pkt.trace_hopcount = req->hopcount_total;
+ i = 0;
+ TAILQ_FOREACH(h, &req->hops_list, entry) {
+ pkt.trace_hops[i].addr = h->ip.addr_ip;
+ pkt.trace_hops[i].delay = h->delay;
+ pkt.trace_hops[i].loss = h->loss;
+ pkt.trace_hops[i].asn = h->asn;
+ i++;
}
+ gg_client_send(_cap.ggcli, &pkt);
+ ggnet_traceroute_trace_free(req);
}
/*
@@ -387,7 +400,7 @@ ip_handle(struct ip *ip, const u_char *pend, u_int wirelen)
const u_char *cp;
struct tcphdr *tcph;
struct udphdr *udph;
- struct icmp *icmp;
+ struct icmp_hdr *icmp;
struct in_addr src, dst;
u_int src_port, dst_port;
u_int proto, close;
@@ -475,12 +488,14 @@ ip_handle(struct ip *ip, const u_char *pend, u_int wirelen)
break;
case IPPROTO_ICMP:
- icmp = (struct icmp *)cp;
+ icmp = (struct icmp_hdr *)cp;
if (NOTRECEIVED(*icmp)) {
log_pinvalid("user: icmp too small");
_cap.pinvalid++;
return;
}
+ if (icmp->icmp_type == ICMP_TIMEXCEED)
+ return; /* not considered real node */
proto = IPPROTO_ICMP;
break;
diff --git a/libglouglou/libggnet.c b/libglouglou/libggnet.c
index 832de54..5f9810b 100644
--- a/libglouglou/libggnet.c
+++ b/libglouglou/libggnet.c
@@ -4,6 +4,7 @@
#include "libggnet.h"
#include "libggnet_dns.h"
+#include "libggnet_traceroute.h"
static struct ggnet_nodegroup *
nodegroup_add(struct ggnet *,
@@ -17,6 +18,7 @@ static struct ggnet_nodegroup *
static void nodegroup_set(struct ggnet *, struct ggnet_node *);
static void nodegroup_unset(struct ggnet *, struct ggnet_node *);
static void _cb_dns_reverse(struct in_addr *, char *, void *);
+static void _cb_traceroute_trace(struct ggnet_traceroute_req *req, void *data);
struct ggnet *
ggnet_new(int manage_connid)
@@ -53,12 +55,25 @@ ggnet_set_grouping(struct ggnet *net, int set,
}
void
+ggnet_setcb_traceroute(struct ggnet *net,
+ void (*cb_link)(struct ggnet *,
+ struct ggnet_node *, struct ggnet_node *),
+ void (*cb_unlink)(struct ggnet *,
+ struct ggnet_node *, struct ggnet_node *))
+{
+ net->cb_traceroute_link = cb_link;
+ net->cb_traceroute_unlink = cb_unlink;
+}
+
+void
ggnet_set_dns(struct ggnet *net, int set,
struct event_base *ev_base,
void (*cb_nodename)(struct ggnet *, struct ggnet_node *))
{
+ printf("XXX ggnet_set_dns %d\n", set);
net->use_dns = set;
if (set) {
+ printf("XXX calling ggnet_dns_new\n");
net->ggdns = ggnet_dns_new(ev_base);
net->cb_nodename = cb_nodename;
}
@@ -67,6 +82,20 @@ ggnet_set_dns(struct ggnet *net, int set,
}
void
+ggnet_set_traceroute(struct ggnet *net, int set, char *iface,
+ struct event_base *ev_base,
+ void (*cb_traceroute)(struct ggnet *, struct ggnet_traceroute_req *))
+{
+ net->use_traceroute = set;
+ if (set) {
+ net->ggtraceroute = ggnet_traceroute_new(ev_base, iface, net->debug);
+ net->cb_traceroute = cb_traceroute;
+ }
+ else if (net->use_traceroute)
+ ggnet_traceroute_free(net->ggtraceroute);
+}
+
+void
ggnet_debug_set(struct ggnet *net, int set)
{
net->debug = set;
@@ -110,6 +139,12 @@ ggnet_node_add(struct ggnet *net, struct in_addr *addr)
nodegroup_set(net, n);
if (net->use_dns)
n->dns_req = ggnet_dns_reverse(net->ggdns, &n->addr, _cb_dns_reverse, n);
+ if (net->use_traceroute) {
+ struct addr ip;
+ addr_aton(inet_ntoa(*addr), &ip);
+ printf("XXX calling trace on %s\n", inet_ntoa(*addr));
+ n->traceroute_req = ggnet_traceroute_trace_tcp(net->ggtraceroute, &ip, 80, _cb_traceroute_trace, NULL, n);
+ }
return n;
}
@@ -163,6 +198,26 @@ ggnet_node_group_get(struct ggnet_node *n)
return n->group;
}
+int
+ggnet_node_path_link(struct ggnet_node *a, struct ggnet_node *b)
+{
+ if (b->path_parent) {
+ if (b->path_parent == a)
+ return 0; /* already path connected */
+ /* remove old path link */
+ LIST_REMOVE(b, entry_path);
+ b->path_parent = NULL;
+ if (a->net->cb_traceroute_unlink)
+ a->net->cb_traceroute_unlink(a->net, a, b);
+ }
+ LIST_INSERT_HEAD(&a->path_to, b, entry_path);
+ b->path_parent = a;
+ if (a->net->cb_traceroute_link)
+ a->net->cb_traceroute_link(a->net, a, b);
+
+ return 1;
+}
+
struct ggnet_conn *
ggnet_conn_add(struct ggnet *net, struct in_addr *src, int src_port,
struct in_addr *dst, int dst_port, int proto, int size,
@@ -487,6 +542,7 @@ _cb_dns_reverse(struct in_addr *ip, char *name, void *data)
struct ggnet *net;
struct ggnet_node *n;
+ printf("XXX _cb_dns_reverse %s\n", name);
n = data;
net = n->net;
n->dns_req = NULL;
@@ -496,3 +552,15 @@ _cb_dns_reverse(struct in_addr *ip, char *name, void *data)
}
}
+static void
+_cb_traceroute_trace(struct ggnet_traceroute_req *req, void *data)
+{
+ struct ggnet *net;
+ struct ggnet_node *n;
+
+ printf("XXX _cb_traceroute_trace %p\n", req);
+ n = data;
+ net = n->net;
+ n->traceroute_req = NULL;
+ net->cb_traceroute(net, req);
+}
diff --git a/libglouglou/libggnet.h b/libglouglou/libggnet.h
index 794639b..fecf2bb 100644
--- a/libglouglou/libggnet.h
+++ b/libglouglou/libggnet.h
@@ -14,6 +14,8 @@
#include <bsd/sys/queue.h>
#endif
+#include "libggnet_traceroute.h"
+
#define GGNET_DNSNAME_MAX 60
#define GGNET_CONN_FREEIDS_COUNT 65536 /* 2^16 as freeids are u_int16_t */
@@ -43,13 +45,17 @@ struct ggnet_nodegroup {
struct ggnet_node {
LIST_ENTRY(ggnet_node) entry;
+ LIST_ENTRY(ggnet_node) entry_path;
struct ggnet *net;
struct in_addr addr;
+ LIST_HEAD(, ggnet_node) path_to; /* traceroute childs */
+ struct ggnet_node *path_parent; /* traceroute parent */
time_t lastseen;
- int used;
+ int used; /* by ggnet_conn */
+ struct ggnet_nodegroup *group; /* XXX for now only one group */
char fqdn[GGNET_DNSNAME_MAX];
- struct ggnet_nodegroup *group; /* XXX for now we support only one group */
struct ggnet_dns_req *dns_req;
+ struct ggnet_traceroute_req *traceroute_req;
void *usrdata;
};
@@ -82,7 +88,7 @@ struct ggnet {
int node_count;
u_int16_t conn_freeids[GGNET_CONN_FREEIDS_COUNT];
int conn_freeids_ptr;
- int manage_connid;
+ int manage_connid; /* XXX rename to active / passive */
time_t time;
int debug;
/* grouping */
@@ -93,6 +99,18 @@ struct ggnet {
int use_dns;
struct ggnet_dns *ggdns;
void (*cb_nodename)(struct ggnet *, struct ggnet_node *);
+ /* traceroute */
+ int use_traceroute;
+ struct ggnet_traceroute *ggtraceroute;
+ void (*cb_traceroute)(struct ggnet *, struct ggnet_traceroute_req *);
+ /* traceroute callbacks */
+ void (*cb_traceroute_link)(struct ggnet *,
+ struct ggnet_node *,
+ struct ggnet_node *);
+ void (*cb_traceroute_unlink)(struct ggnet *,
+ struct ggnet_node *,
+ struct ggnet_node *);
+
};
struct ggnet *ggnet_new(int);
@@ -102,10 +120,21 @@ void ggnet_set_grouping(struct ggnet *, int,
struct ggnet_nodegroup *),
void (*cb_delgroup)(struct ggnet *,
struct ggnet_nodegroup *));
+void ggnet_setcb_traceroute(struct ggnet *,
+ void (*cb_link)(struct ggnet *,
+ struct ggnet_node *,
+ struct ggnet_node *),
+ void (*cb_unlink)(struct ggnet *,
+ struct ggnet_node *,
+ struct ggnet_node *));
void ggnet_set_dns(struct ggnet *net, int set,
struct event_base *ev_base,
void (*cb_nodename)(struct ggnet *,
struct ggnet_node *));
+void ggnet_set_traceroute(struct ggnet *, int, char *,
+ struct event_base *,
+ void (*cb_traceroute)(struct ggnet *,
+ struct ggnet_traceroute_req *));
void ggnet_debug_set(struct ggnet *, int);
void ggnet_free(struct ggnet *);
struct ggnet_node *ggnet_node_add(struct ggnet *, struct in_addr *);
@@ -114,6 +143,8 @@ struct ggnet_node *ggnet_node_find(struct ggnet *, struct in_addr *);
void *ggnet_node_usrdata_get(struct ggnet_node *);
void ggnet_node_usrdata_set(struct ggnet_node *, void *);
struct ggnet_nodegroup *ggnet_node_group_get(struct ggnet_node *);
+int ggnet_node_path_link(struct ggnet_node *a,
+ struct ggnet_node *b);
struct ggnet_conn *ggnet_conn_add(struct ggnet *, struct in_addr *, int,
struct in_addr *, int, int, int, int);
void ggnet_conn_data(struct ggnet *, struct ggnet_conn *,
diff --git a/libglouglou/libggnet_dns.c b/libglouglou/libggnet_dns.c
index c6f8cce..66292b1 100644
--- a/libglouglou/libggnet_dns.c
+++ b/libglouglou/libggnet_dns.c
@@ -18,6 +18,8 @@ ggnet_dns_new(struct event_base *ev_base)
{
struct ggnet_dns *ggdns = NULL;
+ printf("XXX ggnet_dns_new\n");
+
ggdns = calloc(1, sizeof(struct ggnet_dns));
if (!ggdns) {
printf("could not allocate ggnet_dns\n");
@@ -53,6 +55,8 @@ ggnet_dns_reverse(struct ggnet_dns *ggdns,
struct evdns_request *ereq;
struct in_addr nip;
+ printf("XXX ggnet_dns_reverse %d\n", ip->s_addr);
+
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = EVUTIL_AI_CANONNAME;
@@ -105,6 +109,7 @@ _cb_evdns_reverse(int result, char type, int count,
req = arg;
name = addresses;
+ printf("XXX _cb_evdns_reverse %p\n", name);
if (result != DNS_ERR_NONE || count == 0)
req->cb_usr(&req->ip, NULL, req->data);
else
diff --git a/libglouglou/libglouglou.c b/libglouglou/libglouglou.c
index f702d2a..9f41313 100644
--- a/libglouglou/libglouglou.c
+++ b/libglouglou/libglouglou.c
@@ -50,6 +50,8 @@ gg_packet_props_t gg_packet_props[] = {
{ (PACKET_HEADER_SIZE + sizeof((struct gg_packet *)0)->pdat.data) },
[PACKET_NAME] = \
{ ((PACKET_HEADER_SIZE + sizeof((struct gg_packet *)0)->pdat.name) - GG_PKTARG_MAX) },
+ [PACKET_TRACE] = \
+ { ((PACKET_HEADER_SIZE + sizeof((struct gg_packet *)0)->pdat.trace) - (sizeof(struct gg_packet_tracehop) * GG_PKTARG_MAX)) },
[PACKET_FORK] = \
{ (PACKET_HEADER_SIZE + sizeof((struct gg_packet *)0)->pdat.fork) },
[PACKET_EXEC] = \
@@ -514,8 +516,7 @@ pkt_decode(char **buf, int *buf_len)
{
static struct gg_packet newpkt;
struct gg_packet *pkt;
- int len;
- int packet_len;
+ int i, len, packet_len;
len = *buf_len;
@@ -566,6 +567,22 @@ pkt_decode(char **buf, int *buf_len)
strncpy((char *)newpkt.name_fqdn, (char *)pkt->name_fqdn,
newpkt.name_len);
break;
+ case PACKET_TRACE:
+ newpkt.trace_addr = ntohl(pkt->trace_addr);
+ newpkt.trace_hopcount = pkt->trace_hopcount;
+ if (newpkt.trace_hopcount > GG_PKTARG_MAX)
+ invalid("type trace hopcount");
+ packet_len = packet_len \
+ + newpkt.trace_hopcount * sizeof(struct gg_packet_tracehop);
+ if (len < packet_len)
+ goto incomplete;
+ for (i=0; i<newpkt.trace_hopcount; i++) {
+ newpkt.trace_hops[i].addr = ntohl(pkt->trace_hops[i].addr);
+ newpkt.trace_hops[i].delay = ntohs(pkt->trace_hops[i].delay);
+ newpkt.trace_hops[i].loss = pkt->trace_hops[i].loss;
+ newpkt.trace_hops[i].asn = pkt->trace_hops[i].asn;
+ }
+ break;
case PACKET_FORK:
newpkt.fork_pid = ntohl(pkt->fork_pid);
newpkt.fork_ppid = ntohl(pkt->fork_ppid);
@@ -615,6 +632,8 @@ invalid:
int
pkt_encode(struct gg_packet *pkt, struct gg_packet *newpkt)
{
+ int i;
+
if (pkt->type < PACKET_TYPE_MIN || pkt->type > PACKET_TYPE_MAX)
invalid("type");
@@ -643,6 +662,18 @@ pkt_encode(struct gg_packet *pkt, struct gg_packet *newpkt)
strncpy((char *)newpkt->name_fqdn, (char *)pkt->name_fqdn,
pkt->name_len);
break;
+ case PACKET_TRACE:
+ if (pkt->trace_hopcount > GG_PKTARG_MAX)
+ goto invalid;
+ newpkt->trace_addr = htonl(pkt->trace_addr);
+ newpkt->trace_hopcount = pkt->trace_hopcount;
+ for (i=0; i<newpkt->trace_hopcount; i++) {
+ newpkt->trace_hops[i].addr = htonl(pkt->trace_hops[i].addr);
+ newpkt->trace_hops[i].delay = htons(pkt->trace_hops[i].delay);
+ newpkt->trace_hops[i].loss = pkt->trace_hops[i].loss;
+ newpkt->trace_hops[i].asn = pkt->trace_hops[i].asn;
+ }
+ break;
case PACKET_FORK:
newpkt->fork_pid = htonl(pkt->fork_pid);
newpkt->fork_ppid = htonl(pkt->fork_ppid);
@@ -691,6 +722,11 @@ pkt_getsize(struct gg_packet *pkt)
goto invalid;
packet_len = packet_len + pkt->name_len;
break;
+ case PACKET_TRACE:
+ if (pkt->trace_hopcount > GG_PKTARG_MAX)
+ goto invalid;
+ packet_len = packet_len + pkt->trace_hopcount * sizeof(struct gg_packet_tracehop);
+ break;
case PACKET_EXEC:
if (pkt->exec_cmdlen > GG_PKTARG_MAX)
goto invalid;
diff --git a/libglouglou/libglouglou.h b/libglouglou/libglouglou.h
index fb755a7..ac57595 100644
--- a/libglouglou/libglouglou.h
+++ b/libglouglou/libglouglou.h
@@ -35,11 +35,19 @@ enum gg_packet_type { /* u_int8_t */
PACKET_DELCONN = 0x01,
PACKET_DATA = 0x02,
PACKET_NAME = 0x03,
+ PACKET_TRACE = 0x04,
PACKET_FORK = 0x10,
PACKET_EXEC = 0x11,
PACKET_EXIT = 0x12,
};
+struct __attribute__((packed)) gg_packet_tracehop {
+ u_int32_t addr;
+ u_int16_t delay;
+ u_int8_t loss;
+ u_int8_t asn;
+};
+
/* XXX is packed needed everywhere ? */
struct __attribute__((packed)) gg_packet {
u_int8_t ver;
@@ -64,6 +72,11 @@ struct __attribute__((packed)) gg_packet {
u_int8_t len;
u_char fqdn[GG_PKTARG_MAX];
} name;
+ struct __attribute__((packed)) trace {
+ u_int32_t addr;
+ u_int8_t hopcount;
+ struct gg_packet_tracehop hops[GG_PKTARG_MAX];
+ } trace;
struct __attribute__((packed)) fork {
u_int32_t pid;
u_int32_t ppid;
@@ -92,6 +105,9 @@ struct __attribute__((packed)) gg_packet {
#define name_addr pdat.name.addr
#define name_len pdat.name.len
#define name_fqdn pdat.name.fqdn
+#define trace_addr pdat.trace.addr
+#define trace_hopcount pdat.trace.hopcount
+#define trace_hops pdat.trace.hops
#define fork_pid pdat.fork.pid
#define fork_ppid pdat.fork.ppid
#define fork_cpid pdat.fork.cpid