]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_clist.c
Merge pull request #3502 from donaldsharp/socket_to_me_baby
[mirror_frr.git] / bgpd / bgp_clist.c
index 72b1098ede8093853818d2dbf874415b13b3d530..c4a20ca23382ca68ba3077575a43106def051eaa 100644 (file)
@@ -65,7 +65,7 @@ static void community_entry_free(struct community_entry *entry)
        switch (entry->style) {
        case COMMUNITY_LIST_STANDARD:
                if (entry->u.com)
-                       community_free(entry->u.com);
+                       community_free(&entry->u.com);
                break;
        case LARGE_COMMUNITY_LIST_STANDARD:
                if (entry->u.lcom)
@@ -274,8 +274,7 @@ static void community_list_entry_add(struct community_list *list,
 
 /* Delete community-list entry from the list.  */
 static void community_list_entry_delete(struct community_list *list,
-                                       struct community_entry *entry,
-                                       int style)
+                                       struct community_entry *entry)
 {
        if (entry->next)
                entry->next->prev = entry->prev;
@@ -333,71 +332,70 @@ community_list_entry_lookup(struct community_list *list, const void *arg,
 
 static char *community_str_get(struct community *com, int i)
 {
-       int len;
-       u_int32_t comval;
-       u_int16_t as;
-       u_int16_t val;
+       uint32_t comval;
+       uint16_t as;
+       uint16_t val;
        char *str;
-       char *pnt;
 
-       memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t));
+       memcpy(&comval, com_nthval(com, i), sizeof(uint32_t));
        comval = ntohl(comval);
 
        switch (comval) {
        case COMMUNITY_INTERNET:
-               len = strlen(" internet");
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "internet");
                break;
-       case COMMUNITY_NO_EXPORT:
-               len = strlen(" no-export");
+       case COMMUNITY_GSHUT:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "graceful-shutdown");
                break;
-       case COMMUNITY_NO_ADVERTISE:
-               len = strlen(" no-advertise");
+       case COMMUNITY_ACCEPT_OWN:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "accept-own");
                break;
-       case COMMUNITY_LOCAL_AS:
-               len = strlen(" local-AS");
+       case COMMUNITY_ROUTE_FILTER_TRANSLATED_v4:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR,
+                             "route-filter-translated-v4");
                break;
-       case COMMUNITY_GSHUT:
-               len = strlen(" graceful-shutdown");
+       case COMMUNITY_ROUTE_FILTER_v4:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "route-filter-v4");
                break;
-       default:
-               len = strlen(" 65536:65535");
+       case COMMUNITY_ROUTE_FILTER_TRANSLATED_v6:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR,
+                             "route-filter-translated-v6");
                break;
-       }
-
-       /* Allocate memory.  */
-       str = pnt = XMALLOC(MTYPE_COMMUNITY_STR, len);
-
-       switch (comval) {
-       case COMMUNITY_INTERNET:
-               strcpy(pnt, "internet");
-               pnt += strlen("internet");
+       case COMMUNITY_ROUTE_FILTER_v6:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "route-filter-v6");
+               break;
+       case COMMUNITY_LLGR_STALE:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "llgr-stale");
+               break;
+       case COMMUNITY_NO_LLGR:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "no-llgr");
+               break;
+       case COMMUNITY_ACCEPT_OWN_NEXTHOP:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "accept-own-nexthop");
+               break;
+       case COMMUNITY_BLACKHOLE:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "blackhole");
                break;
        case COMMUNITY_NO_EXPORT:
-               strcpy(pnt, "no-export");
-               pnt += strlen("no-export");
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "no-export");
                break;
        case COMMUNITY_NO_ADVERTISE:
-               strcpy(pnt, "no-advertise");
-               pnt += strlen("no-advertise");
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "no-advertise");
                break;
        case COMMUNITY_LOCAL_AS:
-               strcpy(pnt, "local-AS");
-               pnt += strlen("local-AS");
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "local-AS");
                break;
-       case COMMUNITY_GSHUT:
-               strcpy(pnt, "graceful-shutdown");
-               pnt += strlen("graceful-shutdown");
+       case COMMUNITY_NO_PEER:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "no-peer");
                break;
        default:
+               str = XSTRDUP(MTYPE_COMMUNITY_STR, "65536:65535");
                as = (comval >> 16) & 0xFFFF;
                val = comval & 0xFFFF;
-               sprintf(pnt, "%u:%d", as, val);
-               pnt += strlen(pnt);
+               snprintf(str, strlen(str), "%u:%d", as, val);
                break;
        }
 
-       *pnt = '\0';
-
        return str;
 }
 
