]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_aspath.c
Merge pull request #3432 from opensourcerouting/6.0-backport-bgp-ifp-crash
[mirror_frr.git] / bgpd / bgp_aspath.c
index 2b776d218277ce7eadd2675d3288a1c6845cbfac..b532927e80d845acb9c98851046c842597960c60 100644 (file)
@@ -80,8 +80,8 @@
  * NOT the internal representation!
  */
 struct assegment_header {
-       u_char type;
-       u_char length;
+       uint8_t type;
+       uint8_t length;
 };
 
 /* Hash for aspath.  This is the top level structure of AS path. */
@@ -109,7 +109,7 @@ const char *aspath_segment_type_str[] = {"as-invalid", "as-set", "as-sequence",
  * the caller should immediately assign data to the segment, as the segment
  * otherwise is not generally valid
  */
-static struct assegment *assegment_new(u_char type, u_short length)
+static struct assegment *assegment_new(uint8_t type, unsigned short length)
 {
        struct assegment *new;
 
@@ -214,16 +214,11 @@ static struct assegment *assegment_append_asns(struct assegment *seg,
        newas = XREALLOC(MTYPE_AS_SEG_DATA, seg->as,
                         ASSEGMENT_DATA_SIZE(seg->length + num, 1));
 
-       if (newas) {
-               seg->as = newas;
-               memcpy(seg->as + seg->length, asnos,
-                      ASSEGMENT_DATA_SIZE(num, 1));
-               seg->length += num;
-               return seg;
-       }
-
-       assegment_free_all(seg);
-       return NULL;
+       seg->as = newas;
+       memcpy(seg->as + seg->length, asnos,
+              ASSEGMENT_DATA_SIZE(num, 1));
+       seg->length += num;
+       return seg;
 }
 
 static int int_cmp(const void *p1, const void *p2)
@@ -345,7 +340,7 @@ void aspath_unintern(struct aspath **aspath)
 /* Return the start or end delimiters for a particular Segment type */
 #define AS_SEG_START 0
 #define AS_SEG_END 1
-static char aspath_delimiter_char(u_char type, u_char which)
+static char aspath_delimiter_char(uint8_t type, uint8_t which)
 {
        int i;
        struct {
@@ -479,7 +474,7 @@ unsigned int aspath_has_as4(struct aspath *aspath)
 }
 
 /* Convert aspath structure to string expression. */
-static void aspath_make_str_count(struct aspath *as)
+static void aspath_make_str_count(struct aspath *as, bool make_json)
 {
        struct assegment *seg;
        int str_size;
@@ -489,14 +484,19 @@ static void aspath_make_str_count(struct aspath *as)
        json_object *jseg = NULL;
        json_object *jseg_list = NULL;
 
-       as->json = json_object_new_object();
-       jaspath_segments = json_object_new_array();
+       if (make_json) {
+               as->json = json_object_new_object();
+               jaspath_segments = json_object_new_array();
+       }
 
        /* Empty aspath. */
        if (!as->segments) {
-               json_object_string_add(as->json, "string", "Local");
-               json_object_object_add(as->json, "segments", jaspath_segments);
-               json_object_int_add(as->json, "length", 0);
+               if (make_json) {
+                       json_object_string_add(as->json, "string", "Local");
+                       json_object_object_add(as->json, "segments",
+                                              jaspath_segments);
+                       json_object_int_add(as->json, "length", 0);
+               }
                as->str = XMALLOC(MTYPE_AS_STR, 1);
                as->str[0] = '\0';
                as->str_len = 0;
@@ -539,6 +539,7 @@ static void aspath_make_str_count(struct aspath *as)
                        as->str_len = 0;
                        json_object_free(as->json);
                        as->json = NULL;
+
                        return;
                }
 
@@ -564,12 +565,15 @@ static void aspath_make_str_count(struct aspath *as)
                                str_buf + len, str_size - len, "%c",
                                aspath_delimiter_char(seg->type, AS_SEG_START));
 
-               jseg_list = json_object_new_array();
+               if (make_json)
+                       jseg_list = json_object_new_array();
 
                /* write out the ASNs, with their seperators, bar the last one*/
                for (i = 0; i < seg->length; i++) {
-                       json_object_array_add(jseg_list,
-                                             json_object_new_int(seg->as[i]));
+                       if (make_json)
+                               json_object_array_add(
+                                       jseg_list,
+                                       json_object_new_int(seg->as[i]));
 
                        len += snprintf(str_buf + len, str_size - len, "%u",
                                        seg->as[i]);
@@ -579,11 +583,14 @@ static void aspath_make_str_count(struct aspath *as)
                                                "%c", seperator);
                }
 
-               jseg = json_object_new_object();
-               json_object_string_add(jseg, "type",
-                                      aspath_segment_type_str[seg->type]);
-               json_object_object_add(jseg, "list", jseg_list);
-               json_object_array_add(jaspath_segments, jseg);
+               if (make_json) {
+                       jseg = json_object_new_object();
+                       json_object_string_add(
+                               jseg, "type",
+                               aspath_segment_type_str[seg->type]);
+                       json_object_object_add(jseg, "list", jseg_list);
+                       json_object_array_add(jaspath_segments, jseg);
+               }
 
                if (seg->type != AS_SEQUENCE)
                        len += snprintf(
@@ -601,13 +608,16 @@ static void aspath_make_str_count(struct aspath *as)
        as->str = str_buf;
        as->str_len = len;
 
-       json_object_string_add(as->json, "string", str_buf);
-       json_object_object_add(as->json, "segments", jaspath_segments);
-       json_object_int_add(as->json, "length", aspath_count_hops(as));
+       if (make_json) {
+               json_object_string_add(as->json, "string", str_buf);
+               json_object_object_add(as->json, "segments", jaspath_segments);
+               json_object_int_add(as->json, "length", aspath_count_hops(as));
+       }
+
        return;
 }
 
-static void aspath_str_update(struct aspath *as)
+void aspath_str_update(struct aspath *as, bool make_json)
 {
        if (as->str)
                XFREE(MTYPE_AS_STR, as->str);
@@ -617,7 +627,7 @@ static void aspath_str_update(struct aspath *as)
                as->json = NULL;
        }
 
-       aspath_make_str_count(as);
+       aspath_make_str_count(as, make_json);
 }
 
 /* Intern allocated AS path. */
@@ -849,7 +859,7 @@ static void assegment_data_put(struct stream *s, as_t *as, int num,
                }
 }
 
