diff --git a/README.md b/README.md index 992ce5e..be55dff 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,7 @@ Piranha has one configuration file located in <destination folder>/etc/pir # Export options: Choose which route attributes will be exported to the dump files export origin # IGP/EGP/Unknown + export nexthop # NEXT_HOP export aspath # AS_PATH export community # COMMUNITY export extcommunity # EXTENDED COMMUNITY @@ -162,7 +163,7 @@ Piranha has one configuration file located in <destination folder>/etc/pir ### Start/Stop/Restart - /etc/piranhactl + /bin/piranhactl ### Status (state of all neighbors) @@ -187,21 +188,21 @@ With the tool *<install dir>/bin/ptoa* data from the dump files can be exp #### Human readable format - 2017-10-21 21:31:54 peer ip 2a03:2260::5 AS 201701 + 2017-10-21 21:31:54 peer ip 2a03:2260::5 AS 201701 TYPE eBGP 2017-10-21 21:31:54 prefix announce 2a06:dac0::/29 origin IGP aspath 201701 13030 25180 202939 community 5093:5349 6629:6885 7141:7397 2017-10-21 21:31:55 eof #### Machine readable format - 1508621514|P|2a03:2260::5|201701 + 1508621514|P|2a03:2260::5|201701|eBGP 1508621514|A|2a06:dac0::|29|O|I|AP|201701 13030 25180 202939|C|5093:5349 5605:5861 6629:6885 7141:7397 1508621515|E #### JSON format When decoding JSON, you must decode each line individually. Because dump file can have millions of routes, it would use too much resouces for the decoder to decode them at once. This is why there is one JSON object per line. - { "timestamp": 1508621514, "type": "peer", "msg": { "peer": { "proto": "ipv6", "ip": "2a03:2260::5", "asn": 201701 } } } - { "timestamp": 1508621514, "type": "announce", "msg": { "prefix": "2a06:dac0::/29", "origin": "IGP", "aspath": [ 201701, 13030, 25180, 202939 ], "community": [ "5093:5349", "5605:5861", "6629:6885", "7141:7397" ] } } + { "timestamp": 1508621514, "type": "peer", "msg": { "peer": { "proto": "ipv6", "ip": "2a03:2260::5", "asn": 201701, "type": "eBGP" } } } + { "timestamp": 1508621514, "type": "announce", "msg": { "prefix": "2a06:dac0::/29", "origin": "IGP", "nexthop": "2a06:ffff::1", "aspath": [ 201701, 13030, 25180, 202939 ], "community": [ "5093:5349", "5605:5861", "6629:6885", "7141:7397" ] } } { "timestamp": 1508621515, "type": "footer" } ### Message type tags in DUMPs @@ -210,7 +211,7 @@ Colons can be used to align columns. | Human | Machine | JSON | Description | |:----------|:--------|:----------|:---------------------------------------------------------------------------------------------------------------| | peer | P | peer | First message in any dump describing the neighbor | -| announce | A | announce | BGP prefix announce, optional origin (O), aspath (AP), community (C) and extended community (EC) subcomponents | +| announce | A | announce | BGP prefix announce, optional origin (O), nexthop (NH), aspath (AP), community (C) and extended community (EC) subcomponents | | withdrawn | W | withdrawn | BGP prefix withdrawn | | eof | E | footer | Last message in any dump, has no other value | diff --git a/inc/p_defs.h b/inc/p_defs.h index b18d876..a3d2f2b 100644 --- a/inc/p_defs.h +++ b/inc/p_defs.h @@ -103,11 +103,15 @@ #define BGP_ORIGIN_EGP 1 #define BGP_ORIGIN_UNKN 2 +#define BGP_TYPE_IBGP 0 +#define BGP_TYPE_EBGP 1 + #define EXPORT_ORIGIN 0x01 #define EXPORT_ASPATH 0x02 #define EXPORT_COMMUNITY 0x04 #define EXPORT_EXTCOMMUNITY 0x08 #define EXPORT_LARGECOMMUNITY 0x10 +#define EXPORT_NEXT_HOP 0x20 #define DUMP_OPEN 10 #define DUMP_CLOSE 11 @@ -188,6 +192,7 @@ struct dump_msg uint8_t type; uint16_t len; uint64_t ts; + uint64_t uts; #ifdef CC_GCC } __attribute__((packed)); #else @@ -198,6 +203,7 @@ struct dump_header4 { uint32_t ip; uint32_t as; + uint8_t type; #ifdef CC_GCC } __attribute__((packed)); #else @@ -206,8 +212,9 @@ struct dump_header4 struct dump_header6 { - uint8_t ip[16]; + uint8_t ip[16]; uint32_t as; + uint8_t type; #ifdef CC_GCC } __attribute__((packed)); #else @@ -239,6 +246,7 @@ struct dump_announce4 uint8_t mask; uint32_t prefix; uint8_t origin; + uint32_t nexthop; uint8_t aspathlen; uint16_t communitylen; uint16_t extcommunitylen4; @@ -263,6 +271,7 @@ struct dump_announce6 uint8_t mask; uint8_t prefix[16]; uint8_t origin; + uint8_t nexthop[16]; uint8_t aspathlen; uint16_t communitylen; uint16_t extcommunitylen6; @@ -386,6 +395,7 @@ struct peer_t uint8_t allow; uint8_t newallow; /* to avoid peer drop during reconfiguration */ uint8_t status; /* 0 offline, 1 connected, 2 authed */ + uint8_t type; /* iBGP/eBGP */ uint32_t ucount; /* bgp updates count */ union { struct in6_addr ip6; /* peer IPv4 address */ diff --git a/inc/p_dump.h b/inc/p_dump.h index ada4d5a..63f617e 100644 --- a/inc/p_dump.h +++ b/inc/p_dump.h @@ -1,6 +1,6 @@ /*******************************************************************************/ /* */ -/* Copyright 2004-2017 Pascal Gloor */ +/* Copyright 2004-2017 Pascal Gloor */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -17,32 +17,32 @@ /*******************************************************************************/ -void p_dump_open_file (struct peer_t *peer, int id, uint64_t ts); -void p_dump_add_open (struct peer_t *peer, int id, uint64_t ts); -void p_dump_add_close (struct peer_t *peer, int id, uint64_t ts); -void p_dump_add_keepalive (struct peer_t *peer, int id, uint64_t ts); -void p_dump_add_header4 (struct peer_t *peer, int id, uint64_t ts); -void p_dump_add_header6 (struct peer_t *peer, int id, uint64_t ts); -void p_dump_add_footer (struct peer_t *peer, int id, uint64_t ts); -void p_dump_check_file (struct peer_t *peer, int id, uint64_t ts); +void p_dump_open_file (struct peer_t *peer, int id, struct timeval *ts); +void p_dump_add_open (struct peer_t *peer, int id, struct timeval *ts); +void p_dump_add_close (struct peer_t *peer, int id, struct timeval *ts); +void p_dump_add_keepalive (struct peer_t *peer, int id, struct timeval *ts); +void p_dump_add_header4 (struct peer_t *peer, int id, struct timeval *ts); +void p_dump_add_header6 (struct peer_t *peer, int id, struct timeval *ts); +void p_dump_add_footer (struct peer_t *peer, int id, struct timeval *ts); +void p_dump_check_file (struct peer_t *peer, int id, struct timeval *ts); void p_dump_close_file (struct peer_t *peer, int id); -void p_dump_add_withdrawn4 (struct peer_t *peer, int id, uint64_t ts, +void p_dump_add_withdrawn4 (struct peer_t *peer, int id, struct timeval *ts, uint32_t prefix, uint8_t mask); -void p_dump_add_withdrawn6 (struct peer_t *peer, int id, uint64_t ts, +void p_dump_add_withdrawn6 (struct peer_t *peer, int id, struct timeval *ts, uint8_t prefix[16], uint8_t mask); -void p_dump_add_announce4 (struct peer_t *peer, int id, uint64_t ts, +void p_dump_add_announce4 (struct peer_t *peer, int id, struct timeval *ts, uint32_t prefix, uint8_t mask, - uint8_t origin, + uint8_t origin, uint32_t nexthop, void *aspath, uint16_t aspathlen, void *community, uint16_t communitylen, void *extcommunity4, uint16_t extcommunitylen4, void *largecommunity, uint16_t largecommunitylen ); -void p_dump_add_announce6 (struct peer_t *peer, int id, uint64_t ts, +void p_dump_add_announce6 (struct peer_t *peer, int id, struct timeval *ts, uint8_t prefix[16], uint8_t mask, - uint8_t origin, + uint8_t origin, uint8_t nexthop[16], void *aspath, uint16_t aspathlen, void *community, uint16_t communitylen, void *extcommunity6, uint16_t extcommunitylen6, diff --git a/inc/p_ptoa.h b/inc/p_ptoa.h index 6d824e6..2a570c9 100644 --- a/inc/p_ptoa.h +++ b/inc/p_ptoa.h @@ -23,6 +23,8 @@ int main(int argc, char *argv[]); // void mytime(time_t ts); void syntax(char *prog); void print_origin(int mode, uint8_t origin); +void print_nexthop4(int mode, uint32_t nexthop); +void print_nexthop6(int mode, uint8_t nexthop[16]); void print_aspath(int mode, struct dump_announce_aspath *aspath, uint8_t len); void print_community(int mode, struct dump_announce_community *community, uint16_t len); void print_extcommunity4(int mode, struct dump_announce_extcommunity4 *com, uint16_t len); diff --git a/inc/p_tools.h b/inc/p_tools.h index 8675829..d29b43d 100644 --- a/inc/p_tools.h +++ b/inc/p_tools.h @@ -9,4 +9,4 @@ char *p_tools_ip6str(int peerid, struct in6_addr *ip); void p_tools_dump(const char *desc, char *data, int len); -void p_tools_humantime(char *line, size_t len, time_t ts); +void p_tools_humantime(char *line, size_t len, struct timeval *ts); diff --git a/src/p_config.c b/src/p_config.c index 30ee185..be008e7 100644 --- a/src/p_config.c +++ b/src/p_config.c @@ -192,6 +192,8 @@ int p_config_load(struct config_t *config, struct peer_t *peer, uint32_t mytime) config->export |= EXPORT_EXTCOMMUNITY; else if ( ! strcmp(s, "largecommunity") ) config->export |= EXPORT_LARGECOMMUNITY; + else if ( ! strcmp(s, "nexthop") ) + config->export |= EXPORT_NEXT_HOP; #ifdef DEBUG else printf("DEBUG: Unknown export %s\n", s); @@ -275,11 +277,18 @@ int p_config_load(struct config_t *config, struct peer_t *peer, uint32_t mytime) fclose(fd); - /* clearning no more allowed peers */ + + /* clearning no more allowed peers * + * and set session type (eBGP/iBGP) */ { int a; for(a=0; aas ) + peer[a].type = BGP_TYPE_IBGP; + else + peer[a].type = BGP_TYPE_EBGP; + if ( peer[a].newallow == 0 ) { peer[a].status = 0; diff --git a/src/p_dump.c b/src/p_dump.c index d975491..8196b9f 100644 --- a/src/p_dump.c +++ b/src/p_dump.c @@ -31,7 +31,7 @@ #include /* opening file */ -void p_dump_open_file(struct peer_t *peer, int id, uint64_t ts) +void p_dump_open_file(struct peer_t *peer, int id, struct timeval *ts) { struct tm *tm; struct stat sb; @@ -39,7 +39,7 @@ void p_dump_open_file(struct peer_t *peer, int id, uint64_t ts) char filename[1024]; char mytime[100]; - peer[id].filets = ts - ( ts % DUMPINTERVAL ); + peer[id].filets = ts->tv_sec - ( ts->tv_sec % DUMPINTERVAL ); tm = gmtime((time_t*)&peer[id].filets); strftime(mytime, sizeof(mytime), "%Y%m%d%H%M%S" , tm); @@ -71,7 +71,7 @@ void p_dump_open_file(struct peer_t *peer, int id, uint64_t ts) } /* log keepalive msg */ -void p_dump_add_keepalive(struct peer_t *peer, int id, uint64_t ts) +void p_dump_add_keepalive(struct peer_t *peer, int id, struct timeval *ts) { p_dump_check_file(peer,id,ts); @@ -81,7 +81,8 @@ void p_dump_add_keepalive(struct peer_t *peer, int id, uint64_t ts) struct dump_msg msg; msg.type = DUMP_KEEPALIVE; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); msg.len = htobe16(0); fwrite(&msg, sizeof(msg), 1, peer[id].fh); @@ -89,7 +90,7 @@ void p_dump_add_keepalive(struct peer_t *peer, int id, uint64_t ts) } /* log session close */ -void p_dump_add_close(struct peer_t *peer, int id, uint64_t ts) +void p_dump_add_close(struct peer_t *peer, int id, struct timeval *ts) { if ( peer[id].fh == NULL ) { return; } peer[id].empty = 0; @@ -97,7 +98,8 @@ void p_dump_add_close(struct peer_t *peer, int id, uint64_t ts) struct dump_msg msg; msg.type = DUMP_CLOSE; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); msg.len = htobe16(0); fwrite(&msg, sizeof(msg), 1, peer[id].fh); @@ -107,7 +109,7 @@ void p_dump_add_close(struct peer_t *peer, int id, uint64_t ts) } /* log session open */ -void p_dump_add_open(struct peer_t *peer, int id, uint64_t ts) +void p_dump_add_open(struct peer_t *peer, int id, struct timeval *ts) { p_dump_check_file(peer,id,ts); @@ -117,7 +119,8 @@ void p_dump_add_open(struct peer_t *peer, int id, uint64_t ts) struct dump_msg msg; msg.type = DUMP_OPEN; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); msg.len = htobe16(0); fwrite(&msg, sizeof(msg), 1, peer[id].fh); @@ -125,14 +128,15 @@ void p_dump_add_open(struct peer_t *peer, int id, uint64_t ts) } /* footer for each EOF */ -void p_dump_add_footer(struct peer_t *peer, int id, uint64_t ts) +void p_dump_add_footer(struct peer_t *peer, int id, struct timeval *ts) { if ( peer[id].fh == NULL ) { return; } { struct dump_msg msg; msg.type = DUMP_FOOTER; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); msg.len = htobe64(0); fwrite(&msg, sizeof(msg), 1, peer[id].fh); @@ -140,7 +144,7 @@ void p_dump_add_footer(struct peer_t *peer, int id, uint64_t ts) } /* log bgp IPv4 withdrawn msg */ -void p_dump_add_withdrawn4(struct peer_t *peer, int id, uint64_t ts, uint32_t prefix, uint8_t mask) +void p_dump_add_withdrawn4(struct peer_t *peer, int id, struct timeval *ts, uint32_t prefix, uint8_t mask) { p_dump_check_file(peer,id,ts); @@ -151,7 +155,8 @@ void p_dump_add_withdrawn4(struct peer_t *peer, int id, uint64_t ts, uint32_t pr struct dump_withdrawn4 withdrawn; msg.type = DUMP_WITHDRAWN4; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); withdrawn.mask = mask; withdrawn.prefix = htobe32(prefix); @@ -165,7 +170,7 @@ void p_dump_add_withdrawn4(struct peer_t *peer, int id, uint64_t ts, uint32_t pr } /* log bgp IPv6 withdrawn msg */ -void p_dump_add_withdrawn6(struct peer_t *peer, int id, uint64_t ts, uint8_t prefix[16], uint8_t mask) +void p_dump_add_withdrawn6(struct peer_t *peer, int id, struct timeval *ts, uint8_t prefix[16], uint8_t mask) { p_dump_check_file(peer,id,ts); @@ -176,7 +181,8 @@ void p_dump_add_withdrawn6(struct peer_t *peer, int id, uint64_t ts, uint8_t pre struct dump_withdrawn6 withdrawn; msg.type = DUMP_WITHDRAWN6; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); withdrawn.mask = mask; @@ -191,9 +197,9 @@ void p_dump_add_withdrawn6(struct peer_t *peer, int id, uint64_t ts, uint8_t pre } /* log IPv4 bgp announce msg */ -void p_dump_add_announce4(struct peer_t *peer, int id, uint64_t ts, +void p_dump_add_announce4(struct peer_t *peer, int id, struct timeval *ts, uint32_t prefix, uint8_t mask, - uint8_t origin, + uint8_t origin, uint32_t nexthop, void *aspath, uint16_t aspathlen, void *community, uint16_t communitylen, void *extcommunity4, uint16_t extcommunitylen4, @@ -212,7 +218,8 @@ void p_dump_add_announce4(struct peer_t *peer, int id, uint64_t ts, struct dump_announce_largecommunity opt_largecommunity; msg.type = DUMP_ANNOUNCE4; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); msg.len = htobe16(sizeof(announce) + sizeof(opt_aspath.data[0]) * aspathlen + sizeof(opt_community.data[0]) * communitylen @@ -222,6 +229,7 @@ void p_dump_add_announce4(struct peer_t *peer, int id, uint64_t ts, announce.mask = mask; announce.prefix = htobe32(prefix); announce.origin = origin; + announce.nexthop = htobe32(nexthop); announce.aspathlen = aspathlen; announce.communitylen = communitylen; announce.extcommunitylen4 = extcommunitylen4; @@ -297,9 +305,9 @@ void p_dump_add_announce4(struct peer_t *peer, int id, uint64_t ts, } } /* log IPv6 bgp announce msg */ -void p_dump_add_announce6(struct peer_t *peer, int id, uint64_t ts, +void p_dump_add_announce6(struct peer_t *peer, int id, struct timeval *ts, uint8_t prefix[16], uint8_t mask, - uint8_t origin, + uint8_t origin, uint8_t nexthop[16], void *aspath, uint16_t aspathlen, void *community, uint16_t communitylen, void *extcommunity6, uint16_t extcommunitylen6, @@ -318,7 +326,8 @@ void p_dump_add_announce6(struct peer_t *peer, int id, uint64_t ts, struct dump_announce_largecommunity opt_largecommunity; msg.type = DUMP_ANNOUNCE6; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); msg.len = htobe16( sizeof(announce) + sizeof(opt_aspath.data[0]) * aspathlen + sizeof(opt_community.data[0]) * communitylen @@ -328,6 +337,7 @@ void p_dump_add_announce6(struct peer_t *peer, int id, uint64_t ts, memcpy(announce.prefix, prefix, sizeof(announce.prefix)); announce.mask = mask; announce.origin = origin; + memcpy(announce.nexthop, nexthop, sizeof(announce.nexthop)); announce.aspathlen = aspathlen; announce.communitylen = communitylen; announce.extcommunitylen6 = extcommunitylen6; @@ -405,9 +415,9 @@ void p_dump_add_announce6(struct peer_t *peer, int id, uint64_t ts, } /* check if need to reopen a new file */ -void p_dump_check_file(struct peer_t *peer, int id, uint64_t ts) +void p_dump_check_file(struct peer_t *peer, int id, struct timeval *ts) { - uint64_t mts = ts - ( ts % DUMPINTERVAL ); + uint64_t mts = ts->tv_sec - ( ts->tv_sec % DUMPINTERVAL ); if ( mts == peer[id].filets && peer[id].fh != NULL ) { return; } @@ -440,7 +450,7 @@ void p_dump_check_file(struct peer_t *peer, int id, uint64_t ts) } /* file header */ -void p_dump_add_header4(struct peer_t *peer, int id, uint64_t ts) +void p_dump_add_header4(struct peer_t *peer, int id, struct timeval *ts) { if ( peer[id].fh == NULL ) { return; } { @@ -448,11 +458,13 @@ void p_dump_add_header4(struct peer_t *peer, int id, uint64_t ts) struct dump_header4 header; msg.type = DUMP_HEADER4; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); msg.len = htobe16(sizeof(header)); - header.ip = peer[id].ip4.s_addr; - header.as = htobe32(peer[id].as); + header.ip = peer[id].ip4.s_addr; + header.as = htobe32(peer[id].as); + header.type = peer[id].type; fwrite(&msg, sizeof(msg), 1, peer[id].fh); fwrite(&header, sizeof(header), 1, peer[id].fh); @@ -460,7 +472,7 @@ void p_dump_add_header4(struct peer_t *peer, int id, uint64_t ts) } /* file header */ -void p_dump_add_header6(struct peer_t *peer, int id, uint64_t ts) +void p_dump_add_header6(struct peer_t *peer, int id, struct timeval *ts) { if ( peer[id].fh == NULL ) { return; } { @@ -468,11 +480,13 @@ void p_dump_add_header6(struct peer_t *peer, int id, uint64_t ts) struct dump_header6 header; msg.type = DUMP_HEADER6; - msg.ts = htobe64(ts); + msg.ts = htobe64((uint64_t)ts->tv_sec); + msg.uts = htobe64((uint64_t)ts->tv_usec); msg.len = htobe16(sizeof(header)); memcpy(header.ip, peer[id].ip6.s6_addr, sizeof(header.ip)); - header.as = htobe32(peer[id].as); + header.as = htobe32(peer[id].as); + header.type = peer[id].type; fwrite(&msg, sizeof(msg), 1, peer[id].fh); fwrite(&header, sizeof(header), 1, peer[id].fh); diff --git a/src/p_piranha.c b/src/p_piranha.c index e5fd398..b1f2cd9 100644 --- a/src/p_piranha.c +++ b/src/p_piranha.c @@ -160,6 +160,7 @@ void *p_main_peer(void *data) struct sockaddr_in *addr4 = (struct sockaddr_in *)&sockaddr; struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&sockaddr; socklen_t socklen = sizeof(sockaddr); + struct timeval msgtime; memcpy(&sock,data,sizeof(sock)); @@ -257,7 +258,8 @@ void *p_main_peer(void *data) #endif p_main_peer_loop(peerid); - p_dump_add_close(peer, peerid, ts.tv_sec); + gettimeofday(&msgtime, NULL); + p_dump_add_close(peer, peerid, &msgtime); /* peer disconnected, lets wait a bit to avoid direct reconnection */ /* we'll wait DUMPINTERVAL time! */ @@ -278,6 +280,7 @@ void p_main_peer_loop(int id) char *ibuf; char *obuf; uint8_t marker[16]; + struct timeval msgtime; { int a; for(a=0; a 0 ) @@ -503,6 +507,7 @@ void p_main_peer_work(char *ibuf, char *obuf, int id) { int pos = 0; struct bgp_header *header; + struct timeval msgtime; if ( peer[id].ilen < sizeof(struct bgp_header) ) { @@ -514,6 +519,7 @@ void p_main_peer_work(char *ibuf, char *obuf, int id) header = (struct bgp_header*)ibuf; + if ( memcmp(header->marker, marker, sizeof(marker)) != 0 ) { snprintf(logline, sizeof(logline), "%s packet decoding error\n", @@ -549,6 +555,8 @@ void p_main_peer_work(char *ibuf, char *obuf, int id) peer[id].rts = ts.tv_sec; + gettimeofday(&msgtime, NULL); + /* BGP OPEN MSG */ if ( header->type == BGP_OPEN && peer[id].status == 1 ) { @@ -689,7 +697,7 @@ void p_main_peer_work(char *ibuf, char *obuf, int id) peer[id].status = 2; - p_dump_add_open(peer, id, ts.tv_sec); + p_dump_add_open(peer, id, &msgtime); } else if ( header->type == BGP_UPDATE && peer[id].status == 2 ) @@ -698,6 +706,7 @@ void p_main_peer_work(char *ibuf, char *obuf, int id) uint16_t wlen; uint16_t alen; uint8_t origin = 0xff; + uint32_t nexthop = 0xffffff; void *aspath = NULL; uint16_t aspathlen = 0; void *community = NULL; @@ -775,7 +784,7 @@ void p_main_peer_work(char *ibuf, char *obuf, int id) } #endif - p_dump_add_withdrawn4(peer,id,ts.tv_sec,prefix,plen); + p_dump_add_withdrawn4(peer,id,&msgtime,prefix,plen); peer[id].ucount++; } @@ -871,6 +880,21 @@ void p_main_peer_work(char *ibuf, char *obuf, int id) #endif } } + + if ( a[BGP_ATTR_NEXT_HOP].pos != 0xffff && config.export & EXPORT_NEXT_HOP ) + { + uint16_t off = a[BGP_ATTR_NEXT_HOP].pos; + uint16_t codelen = a[BGP_ATTR_NEXT_HOP].len; + + if ( codelen == 4 ) + { + nexthop = be32toh(*(uint32_t*) (ibuf+pos+off)); + #ifdef DEBUG + printf("NEXT_HOP: %s\n", p_tools_ip4str(id, (ibuf+pos+off)) ); + #endif + } + } + if ( a[BGP_ATTR_AS_PATH].pos != 0xffff && config.export & EXPORT_ASPATH ) { uint16_t off = a[BGP_ATTR_AS_PATH].pos; @@ -1010,15 +1034,21 @@ void p_main_peer_work(char *ibuf, char *obuf, int id) { uint16_t off = a[BGP_ATTR_MP_REACH_NLRI].pos; uint16_t codelen = a[BGP_ATTR_MP_REACH_NLRI].len; - int i = 0; - uint16_t afi = ntohs(*(uint16_t*) (ibuf+pos+off)); - uint8_t safi = *(uint8_t*) (ibuf+pos+off+2); - uint8_t nhlen = *(uint8_t*) (ibuf+pos+off+3); + int i = 0; + uint16_t afi = ntohs(*(uint16_t*) (ibuf+pos+off)); + uint8_t safi = *(uint8_t*) (ibuf+pos+off+2); + uint8_t nhlen = *(uint8_t*) (ibuf+pos+off+3); + uint8_t nh[16]; + + memset(nh, 0xff, sizeof(nh)); i += 4 + nhlen + 1; if ( afi == 2 && safi == 1) /* IPv6 Unicast */ { + if ( config.export & EXPORT_NEXT_HOP ) + memcpy(nh, ibuf+pos+off+4, nhlen); + while(i 0 ) print_aspath(mode, &msg.aspath, msg.announce4.aspathlen); @@ -227,6 +234,20 @@ int main(int argc, char *argv[]) if ( msg.announce6.origin != 0xff ) print_origin(mode, msg.announce6.origin); + { + int i; + int doit = 0; + for(i=0; i<16; i++) { + if ( msg.announce6.nexthop[i] != 0xff ) { + doit=1; + break; + } + } + + if ( doit ) + print_nexthop6(mode, msg.announce6.nexthop); + } + if ( msg.announce6.aspathlen > 0 ) print_aspath(mode, &msg.aspath, msg.announce6.aspathlen); @@ -338,6 +359,44 @@ void syntax(char *prog) exit(-1); } +void print_nexthop4(int mode, uint32_t nexthop) +{ + struct in_addr addr; + addr.s_addr = htobe32(nexthop); + + switch(mode) + { + case PTOA_MACHINE: + printf("|NH|%u", nexthop); + break; + case PTOA_HUMAN: + printf(" nexthop %s", inet_ntoa(addr)); + break; + case PTOA_JSON: + printf(", \"nexthop\": \"%s\"", inet_ntoa(addr)); + break; + } +} + +void print_nexthop6(int mode, uint8_t nexthop[16]) +{ + struct in6_addr addr; + memcpy(addr.s6_addr, nexthop, 16); + + switch(mode) + { + case PTOA_MACHINE: + printf("|NH|%s", p_tools_ip6str(0, &addr)); + break; + case PTOA_HUMAN: + printf(" nexthop %s", p_tools_ip6str(0, &addr)); + break; + case PTOA_JSON: + printf(", \"nexthop\": \"%s\"", p_tools_ip6str(0, &addr)); + break; + } +} + void print_origin(int mode, uint8_t origin) { char o = '?'; diff --git a/src/p_tools.c b/src/p_tools.c index d8eb069..502b86d 100644 --- a/src/p_tools.c +++ b/src/p_tools.c @@ -123,9 +123,10 @@ void p_tools_dump(const char *desc, char *data, int len) printf("DUMP END\n"); } -void p_tools_humantime(char *line, size_t len, time_t ts) +void p_tools_humantime(char *line, size_t len, struct timeval *ts) { struct tm *tm; - tm = gmtime(&ts); + tm = gmtime(&ts->tv_sec); strftime(line, len, "%Y-%m-%d %H:%M:%S", tm); + snprintf(line + strlen(line), len - strlen(line), ".%03llu", (long long unsigned)ts->tv_usec / 1000); } diff --git a/src/p_undump.c b/src/p_undump.c index 3b13c85..bd7eb36 100644 --- a/src/p_undump.c +++ b/src/p_undump.c @@ -93,6 +93,7 @@ int p_undump_readmsg(struct dump_file_ctx *ctx, struct dump_full_msg *fmsg) /* convert header fields */ msg.len = be16toh(msg.len); msg.ts = be64toh(msg.ts); + msg.uts = be64toh(msg.uts); memcpy(&fmsg->msg, &msg, sizeof(msg)); #ifdef DEBUG @@ -112,15 +113,17 @@ int p_undump_readmsg(struct dump_file_ctx *ctx, struct dump_full_msg *fmsg) if ( msg.type == DUMP_HEADER4 && !ctx->head ) { struct dump_header4 *header = (struct dump_header4 *)(buffer); - fmsg->header4.ip = be32toh(header->ip); - fmsg->header4.as = be32toh(header->as); + fmsg->header4.ip = be32toh(header->ip); + fmsg->header4.as = be32toh(header->as); + fmsg->header4.type = header->type; ctx->head=1; } else if ( msg.type == DUMP_HEADER6 && !ctx->head ) { struct dump_header6 *header = (struct dump_header6 *)(buffer); memcpy(fmsg->header6.ip,header->ip, sizeof(header->ip)); - fmsg->header6.as = be32toh(header->as); + fmsg->header6.as = be32toh(header->as); + fmsg->header4.type = header->type; ctx->head=1; } else if ( msg.type == DUMP_OPEN && ctx->head ) @@ -156,6 +159,7 @@ int p_undump_readmsg(struct dump_file_ctx *ctx, struct dump_full_msg *fmsg) fmsg->announce4.mask = announce4->mask; fmsg->announce4.prefix = be32toh(announce4->prefix); fmsg->announce4.origin = announce4->origin; + fmsg->announce4.nexthop = be32toh(announce4->nexthop); fmsg->announce4.aspathlen = announce4->aspathlen; fmsg->announce4.communitylen = announce4->communitylen; fmsg->announce4.extcommunitylen4 = announce4->extcommunitylen4; @@ -175,6 +179,7 @@ int p_undump_readmsg(struct dump_file_ctx *ctx, struct dump_full_msg *fmsg) memcpy(fmsg->announce6.prefix, announce6->prefix, sizeof(announce6->prefix)); fmsg->announce6.mask = announce6->mask; fmsg->announce6.origin = announce6->origin; + memcpy(fmsg->announce6.nexthop, announce6->nexthop, sizeof(announce6->nexthop)); fmsg->announce6.aspathlen = announce6->aspathlen; fmsg->announce6.communitylen = announce6->communitylen; fmsg->announce6.extcommunitylen6 = announce6->extcommunitylen6; diff --git a/utils/piranhactl.in b/utils/piranhactl.in index 07c2409..8fb9377 100755 --- a/utils/piranhactl.in +++ b/utils/piranhactl.in @@ -2,7 +2,7 @@ # /*******************************************************************************/ # /* */ -# /* Copyright 2004-2017 Pascal Gloor */ +# /* Copyright 2004-2017 Pascal Gloor */ # /* */ # /* Licensed under the Apache License, Version 2.0 (the "License"); */ # /* you may not use this file except in compliance with the License. */ @@ -23,6 +23,7 @@ PIRANHA="${WDIR}/bin/piranha"; CONFIG="${WDIR}/etc/piranha.conf"; PIDFILE="${WDIR}/var/piranha.pid"; PEERSFILE="${WDIR}/var/piranha.status"; +DUMP="${WDIR}/var/dump/"; case "$1" in @@ -34,6 +35,7 @@ start) then if [ -r ${CONFIG} ] then + test -r "${DUMP}" && find "${DUMP}/" -depth -mindepth 1 -delete ${PIRANHA} ${CONFIG} && echo "ok"; else echo "piranha fatal error, cannot find ${CONFIG}";