summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--iprule.c29
-rw-r--r--iprule.h20
2 files changed, 38 insertions, 11 deletions
diff --git a/iprule.c b/iprule.c
index 3e57888..c3a629f 100644
--- a/iprule.c
+++ b/iprule.c
@@ -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)
diff --git a/iprule.h b/iprule.h
index f05c3c9..89b94b4 100644
--- a/iprule.h
+++ b/iprule.h
@@ -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;