@@ -451,11 +449,11 @@ static int community_regexp_match(struct community *com, regex_t *reg)
 static char *lcommunity_str_get(struct lcommunity *lcom, int i)
 {
        struct lcommunity_val lcomval;
-       u_int32_t globaladmin;
-       u_int32_t localdata1;
-       u_int32_t localdata2;
+       uint32_t globaladmin;
+       uint32_t localdata1;
+       uint32_t localdata2;
        char *str;
-       u_char *ptr;
+       uint8_t *ptr;
        char *pnt;
 
        ptr = lcom->val + (i * LCOMMUNITY_SIZE);
@@ -465,7 +463,7 @@ static char *lcommunity_str_get(struct lcommunity *lcom, int i)
        /* Allocate memory.  48 bytes taken off bgp_lcommunity.c */
        str = pnt = XMALLOC(MTYPE_LCOMMUNITY_STR, 48);
 
-       ptr = (u_char *)lcomval.val;
+       ptr = (uint8_t *)lcomval.val;
        ptr = ptr_get_be32(ptr, &globaladmin);
        ptr = ptr_get_be32(ptr, &localdata1);
        ptr = ptr_get_be32(ptr, &localdata2);
@@ -512,7 +510,7 @@ static int lcommunity_regexp_match(struct lcommunity *com, regex_t *reg)
        if (com == NULL || com->size == 0)
                str = "";
        else
-               str = lcommunity_str(com);
+               str = lcommunity_str(com, false);
 
        /* Regular expression match.  */
        if (regexec(reg, str, 0, NULL, 0) == 0)
@@ -548,47 +546,77 @@ static int ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg)
 static struct community *
 community_regexp_delete (struct community *com, regex_t * reg)
 {
-  int i;
-  u_int32_t comval;
-  /* Maximum is "65535:65535" + '\0'. */
-  char c[12];
-  const char *str;
-
-  if (!com)
-    return NULL;
-
-  i = 0;
-  while (i < com->size)
-    {
-      memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t));
-      comval = ntohl (comval);
-
-      switch (comval)
-        {
-        case COMMUNITY_INTERNET:
-          str = "internet";
-          break;
-        case COMMUNITY_NO_EXPORT:
-          str = "no-export";
-          break;
-        case COMMUNITY_NO_ADVERTISE:
-          str = "no-advertise";
-          break;
-        case COMMUNITY_LOCAL_AS:
-          str = "local-AS";
-          break;
-        default:
-          sprintf (c, "%d:%d", (comval >> 16) & 0xFFFF, comval & 0xFFFF);
-          str = c;
-          break;
-        }
-
-      if (regexec (reg, str, 0, NULL, 0) == 0)
-        community_del_val (com, com_nthval (com, i));
-      else
-        i++;
-    }
-  return com;
+       int i;
+       uint32_t comval;
+       /* Maximum is "65535:65535" + '\0'. */
+       char c[12];
+       const char *str;
+
+       if (!com)
+               return NULL;
+
+       i = 0;
+       while (i < com->size)
+       {
+               memcpy (&comval, com_nthval (com, i), sizeof (uint32_t));
+               comval = ntohl (comval);
+
+               switch (comval) {
+               case COMMUNITY_INTERNET:
+                       str = "internet";
+                       break;
+               case COMMUNITY_ACCEPT_OWN:
+                       str = "accept-own";
+                       break;
+               case COMMUNITY_ROUTE_FILTER_TRANSLATED_v4:
+                       str = "route-filter-translated-v4";
+                       break;
+               case COMMUNITY_ROUTE_FILTER_v4:
+                       str = "route-filter-v4";
+                       break;
+               case COMMUNITY_ROUTE_FILTER_TRANSLATED_v6:
+                       str = "route-filter-translated-v6";
+                       break;
+               case COMMUNITY_ROUTE_FILTER_v6:
+                       str = "route-filter-v6";
+                       break;
+               case COMMUNITY_LLGR_STALE:
+                       str = "llgr-stale";
+                       break;
+               case COMMUNITY_NO_LLGR:
+                       str = "no-llgr";
+                       break;
+               case COMMUNITY_ACCEPT_OWN_NEXTHOP:
+                       str = "accept-own-nexthop";
+                       break;
+               case COMMUNITY_BLACKHOLE:
+                       str = "blackhole";
+                       break;
+               case COMMUNITY_NO_EXPORT:
+                       str = "no-export";
+                       break;
+               case COMMUNITY_NO_ADVERTISE:
+                       str = "no-advertise";
+                       break;
+               case COMMUNITY_LOCAL_AS:
+                       str = "local-AS";
+                       break;
+               case COMMUNITY_NO_PEER:
+                       str = "no-peer";
+                       break;
+               default:
+                       sprintf (c, "%d:%d", (comval >> 16) & 0xFFFF,
+                        comval & 0xFFFF);
+                       str = c;
+                       break;
+               }
+
+               if (regexec (reg, str, 0, NULL, 0) == 0)
+                       community_del_val (com, com_nthval (com, i));
+               else
+                       i++;
+       }
+       return com;
 }
 #endif
 
