-split_netmask(char *str, unsigned int *netmask)
-{
- char *delim, *err = NULL;
-
- delim = strchr(str, '/');
- if (delim) {
- *(delim++) = 0;
-
- *netmask = strtoul(delim, &err, 10);
- if (err && *err)
- return false;
- }
- return true;
-}
-
-static int
-parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netmask)
-{
- char *astr = alloca(strlen(str) + 1);
-
- strcpy(astr, str);
- if (!split_netmask(astr, netmask))
- return 0;
-
- if (af == AF_INET6) {
- if (*netmask > 128)
- return 0;
- } else {
- if (*netmask > 32)
- return 0;
- }
-
- return inet_pton(af, str, addr);
-}
-
-static bool
-parse_addr(struct interface *iface, const char *str, bool v6, int mask)
-{
- struct device_addr *addr;
- int af = v6 ? AF_INET6 : AF_INET;
-
- addr = calloc(1, sizeof(*addr));
- addr->flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4;
- addr->mask = mask;
- if (!parse_ip_and_netmask(af, str, &addr->addr, &addr->mask)) {
- interface_add_error(iface, "proto-static", "INVALID_ADDRESS", &str, 1);
- free(addr);
- return false;
- }
- vlist_add(&iface->proto_addr, &addr->node);
- return true;
-}
-
-static int
-parse_address_option(struct interface *iface, struct blob_attr *attr, bool v6, int netmask)
-{
- struct blob_attr *cur;
- int n_addr = 0;
- int rem;
-
- blobmsg_for_each_attr(cur, attr, rem) {
- n_addr++;
- if (!parse_addr(iface, blobmsg_data(cur), v6, netmask))
- return -1;
- }
-
- return n_addr;
-}
-
-static bool
-parse_gateway_option(struct interface *iface, struct blob_attr *attr, bool v6)
-{
- struct device_route *route;
- const char *str = blobmsg_data(attr);
- int af = v6 ? AF_INET6 : AF_INET;
-
- route = calloc(1, sizeof(*route));
- if (!inet_pton(af, str, &route->nexthop)) {
- interface_add_error(iface, "proto-static",
- "INVALID_GATEWAY", &str, 1);
- free(route);
- return false;
- }
- route->mask = 0;
- route->flags = DEVADDR_DEVICE | (v6 ? DEVADDR_INET6 : DEVADDR_INET4);
- vlist_add(&iface->proto_route, &route->node);
-
- return true;
-}
-
-static int
-proto_apply_static_settings(struct interface *iface, struct blob_attr *attr)
-{
- struct blob_attr *tb[__OPT_MAX];
- struct in_addr ina;
- const char *error;
- int netmask = 32;
- int n_v4 = 0, n_v6 = 0;
-
- blobmsg_parse(static_attrs, __OPT_MAX, tb, blob_data(attr), blob_len(attr));
-
- if (tb[OPT_NETMASK]) {
- if (!inet_aton(blobmsg_data(tb[OPT_NETMASK]), &ina)) {
- error = "INVALID_NETMASK";
- goto error;
- }
-
- netmask = 32 - fls(~(ntohl(ina.s_addr)));
- }
-
- if (tb[OPT_IPADDR])
- n_v4 = parse_address_option(iface, tb[OPT_IPADDR], false, netmask);
-
- if (tb[OPT_IP6ADDR])
- n_v6 = parse_address_option(iface, tb[OPT_IP6ADDR], true, netmask);
-
- if (!n_v4 && !n_v6) {
- error = "NO_ADDRESS";
- goto error;
- }
-
- if (n_v4 < 0 || n_v6 < 0)
- goto out;
-
- if (n_v4 && tb[OPT_GATEWAY]) {
- if (!parse_gateway_option(iface, tb[OPT_GATEWAY], false))
- goto out;
- }
-
- if (n_v6 && tb[OPT_IP6GW]) {
- if (!parse_gateway_option(iface, tb[OPT_IP6GW], true))
- goto out;
- }
-
- return 0;
-
-error:
- interface_add_error(iface, "proto-static", error, NULL, 0);
-out:
- return -1;
-}
-
-static bool