6 #include <netinet/in.h>
10 #include "interface-ip.h"
23 static const struct blobmsg_policy static_attrs
[__OPT_MAX
] = {
24 [OPT_IPADDR
] = { .name
= "ipaddr", .type
= BLOBMSG_TYPE_ARRAY
},
25 [OPT_IP6ADDR
] = { .name
= "ip6addr", .type
= BLOBMSG_TYPE_ARRAY
},
26 [OPT_NETMASK
] = { .name
= "netmask", .type
= BLOBMSG_TYPE_STRING
},
27 [OPT_GATEWAY
] = { .name
= "gateway", .type
= BLOBMSG_TYPE_STRING
},
28 [OPT_IP6GW
] = { .name
= "ip6gw", .type
= BLOBMSG_TYPE_STRING
},
31 static const union config_param_info static_attr_info
[__OPT_MAX
] = {
32 [OPT_IPADDR
] = { .type
= BLOBMSG_TYPE_STRING
},
33 [OPT_IP6ADDR
] = { .type
= BLOBMSG_TYPE_STRING
},
36 static const struct config_param_list static_attr_list
= {
37 .n_params
= __OPT_MAX
,
38 .params
= static_attrs
,
39 .info
= static_attr_info
,
42 struct static_proto_state
{
43 struct interface_proto_state proto
;
45 struct blob_attr
*config
;
49 split_netmask(char *str
, unsigned int *netmask
)
51 char *delim
, *err
= NULL
;
53 delim
= strchr(str
, '/');
57 *netmask
= strtoul(delim
, &err
, 10);
65 parse_ip_and_netmask(int af
, const char *str
, void *addr
, unsigned int *netmask
)
67 char *astr
= alloca(strlen(str
) + 1);
70 if (!split_netmask(astr
, netmask
))
81 return inet_pton(af
, str
, addr
);
85 parse_addr(struct interface_proto_state
*state
, const char *str
, bool v6
, int mask
)
87 struct device_addr
*addr
;
88 int af
= v6
? AF_INET6
: AF_INET
;
90 addr
= calloc(1, sizeof(*addr
));
91 addr
->flags
= v6
? DEVADDR_INET6
: DEVADDR_INET4
;
94 if (!parse_ip_and_netmask(af
, str
, &addr
->addr
, &addr
->mask
)) {
95 interface_add_error(state
->iface
, "proto-static", "INVALID_ADDRESS", &str
, 1);
99 interface_add_address(state
->iface
, addr
);
104 parse_address_option(struct interface_proto_state
*state
, struct blob_attr
*attr
, bool v6
, int netmask
)
106 struct blob_attr
*cur
;
110 blobmsg_for_each_attr(cur
, attr
, rem
) {
112 if (!parse_addr(state
, blobmsg_data(cur
), v6
, netmask
))
120 parse_gateway_option(struct interface_proto_state
*state
, struct blob_attr
*attr
, bool v6
)
122 struct device_route
*route
;
123 const char *str
= blobmsg_data(attr
);
124 int af
= v6
? AF_INET6
: AF_INET
;
126 route
= calloc(1, sizeof(*route
));
127 if (!inet_pton(af
, str
, &route
->nexthop
)) {
128 interface_add_error(state
->iface
, "proto-static",
129 "INVALID_GATEWAY", &str
, 1);
134 route
->flags
= DEVADDR_DEVICE
| (v6
? DEVADDR_INET6
: DEVADDR_INET4
);
135 interface_add_route(state
->iface
, route
);
141 proto_apply_static_settings(struct interface_proto_state
*state
, struct blob_attr
*attr
)
143 struct blob_attr
*tb
[__OPT_MAX
];
147 int n_v4
= 0, n_v6
= 0;
149 blobmsg_parse(static_attrs
, __OPT_MAX
, tb
, blob_data(attr
), blob_len(attr
));
151 if (tb
[OPT_NETMASK
]) {
152 if (!inet_aton(blobmsg_data(tb
[OPT_NETMASK
]), &ina
)) {
153 error
= "INVALID_NETMASK";
157 netmask
= 32 - fls(~(ntohl(ina
.s_addr
)));
161 n_v4
= parse_address_option(state
, tb
[OPT_IPADDR
], false, netmask
);
164 n_v6
= parse_address_option(state
, tb
[OPT_IP6ADDR
], true, netmask
);
166 if (!n_v4
&& !n_v6
) {
167 error
= "NO_ADDRESS";
171 if (n_v4
< 0 || n_v6
< 0)
174 if (n_v4
&& tb
[OPT_GATEWAY
]) {
175 if (!parse_gateway_option(state
, tb
[OPT_GATEWAY
], false))
179 if (n_v6
&& tb
[OPT_IP6GW
]) {
180 if (!parse_gateway_option(state
, tb
[OPT_IP6GW
], true))
187 interface_add_error(state
->iface
, "proto-static", error
, NULL
, 0);
193 static_proto_setup(struct static_proto_state
*state
)
195 return proto_apply_static_settings(&state
->proto
, state
->config
) == 0;
199 static_handler(struct interface_proto_state
*proto
,
200 enum interface_proto_cmd cmd
, bool force
)
202 struct static_proto_state
*state
;
205 state
= container_of(proto
, struct static_proto_state
, proto
);
208 case PROTO_CMD_SETUP
:
209 if (static_proto_setup(state
))
213 case PROTO_CMD_TEARDOWN
:
214 interface_del_ctx_addr(state
->proto
.iface
, proto
);
221 static_free(struct interface_proto_state
*proto
)
223 struct static_proto_state
*state
;
225 state
= container_of(proto
, struct static_proto_state
, proto
);
230 struct interface_proto_state
*
231 static_attach(const struct proto_handler
*h
, struct interface
*iface
,
232 struct blob_attr
*attr
)
234 struct static_proto_state
*state
;
236 state
= calloc(1, sizeof(*state
));
240 state
->config
= malloc(blob_pad_len(attr
));
244 memcpy(state
->config
, attr
, blob_pad_len(attr
));
245 state
->proto
.free
= static_free
;
246 state
->proto
.handler
= static_handler
;
247 state
->proto
.flags
= PROTO_FLAG_IMMEDIATE
;
249 return &state
->proto
;
256 static struct proto_handler static_proto
= {
258 .config_params
= &static_attr_list
,
259 .attach
= static_attach
,
263 static_proto_init(void)
265 add_proto_handler(&static_proto
);