*/
/* Calculated size in bytes of ASN segment data to hold N ASN's */
-#define ASSEGMENT_DATA_SIZE(N,S) \
- ((N) * ( (S) ? AS_VALUE_SIZE : AS16_VALUE_SIZE) )
+#define ASSEGMENT_DATA_SIZE(N, S) \
+ ((N) * ((S) ? AS_VALUE_SIZE : AS16_VALUE_SIZE))
/* Calculated size of segment struct to hold N ASN's */
#define ASSEGMENT_SIZE(N,S) (AS_HEADER_SIZE + ASSEGMENT_DATA_SIZE (N,S))
/* AS_SEQUENCE segments can be packed together */
/* Can the types of X and Y be considered for packing? */
-#define ASSEGMENT_TYPES_PACKABLE(X,Y) \
- ( ((X)->type == (Y)->type) \
- && ((X)->type == AS_SEQUENCE))
+#define ASSEGMENT_TYPES_PACKABLE(X, Y) \
+ (((X)->type == (Y)->type) && ((X)->type == AS_SEQUENCE))
/* Types and length of X,Y suitable for packing? */
-#define ASSEGMENTS_PACKABLE(X,Y) \
- ( ASSEGMENT_TYPES_PACKABLE( (X), (Y)) \
- && ( ((X)->length + (Y)->length) <= AS_SEGMENT_MAX ) )
+#define ASSEGMENTS_PACKABLE(X, Y) \
+ (ASSEGMENT_TYPES_PACKABLE((X), (Y)) \
+ && (((X)->length + (Y)->length) <= AS_SEGMENT_MAX))
-/* As segment header - the on-wire representation
+/* As segment header - the on-wire representation
* NOT the internal representation!
*/
-struct assegment_header
-{
- u_char type;
- u_char length;
+struct assegment_header {
+ u_char type;
+ u_char length;
};
/* Hash for aspath. This is the top level structure of AS path. */
static struct stream *snmp_stream;
/* Callers are required to initialize the memory */
-static as_t *
-assegment_data_new (int num)
+static as_t *assegment_data_new(int num)
{
- return (XMALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1)));
+ return (XMALLOC(MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE(num, 1)));
}
-static void
-assegment_data_free (as_t *asdata)
+static void assegment_data_free(as_t *asdata)
{
- XFREE (MTYPE_AS_SEG_DATA, asdata);
+ XFREE(MTYPE_AS_SEG_DATA, asdata);
}
-const char *aspath_segment_type_str[] = {
- "as-invalid",
- "as-set",
- "as-sequence",
- "as-confed-sequence",
- "as-confed-set"
-};
+const char *aspath_segment_type_str[] = {"as-invalid", "as-set", "as-sequence",
+ "as-confed-sequence", "as-confed-set"};
/* Get a new segment. Note that 0 is an allowed length,
* and will result in a segment with no allocated data segment.
* 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)
-{
- struct assegment *new;
-
- new = XCALLOC (MTYPE_AS_SEG, sizeof (struct assegment));
-
- if (length)
- new->as = assegment_data_new (length);
-
- new->length = length;
- new->type = type;
-
- return new;
-}
-
-static void
-assegment_free (struct assegment *seg)
-{
- if (!seg)
- return;
-
- if (seg->as)
- assegment_data_free (seg->as);
- memset (seg, 0xfe, sizeof(struct assegment));
- XFREE (MTYPE_AS_SEG, seg);
-
- return;
+static struct assegment *assegment_new(u_char type, u_short length)
+{
+ struct assegment *new;
+
+ new = XCALLOC(MTYPE_AS_SEG, sizeof(struct assegment));
+
+ if (length)
+ new->as = assegment_data_new(length);
+
+ new->length = length;
+ new->type = type;
+
+ return new;
+}
+
+static void assegment_free(struct assegment *seg)
+{
+ if (!seg)
+ return;
+
+ if (seg->as)
+ assegment_data_free(seg->as);
+ memset(seg, 0xfe, sizeof(struct assegment));
+ XFREE(MTYPE_AS_SEG, seg);
+
+ return;
}
/* free entire chain of segments */
-static void
-assegment_free_all (struct assegment *seg)
+static void assegment_free_all(struct assegment *seg)
{
- struct assegment *prev;
-
- while (seg)
- {
- prev = seg;
- seg = seg->next;
- assegment_free (prev);
- }
+ struct assegment *prev;
+
+ while (seg) {
+ prev = seg;
+ seg = seg->next;
+ assegment_free(prev);
+ }
}
/* Duplicate just the given assegment and its data */
-static struct assegment *
-assegment_dup (struct assegment *seg)
+static struct assegment *assegment_dup(struct assegment *seg)
{
- struct assegment *new;
-
- new = assegment_new (seg->type, seg->length);
- memcpy (new->as, seg->as, ASSEGMENT_DATA_SIZE (new->length, 1) );
-
- return new;
+ struct assegment *new;
+
+ new = assegment_new(seg->type, seg->length);
+ memcpy(new->as, seg->as, ASSEGMENT_DATA_SIZE(new->length, 1));
+
+ return new;
}
/* Duplicate entire chain of assegments, return the head */
-static struct assegment *
-assegment_dup_all (struct assegment *seg)
-{
- struct assegment *new = NULL;
- struct assegment *head = NULL;
-
- while (seg)
- {
- if (head)
- {
- new->next = assegment_dup (seg);
- new = new->next;
- }
- else
- head = new = assegment_dup (seg);
-
- seg = seg->next;
- }
- return head;
+static struct assegment *assegment_dup_all(struct assegment *seg)
+{
+ struct assegment *new = NULL;
+ struct assegment *head = NULL;
+
+ while (seg) {
+ if (head) {
+ new->next = assegment_dup(seg);
+ new = new->next;
+ } else
+ head = new = assegment_dup(seg);
+
+ seg = seg->next;
+ }
+ return head;
}
/* prepend the as number to given segment, given num of times */
-static struct assegment *
-assegment_prepend_asns (struct assegment *seg, as_t asnum, int num)
+static struct assegment *assegment_prepend_asns(struct assegment *seg,
+ as_t asnum, int num)
{
- as_t *newas;
- int i;
-
- if (!num)
- return seg;
-
- if (num >= AS_SEGMENT_MAX)
- return seg; /* we don't do huge prepends */
-
- if ((newas = assegment_data_new (seg->length + num)) == NULL)
- return seg;
+ as_t *newas;
+ int i;
- for (i = 0; i < num; i++)
- newas[i] = asnum;
+ if (!num)
+ return seg;
- memcpy (newas + num, seg->as, ASSEGMENT_DATA_SIZE (seg->length, 1));
- assegment_data_free (seg->as);
- seg->as = newas;
- seg->length += num;
+ if (num >= AS_SEGMENT_MAX)
+ return seg; /* we don't do huge prepends */
- return seg;
+ if ((newas = assegment_data_new(seg->length + num)) == NULL)
+ return seg;
+
+ for (i = 0; i < num; i++)
+ newas[i] = asnum;
+
+ memcpy(newas + num, seg->as, ASSEGMENT_DATA_SIZE(seg->length, 1));
+ assegment_data_free(seg->as);
+ seg->as = newas;
+ seg->length += num;
+
+ return seg;
}
/* append given array of as numbers to the segment */
-static struct assegment *
-assegment_append_asns (struct assegment *seg, as_t *asnos, int num)
+static struct assegment *assegment_append_asns(struct assegment *seg,
+ as_t *asnos, int num)
{
- as_t *newas;
-
- newas = XREALLOC (MTYPE_AS_SEG_DATA, seg->as,
- ASSEGMENT_DATA_SIZE (seg->length + num, 1));
+ as_t *newas;
- if (newas)
- {
- seg->as = newas;
- memcpy (seg->as + seg->length, asnos, ASSEGMENT_DATA_SIZE(num, 1));
- seg->length += num;
- return 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;
+ assegment_free_all(seg);
+ return NULL;
}
-static int
-int_cmp (const void *p1, const void *p2)
+static int int_cmp(const void *p1, const void *p2)
{
- const as_t *as1 = p1;
- const as_t *as2 = p2;
-
- return (*as1 == *as2)
- ? 0 : ( (*as1 > *as2) ? 1 : -1);
+ const as_t *as1 = p1;
+ const as_t *as2 = p2;
+
+ return (*as1 == *as2) ? 0 : ((*as1 > *as2) ? 1 : -1);
}
/* normalise the segment.
* we want each distinct AS_PATHs to have the exact same internal
* representation - eg, so that our hashing actually works..
*/
-static struct assegment *
-assegment_normalise (struct assegment *head)
-{
- struct assegment *seg = head, *pin;
- struct assegment *tmp;
-
- if (!head)
- return head;
-
- while (seg)
- {
- pin = seg;
-
- /* Sort values SET segments, for determinism in paths to aid
- * creation of hash values / path comparisons
- * and because it helps other lesser implementations ;)
- */
- if (seg->type == AS_SET || seg->type == AS_CONFED_SET)
- {
- int tail = 0;
- int i;
-
- qsort (seg->as, seg->length, sizeof(as_t), int_cmp);
-
- /* weed out dupes */
- for (i=1; i < seg->length; i++)
- {
- if (seg->as[tail] == seg->as[i])
- continue;
-
- tail++;
- if (tail < i)
- seg->as[tail] = seg->as[i];
- }
- /* seg->length can be 0.. */
- if (seg->length)
- seg->length = tail + 1;
+static struct assegment *assegment_normalise(struct assegment *head)
+{
+ struct assegment *seg = head, *pin;
+ struct assegment *tmp;
+
+ if (!head)
+ return head;
+
+ while (seg) {
+ pin = seg;
+
+ /* Sort values SET segments, for determinism in paths to aid
+ * creation of hash values / path comparisons
+ * and because it helps other lesser implementations ;)
+ */
+ if (seg->type == AS_SET || seg->type == AS_CONFED_SET) {
+ int tail = 0;
+ int i;
+
+ qsort(seg->as, seg->length, sizeof(as_t), int_cmp);
+
+ /* weed out dupes */
+ for (i = 1; i < seg->length; i++) {
+ if (seg->as[tail] == seg->as[i])
+ continue;
+
+ tail++;
+ if (tail < i)
+ seg->as[tail] = seg->as[i];
+ }
+ /* seg->length can be 0.. */
+ if (seg->length)
+ seg->length = tail + 1;
+ }
+
+ /* read ahead from the current, pinned segment while the
+ * segments
+ * are packable/mergeable. Append all following packable
+ * segments
+ * to the segment we have pinned and remove these appended
+ * segments.
+ */
+ while (pin->next && ASSEGMENT_TYPES_PACKABLE(pin, pin->next)) {
+ tmp = pin->next;
+ seg = pin->next;
+
+ /* append the next sequence to the pinned sequence */
+ pin = assegment_append_asns(pin, seg->as, seg->length);
+
+ /* bypass the next sequence */
+ pin->next = seg->next;
+
+ /* get rid of the now referenceless segment */
+ assegment_free(tmp);
+ }
+
+ seg = pin->next;
}
-
- /* read ahead from the current, pinned segment while the segments
- * are packable/mergeable. Append all following packable segments
- * to the segment we have pinned and remove these appended
- * segments.
- */
- while (pin->next && ASSEGMENT_TYPES_PACKABLE(pin, pin->next))
- {
- tmp = pin->next;
- seg = pin->next;
-
- /* append the next sequence to the pinned sequence */
- pin = assegment_append_asns (pin, seg->as, seg->length);
-
- /* bypass the next sequence */
- pin->next = seg->next;
-
- /* get rid of the now referenceless segment */
- assegment_free (tmp);
-
- }
-
- seg = pin->next;
- }
- return head;
-}
-
-static struct aspath *
-aspath_new (void)
-{
- return XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
+ return head;
}
-/* Free AS path structure. */
-void
-aspath_free (struct aspath *aspath)
+static struct aspath *aspath_new(void)
{
- if (!aspath)
- return;
- if (aspath->segments)
- assegment_free_all (aspath->segments);
- if (aspath->str)
- XFREE (MTYPE_AS_STR, aspath->str);
+ return XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
+}
- if (aspath->json)
- {
- json_object_free(aspath->json);
- aspath->json = NULL;
- }
+/* Free AS path structure. */
+void aspath_free(struct aspath *aspath)
+{
+ if (!aspath)
+ return;
+ if (aspath->segments)
+ assegment_free_all(aspath->segments);
+ if (aspath->str)
+ XFREE(MTYPE_AS_STR, aspath->str);
+
+ if (aspath->json) {
+ json_object_free(aspath->json);
+ aspath->json = NULL;
+ }
- XFREE (MTYPE_AS_PATH, aspath);
+ XFREE(MTYPE_AS_PATH, aspath);
}
/* Unintern aspath from AS path bucket. */
-void
-aspath_unintern (struct aspath **aspath)
+void aspath_unintern(struct aspath **aspath)
{
- struct aspath *ret;
- struct aspath *asp = *aspath;
-
- if (asp->refcnt)
- asp->refcnt--;
+ struct aspath *ret;
+ struct aspath *asp = *aspath;
+
+ if (asp->refcnt)
+ asp->refcnt--;
- if (asp->refcnt == 0)
- {
- /* This aspath must exist in aspath hash table. */
- ret = hash_release (ashash, asp);
- assert (ret != NULL);
- aspath_free (asp);
- *aspath = NULL;
- }
+ if (asp->refcnt == 0) {
+ /* This aspath must exist in aspath hash table. */
+ ret = hash_release(ashash, asp);
+ assert(ret != NULL);
+ aspath_free(asp);
+ *aspath = NULL;
+ }
}
/* 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)
-{
- int i;
- struct
- {
- int type;
- char start;
- char end;
- } aspath_delim_char [] =
- {
- { AS_SET, '{', '}' },
- { AS_CONFED_SET, '[', ']' },
- { AS_CONFED_SEQUENCE, '(', ')' },
- { 0 }
- };
-
- for (i = 0; aspath_delim_char[i].type != 0; i++)
- {
- if (aspath_delim_char[i].type == type)
- {
- if (which == AS_SEG_START)
- return aspath_delim_char[i].start;
- else if (which == AS_SEG_END)
- return aspath_delim_char[i].end;
+static char aspath_delimiter_char(u_char type, u_char which)
+{
+ int i;
+ struct {
+ int type;
+ char start;
+ char end;
+ } aspath_delim_char[] = {{AS_SET, '{', '}'},
+ {AS_CONFED_SET, '[', ']'},
+ {AS_CONFED_SEQUENCE, '(', ')'},
+ {0}};
+
+ for (i = 0; aspath_delim_char[i].type != 0; i++) {
+ if (aspath_delim_char[i].type == type) {
+ if (which == AS_SEG_START)
+ return aspath_delim_char[i].start;
+ else if (which == AS_SEG_END)
+ return aspath_delim_char[i].end;
+ }
}
- }
- return ' ';
+ return ' ';
}
/* countup asns from this segment and index onward */
-static int
-assegment_count_asns (struct assegment *seg, int from)
-{
- int count = 0;
- while (seg)
- {
- if (!from)
- count += seg->length;
- else
- {
- count += (seg->length - from);
- from = 0;
- }
- seg = seg->next;
- }
- return count;
-}
-
-unsigned int
-aspath_count_confeds (struct aspath *aspath)
-{
- int count = 0;
- struct assegment *seg = aspath->segments;
-
- while (seg)
- {
- if (seg->type == AS_CONFED_SEQUENCE)
- count += seg->length;
- else if (seg->type == AS_CONFED_SET)
- count++;
-
- seg = seg->next;
- }
- return count;
-}
-
-unsigned int
-aspath_count_hops (const struct aspath *aspath)
-{
- int count = 0;
- struct assegment *seg = aspath->segments;
-
- while (seg)
- {
- if (seg->type == AS_SEQUENCE)
- count += seg->length;
- else if (seg->type == AS_SET)
- count++;
-
- seg = seg->next;
- }
- return count;
+static int assegment_count_asns(struct assegment *seg, int from)
+{
+ int count = 0;
+ while (seg) {
+ if (!from)
+ count += seg->length;
+ else {
+ count += (seg->length - from);
+ from = 0;
+ }
+ seg = seg->next;
+ }
+ return count;
+}
+
+unsigned int aspath_count_confeds(struct aspath *aspath)
+{
+ int count = 0;
+ struct assegment *seg = aspath->segments;
+
+ while (seg) {
+ if (seg->type == AS_CONFED_SEQUENCE)
+ count += seg->length;
+ else if (seg->type == AS_CONFED_SET)
+ count++;
+
+ seg = seg->next;
+ }
+ return count;
+}
+
+unsigned int aspath_count_hops(const struct aspath *aspath)
+{
+ int count = 0;
+ struct assegment *seg = aspath->segments;
+
+ while (seg) {
+ if (seg->type == AS_SEQUENCE)
+ count += seg->length;
+ else if (seg->type == AS_SET)
+ count++;
+
+ seg = seg->next;
+ }
+ return count;
}
/* Estimate size aspath /might/ take if encoded into an
* This is a quick estimate, not definitive! aspath_put()
* may return a different number!!
*/
-unsigned int
-aspath_size (struct aspath *aspath)
+unsigned int aspath_size(struct aspath *aspath)
{
- int size = 0;
- struct assegment *seg = aspath->segments;
-
- while (seg)
- {
- size += ASSEGMENT_SIZE(seg->length, 1);
- seg = seg->next;
- }
- return size;
+ int size = 0;
+ struct assegment *seg = aspath->segments;
+
+ while (seg) {
+ size += ASSEGMENT_SIZE(seg->length, 1);
+ seg = seg->next;
+ }
+ return size;
}
/* Return highest public ASN in path */
-as_t
-aspath_highest (struct aspath *aspath)
-{
- struct assegment *seg = aspath->segments;
- as_t highest = 0;
- unsigned int i;
-
- while (seg)
- {
- for (i = 0; i < seg->length; i++)
- if (seg->as[i] > highest && !BGP_AS_IS_PRIVATE(seg->as[i]))
- highest = seg->as[i];
- seg = seg->next;
- }
- return highest;
+as_t aspath_highest(struct aspath *aspath)
+{
+ struct assegment *seg = aspath->segments;
+ as_t highest = 0;
+ unsigned int i;
+
+ while (seg) {
+ for (i = 0; i < seg->length; i++)
+ if (seg->as[i] > highest
+ && !BGP_AS_IS_PRIVATE(seg->as[i]))
+ highest = seg->as[i];
+ seg = seg->next;
+ }
+ return highest;
}
/* Return the left-most ASN in path */
-as_t
-aspath_leftmost (struct aspath *aspath)
+as_t aspath_leftmost(struct aspath *aspath)
{
- struct assegment *seg = aspath->segments;
- as_t leftmost = 0;
+ struct assegment *seg = aspath->segments;
+ as_t leftmost = 0;
- if (seg && seg->length && seg->type == AS_SEQUENCE)
- leftmost = seg->as[0];
+ if (seg && seg->length && seg->type == AS_SEQUENCE)
+ leftmost = seg->as[0];
- return leftmost;
+ return leftmost;
}
/* Return 1 if there are any 4-byte ASes in the path */
-unsigned int
-aspath_has_as4 (struct aspath *aspath)
-{
- struct assegment *seg = aspath->segments;
- unsigned int i;
-
- while (seg)
- {
- for (i = 0; i < seg->length; i++)
- if (seg->as[i] > BGP_AS_MAX)
- return 1;
- seg = seg->next;
- }
- return 0;
+unsigned int aspath_has_as4(struct aspath *aspath)
+{
+ struct assegment *seg = aspath->segments;
+ unsigned int i;
+
+ while (seg) {
+ for (i = 0; i < seg->length; i++)
+ if (seg->as[i] > BGP_AS_MAX)
+ return 1;
+ seg = seg->next;
+ }
+ return 0;
}
/* Convert aspath structure to string expression. */
-static void
-aspath_make_str_count (struct aspath *as)
-{
- struct assegment *seg;
- int str_size;
- int len = 0;
- char *str_buf;
- json_object *jaspath_segments = NULL;
- json_object *jseg = NULL;
- json_object *jseg_list = NULL;
-
- 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);
- as->str = XMALLOC (MTYPE_AS_STR, 1);
- as->str[0] = '\0';
- as->str_len = 0;
- return;
- }
-
- seg = as->segments;
-
- /* ASN takes 5 to 10 chars plus seperator, see below.
- * If there is one differing segment type, we need an additional
- * 2 chars for segment delimiters, and the final '\0'.
- * Hopefully this is large enough to avoid hitting the realloc
- * code below for most common sequences.
- *
- * This was changed to 10 after the well-known BGP assertion, which
- * had hit some parts of the Internet in May of 2009.
- */
+static void aspath_make_str_count(struct aspath *as)
+{
+ struct assegment *seg;
+ int str_size;
+ int len = 0;
+ char *str_buf;
+ json_object *jaspath_segments = NULL;
+ json_object *jseg = NULL;
+ json_object *jseg_list = NULL;
+
+ 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);
+ as->str = XMALLOC(MTYPE_AS_STR, 1);
+ as->str[0] = '\0';
+ as->str_len = 0;
+ return;
+ }
+
+ seg = as->segments;
+
+/* ASN takes 5 to 10 chars plus seperator, see below.
+ * If there is one differing segment type, we need an additional
+ * 2 chars for segment delimiters, and the final '\0'.
+ * Hopefully this is large enough to avoid hitting the realloc
+ * code below for most common sequences.
+ *
+ * This was changed to 10 after the well-known BGP assertion, which
+ * had hit some parts of the Internet in May of 2009.
+ */
#define ASN_STR_LEN (10 + 1)
- str_size = MAX (assegment_count_asns (seg, 0) * ASN_STR_LEN + 2 + 1,
- ASPATH_STR_DEFAULT_LEN);
- str_buf = XMALLOC (MTYPE_AS_STR, str_size);
-
- while (seg)
- {
- int i;
- char seperator;
-
- /* Check AS type validity. Set seperator for segment */
- switch (seg->type)
- {
- case AS_SET:
- case AS_CONFED_SET:
- seperator = ',';
- break;
- case AS_SEQUENCE:
- case AS_CONFED_SEQUENCE:
- seperator = ' ';
- break;
- default:
- XFREE (MTYPE_AS_STR, str_buf);
- as->str = NULL;
- as->str_len = 0;
- json_object_free(as->json);
- as->json = NULL;
- return;
- }
-
- /* We might need to increase str_buf, particularly if path has
- * differing segments types, our initial guesstimate above will
- * have been wrong. Need 10 chars for ASN, a seperator each and
- * potentially two segment delimiters, plus a space between each
- * segment and trailing zero.
- *
- * This definitely didn't work with the value of 5 bytes and
- * 32-bit ASNs.
- */
+ str_size = MAX(assegment_count_asns(seg, 0) * ASN_STR_LEN + 2 + 1,
+ ASPATH_STR_DEFAULT_LEN);
+ str_buf = XMALLOC(MTYPE_AS_STR, str_size);
+
+ while (seg) {
+ int i;
+ char seperator;
+
+ /* Check AS type validity. Set seperator for segment */
+ switch (seg->type) {
+ case AS_SET:
+ case AS_CONFED_SET:
+ seperator = ',';
+ break;
+ case AS_SEQUENCE:
+ case AS_CONFED_SEQUENCE:
+ seperator = ' ';
+ break;
+ default:
+ XFREE(MTYPE_AS_STR, str_buf);
+ as->str = NULL;
+ as->str_len = 0;
+ json_object_free(as->json);
+ as->json = NULL;
+ return;
+ }
+
+/* We might need to increase str_buf, particularly if path has
+ * differing segments types, our initial guesstimate above will
+ * have been wrong. Need 10 chars for ASN, a seperator each and
+ * potentially two segment delimiters, plus a space between each
+ * segment and trailing zero.
+ *
+ * This definitely didn't work with the value of 5 bytes and
+ * 32-bit ASNs.
+ */
#define SEGMENT_STR_LEN(X) (((X)->length * ASN_STR_LEN) + 2 + 1 + 1)
- if ( (len + SEGMENT_STR_LEN(seg)) > str_size)
- {
- str_size = len + SEGMENT_STR_LEN(seg);
- str_buf = XREALLOC (MTYPE_AS_STR, str_buf, str_size);
- }
+ if ((len + SEGMENT_STR_LEN(seg)) > str_size) {
+ str_size = len + SEGMENT_STR_LEN(seg);
+ str_buf = XREALLOC(MTYPE_AS_STR, str_buf, str_size);
+ }
#undef ASN_STR_LEN
#undef SEGMENT_STR_LEN
-
- if (seg->type != AS_SEQUENCE)
- len += snprintf (str_buf + len, str_size - len,
- "%c",
- aspath_delimiter_char (seg->type, AS_SEG_START));
-
- 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]));
-
- len += snprintf (str_buf + len, str_size - len, "%u", seg->as[i]);
-
- if (i < (seg->length - 1))
- len += snprintf (str_buf + len, str_size - len, "%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 (seg->type != AS_SEQUENCE)
- len += snprintf (str_buf + len, str_size - len, "%c",
- aspath_delimiter_char (seg->type, AS_SEG_END));
- if (seg->next)
- len += snprintf (str_buf + len, str_size - len, " ");
-
- seg = seg->next;
- }
-
- assert (len < str_size);
-
- str_buf[len] = '\0';
- 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));
- return;
-}
-
-static void
-aspath_str_update (struct aspath *as)
-{
- if (as->str)
- XFREE (MTYPE_AS_STR, as->str);
-
- if (as->json)
- {
- json_object_free(as->json);
- as->json = NULL;
- }
-
- aspath_make_str_count (as);
+
+ if (seg->type != AS_SEQUENCE)
+ len += snprintf(
+ str_buf + len, str_size - len, "%c",
+ aspath_delimiter_char(seg->type, AS_SEG_START));
+
+ 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]));
+
+ len += snprintf(str_buf + len, str_size - len, "%u",
+ seg->as[i]);
+
+ if (i < (seg->length - 1))
+ len += snprintf(str_buf + len, str_size - len,
+ "%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 (seg->type != AS_SEQUENCE)
+ len += snprintf(
+ str_buf + len, str_size - len, "%c",
+ aspath_delimiter_char(seg->type, AS_SEG_END));
+ if (seg->next)
+ len += snprintf(str_buf + len, str_size - len, " ");
+
+ seg = seg->next;
+ }
+
+ assert(len < str_size);
+
+ str_buf[len] = '\0';
+ 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));
+ return;
+}
+
+static void aspath_str_update(struct aspath *as)
+{
+ if (as->str)
+ XFREE(MTYPE_AS_STR, as->str);
+
+ if (as->json) {
+ json_object_free(as->json);
+ as->json = NULL;
+ }
+
+ aspath_make_str_count(as);
}
/* Intern allocated AS path. */
-struct aspath *
-aspath_intern (struct aspath *aspath)
+struct aspath *aspath_intern(struct aspath *aspath)
{
- struct aspath *find;
+ struct aspath *find;
- /* Assert this AS path structure is not interned and has the string
- representation built. */
- assert (aspath->refcnt == 0);
- assert (aspath->str);
+ /* Assert this AS path structure is not interned and has the string
+ representation built. */
+ assert(aspath->refcnt == 0);
+ assert(aspath->str);
- /* Check AS path hash. */
- find = hash_get (ashash, aspath, hash_alloc_intern);
- if (find != aspath)
- aspath_free (aspath);
+ /* Check AS path hash. */
+ find = hash_get(ashash, aspath, hash_alloc_intern);
+ if (find != aspath)
+ aspath_free(aspath);
- find->refcnt++;
+ find->refcnt++;
- return find;
+ return find;
}
/* Duplicate aspath structure. Created same aspath structure but
reference count and AS path string is cleared. */
-struct aspath *
-aspath_dup (struct aspath *aspath)
+struct aspath *aspath_dup(struct aspath *aspath)
{
- unsigned short buflen = aspath->str_len + 1;
- struct aspath *new;
+ unsigned short buflen = aspath->str_len + 1;
+ struct aspath *new;
- new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
- new->json = NULL;
+ new = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
+ new->json = NULL;
- if (aspath->segments)
- new->segments = assegment_dup_all (aspath->segments);
+ if (aspath->segments)
+ new->segments = assegment_dup_all(aspath->segments);
- if (!aspath->str)
- return new;
+ if (!aspath->str)
+ return new;
- new->str = XMALLOC (MTYPE_AS_STR, buflen);
- new->str_len = aspath->str_len;
+ new->str = XMALLOC(MTYPE_AS_STR, buflen);
+ new->str_len = aspath->str_len;
- /* copy the string data */
- if (aspath->str_len > 0)
- memcpy (new->str, aspath->str, buflen);
- else
- new->str[0] = '\0';
+ /* copy the string data */
+ if (aspath->str_len > 0)
+ memcpy(new->str, aspath->str, buflen);
+ else
+ new->str[0] = '\0';
- return new;
+ return new;
}
-static void *
-aspath_hash_alloc (void *arg)
+static void *aspath_hash_alloc(void *arg)
{
- const struct aspath *aspath = arg;
- struct aspath *new;
+ const struct aspath *aspath = arg;
+ struct aspath *new;
- /* Malformed AS path value. */
- assert (aspath->str);
+ /* Malformed AS path value. */
+ assert(aspath->str);
- /* New aspath structure is needed. */
- new = XMALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
+ /* New aspath structure is needed. */
+ new = XMALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
- /* Reuse segments and string representation */
- new->refcnt = 0;
- new->segments = aspath->segments;
- new->str = aspath->str;
- new->str_len = aspath->str_len;
- new->json = aspath->json;
+ /* Reuse segments and string representation */
+ new->refcnt = 0;
+ new->segments = aspath->segments;
+ new->str = aspath->str;
+ new->str_len = aspath->str_len;
+ new->json = aspath->json;
- return new;
+ return new;
}
/* parse as-segment byte stream in struct assegment */
-static int
-assegments_parse (struct stream *s, size_t length,
- struct assegment **result, int use32bit)
-{
- 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 0;
-
- 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 ))
- return -1;
-
- while (bytes < length)
- {
- int i;
- size_t seg_size;
-
- if ((length - bytes) <= AS_HEADER_SIZE)
- {
- if (head)
- assegment_free_all (head);
- return -1;
- }
-
- /* softly softly, get the header first on its own */
- segh.type = stream_getc (s);
- segh.length = stream_getc (s);
-
- seg_size = ASSEGMENT_SIZE(segh.length, use32bit);
-
- 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 (head)
- assegment_free_all (head);
- return -1;
- }
-
- switch (segh.type)
- {
- case AS_SEQUENCE:
- case AS_SET:
- case AS_CONFED_SEQUENCE:
- case AS_CONFED_SET:
- break;
- default:
- if (head)
- assegment_free_all (head);
- return -1;
- }
-
- /* now its safe to trust lengths */
- seg = assegment_new (segh.type, segh.length);
-
- if (head)
- prev->next = seg;
- else /* it's the first segment */
- head = prev = seg;
-
- 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);
-
- prev = seg;
- }
-
- *result = assegment_normalise (head);
- return 0;
+static int assegments_parse(struct stream *s, size_t length,
+ struct assegment **result, int use32bit)
+{
+ 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 0;
+
+ 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))
+ return -1;
+
+ while (bytes < length) {
+ int i;
+ size_t seg_size;
+
+ if ((length - bytes) <= AS_HEADER_SIZE) {
+ if (head)
+ assegment_free_all(head);
+ return -1;
+ }
+
+ /* softly softly, get the header first on its own */
+ segh.type = stream_getc(s);
+ segh.length = stream_getc(s);
+
+ seg_size = ASSEGMENT_SIZE(segh.length, use32bit);
+
+ 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 (head)
+ assegment_free_all(head);
+ return -1;
+ }
+
+ switch (segh.type) {
+ case AS_SEQUENCE:
+ case AS_SET:
+ case AS_CONFED_SEQUENCE:
+ case AS_CONFED_SET:
+ break;
+ default:
+ if (head)
+ assegment_free_all(head);
+ return -1;
+ }
+
+ /* now its safe to trust lengths */
+ seg = assegment_new(segh.type, segh.length);
+
+ if (head)
+ prev->next = seg;
+ else /* it's the first segment */
+ head = prev = seg;
+
+ 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);
+
+ prev = seg;
+ }
+
+ *result = assegment_normalise(head);
+ return 0;
}
/* 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.
-
+ path hash then return it else make new AS path structure.
+
On error NULL is returned.
*/
-struct aspath *
-aspath_parse (struct stream *s, size_t length, int use32bit)
-{
- 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;
-
- memset (&as, 0, sizeof (struct aspath));
- if (assegments_parse (s, length, &as.segments, use32bit) < 0)
- return NULL;
-
- /* If already same aspath exist then return it. */
- find = hash_get (ashash, &as, aspath_hash_alloc);
-
- /* bug! should not happen, let the daemon crash below */
- assert (find);
-
- /* if the aspath was already hashed free temporary memory. */
- if (find->refcnt)
- {
- assegment_free_all (as.segments);
- /* aspath_key_make() always updates the string */
- XFREE (MTYPE_AS_STR, as.str);
- if (as.json)
- {
- json_object_free(as.json);
- as.json = NULL;
+struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit)
+{
+ 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;
+
+ memset(&as, 0, sizeof(struct aspath));
+ if (assegments_parse(s, length, &as.segments, use32bit) < 0)
+ return NULL;
+
+ /* If already same aspath exist then return it. */
+ find = hash_get(ashash, &as, aspath_hash_alloc);
+
+ /* bug! should not happen, let the daemon crash below */
+ assert(find);
+
+ /* if the aspath was already hashed free temporary memory. */
+ if (find->refcnt) {
+ assegment_free_all(as.segments);
+ /* aspath_key_make() always updates the string */
+ XFREE(MTYPE_AS_STR, as.str);
+ if (as.json) {
+ json_object_free(as.json);
+ as.json = NULL;
+ }
}
- }
- find->refcnt++;
+ find->refcnt++;
- return find;
+ return find;
}
-static void
-assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
+static void assegment_data_put(struct stream *s, as_t *as, int num,
+ int use32bit)
{
- int i;
- assert (num <= AS_SEGMENT_MAX);
-
- for (i = 0; i < num; i++)
- if ( use32bit )
- stream_putl (s, as[i]);
- else
- {
- if ( as[i] <= BGP_AS_MAX )
- stream_putw(s, as[i]);
- else
- stream_putw(s, BGP_AS_TRANS);
- }
+ int i;
+ assert(num <= AS_SEGMENT_MAX);
+
+ for (i = 0; i < num; i++)
+ if (use32bit)
+ stream_putl(s, as[i]);
+ else {
+ if (as[i] <= BGP_AS_MAX)
+ stream_putw(s, as[i]);
+ else
+ stream_putw(s, BGP_AS_TRANS);
+ }
}
-static size_t
-assegment_header_put (struct stream *s, u_char type, int length)
+static size_t assegment_header_put(struct stream *s, u_char type, int length)
{
- size_t lenp;
- assert (length <= AS_SEGMENT_MAX);
- stream_putc (s, type);
- lenp = stream_get_endp (s);
- stream_putc (s, length);
- return lenp;
+ size_t lenp;
+ assert(length <= AS_SEGMENT_MAX);
+ stream_putc(s, type);
+ lenp = stream_get_endp(s);
+ stream_putc(s, length);
+ return lenp;
}
/* write aspath data to stream */
-size_t
-aspath_put (struct stream *s, struct aspath *as, int use32bit )
-{
- struct assegment *seg = as->segments;
- size_t bytes = 0;
-
- if (!seg || seg->length == 0)
- return 0;
-
- if (seg)
- {
- /*
- * Hey, what do we do when we have > STREAM_WRITABLE(s) here?
- * At the moment, we would write out a partial aspath, and our peer
- * will complain and drop the session :-/
- *
- * The general assumption here is that many things tested will
- * never happen. And, in real live, up to now, they have not.
- */
- while (seg && (ASSEGMENT_LEN(seg, use32bit) <= STREAM_WRITEABLE(s)))
- {
- struct assegment *next = seg->next;
- int written = 0;
- int asns_packed = 0;
- size_t lenp;
-
- /* Overlength segments have to be split up */
- 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, use32bit);
- written += AS_SEGMENT_MAX;
- bytes += ASSEGMENT_SIZE (written, use32bit);
- }
-
- /* write the final segment, probably is also the first */
- lenp = assegment_header_put (s, seg->type, seg->length - written);
- assegment_data_put (s, (seg->as + written), seg->length - written,
- use32bit);
-
- /* Sequence-type segments can be 'packed' together
- * Case of a segment which was overlength and split up
- * will be missed here, but that doesn't matter.
- */
- while (next && ASSEGMENTS_PACKABLE (seg, next))
- {
- /* NB: We should never normally get here given we
- * normalise aspath data when parse them. However, better
- * safe than sorry. We potentially could call
- * assegment_normalise here instead, but it's cheaper and
- * easier to do it on the fly here rather than go through
- * the segment list twice every time we write out
- * aspath's.
- */
-
- /* Next segment's data can fit in this one */
- assegment_data_put (s, next->as, next->length, use32bit);
-
- /* update the length of the segment header */
- stream_putc_at (s, lenp, seg->length - written + next->length);
- asns_packed += next->length;
-
- next = next->next;
- }
-
- bytes += ASSEGMENT_SIZE (seg->length - written + asns_packed,
- use32bit);
- seg = next;
- }
- }
- return bytes;
+size_t aspath_put(struct stream *s, struct aspath *as, int use32bit)
+{
+ struct assegment *seg = as->segments;
+ size_t bytes = 0;
+
+ if (!seg || seg->length == 0)
+ return 0;
+
+ if (seg) {
+ /*
+ * Hey, what do we do when we have > STREAM_WRITABLE(s) here?
+ * At the moment, we would write out a partial aspath, and our
+ * peer
+ * will complain and drop the session :-/
+ *
+ * The general assumption here is that many things tested will
+ * never happen. And, in real live, up to now, they have not.
+ */
+ while (seg && (ASSEGMENT_LEN(seg, use32bit)
+ <= STREAM_WRITEABLE(s))) {
+ struct assegment *next = seg->next;
+ int written = 0;
+ int asns_packed = 0;
+ size_t lenp;
+
+ /* Overlength segments have to be split up */
+ 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,
+ use32bit);
+ written += AS_SEGMENT_MAX;
+ bytes += ASSEGMENT_SIZE(written, use32bit);
+ }
+
+ /* write the final segment, probably is also the first
+ */
+ lenp = assegment_header_put(s, seg->type,
+ seg->length - written);
+ assegment_data_put(s, (seg->as + written),
+ seg->length - written, use32bit);
+
+ /* Sequence-type segments can be 'packed' together
+ * Case of a segment which was overlength and split up
+ * will be missed here, but that doesn't matter.
+ */
+ while (next && ASSEGMENTS_PACKABLE(seg, next)) {
+ /* NB: We should never normally get here given
+ * we
+ * normalise aspath data when parse them.
+ * However, better
+ * safe than sorry. We potentially could call
+ * assegment_normalise here instead, but it's
+ * cheaper and
+ * easier to do it on the fly here rather than
+ * go through
+ * the segment list twice every time we write
+ * out
+ * aspath's.
+ */
+
+ /* Next segment's data can fit in this one */
+ assegment_data_put(s, next->as, next->length,
+ use32bit);
+
+ /* update the length of the segment header */
+ stream_putc_at(s, lenp,
+ seg->length - written
+ + next->length);
+ asns_packed += next->length;
+
+ next = next->next;
+ }
+
+ bytes += ASSEGMENT_SIZE(
+ seg->length - written + asns_packed, use32bit);
+ seg = next;
+ }
+ }
+ return bytes;
}
/* This is for SNMP BGP4PATHATTRASPATHSEGMENT
* 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)
+u_char *aspath_snmp_pathseg(struct aspath *as, size_t *varlen)
{
#define SNMP_PATHSEG_MAX 1024
- if (!snmp_stream)
- snmp_stream = stream_new (SNMP_PATHSEG_MAX);
- else
- stream_reset (snmp_stream);
-
- if (!as)
- {
- *varlen = 0;
- return NULL;
- }
- aspath_put (snmp_stream, as, 0); /* use 16 bit for now here */
-
- *varlen = stream_get_endp (snmp_stream);
- return stream_pnt(snmp_stream);
-}
-
+ if (!snmp_stream)
+ snmp_stream = stream_new(SNMP_PATHSEG_MAX);
+ else
+ stream_reset(snmp_stream);
+
+ if (!as) {
+ *varlen = 0;
+ return NULL;
+ }
+ aspath_put(snmp_stream, as, 0); /* use 16 bit for now here */
+
+ *varlen = stream_get_endp(snmp_stream);
+ return stream_pnt(snmp_stream);
+}
+
#define min(A,B) ((A) < (B) ? (A) : (B))
-static struct assegment *
-aspath_aggregate_as_set_add (struct aspath *aspath, struct assegment *asset,
- as_t as)
-{
- int i;
-
- /* If this is first AS set member, create new as-set segment. */
- if (asset == NULL)
- {
- asset = assegment_new (AS_SET, 1);
- if (! aspath->segments)
- aspath->segments = asset;
- else
- {
- struct assegment *seg = aspath->segments;
- while (seg->next)
- seg = seg->next;
- seg->next = asset;
- }
- asset->type = AS_SET;
- asset->length = 1;
- asset->as[0] = as;
- }
- else
- {
- /* Check this AS value already exists or not. */
- for (i = 0; i < asset->length; i++)
- if (asset->as[i] == as)
- return asset;
-
- asset->length++;
- asset->as = XREALLOC (MTYPE_AS_SEG_DATA, asset->as,
- asset->length * AS_VALUE_SIZE);
- asset->as[asset->length - 1] = as;
- }
-
-
- return asset;
+static struct assegment *aspath_aggregate_as_set_add(struct aspath *aspath,
+ struct assegment *asset,
+ as_t as)
+{
+ int i;
+
+ /* If this is first AS set member, create new as-set segment. */
+ if (asset == NULL) {
+ asset = assegment_new(AS_SET, 1);
+ if (!aspath->segments)
+ aspath->segments = asset;
+ else {
+ struct assegment *seg = aspath->segments;
+ while (seg->next)
+ seg = seg->next;
+ seg->next = asset;
+ }
+ asset->type = AS_SET;
+ asset->length = 1;
+ asset->as[0] = as;
+ } else {
+ /* Check this AS value already exists or not. */
+ for (i = 0; i < asset->length; i++)
+ if (asset->as[i] == as)
+ return asset;
+
+ asset->length++;
+ asset->as = XREALLOC(MTYPE_AS_SEG_DATA, asset->as,
+ asset->length * AS_VALUE_SIZE);
+ asset->as[asset->length - 1] = as;
+ }
+
+
+ return asset;
}
/* Modify as1 using as2 for aggregation. */
-struct aspath *
-aspath_aggregate (struct aspath *as1, struct aspath *as2)
-{
- int i;
- int minlen = 0;
- int match = 0;
- int from;
- struct assegment *seg1 = as1->segments;
- struct assegment *seg2 = as2->segments;
- struct aspath *aspath = NULL;
- struct assegment *asset = NULL;
- struct assegment *prevseg = NULL;
-
- /* First of all check common leading sequence. */
- while (seg1 && seg2)
- {
- /* Check segment type. */
- if (seg1->type != seg2->type)
- break;
-
- /* Minimum segment length. */
- minlen = min (seg1->length, seg2->length);
-
- for (match = 0; match < minlen; match++)
- if (seg1->as[match] != seg2->as[match])
- break;
-
- if (match)
- {
- struct assegment *seg = assegment_new (seg1->type, 0);
-
- seg = assegment_append_asns (seg, seg1->as, match);
-
- if (! aspath)
- {
- aspath = aspath_new ();
- aspath->segments = seg;
- }
- else
- prevseg->next = seg;
-
- prevseg = seg;
+struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
+{
+ int i;
+ int minlen = 0;
+ int match = 0;
+ int from;
+ struct assegment *seg1 = as1->segments;
+ struct assegment *seg2 = as2->segments;
+ struct aspath *aspath = NULL;
+ struct assegment *asset = NULL;
+ struct assegment *prevseg = NULL;
+
+ /* First of all check common leading sequence. */
+ while (seg1 && seg2) {
+ /* Check segment type. */
+ if (seg1->type != seg2->type)
+ break;
+
+ /* Minimum segment length. */
+ minlen = min(seg1->length, seg2->length);
+
+ for (match = 0; match < minlen; match++)
+ if (seg1->as[match] != seg2->as[match])
+ break;
+
+ if (match) {
+ struct assegment *seg = assegment_new(seg1->type, 0);
+
+ seg = assegment_append_asns(seg, seg1->as, match);
+
+ if (!aspath) {
+ aspath = aspath_new();
+ aspath->segments = seg;
+ } else
+ prevseg->next = seg;
+
+ prevseg = seg;
+ }
+
+ if (match != minlen || match != seg1->length
+ || seg1->length != seg2->length)
+ break;
+ /* We are moving on to the next segment to reset match */
+ else
+ match = 0;
+
+ seg1 = seg1->next;
+ seg2 = seg2->next;
+ }
+
+ if (!aspath)
+ aspath = aspath_new();
+
+ /* Make as-set using rest of all information. */
+ from = match;
+ while (seg1) {
+ for (i = from; i < seg1->length; i++)
+ asset = aspath_aggregate_as_set_add(aspath, asset,
+ seg1->as[i]);
+
+ from = 0;
+ seg1 = seg1->next;
}
- if (match != minlen || match != seg1->length
- || seg1->length != seg2->length)
- break;
- /* We are moving on to the next segment to reset match */
- else
- match = 0;
-
- seg1 = seg1->next;
- seg2 = seg2->next;
- }
-
- if (! aspath)
- aspath = aspath_new();
-
- /* Make as-set using rest of all information. */
- from = match;
- while (seg1)
- {
- for (i = from; i < seg1->length; i++)
- asset = aspath_aggregate_as_set_add (aspath, asset, seg1->as[i]);
-
- from = 0;
- seg1 = seg1->next;
- }
-
- from = match;
- while (seg2)
- {
- for (i = from; i < seg2->length; i++)
- asset = aspath_aggregate_as_set_add (aspath, asset, seg2->as[i]);
-
- from = 0;
- seg2 = seg2->next;
- }
-
- assegment_normalise (aspath->segments);
- aspath_str_update (aspath);
- return aspath;
+ from = match;
+ while (seg2) {
+ for (i = from; i < seg2->length; i++)
+ asset = aspath_aggregate_as_set_add(aspath, asset,
+ seg2->as[i]);
+
+ from = 0;
+ seg2 = seg2->next;
+ }
+
+ assegment_normalise(aspath->segments);
+ aspath_str_update(aspath);
+ return aspath;
}
/* When a BGP router receives an UPDATE with an MP_REACH_NLRI
attribute, check the leftmost AS number in the AS_PATH attribute is
- or not the peer's AS number. */
-int
-aspath_firstas_check (struct aspath *aspath, as_t asno)
+ or not the peer's AS number. */
+int aspath_firstas_check(struct aspath *aspath, as_t asno)
{
- if ( (aspath == NULL) || (aspath->segments == NULL) )
- return 0;
-
- if (aspath->segments
- && (aspath->segments->type == AS_SEQUENCE)
- && (aspath->segments->as[0] == asno ))
- return 1;
+ if ((aspath == NULL) || (aspath->segments == NULL))
+ return 0;
+
+ if (aspath->segments && (aspath->segments->type == AS_SEQUENCE)
+ && (aspath->segments->as[0] == asno))
+ return 1;
- return 0;
+ return 0;
}
-unsigned int
-aspath_get_first_as (struct aspath *aspath)
+unsigned int aspath_get_first_as(struct aspath *aspath)
{
- if (aspath == NULL || aspath->segments == NULL)
- return 0;
+ if (aspath == NULL || aspath->segments == NULL)
+ return 0;
- return aspath->segments->as[0];
+ return aspath->segments->as[0];
}
-unsigned int
-aspath_get_last_as (struct aspath *aspath)
+unsigned int aspath_get_last_as(struct aspath *aspath)
{
- int i;
- unsigned int last_as = 0;
- const struct assegment *seg;
+ int i;
+ unsigned int last_as = 0;
+ const struct assegment *seg;
- if (aspath == NULL || aspath->segments == NULL)
- return last_as;
+ if (aspath == NULL || aspath->segments == NULL)
+ return last_as;
- seg = aspath->segments;
+ seg = aspath->segments;
- while (seg)
- {
- if (seg->type == AS_SEQUENCE || seg->type == AS_CONFED_SEQUENCE)
- for (i = 0; i < seg->length; i++)
- last_as = seg->as[i];
- seg = seg->next;
- }
+ while (seg) {
+ if (seg->type == AS_SEQUENCE || seg->type == AS_CONFED_SEQUENCE)
+ for (i = 0; i < seg->length; i++)
+ last_as = seg->as[i];
+ seg = seg->next;
+ }
- return last_as;
+ return last_as;
}
/* AS path loop check. If aspath contains asno then return >= 1. */
-int
-aspath_loop_check (struct aspath *aspath, as_t asno)
-{
- struct assegment *seg;
- int count = 0;
-
- if ( (aspath == NULL) || (aspath->segments == NULL) )
- return 0;
-
- seg = aspath->segments;
-
- while (seg)
- {
- int i;
-
- for (i = 0; i < seg->length; i++)
- if (seg->as[i] == asno)
- count++;
-
- seg = seg->next;
- }
- return count;
+int aspath_loop_check(struct aspath *aspath, as_t asno)
+{
+ struct assegment *seg;
+ int count = 0;
+
+ if ((aspath == NULL) || (aspath->segments == NULL))
+ return 0;
+
+ seg = aspath->segments;
+
+ while (seg) {
+ int i;
+
+ for (i = 0; i < seg->length; i++)
+ if (seg->as[i] == asno)
+ count++;
+
+ seg = seg->next;
+ }
+ return count;
}
/* When all of AS path is private AS return 1. */
-int
-aspath_private_as_check (struct aspath *aspath)
+int aspath_private_as_check(struct aspath *aspath)
{
- struct assegment *seg;
+ struct assegment *seg;
- if ( !(aspath && aspath->segments) )
- return 0;
+ if (!(aspath && aspath->segments))
+ return 0;
- seg = aspath->segments;
+ seg = aspath->segments;
- while (seg)
- {
- int i;
+ while (seg) {
+ int i;
- for (i = 0; i < seg->length; i++)
- {
- if (!BGP_AS_IS_PRIVATE(seg->as[i]))
- return 0;
+ for (i = 0; i < seg->length; i++) {
+ if (!BGP_AS_IS_PRIVATE(seg->as[i]))
+ return 0;
+ }
+ seg = seg->next;
}
- seg = seg->next;
- }
- return 1;
+ return 1;
}
/* Return True if the entire ASPATH consist of the specified ASN */
-int
-aspath_single_asn_check (struct aspath *aspath, as_t asn)
+int aspath_single_asn_check(struct aspath *aspath, as_t asn)
{
- struct assegment *seg;
+ struct assegment *seg;
- if ( !(aspath && aspath->segments) )
- return 0;
+ if (!(aspath && aspath->segments))
+ return 0;
- seg = aspath->segments;
+ seg = aspath->segments;
- while (seg)
- {
- int i;
+ while (seg) {
+ int i;
- for (i = 0; i < seg->length; i++)
- {
- if (seg->as[i] != asn)
- return 0;
+ for (i = 0; i < seg->length; i++) {
+ if (seg->as[i] != asn)
+ return 0;
+ }
+ seg = seg->next;
}
- seg = seg->next;
- }
- return 1;
+ return 1;
}
/* Replace all instances of the target ASN with our own ASN */
-struct aspath *
-aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn,
- as_t our_asn)
+struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
+ as_t target_asn, as_t our_asn)
{
- struct aspath *new;
- struct assegment *seg;
+ struct aspath *new;
+ struct assegment *seg;
- new = aspath_dup(aspath);
- seg = new->segments;
+ new = aspath_dup(aspath);
+ seg = new->segments;
- while (seg)
- {
- int i;
+ while (seg) {
+ int i;
- for (i = 0; i < seg->length; i++)
- {
- if (seg->as[i] == target_asn)
- seg->as[i] = our_asn;
+ for (i = 0; i < seg->length; i++) {
+ if (seg->as[i] == target_asn)
+ seg->as[i] = our_asn;
+ }
+ seg = seg->next;
}
- seg = seg->next;
- }
- aspath_str_update(new);
- return new;
+ aspath_str_update(new);
+ return new;
}
/* Replace all private ASNs with our own ASN */
-struct aspath *
-aspath_replace_private_asns (struct aspath *aspath, as_t asn)
+struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn)
{
- struct aspath *new;
- struct assegment *seg;
+ struct aspath *new;
+ struct assegment *seg;
- new = aspath_dup(aspath);
- seg = new->segments;
+ new = aspath_dup(aspath);
+ seg = new->segments;
- while (seg)
- {
- int i;
+ while (seg) {
+ int i;
- for (i = 0; i < seg->length; i++)
- {
- if (BGP_AS_IS_PRIVATE(seg->as[i]))
- seg->as[i] = asn;
+ for (i = 0; i < seg->length; i++) {
+ if (BGP_AS_IS_PRIVATE(seg->as[i]))
+ seg->as[i] = asn;
+ }
+ seg = seg->next;
}
- seg = seg->next;
- }
- aspath_str_update(new);
- return new;
+ aspath_str_update(new);
+ return new;
}
/* Remove all private ASNs */
-struct aspath *
-aspath_remove_private_asns (struct aspath *aspath)
-{
- struct aspath *new;
- struct assegment *seg;
- struct assegment *new_seg;
- struct assegment *last_new_seg;
- int i;
- int j;
- int public = 0;
-
- new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
-
- new->json = NULL;
- new_seg = NULL;
- last_new_seg = NULL;
- seg = aspath->segments;
- while (seg)
- {
- public = 0;
- for (i = 0; i < seg->length; i++)
- {
- // ASN is public
- if (!BGP_AS_IS_PRIVATE(seg->as[i]))
- {
- public++;
- }
- }
-
- // The entire segment is private so skip it
- if (!public)
- {
- seg = seg->next;
- continue;
- }
-
- // The entire segment is public so copy it
- else if (public == seg->length)
- {
- new_seg = assegment_dup (seg);
- }
-
- // The segment is a mix of public and private ASNs. Copy as many spots as
- // there are public ASNs then come back and fill in only the public ASNs.
- else
- {
- new_seg = assegment_new (seg->type, public);
- j = 0;
- for (i = 0; i < seg->length; i++)
- {
- // ASN is public
- if (!BGP_AS_IS_PRIVATE(seg->as[i]))
- {
- new_seg->as[j] = seg->as[i];
- j++;
- }
- }
- }
-
- // This is the first segment so set the aspath segments pointer to this one
- if (!last_new_seg)
- new->segments = new_seg;
- else
- last_new_seg->next = new_seg;
-
- last_new_seg = new_seg;
- seg = seg->next;
- }
-
- aspath_str_update(new);
- return new;
-}
-
-/* AS path confed check. If aspath contains confed set or sequence then return 1. */
-int
-aspath_confed_check (struct aspath *aspath)
-{
- struct assegment *seg;
-
- if ( !(aspath && aspath->segments) )
- return 0;
-
- seg = aspath->segments;
-
- while (seg)
- {
- if (seg->type == AS_CONFED_SET || seg->type == AS_CONFED_SEQUENCE)
- return 1;
- seg = seg->next;
- }
- return 0;
+struct aspath *aspath_remove_private_asns(struct aspath *aspath)
+{
+ struct aspath *new;
+ struct assegment *seg;
+ struct assegment *new_seg;
+ struct assegment *last_new_seg;
+ int i;
+ int j;
+ int public = 0;
+
+ new = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
+
+ new->json = NULL;
+ new_seg = NULL;
+ last_new_seg = NULL;
+ seg = aspath->segments;
+ while (seg) {
+ public
+ = 0;
+ for (i = 0; i < seg->length; i++) {
+ // ASN is public
+ if (!BGP_AS_IS_PRIVATE(seg->as[i])) {
+ public
+ ++;
+ }
+ }
+
+ // The entire segment is private so skip it
+ if (!public) {
+ seg = seg->next;
+ continue;
+ }
+
+ // The entire segment is public so copy it
+ else if (public == seg->length) {
+ new_seg = assegment_dup(seg);
+ }
+
+ // The segment is a mix of public and private ASNs. Copy as many
+ // spots as
+ // there are public ASNs then come back and fill in only the
+ // public ASNs.
+ else {
+ new_seg = assegment_new(seg->type, public);
+ j = 0;
+ for (i = 0; i < seg->length; i++) {
+ // ASN is public
+ if (!BGP_AS_IS_PRIVATE(seg->as[i])) {
+ new_seg->as[j] = seg->as[i];
+ j++;
+ }
+ }
+ }
+
+ // This is the first segment so set the aspath segments pointer
+ // to this one
+ if (!last_new_seg)
+ new->segments = new_seg;
+ else
+ last_new_seg->next = new_seg;
+
+ last_new_seg = new_seg;
+ seg = seg->next;
+ }
+
+ aspath_str_update(new);
+ return new;
+}
+
+/* AS path confed check. If aspath contains confed set or sequence then return
+ * 1. */
+int aspath_confed_check(struct aspath *aspath)
+{
+ struct assegment *seg;
+
+ if (!(aspath && aspath->segments))
+ return 0;
+
+ seg = aspath->segments;
+
+ while (seg) {
+ if (seg->type == AS_CONFED_SET
+ || seg->type == AS_CONFED_SEQUENCE)
+ return 1;
+ seg = seg->next;
+ }
+ return 0;
}
/* Leftmost AS path segment confed check. If leftmost AS segment is of type
AS_CONFED_SEQUENCE or AS_CONFED_SET then return 1. */
-int
-aspath_left_confed_check (struct aspath *aspath)
+int aspath_left_confed_check(struct aspath *aspath)
{
- if ( !(aspath && aspath->segments) )
- return 0;
+ if (!(aspath && aspath->segments))
+ return 0;
- if ( (aspath->segments->type == AS_CONFED_SEQUENCE)
- || (aspath->segments->type == AS_CONFED_SET) )
- return 1;
+ if ((aspath->segments->type == AS_CONFED_SEQUENCE)
+ || (aspath->segments->type == AS_CONFED_SET))
+ return 1;
- return 0;
+ return 0;
}
/* Merge as1 to as2. as2 should be uninterned aspath. */
-static struct aspath *
-aspath_merge (struct aspath *as1, struct aspath *as2)
+static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2)
{
- struct assegment *last, *new;
+ struct assegment *last, *new;
- if (! as1 || ! as2)
- return NULL;
+ if (!as1 || !as2)
+ return NULL;
- last = new = assegment_dup_all (as1->segments);
-
- /* find the last valid segment */
- while (last && last->next)
- last = last->next;
-
- last->next = as2->segments;
- as2->segments = new;
- aspath_str_update (as2);
- return as2;
+ last = new = assegment_dup_all(as1->segments);
+
+ /* find the last valid segment */
+ while (last && last->next)
+ last = last->next;
+
+ last->next = as2->segments;
+ as2->segments = new;
+ aspath_str_update(as2);
+ return as2;
}
/* Prepend as1 to as2. as2 should be uninterned aspath. */
-struct aspath *
-aspath_prepend (struct aspath *as1, struct aspath *as2)
-{
- struct assegment *seg1;
- struct assegment *seg2;
-
- if (! as1 || ! as2)
- return NULL;
-
- seg1 = as1->segments;
- seg2 = as2->segments;
-
- /* 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);
- return as2;
- }
-
- /* If as1 is empty AS, no prepending to do. */
- if (seg1 == NULL)
- return as2;
-
- /* find the tail as1's segment chain. */
- while (seg1 && seg1->next)
- seg1 = seg1->next;
-
- /* Delete any AS_CONFED_SEQUENCE segment from as2. */
- if (seg1->type == AS_SEQUENCE && seg2->type == AS_CONFED_SEQUENCE)
- as2 = aspath_delete_confed_seq (as2);
-
- /* Compare last segment type of as1 and first segment type of as2. */
- if (seg1->type != seg2->type)
- return aspath_merge (as1, as2);
-
- if (seg1->type == AS_SEQUENCE)
- {
- /* We have two chains of segments, as1->segments and seg2,
- * and we have to attach them together, merging the attaching
- * segments together into one.
- *
- * 1. dupe as1->segments onto head of as2
- * 2. merge seg2's asns onto last segment of this new chain
- * 3. attach chain after seg2
- */
-
- /* dupe as1 onto as2's head */
- seg1 = as2->segments = assegment_dup_all (as1->segments);
-
- /* refind the tail of as2, reusing seg1 */
- while (seg1 && seg1->next)
- seg1 = seg1->next;
-
- /* merge the old head, seg2, into tail, seg1 */
- seg1 = assegment_append_asns (seg1, seg2->as, seg2->length);
-
- /* bypass the merged seg2, and attach any chain after it to
- * chain descending from as2's head
- */
- seg1->next = seg2->next;
-
- /* seg2 is now referenceless and useless*/
- assegment_free (seg2);
-
- /* we've now prepended as1's segment chain to as2, merging
- * the inbetween AS_SEQUENCE of seg2 in the process
- */
- aspath_str_update (as2);
- return as2;
- }
- else
- {
- /* AS_SET merge code is needed at here. */
- return aspath_merge (as1, as2);
- }
- /* XXX: Ermmm, what if as1 has multiple segments?? */
-
- /* Not reached */
+struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
+{
+ struct assegment *seg1;
+ struct assegment *seg2;
+
+ if (!as1 || !as2)
+ return NULL;
+
+ seg1 = as1->segments;
+ seg2 = as2->segments;
+
+ /* 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);
+ return as2;
+ }
+
+ /* If as1 is empty AS, no prepending to do. */
+ if (seg1 == NULL)
+ return as2;
+
+ /* find the tail as1's segment chain. */
+ while (seg1 && seg1->next)
+ seg1 = seg1->next;
+
+ /* Delete any AS_CONFED_SEQUENCE segment from as2. */
+ if (seg1->type == AS_SEQUENCE && seg2->type == AS_CONFED_SEQUENCE)
+ as2 = aspath_delete_confed_seq(as2);
+
+ /* Compare last segment type of as1 and first segment type of as2. */
+ if (seg1->type != seg2->type)
+ return aspath_merge(as1, as2);
+
+ if (seg1->type == AS_SEQUENCE) {
+ /* We have two chains of segments, as1->segments and seg2,
+ * and we have to attach them together, merging the attaching
+ * segments together into one.
+ *
+ * 1. dupe as1->segments onto head of as2
+ * 2. merge seg2's asns onto last segment of this new chain
+ * 3. attach chain after seg2
+ */
+
+ /* dupe as1 onto as2's head */
+ seg1 = as2->segments = assegment_dup_all(as1->segments);
+
+ /* refind the tail of as2, reusing seg1 */
+ while (seg1 && seg1->next)
+ seg1 = seg1->next;
+
+ /* merge the old head, seg2, into tail, seg1 */
+ seg1 = assegment_append_asns(seg1, seg2->as, seg2->length);
+
+ /* bypass the merged seg2, and attach any chain after it to
+ * chain descending from as2's head
+ */
+ seg1->next = seg2->next;
+
+ /* seg2 is now referenceless and useless*/
+ assegment_free(seg2);
+
+ /* we've now prepended as1's segment chain to as2, merging
+ * the inbetween AS_SEQUENCE of seg2 in the process
+ */
+ aspath_str_update(as2);
+ return as2;
+ } else {
+ /* AS_SET merge code is needed at here. */
+ return aspath_merge(as1, as2);
+ }
+ /* XXX: Ermmm, what if as1 has multiple segments?? */
+
+ /* Not reached */
}
/* Iterate over AS_PATH segments and wipe all occurences of the
* version of aspath_dup(), which allocates memory to hold the new
* data, not the original. The new AS path is returned.
*/
-struct aspath *
-aspath_filter_exclude (struct aspath * source, struct aspath * exclude_list)
-{
- struct assegment * srcseg, * exclseg, * lastseg;
- struct aspath * newpath;
-
- newpath = aspath_new();
- lastseg = NULL;
-
- for (srcseg = source->segments; srcseg; srcseg = srcseg->next)
- {
- unsigned i, y, newlen = 0, done = 0, skip_as;
- struct assegment * newseg;
-
- /* Find out, how much ASns are we going to pick from this segment.
- * We can't perform filtering right inline, because the size of
- * the new segment isn't known at the moment yet.
- */
- for (i = 0; i < srcseg->length; i++)
- {
- skip_as = 0;
- for (exclseg = exclude_list->segments; exclseg && !skip_as; exclseg = exclseg->next)
- for (y = 0; y < exclseg->length; y++)
- if (srcseg->as[i] == exclseg->as[y])
- {
- skip_as = 1;
- // There's no sense in testing the rest of exclusion list, bail out.
- break;
- }
- if (!skip_as)
- newlen++;
- }
- /* newlen is now the number of ASns to copy */
- if (!newlen)
- continue;
-
- /* Actual copying. Allocate memory and iterate once more, performing filtering. */
- newseg = assegment_new (srcseg->type, newlen);
- for (i = 0; i < srcseg->length; i++)
- {
- skip_as = 0;
- for (exclseg = exclude_list->segments; exclseg && !skip_as; exclseg = exclseg->next)
- for (y = 0; y < exclseg->length; y++)
- if (srcseg->as[i] == exclseg->as[y])
- {
- skip_as = 1;
- break;
- }
- if (skip_as)
- continue;
- newseg->as[done++] = srcseg->as[i];
- }
- /* At his point newlen must be equal to done, and both must be positive. Append
- * the filtered segment to the gross result. */
- if (!lastseg)
- newpath->segments = newseg;
- else
- lastseg->next = newseg;
- lastseg = newseg;
- }
- aspath_str_update (newpath);
- /* 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 necessary,
- * by having a match rule against certain AS_PATH regexps in the route-map index.
- */
- aspath_free (source);
- return newpath;
+struct aspath *aspath_filter_exclude(struct aspath *source,
+ struct aspath *exclude_list)
+{
+ struct assegment *srcseg, *exclseg, *lastseg;
+ struct aspath *newpath;
+
+ newpath = aspath_new();
+ lastseg = NULL;
+
+ for (srcseg = source->segments; srcseg; srcseg = srcseg->next) {
+ unsigned i, y, newlen = 0, done = 0, skip_as;
+ struct assegment *newseg;
+
+ /* Find out, how much ASns are we going to pick from this
+ * segment.
+ * We can't perform filtering right inline, because the size of
+ * the new segment isn't known at the moment yet.
+ */
+ for (i = 0; i < srcseg->length; i++) {
+ skip_as = 0;
+ for (exclseg = exclude_list->segments;
+ exclseg && !skip_as; exclseg = exclseg->next)
+ for (y = 0; y < exclseg->length; y++)
+ if (srcseg->as[i] == exclseg->as[y]) {
+ skip_as = 1;
+ // There's no sense in testing
+ // the rest of exclusion list,
+ // bail out.
+ break;
+ }
+ if (!skip_as)
+ newlen++;
+ }
+ /* newlen is now the number of ASns to copy */
+ if (!newlen)
+ continue;
+
+ /* Actual copying. Allocate memory and iterate once more,
+ * performing filtering. */
+ newseg = assegment_new(srcseg->type, newlen);
+ for (i = 0; i < srcseg->length; i++) {
+ skip_as = 0;
+ for (exclseg = exclude_list->segments;
+ exclseg && !skip_as; exclseg = exclseg->next)
+ for (y = 0; y < exclseg->length; y++)
+ if (srcseg->as[i] == exclseg->as[y]) {
+ skip_as = 1;
+ break;
+ }
+ if (skip_as)
+ continue;
+ newseg->as[done++] = srcseg->as[i];
+ }
+ /* At his point newlen must be equal to done, and both must be
+ * positive. Append
+ * the filtered segment to the gross result. */
+ if (!lastseg)
+ newpath->segments = newseg;
+ else
+ lastseg->next = newseg;
+ lastseg = newseg;
+ }
+ aspath_str_update(newpath);
+ /* 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
+ * necessary,
+ * by having a match rule against certain AS_PATH regexps in the
+ * route-map index.
+ */
+ aspath_free(source);
+ return newpath;
}
/* 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)
-{
- struct assegment *assegment = aspath->segments;
- unsigned i;
-
- if (assegment && assegment->type == type)
- {
- /* extend existing segment */
- aspath->segments = assegment_prepend_asns (aspath->segments, asno, num);
- }
- else
- {
- /* prepend with new segment */
- struct assegment *newsegment = assegment_new (type, num);
- for (i = 0; i < num; i++)
- newsegment->as[i] = asno;
-
- /* insert potentially replacing empty segment */
- if (assegment && assegment->length == 0)
- {
- newsegment->next = assegment->next;
- assegment_free (assegment);
+static struct aspath *aspath_add_asns(struct aspath *aspath, as_t asno,
+ u_char type, unsigned num)
+{
+ struct assegment *assegment = aspath->segments;
+ unsigned i;
+
+ if (assegment && assegment->type == type) {
+ /* extend existing segment */
+ aspath->segments =
+ assegment_prepend_asns(aspath->segments, asno, num);
+ } else {
+ /* prepend with new segment */
+ struct assegment *newsegment = assegment_new(type, num);
+ for (i = 0; i < num; i++)
+ newsegment->as[i] = asno;
+
+ /* insert potentially replacing empty segment */
+ if (assegment && assegment->length == 0) {
+ newsegment->next = assegment->next;
+ assegment_free(assegment);
+ } else
+ newsegment->next = assegment;
+ aspath->segments = newsegment;
}
- else
- newsegment->next = assegment;
- aspath->segments = newsegment;
- }
- aspath_str_update (aspath);
- return aspath;
+ aspath_str_update(aspath);
+ return aspath;
}
/* Add specified AS to the leftmost of aspath num times. */
-struct aspath *
-aspath_add_seq_n (struct aspath *aspath, as_t asno, unsigned num)
+struct aspath *aspath_add_seq_n(struct aspath *aspath, as_t asno, unsigned num)
{
- return aspath_add_asns (aspath, asno, AS_SEQUENCE, num);
+ return aspath_add_asns(aspath, asno, AS_SEQUENCE, num);
}
/* Add specified AS to the leftmost of aspath. */
-struct aspath *
-aspath_add_seq (struct aspath *aspath, as_t asno)
+struct aspath *aspath_add_seq(struct aspath *aspath, as_t asno)
{
- return aspath_add_asns (aspath, asno, AS_SEQUENCE, 1);
+ return aspath_add_asns(aspath, asno, AS_SEQUENCE, 1);
}
/* Compare leftmost AS value for MED check. If as1's leftmost AS and
as2's leftmost AS is same return 1. */
-int
-aspath_cmp_left (const struct aspath *aspath1, const struct aspath *aspath2)
+int aspath_cmp_left(const struct aspath *aspath1, const struct aspath *aspath2)
{
- const struct assegment *seg1;
- const struct assegment *seg2;
+ const struct assegment *seg1;
+ const struct assegment *seg2;
+
+ if (!(aspath1 && aspath2))
+ return 0;
- if (!(aspath1 && aspath2))
- return 0;
+ seg1 = aspath1->segments;
+ seg2 = aspath2->segments;
- seg1 = aspath1->segments;
- seg2 = aspath2->segments;
+ /* If both paths are originated in this AS then we do want to compare
+ * MED */
+ if (!seg1 && !seg2)
+ return 1;
- /* If both paths are originated in this AS then we do want to compare MED */
- if (!seg1 && !seg2)
- return 1;
+ /* find first non-confed segments for each */
+ while (seg1 && ((seg1->type == AS_CONFED_SEQUENCE)
+ || (seg1->type == AS_CONFED_SET)))
+ seg1 = seg1->next;
- /* find first non-confed segments for each */
- while (seg1 && ((seg1->type == AS_CONFED_SEQUENCE)
- || (seg1->type == AS_CONFED_SET)))
- seg1 = seg1->next;
+ while (seg2 && ((seg2->type == AS_CONFED_SEQUENCE)
+ || (seg2->type == AS_CONFED_SET)))
+ seg2 = seg2->next;
- while (seg2 && ((seg2->type == AS_CONFED_SEQUENCE)
- || (seg2->type == AS_CONFED_SET)))
- seg2 = seg2->next;
+ /* Check as1's */
+ if (!(seg1 && seg2 && (seg1->type == AS_SEQUENCE)
+ && (seg2->type == AS_SEQUENCE)))
+ return 0;
- /* Check as1's */
- if (!(seg1 && seg2
- && (seg1->type == AS_SEQUENCE) && (seg2->type == AS_SEQUENCE)))
- return 0;
-
- if (seg1->as[0] == seg2->as[0])
- return 1;
+ if (seg1->as[0] == seg2->as[0])
+ return 1;
- return 0;
+ return 0;
}
/* Truncate an aspath after a number of hops, and put the hops remaining
* Returned aspath is a /new/ aspath, which should either by free'd or
* interned by the caller, as desired.
*/
-struct aspath *
-aspath_reconcile_as4 ( struct aspath *aspath, struct aspath *as4path)
-{
- struct assegment *seg, *newseg, *prevseg = NULL;
- struct aspath *newpath = NULL, *mergedpath;
- int hops, cpasns = 0;
-
- if (!aspath)
- return NULL;
-
- seg = aspath->segments;
-
- /* CONFEDs should get reconciled too.. */
- hops = (aspath_count_hops (aspath) + aspath_count_confeds (aspath))
- - aspath_count_hops (as4path);
-
- if (hops < 0)
- {
- if (BGP_DEBUG (as4, AS4))
- zlog_warn ("[AS4] Fewer hops in AS_PATH than NEW_AS_PATH");
- /* Something's gone wrong. The RFC says we should now ignore AS4_PATH,
- * which is daft behaviour - it contains vital loop-detection
- * information which must have been removed from AS_PATH.
- */
- hops = aspath_count_hops (aspath);
- }
-
- if (!hops)
- {
- newpath = aspath_dup (as4path);
- aspath_str_update(newpath);
- return newpath;
- }
-
- if ( BGP_DEBUG(as4, AS4))
- zlog_debug("[AS4] got AS_PATH %s and AS4_PATH %s synthesizing now",
- aspath->str, as4path->str);
-
- while (seg && hops > 0)
- {
- switch (seg->type)
- {
- case AS_SET:
- case AS_CONFED_SET:
- hops--;
- cpasns = seg->length;
- break;
- case AS_CONFED_SEQUENCE:
- /* Should never split a confed-sequence, if hop-count
- * suggests we must then something's gone wrong somewhere.
- *
- * Most important goal is to preserve AS_PATHs prime function
- * as loop-detector, so we fudge the numbers so that the entire
- * confed-sequence is merged in.
- */
- if (hops < seg->length)
- {
- if (BGP_DEBUG (as4, AS4))
- zlog_debug ("[AS4] AS4PATHmangle: AS_CONFED_SEQUENCE falls"
- " across 2/4 ASN boundary somewhere, broken..");
- hops = seg->length;
- }
- /* fallthru */
- case AS_SEQUENCE:
- cpasns = MIN(seg->length, hops);
- hops -= seg->length;
+struct aspath *aspath_reconcile_as4(struct aspath *aspath,
+ struct aspath *as4path)
+{
+ struct assegment *seg, *newseg, *prevseg = NULL;
+ struct aspath *newpath = NULL, *mergedpath;
+ int hops, cpasns = 0;
+
+ if (!aspath)
+ return NULL;
+
+ seg = aspath->segments;
+
+ /* CONFEDs should get reconciled too.. */
+ hops = (aspath_count_hops(aspath) + aspath_count_confeds(aspath))
+ - aspath_count_hops(as4path);
+
+ if (hops < 0) {
+ if (BGP_DEBUG(as4, AS4))
+ zlog_warn(
+ "[AS4] Fewer hops in AS_PATH than NEW_AS_PATH");
+ /* Something's gone wrong. The RFC says we should now ignore
+ * AS4_PATH,
+ * which is daft behaviour - it contains vital loop-detection
+ * information which must have been removed from AS_PATH.
+ */
+ hops = aspath_count_hops(aspath);
+ }
+
+ if (!hops) {
+ newpath = aspath_dup(as4path);
+ aspath_str_update(newpath);
+ return newpath;
}
-
- assert (cpasns <= seg->length);
-
- newseg = assegment_new (seg->type, 0);
- newseg = assegment_append_asns (newseg, seg->as, cpasns);
-
- if (!newpath)
- {
- newpath = aspath_new ();
- newpath->segments = newseg;
- }
- else
- prevseg->next = newseg;
-
- prevseg = newseg;
- seg = seg->next;
- }
-
- /* We may be able to join some segments here, and we must
- * do this because... we want normalised aspaths in out hash
- * and we do not want to stumble in aspath_put.
- */
- mergedpath = aspath_merge (newpath, aspath_dup(as4path));
- aspath_free (newpath);
- mergedpath->segments = assegment_normalise (mergedpath->segments);
- aspath_str_update (mergedpath);
-
- if ( BGP_DEBUG(as4, AS4))
- zlog_debug ("[AS4] result of synthesizing is %s",
- mergedpath->str);
-
- return mergedpath;
+
+ if (BGP_DEBUG(as4, AS4))
+ zlog_debug(
+ "[AS4] got AS_PATH %s and AS4_PATH %s synthesizing now",
+ aspath->str, as4path->str);
+
+ while (seg && hops > 0) {
+ switch (seg->type) {
+ case AS_SET:
+ case AS_CONFED_SET:
+ hops--;
+ cpasns = seg->length;
+ break;
+ case AS_CONFED_SEQUENCE:
+ /* Should never split a confed-sequence, if hop-count
+ * suggests we must then something's gone wrong
+ * somewhere.
+ *
+ * Most important goal is to preserve AS_PATHs prime
+ * function
+ * as loop-detector, so we fudge the numbers so that the
+ * entire
+ * confed-sequence is merged in.
+ */
+ if (hops < seg->length) {
+ if (BGP_DEBUG(as4, AS4))
+ zlog_debug(
+ "[AS4] AS4PATHmangle: AS_CONFED_SEQUENCE falls"
+ " across 2/4 ASN boundary somewhere, broken..");
+ hops = seg->length;
+ }
+ /* fallthru */
+ case AS_SEQUENCE:
+ cpasns = MIN(seg->length, hops);
+ hops -= seg->length;
+ }
+
+ assert(cpasns <= seg->length);
+
+ newseg = assegment_new(seg->type, 0);
+ newseg = assegment_append_asns(newseg, seg->as, cpasns);
+
+ if (!newpath) {
+ newpath = aspath_new();
+ newpath->segments = newseg;
+ } else
+ prevseg->next = newseg;
+
+ prevseg = newseg;
+ seg = seg->next;
+ }
+
+ /* We may be able to join some segments here, and we must
+ * do this because... we want normalised aspaths in out hash
+ * and we do not want to stumble in aspath_put.
+ */
+ mergedpath = aspath_merge(newpath, aspath_dup(as4path));
+ aspath_free(newpath);
+ mergedpath->segments = assegment_normalise(mergedpath->segments);
+ aspath_str_update(mergedpath);
+
+ if (BGP_DEBUG(as4, AS4))
+ zlog_debug("[AS4] result of synthesizing is %s",
+ mergedpath->str);
+
+ return mergedpath;
}
/* Compare leftmost AS value for MED check. If as1's leftmost AS and
as2's leftmost AS is same return 1. (confederation as-path
only). */
-int
-aspath_cmp_left_confed (const struct aspath *aspath1, const struct aspath *aspath2)
+int aspath_cmp_left_confed(const struct aspath *aspath1,
+ const struct aspath *aspath2)
{
- if (! (aspath1 && aspath2) )
- return 0;
-
- if ( !(aspath1->segments && aspath2->segments) )
- return 0;
-
- if ( (aspath1->segments->type != AS_CONFED_SEQUENCE)
- || (aspath2->segments->type != AS_CONFED_SEQUENCE) )
- return 0;
-
- if (aspath1->segments->as[0] == aspath2->segments->as[0])
- return 1;
+ if (!(aspath1 && aspath2))
+ return 0;
- return 0;
+ if (!(aspath1->segments && aspath2->segments))
+ return 0;
+
+ if ((aspath1->segments->type != AS_CONFED_SEQUENCE)
+ || (aspath2->segments->type != AS_CONFED_SEQUENCE))
+ return 0;
+
+ if (aspath1->segments->as[0] == aspath2->segments->as[0])
+ return 1;
+
+ return 0;
}
/* Delete all AS_CONFED_SEQUENCE/SET segments from aspath.
* removed from the AS_PATH attribute, leaving the sanitized
* AS_PATH attribute to be operated on by steps 2, 3 or 4.
*/
-struct aspath *
-aspath_delete_confed_seq (struct aspath *aspath)
+struct aspath *aspath_delete_confed_seq(struct aspath *aspath)
{
- struct assegment *seg, *prev, *next;
- char removed_confed_segment;
+ struct assegment *seg, *prev, *next;
+ char removed_confed_segment;
+
+ if (!(aspath && aspath->segments))
+ return aspath;
- if (!(aspath && aspath->segments))
- return aspath;
+ seg = aspath->segments;
+ removed_confed_segment = 0;
+ next = NULL;
+ prev = NULL;
- seg = aspath->segments;
- removed_confed_segment = 0;
- next = NULL;
- prev = NULL;
-
- while (seg)
- {
- next = seg->next;
+ while (seg) {
+ next = seg->next;
- if (seg->type == AS_CONFED_SEQUENCE || seg->type == AS_CONFED_SET)
- {
- /* This is the first segment in the aspath */
- if (aspath->segments == seg)
- aspath->segments = seg->next;
- else
- prev->next = seg->next;
+ if (seg->type == AS_CONFED_SEQUENCE
+ || seg->type == AS_CONFED_SET) {
+ /* This is the first segment in the aspath */
+ if (aspath->segments == seg)
+ aspath->segments = seg->next;
+ else
+ prev->next = seg->next;
- assegment_free (seg);
- removed_confed_segment = 1;
- }
- else
- prev = seg;
+ assegment_free(seg);
+ removed_confed_segment = 1;
+ } else
+ prev = seg;
- seg = next;
- }
+ seg = next;
+ }
- if (removed_confed_segment)
- aspath_str_update (aspath);
+ if (removed_confed_segment)
+ aspath_str_update(aspath);
- return aspath;
+ return aspath;
}
/* Add new AS number to the leftmost part of the aspath as
AS_CONFED_SEQUENCE. */
-struct aspath*
-aspath_add_confed_seq (struct aspath *aspath, as_t asno)
+struct aspath *aspath_add_confed_seq(struct aspath *aspath, as_t asno)
{
- return aspath_add_asns (aspath, asno, AS_CONFED_SEQUENCE, 1);
+ return aspath_add_asns(aspath, asno, AS_CONFED_SEQUENCE, 1);
}
/* Add new as value to as path structure. */
-static void
-aspath_as_add (struct aspath *as, as_t asno)
+static void aspath_as_add(struct aspath *as, as_t asno)
{
- struct assegment *seg = as->segments;
+ struct assegment *seg = as->segments;
+
+ if (!seg)
+ return;
- if (!seg)
- return;
-
- /* Last segment search procedure. */
- while (seg->next)
- seg = seg->next;
+ /* Last segment search procedure. */
+ while (seg->next)
+ seg = seg->next;
- assegment_append_asns (seg, &asno, 1);
+ assegment_append_asns(seg, &asno, 1);
}
/* Add new as segment to the as path. */
-static void
-aspath_segment_add (struct aspath *as, int type)
+static void aspath_segment_add(struct aspath *as, int type)
{
- struct assegment *seg = as->segments;
- struct assegment *new = assegment_new (type, 0);
+ struct assegment *seg = as->segments;
+ struct assegment *new = assegment_new(type, 0);
- if (seg)
- {
- while (seg->next)
- seg = seg->next;
- seg->next = new;
- }
- else
- as->segments = new;
+ if (seg) {
+ while (seg->next)
+ seg = seg->next;
+ seg->next = new;
+ } else
+ as->segments = new;
}
-struct aspath *
-aspath_empty (void)
+struct aspath *aspath_empty(void)
{
- return aspath_parse (NULL, 0, 1); /* 32Bit ;-) */
+ return aspath_parse(NULL, 0, 1); /* 32Bit ;-) */
}
-struct aspath *
-aspath_empty_get (void)
+struct aspath *aspath_empty_get(void)
{
- struct aspath *aspath;
+ struct aspath *aspath;
- aspath = aspath_new ();
- aspath_make_str_count (aspath);
- return aspath;
+ aspath = aspath_new();
+ aspath_make_str_count(aspath);
+ return aspath;
}
-unsigned long
-aspath_count (void)
+unsigned long aspath_count(void)
{
- return ashash->count;
-}
+ return ashash->count;
+}
-/*
+/*
Theoretically, one as path can have:
One BGP packet size should be less than 4096.
*/
/* AS path string lexical token enum. */
-enum as_token
-{
- as_token_asval,
- as_token_set_start,
- as_token_set_end,
- as_token_confed_seq_start,
- as_token_confed_seq_end,
- as_token_confed_set_start,
- as_token_confed_set_end,
- as_token_unknown
+enum as_token {
+ as_token_asval,
+ as_token_set_start,
+ as_token_set_end,
+ as_token_confed_seq_start,
+ as_token_confed_seq_end,
+ as_token_confed_set_start,
+ as_token_confed_set_end,
+ as_token_unknown
};
/* Return next token and point for string parse. */
-static const char *
-aspath_gettoken (const char *buf, enum as_token *token, u_long *asno)
-{
- const char *p = buf;
-
- /* Skip seperators (space for sequences, ',' for sets). */
- while (isspace ((int) *p) || *p == ',')
- p++;
-
- /* Check the end of the string and type specify characters
- (e.g. {}()). */
- switch (*p)
- {
- case '\0':
- return NULL;
- case '{':
- *token = as_token_set_start;
- p++;
- return p;
- case '}':
- *token = as_token_set_end;
- p++;
- return p;
- case '(':
- *token = as_token_confed_seq_start;
- p++;
- return p;
- case ')':
- *token = as_token_confed_seq_end;
- p++;
- return p;
- case '[':
- *token = as_token_confed_set_start;
- p++;
- return p;
- case ']':
- *token = as_token_confed_set_end;
- p++;
- return p;
- }
-
- /* Check actual AS value. */
- if (isdigit ((int) *p))
- {
- as_t asval;
-
- *token = as_token_asval;
- asval = (*p - '0');
- p++;
-
- while (isdigit ((int) *p))
- {
- asval *= 10;
- asval += (*p - '0');
- p++;
- }
- *asno = asval;
- return p;
- }
-
- /* There is no match then return unknown token. */
- *token = as_token_unknown;
- return p++;
-}
-
-struct aspath *
-aspath_str2aspath (const char *str)
-{
- enum as_token token = as_token_unknown;
- u_short as_type;
- u_long asno = 0;
- struct aspath *aspath;
- int needtype;
-
- aspath = aspath_new ();
-
- /* We start default type as AS_SEQUENCE. */
- as_type = AS_SEQUENCE;
- needtype = 1;
-
- while ((str = aspath_gettoken (str, &token, &asno)) != NULL)
- {
- switch (token)
- {
- case as_token_asval:
- if (needtype)
- {
- aspath_segment_add (aspath, as_type);
- needtype = 0;
- }
- aspath_as_add (aspath, asno);
- break;
- case as_token_set_start:
- as_type = AS_SET;
- aspath_segment_add (aspath, as_type);
- needtype = 0;
- break;
- case as_token_set_end:
- as_type = AS_SEQUENCE;
- needtype = 1;
- break;
- case as_token_confed_seq_start:
- as_type = AS_CONFED_SEQUENCE;
- aspath_segment_add (aspath, as_type);
- needtype = 0;
- break;
- case as_token_confed_seq_end:
- as_type = AS_SEQUENCE;
- needtype = 1;
- break;
- case as_token_confed_set_start:
- as_type = AS_CONFED_SET;
- aspath_segment_add (aspath, as_type);
- needtype = 0;
- break;
- case as_token_confed_set_end:
- as_type = AS_SEQUENCE;
- needtype = 1;
- break;
- case as_token_unknown:
- default:
- aspath_free (aspath);
- return NULL;
+static const char *aspath_gettoken(const char *buf, enum as_token *token,
+ u_long *asno)
+{
+ const char *p = buf;
+
+ /* Skip seperators (space for sequences, ',' for sets). */
+ while (isspace((int)*p) || *p == ',')
+ p++;
+
+ /* Check the end of the string and type specify characters
+ (e.g. {}()). */
+ switch (*p) {
+ case '\0':
+ return NULL;
+ case '{':
+ *token = as_token_set_start;
+ p++;
+ return p;
+ case '}':
+ *token = as_token_set_end;
+ p++;
+ return p;
+ case '(':
+ *token = as_token_confed_seq_start;
+ p++;
+ return p;
+ case ')':
+ *token = as_token_confed_seq_end;
+ p++;
+ return p;
+ case '[':
+ *token = as_token_confed_set_start;
+ p++;
+ return p;
+ case ']':
+ *token = as_token_confed_set_end;
+ p++;
+ return p;
+ }
+
+ /* Check actual AS value. */
+ if (isdigit((int)*p)) {
+ as_t asval;
+
+ *token = as_token_asval;
+ asval = (*p - '0');
+ p++;
+
+ while (isdigit((int)*p)) {
+ asval *= 10;
+ asval += (*p - '0');
+ p++;
+ }
+ *asno = asval;
+ return p;
}
- }
- aspath_make_str_count (aspath);
+ /* There is no match then return unknown token. */
+ *token = as_token_unknown;
+ return p++;
+}
+
+struct aspath *aspath_str2aspath(const char *str)
+{
+ enum as_token token = as_token_unknown;
+ u_short as_type;
+ u_long asno = 0;
+ struct aspath *aspath;
+ int needtype;
+
+ aspath = aspath_new();
+
+ /* We start default type as AS_SEQUENCE. */
+ as_type = AS_SEQUENCE;
+ needtype = 1;
+
+ while ((str = aspath_gettoken(str, &token, &asno)) != NULL) {
+ switch (token) {
+ case as_token_asval:
+ if (needtype) {
+ aspath_segment_add(aspath, as_type);
+ needtype = 0;
+ }
+ aspath_as_add(aspath, asno);
+ break;
+ case as_token_set_start:
+ as_type = AS_SET;
+ aspath_segment_add(aspath, as_type);
+ needtype = 0;
+ break;
+ case as_token_set_end:
+ as_type = AS_SEQUENCE;
+ needtype = 1;
+ break;
+ case as_token_confed_seq_start:
+ as_type = AS_CONFED_SEQUENCE;
+ aspath_segment_add(aspath, as_type);
+ needtype = 0;
+ break;
+ case as_token_confed_seq_end:
+ as_type = AS_SEQUENCE;
+ needtype = 1;
+ break;
+ case as_token_confed_set_start:
+ as_type = AS_CONFED_SET;
+ aspath_segment_add(aspath, as_type);
+ needtype = 0;
+ break;
+ case as_token_confed_set_end:
+ as_type = AS_SEQUENCE;
+ needtype = 1;
+ break;
+ case as_token_unknown:
+ default:
+ aspath_free(aspath);
+ return NULL;
+ }
+ }
+
+ aspath_make_str_count(aspath);
- return aspath;
+ return aspath;
}
/* Make hash value by raw aspath data. */
-unsigned int
-aspath_key_make (void *p)
+unsigned int aspath_key_make(void *p)
{
- struct aspath *aspath = (struct aspath *) p;
- unsigned int key = 0;
+ struct aspath *aspath = (struct aspath *)p;
+ unsigned int key = 0;
- if (!aspath->str)
- aspath_str_update (aspath);
+ if (!aspath->str)
+ aspath_str_update(aspath);
- key = jhash (aspath->str, aspath->str_len, 2334325);
+ key = jhash(aspath->str, aspath->str_len, 2334325);
- return key;
+ return key;
}
/* If two aspath have same value then return 1 else return 0 */
-int
-aspath_cmp (const void *arg1, const void *arg2)
-{
- const struct assegment *seg1 = ((const struct aspath *)arg1)->segments;
- const struct assegment *seg2 = ((const struct aspath *)arg2)->segments;
-
- while (seg1 || seg2)
- {
- int i;
- if ((!seg1 && seg2) || (seg1 && !seg2))
- return 0;
- if (seg1->type != seg2->type)
- return 0;
- if (seg1->length != seg2->length)
- return 0;
- for (i = 0; i < seg1->length; i++)
- if (seg1->as[i] != seg2->as[i])
- return 0;
- seg1 = seg1->next;
- seg2 = seg2->next;
- }
- return 1;
+int aspath_cmp(const void *arg1, const void *arg2)
+{
+ const struct assegment *seg1 = ((const struct aspath *)arg1)->segments;
+ const struct assegment *seg2 = ((const struct aspath *)arg2)->segments;
+
+ while (seg1 || seg2) {
+ int i;
+ if ((!seg1 && seg2) || (seg1 && !seg2))
+ return 0;
+ if (seg1->type != seg2->type)
+ return 0;
+ if (seg1->length != seg2->length)
+ return 0;
+ for (i = 0; i < seg1->length; i++)
+ if (seg1->as[i] != seg2->as[i])
+ return 0;
+ seg1 = seg1->next;
+ seg2 = seg2->next;
+ }
+ return 1;
}
/* AS path hash initialize. */
-void
-aspath_init (void)
+void aspath_init(void)
{
- ashash = hash_create_size (32768, aspath_key_make, aspath_cmp, NULL);
+ ashash = hash_create_size(32768, aspath_key_make, aspath_cmp, NULL);
}
-void
-aspath_finish (void)
+void aspath_finish(void)
{
- hash_clean (ashash, (void (*)(void *))aspath_free);
- hash_free (ashash);
- ashash = NULL;
-
- if (snmp_stream)
- stream_free (snmp_stream);
+ hash_clean(ashash, (void (*)(void *))aspath_free);
+ hash_free(ashash);
+ ashash = NULL;
+
+ if (snmp_stream)
+ stream_free(snmp_stream);
}
/* return and as path value */
-const char *
-aspath_print (struct aspath *as)
+const char *aspath_print(struct aspath *as)
{
- return (as ? as->str : NULL);
+ return (as ? as->str : NULL);
}
/* Printing functions */
/* Feed the AS_PATH to the vty; the suffix string follows it only in case
* AS_PATH wasn't empty.
*/
-void
-aspath_print_vty (struct vty *vty, const char *format, struct aspath *as, const char * suffix)
+void aspath_print_vty(struct vty *vty, const char *format, struct aspath *as,
+ const char *suffix)
{
- assert (format);
- vty_out (vty, format, as->str);
- if (as->str_len && strlen (suffix))
- vty_out (vty, "%s", suffix);
+ assert(format);
+ vty_out(vty, format, as->str);
+ if (as->str_len && strlen(suffix))
+ vty_out(vty, "%s", suffix);
}
-static void
-aspath_show_all_iterator (struct hash_backet *backet, struct vty *vty)
+static void aspath_show_all_iterator(struct hash_backet *backet,
+ struct vty *vty)
{
- struct aspath *as;
+ struct aspath *as;
- as = (struct aspath *) backet->data;
+ as = (struct aspath *)backet->data;
- vty_out (vty, "[%p:%u] (%ld) ", (void *)backet, backet->key, as->refcnt);
- vty_out (vty, "%s\n", as->str);
+ vty_out(vty, "[%p:%u] (%ld) ", (void *)backet, backet->key, as->refcnt);
+ vty_out(vty, "%s\n", as->str);
}
/* Print all aspath and hash information. This function is used from
`show [ip] bgp paths' command. */
-void
-aspath_print_all_vty (struct vty *vty)
+void aspath_print_all_vty(struct vty *vty)
{
- hash_iterate (ashash,
- (void (*) (struct hash_backet *, void *))
- aspath_show_all_iterator,
- vty);
+ hash_iterate(ashash, (void (*)(struct hash_backet *,
+ void *))aspath_show_all_iterator,
+ vty);
}