@@ -694,8 +722,8 @@ struct community *community_list_match_delete(struct community *com,
                                              struct community_list *list)
 {
        struct community_entry *entry;
-       u_int32_t val;
-       u_int32_t com_index_to_delete[com->size];
+       uint32_t val;
+       uint32_t com_index_to_delete[com->size];
        int delete_index = 0;
        int i;
 
@@ -852,7 +880,7 @@ int community_list_set(struct community_list_handler *ch, const char *name,
 
 /* Unset community-list */
 int community_list_unset(struct community_list_handler *ch, const char *name,
-                        const char *str, int direct, int style, int delete_all)
+                        const char *str, int direct, int style)
 {
        struct community_entry *entry = NULL;
        struct community_list *list;
@@ -864,27 +892,25 @@ int community_list_unset(struct community_list_handler *ch, const char *name,
                return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
 
        /* Delete all of entry belongs to this community-list.  */
-       if (delete_all) {
+       if (!str) {
                community_list_delete(list);
                route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
                return 0;
        }
 
-       if (style == COMMUNITY_LIST_STANDARD) {
-               if (str)
-                       com = community_str2com(str);
-       }
+       if (style == COMMUNITY_LIST_STANDARD)
+               com = community_str2com(str);
 
        if (com) {
                entry = community_list_entry_lookup(list, com, direct);
-               community_free(com);
+               community_free(&com);
        } else
                entry = community_list_entry_lookup(list, str, direct);
 
        if (!entry)
                return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
 
-       community_list_entry_delete(list, entry, style);
+       community_list_entry_delete(list, entry);
        route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
 
        return 0;
@@ -895,8 +921,8 @@ struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom,
                                                struct community_list *list)
 {
        struct community_entry *entry;
-       u_int32_t com_index_to_delete[lcom->size];
-       u_char *ptr;
+       uint32_t com_index_to_delete[lcom->size];
+       uint8_t *ptr;
        int delete_index = 0;
        int i;
 
@@ -988,13 +1014,8 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name,
        entry->any = (str ? 0 : 1);
        entry->u.lcom = lcom;
        entry->reg = regex;
-       if (lcom)
-               entry->config = lcommunity_lcom2str(
-                       lcom, LCOMMUNITY_FORMAT_COMMUNITY_LIST);
-       else if (regex)
-               entry->config = XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str);
-       else
-               entry->config = NULL;
+       entry->config =
+               (regex ? XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL);
 
        /* Do not put duplicated community entry.  */
        if (community_list_dup_check(list, entry))
@@ -1047,7 +1068,7 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name,
        if (!entry)
                return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
 
-       community_list_entry_delete(list, entry, style);
+       community_list_entry_delete(list, entry);
 
        return 0;
 }
@@ -1061,7 +1082,8 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name,
        struct ecommunity *ecom = NULL;
        regex_t *regex = NULL;
 
-       entry = NULL;
+       if (str == NULL)
+               return COMMUNITY_LIST_ERR_MALFORMED_VAL;
 
        /* Get community list. */
        list = community_list_get(ch, name, EXTCOMMUNITY_LIST_MASTER);
@@ -1096,7 +1118,7 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name,
        entry = community_entry_new();
        entry->direct = direct;
        entry->style = style;
-       entry->any = (str ? 0 : 1);
+       entry->any = 0;
        if (ecom)
                entry->config = ecommunity_ecom2str(
                        ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0);
@@ -1117,11 +1139,13 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name,
        return 0;
 }
 
-/* Unset extcommunity-list.  When str is NULL, delete all of
-   extcommunity-list entry belongs to the specified name.  */
+/* Unset extcommunity-list.
+ *
+ * When str is NULL, delete all extcommunity-list entries belonging to the
+ * specified name.
+ */
 int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
-                           const char *str, int direct, int style,
-                           int delete_all)
+                           const char *str, int direct, int style)
 {
        struct community_entry *entry = NULL;
        struct community_list *list;
@@ -1133,16 +1157,14 @@ int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
                return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
 
        /* Delete all of entry belongs to this extcommunity-list.  */
-       if (delete_all) {
+       if (!str) {
                community_list_delete(list);
                route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
                return 0;
        }
 
-       if (style == EXTCOMMUNITY_LIST_STANDARD) {
-               if (str)
-                       ecom = ecommunity_str2com(str, 0, 1);
-       }
+       if (style == EXTCOMMUNITY_LIST_STANDARD)
+               ecom = ecommunity_str2com(str, 0, 1);
 
        if (ecom) {
                entry = community_list_entry_lookup(list, ecom, direct);
@@ -1153,7 +1175,7 @@ int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
        if (!entry)
                return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
 
-       community_list_entry_delete(list, entry, style);
+       community_list_entry_delete(list, entry);
        route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
 
        return 0;