diff options
author | Chris Hall <GMCH@hestia.halldom.com> | 2010-08-30 13:43:54 +0100 |
---|---|---|
committer | Chris Hall <GMCH@hestia.halldom.com> | 2010-08-30 13:43:54 +0100 |
commit | 5742d229c2dfe86e626cf9287f99ff7f10673c34 (patch) | |
tree | dcdf805190db0f4b605676fbfe1a51284b904a47 | |
parent | a814c0b5b769195da9e3d00c77cd94d35936ec19 (diff) | |
download | quagga-5742d229c2dfe86e626cf9287f99ff7f10673c34.tar.bz2 quagga-5742d229c2dfe86e626cf9287f99ff7f10673c34.tar.xz |
bgpd: fix handling of AS path data
* bgpd/bgp_aspath.c
* assegments_parse(): add handling of AS4_PATH input, update bounds
checks, add check for AS segment type
* aspath_parse(): add handling of AS4_PATH input, expect
assegments_parse() to do length checking
* aspath_empty(): update for the new function prototype
* bgpd/bgp_aspath.h: ditto
* tests/aspath_test.c: ditto
* bgpd/bgp_attr.c
* bgp_attr_aspath(): add handling of AS4_PATH input, update flags
checks, change returned type
* bgp_attr_as4_path(): discard, superseded by bgp_attr_aspath()
* bgp_attr_parse(): update respectively
Bump version to "ex06" (configure.c).
-rw-r--r-- | bgpd/bgp_aspath.c | 143 | ||||
-rw-r--r-- | bgpd/bgp_aspath.h | 2 | ||||
-rw-r--r-- | bgpd/bgp_attr.c | 116 | ||||
-rw-r--r-- | bgpd/bgp_damp.c | 8 | ||||
-rwxr-xr-x | configure.ac | 2 | ||||
-rw-r--r-- | tests/aspath_test.c | 178 |
6 files changed, 245 insertions, 204 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 1053f1e8..5a6ad91f 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -671,57 +671,82 @@ aspath_hash_alloc (void *arg) return aspath; } -/* parse as-segment byte stream in struct assegment */ +/* parse *not-empty* as-segment byte stream in struct assegment + * + * Requires stream to be positioned immediately after the length field of the + * atttribute red-tape, and for the length != 0. + * + * Returns NULL if the AS_PATH or AS4_PATH is not valid. + */ static struct assegment * -assegments_parse (struct stream *s, size_t length, int use32bit) +assegments_parse (struct stream *s, size_t length, int use32bit, int as4_path) { struct assegment_header segh; struct assegment *seg, *prev = NULL, *head = NULL; - size_t bytes = 0; - /* empty aspath (ie iBGP or somesuch) */ - if (length == 0) - return NULL; + assert (length > 0); /* does not expect empty AS_PATH or AS4_PATH */ if (BGP_DEBUG (as4, AS4_SEGMENT)) zlog_debug ("[AS4SEG] Parse aspath segment: got total byte length %lu", (unsigned long) length); - /* basic checks */ - if ( (STREAM_READABLE(s) < length) - || (STREAM_READABLE(s) < AS_HEADER_SIZE) - || (length % AS16_VALUE_SIZE )) + + /* double check that length does not exceed stream */ + if (STREAM_READABLE(s) < length) return NULL; - while ( (STREAM_READABLE(s) > AS_HEADER_SIZE) - && (bytes < length)) + /* deal with each segment in turn */ + while (length > 0) { int i; - int seg_size; + size_t seg_size; /* softly softly, get the header first on its own */ - segh.type = stream_getc (s); - segh.length = stream_getc (s); + if (length >= AS_HEADER_SIZE) + { + segh.type = stream_getc (s); + segh.length = stream_getc (s); - seg_size = ASSEGMENT_SIZE(segh.length, use32bit); + seg_size = ASSEGMENT_SIZE(segh.length, use32bit); + /* includes the segment type and length red tape */ - if (BGP_DEBUG (as4, AS4_SEGMENT)) - zlog_debug ("[AS4SEG] Parse aspath segment: got type %d, length %d", - segh.type, segh.length); - - /* check it.. */ - if ( ((bytes + seg_size) > length) - /* 1771bis 4.3b: seg length contains one or more */ - || (segh.length == 0) - /* Paranoia in case someone changes type of segment length. - * Shift both values by 0x10 to make the comparison operate - * on more, than 8 bits (otherwise it's a warning, bug #564). - */ - || ((sizeof segh.length > 1) && (0x10 + segh.length > 0x10 + AS_SEGMENT_MAX)) ) + if (BGP_DEBUG (as4, AS4_SEGMENT)) + zlog_debug ("[AS4SEG] Parse aspath segment: got type %d, length %d", + segh.type, segh.length); + + /* Check that the segment type is valid */ + switch (segh.type) + { + case AS_SEQUENCE: + case AS_SET: + break ; + + case AS_CONFED_SEQUENCE: + case AS_CONFED_SET: + if (!as4_path) + break ; + /* RFC4893 3: "invalid for the AS4_PATH attribute" */ + /* fall through */ + + default: /* reject unknown or invalid AS_PATH segment types */ + seg_size = 0 ; + } ; + } + else + seg_size = 0 ; + + /* Stop now if segment is not valid (discarding anything collected to date) + * + * RFC4271 4.3, Path Attributes, b) AS_PATH: + * + * "path segment value field contains one or more AS numbers" + */ + if ((seg_size == 0) || (seg_size > length) || (segh.length == 0)) { - if (head) - assegment_free_all (head); + assegment_free_all (head); return NULL; - } + } ; + + length -= seg_size ; /* now its safe to trust lengths */ seg = assegment_new (segh.type, segh.length); @@ -734,11 +759,9 @@ assegments_parse (struct stream *s, size_t length, int use32bit) for (i = 0; i < segh.length; i++) seg->as[i] = (use32bit) ? stream_getl (s) : stream_getw (s); - bytes += seg_size; - if (BGP_DEBUG (as4, AS4_SEGMENT)) - zlog_debug ("[AS4SEG] Parse aspath segment: Bytes now: %lu", - (unsigned long) bytes); + zlog_debug ("[AS4SEG] Parse aspath segment: length left: %lu", + (unsigned long) length); prev = seg; } @@ -746,30 +769,42 @@ assegments_parse (struct stream *s, size_t length, int use32bit) return assegment_normalise (head); } -/* AS path parse function. pnt is a pointer to byte stream and length - is length of byte stream. If there is same AS path in the the AS - path hash then return it else make new AS path structure. */ +/* AS path parse function -- parses AS_PATH and AS4_PATH attributes + * + * Requires: s -- stream, currently positioned before first segment + * of AS_PATH or AS4_PATH (ie after attribute header) + * length -- length of the value of the AS_PATH or AS4_PATH + * use32bit -- true <=> 4Byte ASN, otherwise 2Byte ASN + * as4_path -- true <=> AS4_PATH, otherwise AS_PATH + * + * Returns: if valid: address of struct aspath in the hash of known aspaths, + * with reference count incremented. + * else: NULL + * + * NB: empty AS path (length == 0) is valid. The returned struct aspath will + * have segments == NULL and str == zero length string (unique). + */ struct aspath * -aspath_parse (struct stream *s, size_t length, int use32bit) +aspath_parse (struct stream *s, size_t length, int use32bit, int as4_path) { struct aspath as; struct aspath *find; - /* If length is odd it's malformed AS path. */ - /* Nit-picking: if (use32bit == 0) it is malformed if odd, - * otherwise its malformed when length is larger than 2 and (length-2) - * is not dividable by 4. - * But... this time we're lazy - */ - if (length % AS16_VALUE_SIZE ) - return NULL; - + /* Parse each segment and construct normalised list of struct assegment */ memset (&as, 0, sizeof (struct aspath)); - as.segments = assegments_parse (s, length, use32bit); + if (length != 0) + { + as.segments = assegments_parse (s, length, use32bit, as4_path); - /* If already same aspath exist then return it. */ + if (as.segments == NULL) + return NULL ; /* Invalid AS_PATH or AS4_PATH */ + } ; + + /* If already same aspath exist then return it. */ find = hash_get (ashash, &as, aspath_hash_alloc); + assert(find) ; /* valid aspath, so must find or create */ + /* aspath_hash_alloc dupes segments too. that probably could be * optimised out. */ @@ -777,12 +812,10 @@ aspath_parse (struct stream *s, size_t length, int use32bit) if (as.str) XFREE (MTYPE_AS_STR, as.str); - if (! find) - return NULL; find->refcnt++; return find; -} +} ; static inline void assegment_data_put (struct stream *s, as_t *as, int num, int use32bit) @@ -1605,7 +1638,7 @@ aspath_segment_add (struct aspath *as, int type) struct aspath * aspath_empty (void) { - return aspath_parse (NULL, 0, 1); /* 32Bit ;-) */ + return aspath_parse (NULL, 0, 1, 0); /* 32Bit ;-) not AS4_PATH */ } struct aspath * diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index 4556c503..895379aa 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -70,7 +70,7 @@ struct aspath /* Prototypes. */ extern void aspath_init (void); extern void aspath_finish (void); -extern struct aspath *aspath_parse (struct stream *, size_t, int); +extern struct aspath *aspath_parse (struct stream *, size_t, int, int); extern struct aspath *aspath_dup (struct aspath *); extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *); extern struct aspath *aspath_prepend (struct aspath *, struct aspath *); diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e3ef01d7..688cc015 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -869,52 +869,77 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length, return 0; } -/* Parse AS path information. This function is wrapper of - aspath_parse. */ -static int +/* Parse AS path information. This function is wrapper of aspath_parse. + * + * Parses AS_PATH or AS4_PATH. + * + * Returns: if valid: address of struct aspath in the hash of known aspaths, + * with reference count incremented. + * else: NULL + * + * NB: empty AS path (length == 0) is valid. The returned struct aspath will + * have segments == NULL and str == zero length string (unique). + */ +static struct aspath * bgp_attr_aspath (struct peer *peer, bgp_size_t length, - struct attr *attr, u_char flag, u_char *startp) + struct attr *attr, u_char flag, u_char *startp, int as4_path) { - bgp_size_t total; + u_char require ; + struct aspath *asp ; - total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3); + /* Check the attribute flags */ + require = as4_path ? BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS + : BGP_ATTR_FLAG_TRANS ; - /* Flag check. */ - if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL) - || ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS)) + if ((flag & (BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS)) != require) { + const char* path_type ; + bgp_size_t total; + + path_type = as4_path ? "AS4_PATH" : "AS_PATH" ; + + if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)) zlog (peer->log, LOG_ERR, - "As-Path attribute flag isn't transitive %d", flag); - bgp_peer_down_error_with_data (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, - startp, total); - return -1; - } + "%s attribute flag isn't transitive %d", path_type, flag) ; - /* - * peer with AS4 => will get 4Byte ASnums provided AS4 was advertised - * otherwise, will get 16 Bit + if ((flag & BGP_ATTR_FLAG_OPTIONAL) != (require & BGP_ATTR_FLAG_OPTIONAL)) + zlog (peer->log, LOG_ERR, + "%s attribute flag must %sbe optional %d", path_type, + (flag & BGP_ATTR_FLAG_OPTIONAL) ? "not " : "", flag) ; + + total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3); + + bgp_peer_down_error_with_data (peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, + startp, total) ; + + return NULL ; + } ; + + /* Parse the AS_PATH/AS4_PATH body. + * + * For AS_PATH peer with AS4 => 4Byte ASN otherwise 2Byte ASN + * AS4_PATH 4Byte ASN */ - attr->aspath = aspath_parse (peer->ibuf, length, PEER_CAP_AS4_USE(peer)) ; + asp = aspath_parse (peer->ibuf, length, + as4_path || PEER_CAP_AS4_USE(peer), as4_path) ; - /* In case of IBGP, length will be zero. */ - if (! attr->aspath) + if (asp != NULL) { - zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length); - bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_AS_PATH); - return -1; + attr->flag |= ATTR_FLAG_BIT (as4_path ? BGP_ATTR_AS4_PATH + : BGP_ATTR_AS_PATH) ; } + else + { + zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length); - /* Forward pointer. */ -/* stream_forward_getp (peer->ibuf, length);*/ + /* TODO: should BGP_NOTIFY_UPDATE_MAL_AS_PATH be sent for AS4_PATH ?? */ + bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_AS_PATH) ; + } ; - /* Set aspath attribute flag. */ - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); - - return 0; -} + return asp ; +} ; static int bgp_attr_aspath_check( struct peer *peer, struct attr *attr) @@ -969,21 +994,6 @@ static int bgp_attr_aspath_check( struct peer *peer, } -/* Parse AS4 path information. This function is another wrapper of - aspath_parse. */ -static int -bgp_attr_as4_path (struct peer *peer, bgp_size_t length, - struct attr *attr, struct aspath **as4_path) -{ - *as4_path = aspath_parse (peer->ibuf, length, 1); - - /* Set aspath attribute flag. */ - if (as4_path) - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH); - - return 0; -} - /* Nexthop attribute. */ static int bgp_attr_nexthop (struct peer *peer, bgp_size_t length, @@ -1723,11 +1733,13 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, ret = bgp_attr_origin (peer, length, attr, flag, startp); break; case BGP_ATTR_AS_PATH: - ret = bgp_attr_aspath (peer, length, attr, flag, startp); - break; + attr->aspath = bgp_attr_aspath (peer, length, attr, flag, startp, 0); + ret = attr->aspath ? 0 : -1 ; + break; case BGP_ATTR_AS4_PATH: - ret = bgp_attr_as4_path (peer, length, attr, &as4_path ); - break; + as4_path = bgp_attr_aspath (peer, length, attr, flag, startp, 1); + ret = as4_path ? 0 : -1 ; + break; case BGP_ATTR_NEXT_HOP: ret = bgp_attr_nexthop (peer, length, attr, flag, startp); break; diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 52a93eb7..a474b606 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -405,7 +405,7 @@ bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup) /* Decay-array computations */ damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T); - damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY, + damp->decay_array = XCALLOC (MTYPE_BGP_DAMP_ARRAY, sizeof(double) * (damp->decay_array_size)); damp->decay_array[0] = 1.0; damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5)); @@ -423,14 +423,10 @@ bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup) damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list_size * sizeof (struct bgp_reuse_node *)); - memset (damp->reuse_list, 0x00, - damp->reuse_list_size * sizeof (struct bgp_reuse_node *)); /* Reuse-array computations */ - damp->reuse_index = XMALLOC (MTYPE_BGP_DAMP_ARRAY, + damp->reuse_index = XCALLOC (MTYPE_BGP_DAMP_ARRAY, sizeof(int) * damp->reuse_index_size); - memset (damp->reuse_index, 0x00, - damp->reuse_list_size * sizeof (int)); reuse_max_ratio = (double)damp->ceiling/damp->reuse_limit; j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0)); diff --git a/configure.ac b/configure.ac index a4c411bb..983ebae9 100755 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,7 @@ ## $Id$ AC_PREREQ(2.53) -AC_INIT(Quagga, 0.99.15ex05, [http://bugzilla.quagga.net]) +AC_INIT(Quagga, 0.99.15ex06, [http://bugzilla.quagga.net]) AC_CONFIG_SRCDIR(lib/zebra.h) AC_CONFIG_MACRO_DIR([m4]) diff --git a/tests/aspath_test.c b/tests/aspath_test.c index fb504f31..ff9d4d5e 100644 --- a/tests/aspath_test.c +++ b/tests/aspath_test.c @@ -21,7 +21,7 @@ struct thread_master *master = NULL; static int failed = 0; /* specification for a test - what the results should be */ -struct test_spec +struct test_spec { const char *shouldbe; /* the string the path should parse to */ const char *shouldbe_delete_confed; /* ditto, but once confeds are deleted */ @@ -44,9 +44,9 @@ static struct test_segment { const u_char asdata[1024]; int len; struct test_spec sp; -} test_segments [] = +} test_segments [] = { - { /* 0 */ + { /* 0 */ "seq1", "seq(8466,3,52737,4096)", { 0x2,0x4, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00 }, @@ -68,7 +68,7 @@ static struct test_segment { { /* 2 */ "seq3", "seq(8466,3,52737,4096,8722,4)", - { 0x2,0x6, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, + { 0x2,0x6, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x22,0x12, 0x00,0x04}, 14, { "8466 3 52737 4096 8722 4", @@ -90,7 +90,7 @@ static struct test_segment { "seq(8467, 59649) set(4196,48658) set(17322,30745)", { 0x2,0x2, 0x21,0x13, 0xe9,0x01, 0x1,0x2, 0x10,0x64, 0xbe,0x12, - 0x1,0x2, 0x43,0xaa, 0x78,0x19 }, + 0x1,0x2, 0x43,0xaa, 0x78,0x19 }, 18, { "8467 59649 {4196,48658} {17322,30745}", "8467 59649 {4196,48658} {17322,30745}", @@ -150,7 +150,7 @@ static struct test_segment { { /* 10 */ "seq4", "seq(8466,2,52737,4096,8722,4)", - { 0x2,0x6, 0x21,0x12, 0x00,0x02, 0xce,0x01, 0x10,0x00, + { 0x2,0x6, 0x21,0x12, 0x00,0x02, 0xce,0x01, 0x10,0x00, 0x22,0x12, 0x00,0x04}, 14, { "8466 2 52737 4096 8722 4", @@ -160,7 +160,7 @@ static struct test_segment { { /* 11 */ "tripleseq1", "seq(8466,2,52737) seq(4096,8722,4) seq(8722)", - { 0x2,0x3, 0x21,0x12, 0x00,0x02, 0xce,0x01, + { 0x2,0x3, 0x21,0x12, 0x00,0x02, 0xce,0x01, 0x2,0x3, 0x10,0x00, 0x22,0x12, 0x00,0x04, 0x2,0x1, 0x22,0x12}, 20, @@ -168,7 +168,7 @@ static struct test_segment { "8466 2 52737 4096 8722 4 8722", 7, 0, NOT_ALL_PRIVATE, 4096, 1, 8466 }, }, - { /* 12 */ + { /* 12 */ "someprivate", "seq(8466,64512,52737,65535)", { 0x2,0x4, 0x21,0x12, 0xfc,0x00, 0xce,0x01, 0xff,0xff }, @@ -177,7 +177,7 @@ static struct test_segment { "8466 64512 52737 65535", 4, 0, NOT_ALL_PRIVATE, 65535, 4, 8466 }, }, - { /* 13 */ + { /* 13 */ "allprivate", "seq(65534,64512,64513,65535)", { 0x2,0x4, 0xff,0xfe, 0xfc,0x00, 0xfc,0x01, 0xff,0xff }, @@ -186,7 +186,7 @@ static struct test_segment { "65534 64512 64513 65535", 4, 0, ALL_PRIVATE, 65534, 4, 65534 }, }, - { /* 14 */ + { /* 14 */ "long", "seq(8466,3,52737,4096,34285,<repeated 49 more times>)", { 0x2,0xfa, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, @@ -265,7 +265,7 @@ static struct test_segment { "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285", - + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " @@ -293,7 +293,7 @@ static struct test_segment { "8466 3 52737 4096 34285 8466 3 52737 4096 34285", 250, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, }, - { /* 15 */ + { /* 15 */ "seq1extra", "seq(8466,3,52737,4096,3456)", { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80 }, @@ -309,7 +309,7 @@ static struct test_segment { 0, { "", "", 0, 0, 0, 0, 0, 0 }, }, - { /* 17 */ + { /* 17 */ "redundantset", "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153)", { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80, @@ -337,7 +337,7 @@ static struct test_segment { { /* 19 */ "reconcile_new_asp", "set(2457,61697,4369), seq(1842,41591,51793)", - { + { 0x1,0x3, 0x09,0x99, 0xf1,0x01, 0x11,0x11, 0x2,0x3, 0x07,0x32, 0xa2,0x77, 0xca,0x51 }, 16, @@ -390,7 +390,7 @@ static struct test_segment { "23456 23456 23456 6435 59408", 5, 0, NOT_ALL_PRIVATE, 59408, 1, 23456 }, }, - { /* 24 */ + { /* 24 */ "redundantset2", "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153,7099)", { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80, @@ -402,7 +402,7 @@ static struct test_segment { "8466 3 52737 4096 3456 {7099,8153}", 6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, }, - { /* 25 */ + { /* 25 */ "zero-size overflow", "#ASNs = 0, data = seq(8466 3 52737 4096 3456)", { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80 }, @@ -410,10 +410,10 @@ static struct test_segment { { "", "", 0, 0, 0, 0, 0, 0 }, }, - { /* 26 */ + { /* 26 */ "zero-size overflow + valid segment", "seq(#AS=0:8466 3 52737),seq(4096 3456)", - { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, + { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x2,0x2, 0x10,0x00, 0x0d,0x80 }, 14 , @@ -428,7 +428,7 @@ static struct tests { const struct test_segment *test1; const struct test_segment *test2; struct test_spec sp; -} prepend_tests[] = +} prepend_tests[] = { { &test_segments[0], &test_segments[1], { "8466 3 52737 4096 8722 4", @@ -504,7 +504,7 @@ static struct tests { "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 2 52737 4096 8722 4 8722", - + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " @@ -570,7 +570,7 @@ struct tests reconcile_tests[] = }, { NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, } }, }; - + struct tests aggregate_tests[] = { { &test_segments[0], &test_segments[2], @@ -603,7 +603,7 @@ struct tests aggregate_tests[] = { NULL, NULL, { NULL, 0, 0} }, }; -struct compare_tests +struct compare_tests { int test_index1; int test_index2; @@ -643,17 +643,17 @@ make_aspath (const u_char *data, size_t len, int use32bit) { struct stream *s = NULL; struct aspath *as; - + if (len) { s = stream_new (len); stream_put (s, data, len); } - as = aspath_parse (s, len, use32bit); - + as = aspath_parse (s, len, use32bit, 0); + if (s) stream_free (s); - + return as; } @@ -670,7 +670,7 @@ printbytes (const u_char *bytes, int len) i++; } printf ("\n"); -} +} /* validate the given aspath */ static int @@ -681,27 +681,27 @@ validate (struct aspath *as, const struct test_spec *sp) const u_char *out; static struct stream *s; struct aspath *asinout, *asconfeddel, *asstr, *as4; - + out = aspath_snmp_pathseg (as, &bytes); asinout = make_aspath (out, bytes, 0); - + /* Excercise AS4 parsing a bit, with a dogfood test */ if (!s) s = stream_new (4096); bytes4 = aspath_put (s, as, 1); as4 = make_aspath (STREAM_DATA(s), bytes4, 1); - + asstr = aspath_str2aspath (sp->shouldbe); - + asconfeddel = aspath_delete_confed_seq (aspath_dup (asinout)); - + printf ("got: %s\n", aspath_print(as)); - + /* the parsed path should match the specified 'shouldbe' string. * We should pass the "eat our own dog food" test, be able to output * this path and then input it again. Ie the path resulting from: * - * aspath_parse(aspath_put(as)) + * aspath_parse(aspath_put(as)) * * should: * @@ -716,7 +716,7 @@ validate (struct aspath *as, const struct test_spec *sp) * * aspath_parse(aspath_put(as,USE32BIT)) * - * Confederation related tests: + * Confederation related tests: * - aspath_delete_confed_seq(aspath) should match shouldbe_confed * - aspath_delete_confed_seq should be idempotent. */ @@ -737,9 +737,9 @@ validate (struct aspath *as, const struct test_spec *sp) fails++; printf ("shouldbe:\n%s\n", sp->shouldbe); printf ("as4:\n%s\n", aspath_print (as4)); - printf ("hash keys: in: %d out->in: %d\n", + printf ("hash keys: in: %d out->in: %d\n", aspath_key_make (as), aspath_key_make (asinout)); - printf ("hops: %d, counted %d %d\n", sp->hops, + printf ("hops: %d, counted %d %d\n", sp->hops, aspath_count_hops (as), aspath_count_hops (asinout) ); printf ("confeds: %d, counted %d %d\n", sp->confeds, @@ -749,13 +749,13 @@ validate (struct aspath *as, const struct test_spec *sp) printbytes (out, bytes); } /* basic confed related tests */ - if ((aspath_print (asconfeddel) == NULL + if ((aspath_print (asconfeddel) == NULL && sp->shouldbe_delete_confed != NULL) - || (aspath_print (asconfeddel) != NULL + || (aspath_print (asconfeddel) != NULL && sp->shouldbe_delete_confed == NULL) || strcmp(aspath_print (asconfeddel), sp->shouldbe_delete_confed) /* delete_confed_seq should be idempotent */ - || (aspath_key_make (asconfeddel) + || (aspath_key_make (asconfeddel) != aspath_key_make (aspath_delete_confed_seq (asconfeddel)))) { failed++; @@ -772,7 +772,7 @@ validate (struct aspath *as, const struct test_spec *sp) fails++; printf ("asstr: %s\n", aspath_print (asstr)); } - + /* loop, private and first as checks */ if ((sp->does_loop && aspath_loop_check (as, sp->does_loop) == 0) || (sp->doesnt_loop && aspath_loop_check (as, sp->doesnt_loop) != 0) @@ -792,11 +792,11 @@ validate (struct aspath *as, const struct test_spec *sp) } aspath_unintern (asinout); aspath_unintern (as4); - + aspath_free (asconfeddel); aspath_free (asstr); stream_reset (s); - + return fails; } @@ -811,9 +811,9 @@ empty_get_test () printf ("%s\n", OK); else printf ("%s!\n", FAILED); - + printf ("\n"); - + aspath_free (as); } @@ -822,7 +822,7 @@ static void parse_test (struct test_segment *t) { struct aspath *asp; - + printf ("%s: %s\n", t->name, t->desc); asp = make_aspath (t->asdata, t->len, 0); @@ -833,7 +833,7 @@ parse_test (struct test_segment *t) printf (OK "\n"); else printf (FAILED "\n"); - + printf ("\n"); aspath_unintern (asp); } @@ -843,25 +843,25 @@ static void prepend_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; - + printf ("prepend %s: %s\n", t->test1->name, t->test1->desc); printf ("to %s: %s\n", t->test2->name, t->test2->desc); - + asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - + ascratch = aspath_dup (asp2); aspath_unintern (asp2); - + asp2 = aspath_prepend (asp1, ascratch); - + printf ("aspath: %s\n", aspath_print (asp2)); - + if (!validate (asp2, &t->sp)) printf ("%s\n", OK); else printf ("%s!\n", FAILED); - + printf ("\n"); aspath_unintern (asp1); aspath_free (asp2); @@ -872,24 +872,24 @@ static void empty_prepend_test (struct test_segment *t) { struct aspath *asp1, *asp2, *ascratch; - + printf ("empty prepend %s: %s\n", t->name, t->desc); - + asp1 = make_aspath (t->asdata, t->len, 0); asp2 = aspath_empty (); - + ascratch = aspath_dup (asp2); aspath_unintern (asp2); - + asp2 = aspath_prepend (asp1, ascratch); - + printf ("aspath: %s\n", aspath_print (asp2)); - + if (!validate (asp2, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); - + printf ("\n"); aspath_unintern (asp1); aspath_free (asp2); @@ -900,20 +900,20 @@ static void as4_reconcile_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; - + printf ("reconciling %s:\n %s\n", t->test1->name, t->test1->desc); printf ("with %s:\n %s\n", t->test2->name, t->test2->desc); - + asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - + ascratch = aspath_reconcile_as4 (asp1, asp2); - + if (!validate (ascratch, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); - + printf ("\n"); aspath_unintern (asp1); aspath_unintern (asp2); @@ -926,20 +926,20 @@ static void aggregate_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; - + printf ("aggregate %s: %s\n", t->test1->name, t->test1->desc); printf ("with %s: %s\n", t->test2->name, t->test2->desc); - + asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - + ascratch = aspath_aggregate (asp1, asp2); - + if (!validate (ascratch, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); - + printf ("\n"); aspath_unintern (asp1); aspath_unintern (asp2); @@ -960,23 +960,23 @@ cmp_test () struct test_segment *t1 = &test_segments[left_compare[i].test_index1]; struct test_segment *t2 = &test_segments[left_compare[i].test_index2]; struct aspath *asp1, *asp2; - + printf ("left cmp %s: %s\n", t1->name, t1->desc); printf ("and %s: %s\n", t2->name, t2->desc); - + asp1 = make_aspath (t1->asdata, t1->len, 0); asp2 = make_aspath (t2->asdata, t2->len, 0); - + if (aspath_cmp_left (asp1, asp2) != left_compare[i].shouldbe_cmp || aspath_cmp_left (asp2, asp1) != left_compare[i].shouldbe_cmp - || aspath_cmp_left_confed (asp1, asp2) + || aspath_cmp_left_confed (asp1, asp2) != left_compare[i].shouldbe_confed - || aspath_cmp_left_confed (asp2, asp1) + || aspath_cmp_left_confed (asp2, asp1) != left_compare[i].shouldbe_confed) { failed++; printf (FAILED "\n"); - printf ("result should be: cmp: %d, confed: %d\n", + printf ("result should be: cmp: %d, confed: %d\n", left_compare[i].shouldbe_cmp, left_compare[i].shouldbe_confed); printf ("got: cmp %d, cmp_confed: %d\n", @@ -987,13 +987,13 @@ cmp_test () } else printf (OK "\n"); - + printf ("\n"); aspath_unintern (asp1); aspath_unintern (asp2); } } - + int main (void) { @@ -1004,30 +1004,30 @@ main (void) parse_test (&test_segments[i]); empty_prepend_test (&test_segments[i++]); } - + i = 0; while (prepend_tests[i].test1) prepend_test (&prepend_tests[i++]); - + i = 0; while (aggregate_tests[i].test1) aggregate_test (&aggregate_tests[i++]); - + i = 0; - + while (reconcile_tests[i].test1) as4_reconcile_test (&reconcile_tests[i++]); - + i = 0; - + cmp_test(); - + i = 0; - + empty_get_test(); - + printf ("failures: %d\n", failed); printf ("aspath count: %ld\n", aspath_count()); - + return (failed + aspath_count()); } |