-static size_t assegment_header_put(struct stream *s, u_char type, int length)
+static size_t assegment_header_put(struct stream *s, uint8_t type, int length)
 {
        size_t lenp;
        assert(length <= AS_SEGMENT_MAX);
@@ -889,10 +899,11 @@ size_t aspath_put(struct stream *s, struct aspath *as, int use32bit)
                        while ((seg->length - written) > AS_SEGMENT_MAX) {
                                assegment_header_put(s, seg->type,
                                                     AS_SEGMENT_MAX);
-                               assegment_data_put(s, seg->as, AS_SEGMENT_MAX,
+                               assegment_data_put(s, (seg->as + written), AS_SEGMENT_MAX,
                                                   use32bit);
                                written += AS_SEGMENT_MAX;
-                               bytes += ASSEGMENT_SIZE(AS_SEGMENT_MAX, use32bit);
+                               bytes += ASSEGMENT_SIZE(AS_SEGMENT_MAX,
+                                                       use32bit);
                        }
 
                        /* write the final segment, probably is also the first
@@ -946,7 +957,7 @@ size_t aspath_put(struct stream *s, struct aspath *as, int use32bit)
  * We have no way to manage the storage, so we use a static stream
  * wrapper around aspath_put.
  */
-u_char *aspath_snmp_pathseg(struct aspath *as, size_t *varlen)
+uint8_t *aspath_snmp_pathseg(struct aspath *as, size_t *varlen)
 {
 #define SNMP_PATHSEG_MAX 1024
 
@@ -1079,7 +1090,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
        }
 
        assegment_normalise(aspath->segments);
-       aspath_str_update(aspath);
+       aspath_str_update(aspath, false);
        return aspath;
 }
 
@@ -1214,7 +1225,7 @@ struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
                seg = seg->next;
        }
 
-       aspath_str_update(new);
+       aspath_str_update(new, false);
        return new;
 }
 
@@ -1237,7 +1248,7 @@ struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn)
                seg = seg->next;
        }
 
-       aspath_str_update(new);
+       aspath_str_update(new, false);
        return new;
 }
 
@@ -1307,7 +1318,7 @@ struct aspath *aspath_remove_private_asns(struct aspath *aspath)
                seg = seg->next;
        }
 
-       aspath_str_update(new);
+       aspath_str_update(new, false);
        return new;
 }
 
@@ -1362,7 +1373,7 @@ static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2)
 
        last->next = as2->segments;
        as2->segments = new;
-       aspath_str_update(as2);
+       aspath_str_update(as2, false);
        return as2;
 }
 
@@ -1381,7 +1392,7 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
        /* If as2 is empty, only need to dupe as1's chain onto as2 */
        if (seg2 == NULL) {
                as2->segments = assegment_dup_all(as1->segments);
-               aspath_str_update(as2);
+               aspath_str_update(as2, false);
                return as2;
        }
 
