diff options
-rw-r--r-- | device.c | 50 | ||||
-rw-r--r-- | device.h | 15 | ||||
-rw-r--r-- | system-linux.c | 91 |
3 files changed, 156 insertions, 0 deletions
@@ -54,6 +54,11 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_SENDREDIRECTS] = { .name = "sendredirects", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_NEIGHLOCKTIME] = { .name = "neighlocktime", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_ISOLATE] = { .name = "isolate", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_DROP_V4_UNICAST_IN_L2_MULTICAST] = { .name = "drop_v4_unicast_in_l2_multicast", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_DROP_V6_UNICAST_IN_L2_MULTICAST] = { .name = "drop_v6_unicast_in_l2_multicast", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_DROP_GRATUITOUS_ARP] = { .name = "drop_gratuitous_arp", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_DROP_UNSOLICITED_NA] = { .name = "drop_unsolicited_na", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_ARP_ACCEPT] = { .name = "arp_accept", .type = BLOBMSG_TYPE_BOOL }, }; const struct uci_blob_param_list device_attr_list = { @@ -255,6 +260,16 @@ device_merge_settings(struct device *dev, struct device_settings *n) n->unicast_flood = s->unicast_flood; n->sendredirects = s->flags & DEV_OPT_SENDREDIRECTS ? s->sendredirects : os->sendredirects; + n->drop_v4_unicast_in_l2_multicast = s->flags & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST ? + s->drop_v4_unicast_in_l2_multicast : os->drop_v4_unicast_in_l2_multicast; + n->drop_v6_unicast_in_l2_multicast = s->flags & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST ? + s->drop_v6_unicast_in_l2_multicast : os->drop_v6_unicast_in_l2_multicast; + n->drop_gratuitous_arp = s->flags & DEV_OPT_DROP_GRATUITOUS_ARP ? + s->drop_gratuitous_arp : os->drop_gratuitous_arp; + n->drop_unsolicited_na = s->flags & DEV_OPT_DROP_UNSOLICITED_NA ? + s->drop_unsolicited_na : os->drop_unsolicited_na; + n->arp_accept = s->flags & DEV_OPT_ARP_ACCEPT ? + s->arp_accept : os->arp_accept; n->flags = s->flags | os->flags | os->valid_flags; } @@ -399,6 +414,31 @@ device_init_settings(struct device *dev, struct blob_attr **tb) s->flags |= DEV_OPT_ISOLATE; } + if ((cur = tb[DEV_ATTR_DROP_V4_UNICAST_IN_L2_MULTICAST])) { + s->drop_v4_unicast_in_l2_multicast = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST; + } + + if ((cur = tb[DEV_ATTR_DROP_V6_UNICAST_IN_L2_MULTICAST])) { + s->drop_v6_unicast_in_l2_multicast = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST; + } + + if ((cur = tb[DEV_ATTR_DROP_GRATUITOUS_ARP])) { + s->drop_gratuitous_arp = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_DROP_GRATUITOUS_ARP; + } + + if ((cur = tb[DEV_ATTR_DROP_UNSOLICITED_NA])) { + s->drop_unsolicited_na = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_DROP_UNSOLICITED_NA; + } + + if ((cur = tb[DEV_ATTR_ARP_ACCEPT])) { + s->arp_accept = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_ARP_ACCEPT; + } + device_set_disabled(dev, disabled); } @@ -1107,6 +1147,16 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_u8(b, "unicast_flood", st.unicast_flood); if (st.flags & DEV_OPT_SENDREDIRECTS) blobmsg_add_u8(b, "sendredirects", st.sendredirects); + if (st.flags & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST) + blobmsg_add_u8(b, "drop_v4_unicast_in_l2_multicast", st.drop_v4_unicast_in_l2_multicast); + if (st.flags & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST) + blobmsg_add_u8(b, "drop_v6_unicast_in_l2_multicast", st.drop_v6_unicast_in_l2_multicast); + if (st.flags & DEV_OPT_DROP_GRATUITOUS_ARP) + blobmsg_add_u8(b, "drop_gratuitous_arp", st.drop_gratuitous_arp); + if (st.flags & DEV_OPT_DROP_UNSOLICITED_NA) + blobmsg_add_u8(b, "drop_unsolicited_na", st.drop_unsolicited_na); + if (st.flags & DEV_OPT_ARP_ACCEPT) + blobmsg_add_u8(b, "arp_accept", st.arp_accept); } s = blobmsg_open_table(b, "statistics"); @@ -54,6 +54,11 @@ enum { DEV_ATTR_NEIGHLOCKTIME, DEV_ATTR_ISOLATE, DEV_ATTR_IP6SEGMENTROUTING, + DEV_ATTR_DROP_V4_UNICAST_IN_L2_MULTICAST, + DEV_ATTR_DROP_V6_UNICAST_IN_L2_MULTICAST, + DEV_ATTR_DROP_GRATUITOUS_ARP, + DEV_ATTR_DROP_UNSOLICITED_NA, + DEV_ATTR_ARP_ACCEPT, __DEV_ATTR_MAX, }; @@ -109,6 +114,11 @@ enum { DEV_OPT_NEIGHLOCKTIME = (1 << 22), DEV_OPT_ISOLATE = (1 << 23), DEV_OPT_IP6SEGMENTROUTING = (1 << 24), + DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST = (1 << 25), + DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST = (1 << 26), + DEV_OPT_DROP_GRATUITOUS_ARP = (1 << 27), + DEV_OPT_DROP_UNSOLICITED_NA = (1 << 28), + DEV_OPT_ARP_ACCEPT = (1 << 29), }; /* events broadcasted to all users of a device */ @@ -177,6 +187,11 @@ struct device_settings { bool sendredirects; bool ip6segmentrouting; bool isolate; + bool drop_v4_unicast_in_l2_multicast; + bool drop_v6_unicast_in_l2_multicast; + bool drop_gratuitous_arp; + bool drop_unsolicited_na; + bool arp_accept; }; /* diff --git a/system-linux.c b/system-linux.c index 0a6b0d2..b9e440e 100644 --- a/system-linux.c +++ b/system-linux.c @@ -364,6 +364,31 @@ static void system_set_sendredirects(struct device *dev, const char *val) system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val); } +static void system_set_drop_v4_unicast_in_l2_multicast(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/drop_unicast_in_l2_multicast", dev->ifname, val); +} + +static void system_set_drop_v6_unicast_in_l2_multicast(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/drop_unicast_in_l2_multicast", dev->ifname, val); +} + +static void system_set_drop_gratuitous_arp(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp", dev->ifname, val); +} + +static void system_set_drop_unsolicited_na(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na", dev->ifname, val); +} + +static void system_set_arp_accept(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/arp_accept", dev->ifname, val); +} + static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val) { system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val); @@ -586,6 +611,37 @@ static int system_get_sendredirects(struct device *dev, char *buf, const size_t dev->ifname, buf, buf_sz); } + +static int system_get_drop_v4_unicast_in_l2_multicast(struct device *dev, char *buf, const size_t buf_sz) +{ + return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/drop_unicast_in_l2_multicast", + dev->ifname, buf, buf_sz); +} + +static int system_get_drop_v6_unicast_in_l2_multicast(struct device *dev, char *buf, const size_t buf_sz) +{ + return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/drop_unicast_in_l2_multicast", + dev->ifname, buf, buf_sz); +} + +static int system_get_drop_gratuitous_arp(struct device *dev, char *buf, const size_t buf_sz) +{ + return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp", + dev->ifname, buf, buf_sz); +} + +static int system_get_drop_unsolicited_na(struct device *dev, char *buf, const size_t buf_sz) +{ + return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na", + dev->ifname, buf, buf_sz); +} + +static int system_get_arp_accept(struct device *dev, char *buf, const size_t buf_sz) +{ + return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/arp_accept", + dev->ifname, buf, buf_sz); +} + /* Evaluate netlink messages */ static int cb_rtnl_event(struct nl_msg *msg, void *arg) { @@ -1650,6 +1706,31 @@ system_if_get_settings(struct device *dev, struct device_settings *s) s->sendredirects = strtoul(buf, NULL, 0); s->flags |= DEV_OPT_SENDREDIRECTS; } + + if (!system_get_drop_v4_unicast_in_l2_multicast(dev, buf, sizeof(buf))) { + s->drop_v4_unicast_in_l2_multicast = strtoul(buf, NULL, 0); + s->flags |= DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST; + } + + if (!system_get_drop_v6_unicast_in_l2_multicast(dev, buf, sizeof(buf))) { + s->drop_v6_unicast_in_l2_multicast = strtoul(buf, NULL, 0); + s->flags |= DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST; + } + + if (!system_get_drop_gratuitous_arp(dev, buf, sizeof(buf))) { + s->drop_gratuitous_arp = strtoul(buf, NULL, 0); + s->flags |= DEV_OPT_DROP_GRATUITOUS_ARP; + } + + if (!system_get_drop_unsolicited_na(dev, buf, sizeof(buf))) { + s->drop_unsolicited_na = strtoul(buf, NULL, 0); + s->flags |= DEV_OPT_DROP_UNSOLICITED_NA; + } + + if (!system_get_arp_accept(dev, buf, sizeof(buf))) { + s->arp_accept = strtoul(buf, NULL, 0); + s->flags |= DEV_OPT_ARP_ACCEPT; + } } void @@ -1738,6 +1819,16 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned } if (apply_mask & DEV_OPT_SENDREDIRECTS) system_set_sendredirects(dev, s->sendredirects ? "1" : "0"); + if (apply_mask & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST) + system_set_drop_v4_unicast_in_l2_multicast(dev, s->drop_v4_unicast_in_l2_multicast ? "1" : "0"); + if (apply_mask & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST) + system_set_drop_v6_unicast_in_l2_multicast(dev, s->drop_v6_unicast_in_l2_multicast ? "1" : "0"); + if (apply_mask & DEV_OPT_DROP_GRATUITOUS_ARP) + system_set_drop_gratuitous_arp(dev, s->drop_gratuitous_arp ? "1" : "0"); + if (apply_mask & DEV_OPT_DROP_UNSOLICITED_NA) + system_set_drop_unsolicited_na(dev, s->drop_unsolicited_na ? "1" : "0"); + if (apply_mask & DEV_OPT_ARP_ACCEPT) + system_set_arp_accept(dev, s->arp_accept ? "1" : "0"); } int system_if_up(struct device *dev) |