6 #include <netinet/in.h>
13 struct static_proto_state {
14 struct interface_proto_state proto;
16 struct uci_section *section;
17 struct interface *iface;
21 split_netmask(char *str, unsigned int *netmask)
23 char *delim, *err = NULL;
25 delim = strchr(str, '/');
29 *netmask = strtoul(delim, &err, 10);
37 parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netmask)
39 char *astr = alloca(strlen(str) + 1);
42 if (!split_netmask(astr, netmask))
53 return inet_pton(af, str, addr);
57 parse_addr(struct static_proto_state *state, const char *str, bool v6, int mask)
59 struct device_addr *addr;
60 int af = v6 ? AF_INET6 : AF_INET;
62 addr = calloc(1, sizeof(*addr));
63 addr->flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4;
66 if (!parse_ip_and_netmask(af, str, &addr->addr, &addr->mask)) {
67 interface_add_error(state->iface, "proto-static", "INVALID_ADDRESS", &str, 1);
71 interface_add_address(state->iface, addr);
76 parse_address_option(struct static_proto_state *state, struct uci_option *o, bool v6, int netmask)
78 struct uci_element *e;
81 if (o->type == UCI_TYPE_STRING) {
83 if (!parse_addr(state, o->v.string, v6, netmask))
86 uci_foreach_element(&o->v.list, e) {
88 if (!parse_addr(state, e->name, v6, netmask))
105 static const struct uci_parse_option opts[__OPT_MAX] = {
106 [OPT_IPADDR] = { .name = "ipaddr" },
107 [OPT_IP6ADDR] = { .name = "ip6addr" },
108 [OPT_NETMASK] = { .name = "netmask", .type = UCI_TYPE_STRING },
109 [OPT_GATEWAY] = { .name = "gateway", .type = UCI_TYPE_STRING },
110 [OPT_IP6GW] = { .name = "ip6gw", .type = UCI_TYPE_STRING },
114 static_proto_setup(struct static_proto_state *state)
116 struct uci_option *tb[__OPT_MAX];
120 int n_v4 = 0, n_v6 = 0;
122 uci_parse_section(state->section, opts, __OPT_MAX, tb);
124 if (tb[OPT_NETMASK]) {
125 if (!inet_aton(tb[OPT_NETMASK]->v.string, &ina)) {
126 error = "INVALID_NETMASK";
130 netmask = 32 - fls(~(ntohl(ina.s_addr)));
134 n_v4 = parse_address_option(state, tb[OPT_IPADDR], false, netmask);
137 n_v6 = parse_address_option(state, tb[OPT_IP6ADDR], true, netmask);
139 if (!n_v4 && !n_v6) {
140 error = "NO_ADDRESS";
144 if (n_v4 < 0 || n_v6 < 0)
148 if (ps.n_v4 && tb[OPT_GATEWAY]) {
149 if (!inet_pton(AF_INET, tb[OPT_GATEWAY]->v.string, &ps.ipv4gw)) {
150 error = "INVALID_GATEWAY";
153 ps.flags |= STATIC_F_IPV4GW;
156 if (ps.n_v6 && tb[OPT_IP6GW]) {
157 if (!inet_pton(AF_INET6, tb[OPT_IP6GW]->v.string, &ps.ipv6gw)) {
158 error = "INVALID_GATEWAY";
161 ps.flags |= STATIC_F_IPV6GW;
168 interface_add_error(state->iface, "proto-static", error, NULL, 0);
174 static_handler(struct interface_proto_state *proto,
175 enum interface_proto_cmd cmd, bool force)
177 struct static_proto_state *state;
180 state = container_of(proto, struct static_proto_state, proto);
183 case PROTO_CMD_SETUP:
184 if (static_proto_setup(state))
188 case PROTO_CMD_TEARDOWN:
189 interface_del_ctx_addr(state->iface, state);
196 static_free(struct interface_proto_state *proto)
198 struct static_proto_state *state;
200 state = container_of(proto, struct static_proto_state, proto);
204 struct interface_proto_state *
205 static_attach(struct proto_handler *h, struct interface *iface,
206 struct uci_section *s)
208 struct static_proto_state *state;
210 state = calloc(1, sizeof(*state));
211 state->iface = iface;
213 state->proto.free = static_free;
214 state->proto.handler = static_handler;
215 state->proto.flags = PROTO_FLAG_IMMEDIATE;
217 return &state->proto;
220 static struct proto_handler static_proto = {
222 .attach = static_attach,
226 static_proto_init(void)
228 add_proto_handler(&static_proto);