2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
18 #include <arpa/inet.h>
19 #include <netinet/in.h>
23 #include "interface.h"
24 #include "interface-ip.h"
27 static struct avl_tree handlers
;
41 static const struct blobmsg_policy proto_ip_attributes
[__OPT_MAX
] = {
42 [OPT_IPADDR
] = { .name
= "ipaddr", .type
= BLOBMSG_TYPE_ARRAY
},
43 [OPT_IP6ADDR
] = { .name
= "ip6addr", .type
= BLOBMSG_TYPE_ARRAY
},
44 [OPT_NETMASK
] = { .name
= "netmask", .type
= BLOBMSG_TYPE_STRING
},
45 [OPT_BROADCAST
] = { .name
= "broadcast", .type
= BLOBMSG_TYPE_STRING
},
46 [OPT_GATEWAY
] = { .name
= "gateway", .type
= BLOBMSG_TYPE_STRING
},
47 [OPT_IP6GW
] = { .name
= "ip6gw", .type
= BLOBMSG_TYPE_STRING
},
48 [OPT_IP6PREFIX
] = { .name
= "ip6prefix", .type
= BLOBMSG_TYPE_ARRAY
},
49 [OPT_IP6ASSIGN
] = { .name
= "ip6assign", .type
= BLOBMSG_TYPE_INT32
},
52 static const union config_param_info proto_ip_attr_info
[__OPT_MAX
] = {
53 [OPT_IPADDR
] = { .type
= BLOBMSG_TYPE_STRING
},
54 [OPT_IP6ADDR
] = { .type
= BLOBMSG_TYPE_STRING
},
55 [OPT_IP6PREFIX
] = { .type
= BLOBMSG_TYPE_STRING
},
58 const struct config_param_list proto_ip_attr
= {
59 .n_params
= __OPT_MAX
,
60 .params
= proto_ip_attributes
,
61 .info
= proto_ip_attr_info
,
72 static const struct blobmsg_policy proto_ip_addr
[__ADDR_MAX
] = {
73 [ADDR_IPADDR
] = { .name
= "ipaddr", .type
= BLOBMSG_TYPE_STRING
},
74 [ADDR_MASK
] = { .name
= "mask", .type
= BLOBMSG_TYPE_STRING
},
75 [ADDR_BROADCAST
] = { .name
= "broadcast", .type
= BLOBMSG_TYPE_STRING
},
76 [ADDR_PTP
] = { .name
= "ptp", .type
= BLOBMSG_TYPE_STRING
},
79 static struct device_addr
*
80 alloc_device_addr(bool v6
, bool ext
)
82 struct device_addr
*addr
;
84 addr
= calloc(1, sizeof(*addr
));
85 addr
->flags
= v6
? DEVADDR_INET6
: DEVADDR_INET4
;
87 addr
->flags
|= DEVADDR_EXTERNAL
;
93 parse_addr(struct interface
*iface
, const char *str
, bool v6
, int mask
,
94 bool ext
, uint32_t broadcast
)
96 struct device_addr
*addr
;
97 int af
= v6
? AF_INET6
: AF_INET
;
99 addr
= alloc_device_addr(v6
, ext
);
104 if (!parse_ip_and_netmask(af
, str
, &addr
->addr
, &addr
->mask
)) {
105 interface_add_error(iface
, "proto", "INVALID_ADDRESS", &str
, 1);
111 addr
->broadcast
= broadcast
;
113 vlist_add(&iface
->proto_ip
.addr
, &addr
->node
, &addr
->flags
);
118 parse_static_address_option(struct interface
*iface
, struct blob_attr
*attr
,
119 bool v6
, int netmask
, bool ext
, uint32_t broadcast
)
121 struct blob_attr
*cur
;
125 blobmsg_for_each_attr(cur
, attr
, rem
) {
126 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
130 if (!parse_addr(iface
, blobmsg_data(cur
), v6
, netmask
, ext
,
138 static struct device_addr
*
139 parse_address_item(struct blob_attr
*attr
, bool v6
, bool ext
)
141 struct device_addr
*addr
;
142 struct blob_attr
*tb
[__ADDR_MAX
];
143 struct blob_attr
*cur
;
145 if (blobmsg_type(attr
) != BLOBMSG_TYPE_TABLE
)
148 addr
= alloc_device_addr(v6
, ext
);
152 blobmsg_parse(proto_ip_addr
, __ADDR_MAX
, tb
, blobmsg_data(attr
), blobmsg_data_len(attr
));
154 addr
->mask
= v6
? 128 : 32;
155 if ((cur
= tb
[ADDR_MASK
])) {
156 unsigned int new_mask
;
158 new_mask
= parse_netmask_string(blobmsg_data(cur
), v6
);
159 if (new_mask
> addr
->mask
)
162 addr
->mask
= new_mask
;
165 cur
= tb
[ADDR_IPADDR
];
169 if (!inet_pton(v6
? AF_INET6
: AF_INET
, blobmsg_data(cur
), &addr
->addr
))
173 if ((cur
= tb
[ADDR_BROADCAST
]) &&
174 !inet_pton(AF_INET
, blobmsg_data(cur
), &addr
->broadcast
))
176 if ((cur
= tb
[ADDR_PTP
]) &&
177 !inet_pton(AF_INET
, blobmsg_data(cur
), &addr
->point_to_point
))
189 parse_address_list(struct interface
*iface
, struct blob_attr
*attr
, bool v6
,
192 struct device_addr
*addr
;
193 struct blob_attr
*cur
;
197 blobmsg_for_each_attr(cur
, attr
, rem
) {
198 addr
= parse_address_item(cur
, v6
, ext
);
203 vlist_add(&iface
->proto_ip
.addr
, &addr
->node
, &addr
->flags
);
210 parse_gateway_option(struct interface
*iface
, struct blob_attr
*attr
, bool v6
)
212 struct device_route
*route
;
213 const char *str
= blobmsg_data(attr
);
214 int af
= v6
? AF_INET6
: AF_INET
;
216 route
= calloc(1, sizeof(*route
));
217 if (!inet_pton(af
, str
, &route
->nexthop
)) {
218 interface_add_error(iface
, "proto", "INVALID_GATEWAY", &str
, 1);
224 route
->flags
= (v6
? DEVADDR_INET6
: DEVADDR_INET4
);
225 vlist_add(&iface
->proto_ip
.route
, &route
->node
, &route
->flags
);
231 parse_ip6assign_option(struct interface
*iface
, struct blob_attr
*attr
)
233 uint8_t oldval
= iface
->proto_ip
.assignment_length
;
234 uint8_t newval
= blobmsg_get_u32(attr
);
236 struct device_prefix
*prefix
;
237 list_for_each_entry(prefix
, &prefixes
, head
) {
238 if (oldval
&& oldval
!= newval
)
239 interface_ip_set_prefix_assignment(prefix
, iface
, 0);
241 if (newval
&& newval
<= 64)
242 interface_ip_set_prefix_assignment(prefix
, iface
, newval
);
245 iface
->proto_ip
.assignment_length
= newval
;
250 parse_prefix_option(struct interface
*iface
, const char *str
, size_t len
)
252 char buf
[128] = {0}, *saveptr
;
253 if (len
> sizeof(buf
))
256 memcpy(buf
, str
, len
);
257 char *addrstr
= strtok_r(buf
, "/", &saveptr
);
261 char *lengthstr
= strtok_r(NULL
, ",", &saveptr
);
265 char *prefstr
= strtok_r(NULL
, ",", &saveptr
);
266 char *validstr
= (!prefstr
) ? NULL
: strtok_r(NULL
, ",", &saveptr
);
268 uint32_t pref
= (!prefstr
) ? 0 : strtoul(prefstr
, NULL
, 10);
269 uint32_t valid
= (!validstr
) ? 0 : strtoul(validstr
, NULL
, 10);
271 uint8_t length
= strtoul(lengthstr
, NULL
, 10);
272 if (length
< 1 || length
> 64)
275 struct in6_addr addr
;
276 if (inet_pton(AF_INET6
, addrstr
, &addr
) < 1)
279 time_t now
= system_get_rtime();
280 time_t preferred_until
= 0;
281 if (prefstr
&& pref
!= 0xffffffffU
)
282 preferred_until
= pref
+ now
;
284 time_t valid_until
= 0;
285 if (validstr
&& valid
!= 0xffffffffU
)
286 valid_until
= valid
+ now
;
288 interface_ip_add_device_prefix(iface
, &addr
, length
,
289 valid_until
, preferred_until
);
294 parse_prefix_list(struct interface
*iface
, struct blob_attr
*attr
)
296 struct blob_attr
*cur
;
300 blobmsg_for_each_attr(cur
, attr
, rem
) {
301 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
305 if (!parse_prefix_option(iface
, blobmsg_data(cur
),
306 blobmsg_data_len(cur
)))
314 proto_apply_static_ip_settings(struct interface
*iface
, struct blob_attr
*attr
)
316 struct blob_attr
*tb
[__OPT_MAX
];
317 struct blob_attr
*cur
;
319 unsigned int netmask
= 32;
320 int n_v4
= 0, n_v6
= 0;
321 struct in_addr bcast
= {};
323 blobmsg_parse(proto_ip_attributes
, __OPT_MAX
, tb
, blob_data(attr
), blob_len(attr
));
325 if ((cur
= tb
[OPT_NETMASK
])) {
326 netmask
= parse_netmask_string(blobmsg_data(cur
), false);
328 error
= "INVALID_NETMASK";
333 if ((cur
= tb
[OPT_BROADCAST
])) {
334 if (!inet_pton(AF_INET
, blobmsg_data(cur
), &bcast
)) {
335 error
= "INVALID_BROADCAST";
340 if ((cur
= tb
[OPT_IPADDR
]))
341 n_v4
= parse_static_address_option(iface
, cur
, false,
342 netmask
, false, bcast
.s_addr
);
344 if ((cur
= tb
[OPT_IP6ADDR
]))
345 n_v6
= parse_static_address_option(iface
, cur
, true,
348 if ((cur
= tb
[OPT_IP6PREFIX
]))
349 if (parse_prefix_list(iface
, cur
) < 0)
352 if (n_v4
< 0 || n_v6
< 0)
355 if ((cur
= tb
[OPT_GATEWAY
])) {
356 if (n_v4
&& !parse_gateway_option(iface
, cur
, false))
360 if ((cur
= tb
[OPT_IP6GW
])) {
361 if (n_v6
&& !parse_gateway_option(iface
, cur
, true))
365 if ((cur
= tb
[OPT_IP6ASSIGN
]))
366 if (!parse_ip6assign_option(iface
, cur
))
372 interface_add_error(iface
, "proto", error
, NULL
, 0);
378 proto_apply_ip_settings(struct interface
*iface
, struct blob_attr
*attr
, bool ext
)
380 struct blob_attr
*tb
[__OPT_MAX
];
381 struct blob_attr
*cur
;
382 int n_v4
= 0, n_v6
= 0;
384 blobmsg_parse(proto_ip_attributes
, __OPT_MAX
, tb
, blob_data(attr
), blob_len(attr
));
386 if ((cur
= tb
[OPT_IPADDR
]))
387 n_v4
= parse_address_list(iface
, cur
, false, ext
);
389 if ((cur
= tb
[OPT_IP6ADDR
]))
390 n_v6
= parse_address_list(iface
, cur
, true, ext
);
392 if ((cur
= tb
[OPT_IP6PREFIX
]))
393 if (parse_prefix_list(iface
, cur
) < 0)
396 if (n_v4
< 0 || n_v6
< 0)
399 if ((cur
= tb
[OPT_GATEWAY
])) {
400 if (n_v4
&& !parse_gateway_option(iface
, cur
, false))
404 if ((cur
= tb
[OPT_IP6GW
])) {
405 if (n_v6
&& !parse_gateway_option(iface
, cur
, true))
409 if ((cur
= tb
[OPT_IP6ASSIGN
]))
410 if (!parse_ip6assign_option(iface
, cur
))
419 void add_proto_handler(struct proto_handler
*p
)
422 avl_init(&handlers
, avl_strcmp
, false, NULL
);
427 p
->avl
.key
= p
->name
;
428 avl_insert(&handlers
, &p
->avl
);
432 default_proto_free(struct interface_proto_state
*proto
)
438 invalid_proto_handler(struct interface_proto_state
*proto
,
439 enum interface_proto_cmd cmd
, bool force
)
445 no_proto_handler(struct interface_proto_state
*proto
,
446 enum interface_proto_cmd cmd
, bool force
)
451 static struct interface_proto_state
*
452 default_proto_attach(const struct proto_handler
*h
,
453 struct interface
*iface
, struct blob_attr
*attr
)
455 struct interface_proto_state
*proto
;
457 proto
= calloc(1, sizeof(*proto
));
458 proto
->free
= default_proto_free
;
459 proto
->cb
= no_proto_handler
;
464 static const struct proto_handler no_proto
= {
466 .flags
= PROTO_FLAG_IMMEDIATE
,
467 .attach
= default_proto_attach
,
470 static const struct proto_handler
*
471 get_proto_handler(const char *name
)
473 struct proto_handler
*proto
;
475 if (!strcmp(name
, "none"))
481 return avl_find_element(&handlers
, name
, proto
, avl
);
485 proto_dump_handlers(struct blob_buf
*b
)
487 struct proto_handler
*p
;
490 avl_for_each_element(&handlers
, p
, avl
) {
491 c
= blobmsg_open_table(b
, p
->name
);
492 blobmsg_add_u8(b
, "no_device", !!(p
->flags
& PROTO_FLAG_NODEV
));
493 blobmsg_close_table(b
, c
);
498 proto_init_interface(struct interface
*iface
, struct blob_attr
*attr
)
500 const struct proto_handler
*proto
= iface
->proto_handler
;
501 struct interface_proto_state
*state
= NULL
;
506 state
= proto
->attach(proto
, iface
, attr
);
508 state
= no_proto
.attach(&no_proto
, iface
, attr
);
509 state
->cb
= invalid_proto_handler
;
512 state
->handler
= proto
;
513 interface_set_proto_state(iface
, state
);
517 proto_attach_interface(struct interface
*iface
, const char *proto_name
)
519 const struct proto_handler
*proto
= &no_proto
;
522 proto
= get_proto_handler(proto_name
);
524 interface_add_error(iface
, "proto", "INVALID_PROTO", NULL
, 0);
529 iface
->proto_handler
= proto
;
533 interface_proto_event(struct interface_proto_state
*proto
,
534 enum interface_proto_cmd cmd
, bool force
)
536 enum interface_proto_event ev
;
539 ret
= proto
->cb(proto
, cmd
, force
);
540 if (ret
|| !(proto
->handler
->flags
& PROTO_FLAG_IMMEDIATE
))
544 case PROTO_CMD_SETUP
:
547 case PROTO_CMD_TEARDOWN
:
553 proto
->proto_event(proto
, ev
);