diff options
-rw-r--r-- | iprule.c | 29 | ||||
-rw-r--r-- | iprule.h | 20 |
2 files changed, 38 insertions, 11 deletions
@@ -290,7 +290,7 @@ iprule_add(struct blob_attr *attr, bool v6) rule->flags |= IPRULE_GOTO; } - vlist_add(&iprules, &rule->node, &rule->flags); + vlist_add(&iprules, &rule->node, rule); return; error: @@ -320,7 +320,32 @@ iprule_update_complete(void) static int rule_cmp(const void *k1, const void *k2, void *ptr) { - return memcmp(k1, k2, sizeof(struct iprule)-offsetof(struct iprule, flags)); + const struct iprule *r1 = k1, *r2 = k2; + int ret; + + /* First compare the interface names */ + if (r1->flags & IPRULE_IN || r2->flags & IPRULE_IN) { + char *str1 = r1->flags & IPRULE_IN ? r1->in_iface : ""; + char *str2 = r2->flags & IPRULE_IN ? r2->in_iface : ""; + + ret = strcmp(str1, str2); + if (ret) + return ret; + } + + if (r1->flags & IPRULE_OUT || r2->flags & IPRULE_OUT) { + char *str1 = r1->flags & IPRULE_OUT ? r1->out_iface : ""; + char *str2 = r2->flags & IPRULE_OUT ? r2->out_iface : ""; + + ret = strcmp(str1, str2); + if (ret) + return ret; + } + + /* Next compare everything after the flags field */ + return memcmp(k1 + offsetof(struct iprule, flags), + k2 + offsetof(struct iprule, flags), + sizeof(struct iprule) - offsetof(struct iprule, flags)); } static void deregister_interfaces(struct iprule *rule) @@ -69,15 +69,6 @@ struct iprule { struct vlist_node node; unsigned int order; - /* everything below is used as avl tree key */ - enum iprule_flags flags; - - bool invert; - - /* uci interface name */ - char *in_iface; - char *out_iface; - /* to receive interface events */ struct interface_user in_iface_user; struct interface_user out_iface_user; @@ -86,6 +77,17 @@ struct iprule { char in_dev[IFNAMSIZ + 1]; char out_dev[IFNAMSIZ + 1]; + /* everything below is used as avl tree key */ + /* don't change the order */ + + /* uci interface name */ + char *in_iface; + char *out_iface; + + enum iprule_flags flags; + + bool invert; + unsigned int src_mask; union if_addr src_addr; |