summaryrefslogtreecommitdiff
path: root/bgpd/bgp_aspath.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_aspath.c')
-rw-r--r--bgpd/bgp_aspath.c148
1 files changed, 146 insertions, 2 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 2c0de43c9b..0e70de9d46 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -21,6 +21,7 @@
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_errors.h"
+#include "bgpd/bgp_filter.h"
/* Attr. Flags and Attr. Type Code. */
#define AS_HEADER_SIZE 2
@@ -1015,8 +1016,6 @@ static struct assegment *aspath_aggregate_as_set_add(struct aspath *aspath,
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. */
@@ -1230,6 +1229,46 @@ bool aspath_private_as_check(struct aspath *aspath)
return true;
}
+/* Replace all ASN instances of the regex rule with our own ASN */
+struct aspath *aspath_replace_regex_asn(struct aspath *aspath,
+ struct as_list *acl_list, as_t our_asn)
+{
+ struct aspath *new;
+ struct assegment *cur_seg;
+ struct as_list *cur_as_list;
+ struct as_filter *cur_as_filter;
+ char str_buf[ASPATH_STR_DEFAULT_LEN];
+ uint32_t i;
+
+ new = aspath_dup(aspath);
+ cur_seg = new->segments;
+
+ while (cur_seg) {
+ cur_as_list = acl_list;
+ while (cur_as_list) {
+ cur_as_filter = cur_as_list->head;
+ while (cur_as_filter) {
+ for (i = 0; i < cur_seg->length; i++) {
+ snprintfrr(str_buf,
+ ASPATH_STR_DEFAULT_LEN,
+ ASN_FORMAT(new->asnotation),
+ &cur_seg->as[i]);
+ if (!regexec(cur_as_filter->reg,
+ str_buf, 0, NULL, 0))
+ cur_seg->as[i] = our_asn;
+ }
+ cur_as_filter = cur_as_filter->next;
+ }
+ cur_as_list = cur_as_list->next;
+ }
+ cur_seg = cur_seg->next;
+ }
+
+ aspath_str_update(new, false);
+ return new;
+}
+
+
/* 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)
@@ -1598,6 +1637,111 @@ struct aspath *aspath_filter_exclude(struct aspath *source,
return newpath;
}
+struct aspath *aspath_filter_exclude_all(struct aspath *source)
+{
+ struct aspath *newpath;
+
+ newpath = aspath_new(source->asnotation);
+
+ 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
+ * 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_acl(struct aspath *source,
+ struct as_list *acl_list)
+{
+ struct assegment *cur_seg, *new_seg, *prev_seg, *next_seg;
+ struct as_list *cur_as_list;
+ struct as_filter *cur_as_filter;
+ char str_buf[ASPATH_STR_DEFAULT_LEN];
+ uint32_t nb_as_del;
+ uint32_t i, j;
+
+ cur_seg = source->segments;
+ prev_seg = NULL;
+ /* segments from source aspath */
+ while (cur_seg) {
+ next_seg = cur_seg->next;
+ cur_as_list = acl_list;
+ nb_as_del = 0;
+ /* aspath filter list from acl_list */
+ while (cur_as_list) {
+ cur_as_filter = cur_as_list->head;
+ while (cur_as_filter) {
+ for (i = 0; i < cur_seg->length; i++) {
+ if (cur_seg->as[i] == 0)
+ continue;
+
+ snprintfrr(str_buf,
+ ASPATH_STR_DEFAULT_LEN,
+ ASN_FORMAT(source->asnotation),
+ &cur_seg->as[i]);
+ if (!regexec(cur_as_filter->reg,
+ str_buf, 0, NULL, 0)) {
+ cur_seg->as[i] = 0;
+ nb_as_del++;
+ }
+ }
+
+ cur_as_filter = cur_as_filter->next;
+ }
+
+ cur_as_list = cur_as_list->next;
+ }
+ /* full segment is excluded remove it */
+ if (nb_as_del == cur_seg->length) {
+ if (cur_seg == source->segments)
+ /* first segment */
+ source->segments = cur_seg->next;
+ else if (prev_seg)
+ prev_seg->next = cur_seg->next;
+ assegment_free(cur_seg);
+ }
+ /* change in segment size -> new allocation and replace segment*/
+ else if (nb_as_del) {
+ new_seg = assegment_new(cur_seg->type,
+ cur_seg->length - nb_as_del);
+ j = 0;
+ for (i = 0; i < cur_seg->length; i++) {
+ if (cur_seg->as[i] == 0)
+ continue;
+ new_seg->as[j] = cur_seg->as[i];
+ j++;
+ }
+ new_seg->next = next_seg;
+ if (cur_seg == source->segments)
+ /* first segment */
+ source->segments = new_seg;
+ else if (prev_seg)
+ prev_seg->next = new_seg;
+ assegment_free(cur_seg);
+ prev_seg = new_seg;
+ } else
+ prev_seg = cur_seg;
+ cur_seg = next_seg;
+ }
+
+
+ aspath_str_update(source, 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
+ * necessary,
+ * by having a match rule against certain AS_PATH regexps in the
+ * route-map index.
+ */
+ return source;
+}
+
+
/* Add specified AS to the leftmost of aspath. */
static struct aspath *aspath_add_asns(struct aspath *aspath, as_t asno,
uint8_t type, unsigned num)