@@ -1432,7 +1443,7 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
                /* we've now prepended as1's segment chain to as2, merging
                 * the inbetween AS_SEQUENCE of seg2 in the process
                 */
-               aspath_str_update(as2);
+               aspath_str_update(as2, false);
                return as2;
        } else {
                /* AS_SET merge code is needed at here. */
@@ -1511,7 +1522,7 @@ struct aspath *aspath_filter_exclude(struct aspath *source,
                        lastseg->next = newseg;
                lastseg = newseg;
        }
-       aspath_str_update(newpath);
+       aspath_str_update(newpath, false);
        /* We are happy returning even an empty AS_PATH, because the
         * administrator
         * might expect this very behaviour. There's a mean to avoid this, if
@@ -1525,7 +1536,7 @@ struct aspath *aspath_filter_exclude(struct aspath *source,
 
 /* Add specified AS to the leftmost of aspath. */
 static struct aspath *aspath_add_asns(struct aspath *aspath, as_t asno,
-                                     u_char type, unsigned num)
+                                     uint8_t type, unsigned num)
 {
        struct assegment *assegment = aspath->segments;
        unsigned i;
@@ -1549,7 +1560,7 @@ static struct aspath *aspath_add_asns(struct aspath *aspath, as_t asno,
                aspath->segments = newsegment;
        }
 
-       aspath_str_update(aspath);
+       aspath_str_update(aspath, false);
        return aspath;
 }
 
@@ -1616,7 +1627,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
        struct aspath *newpath = NULL, *mergedpath;
        int hops, cpasns = 0;
 
-       if (!aspath)
+       if (!aspath || !as4path)
                return NULL;
 
        seg = aspath->segments;
@@ -1639,7 +1650,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
 
        if (!hops) {
                newpath = aspath_dup(as4path);
-               aspath_str_update(newpath);
+               aspath_str_update(newpath, false);
                return newpath;
        }
 
@@ -1701,7 +1712,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
        mergedpath = aspath_merge(newpath, aspath_dup(as4path));
        aspath_free(newpath);
        mergedpath->segments = assegment_normalise(mergedpath->segments);
-       aspath_str_update(mergedpath);
+       aspath_str_update(mergedpath, false);
 
        if (BGP_DEBUG(as4, AS4))
                zlog_debug("[AS4] result of synthesizing is %s",
@@ -1773,7 +1784,7 @@ struct aspath *aspath_delete_confed_seq(struct aspath *aspath)
        }
 
        if (removed_confed_segment)
-               aspath_str_update(aspath);
+               aspath_str_update(aspath, false);
 
        return aspath;
 }
@@ -1824,7 +1835,7 @@ struct aspath *aspath_empty_get(void)
        struct aspath *aspath;
 
        aspath = aspath_new();
-       aspath_make_str_count(aspath);
+       aspath_make_str_count(aspath, false);
        return aspath;
 }
 
@@ -1856,7 +1867,7 @@ enum as_token {
 
 /* Return next token and point for string parse. */
 static const char *aspath_gettoken(const char *buf, enum as_token *token,
-                                  u_long *asno)
+                                  unsigned long *asno)
 {
        const char *p = buf;
 
@@ -1914,14 +1925,15 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
 
        /* There is no match then return unknown token. */
        *token = as_token_unknown;
-       return p++;
+       p++;
+       return p;
 }
 
 struct aspath *aspath_str2aspath(const char *str)
 {
        enum as_token token = as_token_unknown;
-       u_short as_type;
-       u_long asno = 0;
+       unsigned short as_type;
+       unsigned long asno = 0;
        struct aspath *aspath;
        int needtype;
 
@@ -1974,7 +1986,7 @@ struct aspath *aspath_str2aspath(const char *str)
                }
        }
 
-       aspath_make_str_count(aspath);
+       aspath_make_str_count(aspath, false);
 
        return aspath;
 }
@@ -1986,7 +1998,7 @@ unsigned int aspath_key_make(void *p)
        unsigned int key = 0;
 
        if (!aspath->str)
-               aspath_str_update(aspath);
+               aspath_str_update(aspath, false);
 
        key = jhash(aspath->str, aspath->str_len, 2334325);
 
@@ -2019,9 +2031,7 @@ int aspath_cmp(const void *arg1, const void *arg2)
 /* AS path hash initialize. */
 void aspath_init(void)
 {
-       ashash = hash_create_size(32768,
-                                 aspath_key_make,
-                                 aspath_cmp,
+       ashash = hash_create_size(32768, aspath_key_make, aspath_cmp,
                                  "BGP AS Path");
 }