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
,
75 static const struct blobmsg_policy proto_ip_addr
[__ADDR_MAX
] = {
76 [ADDR_IPADDR
] = { .name
= "ipaddr", .type
= BLOBMSG_TYPE_STRING
},
77 [ADDR_MASK
] = { .name
= "mask", .type
= BLOBMSG_TYPE_STRING
},
78 [ADDR_BROADCAST
] = { .name
= "broadcast", .type
= BLOBMSG_TYPE_STRING
},
79 [ADDR_PTP
] = { .name
= "ptp", .type
= BLOBMSG_TYPE_STRING
},
80 [ADDR_PREFERRED
] = { .name
= "preferred", .type
= BLOBMSG_TYPE_INT32
},
81 [ADDR_VALID
] = { .name
= "valid", .type
= BLOBMSG_TYPE_INT32
},
82 [ADDR_OFFLINK
] = { .name
= "offlink", .type
= BLOBMSG_TYPE_BOOL
},
85 static struct device_addr
*
86 alloc_device_addr(bool v6
, bool ext
)
88 struct device_addr
*addr
;
90 addr
= calloc(1, sizeof(*addr
));
91 addr
->flags
= v6
? DEVADDR_INET6
: DEVADDR_INET4
;
93 addr
->flags
|= DEVADDR_EXTERNAL
;
99 parse_addr(struct interface
*iface
, const char *str
, bool v6
, int mask
,
100 bool ext
, uint32_t broadcast
)
102 struct device_addr
*addr
;
103 int af
= v6
? AF_INET6
: AF_INET
;
105 addr
= alloc_device_addr(v6
, ext
);
110 if (!parse_ip_and_netmask(af
, str
, &addr
->addr
, &addr
->mask
)) {
111 interface_add_error(iface
, "proto", "INVALID_ADDRESS", &str
, 1);
117 addr
->broadcast
= broadcast
;
119 vlist_add(&iface
->proto_ip
.addr
, &addr
->node
, &addr
->flags
);
124 parse_static_address_option(struct interface
*iface
, struct blob_attr
*attr
,
125 bool v6
, int netmask
, bool ext
, uint32_t broadcast
)
127 struct blob_attr
*cur
;
131 blobmsg_for_each_attr(cur
, attr
, rem
) {
132 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
136 if (!parse_addr(iface
, blobmsg_data(cur
), v6
, netmask
, ext
,
144 static struct device_addr
*
145 parse_address_item(struct blob_attr
*attr
, bool v6
, bool ext
)
147 struct device_addr
*addr
;
148 struct blob_attr
*tb
[__ADDR_MAX
];
149 struct blob_attr
*cur
;
151 if (blobmsg_type(attr
) != BLOBMSG_TYPE_TABLE
)
154 addr
= alloc_device_addr(v6
, ext
);
158 blobmsg_parse(proto_ip_addr
, __ADDR_MAX
, tb
, blobmsg_data(attr
), blobmsg_data_len(attr
));
160 addr
->mask
= v6
? 128 : 32;
161 if ((cur
= tb
[ADDR_MASK
])) {
162 unsigned int new_mask
;
164 new_mask
= parse_netmask_string(blobmsg_data(cur
), v6
);
165 if (new_mask
> addr
->mask
)
168 addr
->mask
= new_mask
;
171 cur
= tb
[ADDR_IPADDR
];
175 if (!inet_pton(v6
? AF_INET6
: AF_INET
, blobmsg_data(cur
), &addr
->addr
))
178 if ((cur
= tb
[ADDR_OFFLINK
]) && blobmsg_get_bool(cur
))
179 addr
->flags
|= DEVADDR_OFFLINK
;
182 if ((cur
= tb
[ADDR_BROADCAST
]) &&
183 !inet_pton(AF_INET
, blobmsg_data(cur
), &addr
->broadcast
))
185 if ((cur
= tb
[ADDR_PTP
]) &&
186 !inet_pton(AF_INET
, blobmsg_data(cur
), &addr
->point_to_point
))
189 time_t now
= system_get_rtime();
190 if ((cur
= tb
[ADDR_PREFERRED
])) {
191 uint32_t preferred
= blobmsg_get_u32(cur
);
192 if (preferred
< UINT32_MAX
)
193 addr
->preferred_until
= now
+ preferred
;
196 if ((cur
= tb
[ADDR_VALID
])) {
197 uint32_t valid
= blobmsg_get_u32(cur
);
198 if (valid
< UINT32_MAX
)
199 addr
->valid_until
= now
+ valid
;
203 if (addr
->valid_until
) {
204 if (!addr
->preferred_until
)
205 addr
->preferred_until
= addr
->valid_until
;
206 else if (addr
->preferred_until
> addr
->valid_until
)
219 parse_address_list(struct interface
*iface
, struct blob_attr
*attr
, bool v6
,
222 struct device_addr
*addr
;
223 struct blob_attr
*cur
;
227 blobmsg_for_each_attr(cur
, attr
, rem
) {
228 addr
= parse_address_item(cur
, v6
, ext
);
233 vlist_add(&iface
->proto_ip
.addr
, &addr
->node
, &addr
->flags
);
240 parse_gateway_option(struct interface
*iface
, struct blob_attr
*attr
, bool v6
)
242 struct device_route
*route
;
243 const char *str
= blobmsg_data(attr
);
244 int af
= v6
? AF_INET6
: AF_INET
;
246 route
= calloc(1, sizeof(*route
));
247 if (!inet_pton(af
, str
, &route
->nexthop
)) {
248 interface_add_error(iface
, "proto", "INVALID_GATEWAY", &str
, 1);
254 route
->flags
= (v6
? DEVADDR_INET6
: DEVADDR_INET4
);
255 vlist_add(&iface
->proto_ip
.route
, &route
->node
, &route
->flags
);
261 parse_ip6assign_option(struct interface
*iface
, struct blob_attr
*attr
)
263 uint8_t oldval
= iface
->proto_ip
.assignment_length
;
264 uint8_t newval
= blobmsg_get_u32(attr
);
266 struct device_prefix
*prefix
;
267 list_for_each_entry(prefix
, &prefixes
, head
) {
268 if (oldval
&& oldval
!= newval
)
269 interface_ip_set_prefix_assignment(prefix
, iface
, 0);
271 if (newval
&& newval
<= 64)
272 interface_ip_set_prefix_assignment(prefix
, iface
, newval
);
275 iface
->proto_ip
.assignment_length
= newval
;
280 parse_prefix_option(struct interface
*iface
, const char *str
, size_t len
)
282 char buf
[128] = {0}, *saveptr
;
283 if (len
> sizeof(buf
))
286 memcpy(buf
, str
, len
);
287 char *addrstr
= strtok_r(buf
, "/", &saveptr
);
291 char *lengthstr
= strtok_r(NULL
, ",", &saveptr
);
295 char *prefstr
= strtok_r(NULL
, ",", &saveptr
);
296 char *validstr
= (!prefstr
) ? NULL
: strtok_r(NULL
, ",", &saveptr
);
298 uint32_t pref
= (!prefstr
) ? 0 : strtoul(prefstr
, NULL
, 10);
299 uint32_t valid
= (!validstr
) ? 0 : strtoul(validstr
, NULL
, 10);
301 uint8_t length
= strtoul(lengthstr
, NULL
, 10);
302 if (length
< 1 || length
> 64)
305 struct in6_addr addr
;
306 if (inet_pton(AF_INET6
, addrstr
, &addr
) < 1)
309 time_t now
= system_get_rtime();
310 time_t preferred_until
= 0;
311 if (prefstr
&& pref
!= 0xffffffffU
)
312 preferred_until
= pref
+ now
;
314 time_t valid_until
= 0;
315 if (validstr
&& valid
!= 0xffffffffU
)
316 valid_until
= valid
+ now
;
318 interface_ip_add_device_prefix(iface
, &addr
, length
,
319 valid_until
, preferred_until
);
324 parse_prefix_list(struct interface
*iface
, struct blob_attr
*attr
)
326 struct blob_attr
*cur
;
330 blobmsg_for_each_attr(cur
, attr
, rem
) {
331 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
335 if (!parse_prefix_option(iface
, blobmsg_data(cur
),
336 blobmsg_data_len(cur
)))
344 proto_apply_static_ip_settings(struct interface
*iface
, struct blob_attr
*attr
)
346 struct blob_attr
*tb
[__OPT_MAX
];
347 struct blob_attr
*cur
;
349 unsigned int netmask
= 32;
350 int n_v4
= 0, n_v6
= 0;
351 struct in_addr bcast
= {};
353 blobmsg_parse(proto_ip_attributes
, __OPT_MAX
, tb
, blob_data(attr
), blob_len(attr
));
355 if ((cur
= tb
[OPT_NETMASK
])) {
356 netmask
= parse_netmask_string(blobmsg_data(cur
), false);
358 error
= "INVALID_NETMASK";
363 if ((cur
= tb
[OPT_BROADCAST
])) {
364 if (!inet_pton(AF_INET
, blobmsg_data(cur
), &bcast
)) {
365 error
= "INVALID_BROADCAST";
370 if ((cur
= tb
[OPT_IPADDR
]))
371 n_v4
= parse_static_address_option(iface
, cur
, false,
372 netmask
, false, bcast
.s_addr
);
374 if ((cur
= tb
[OPT_IP6ADDR
]))
375 n_v6
= parse_static_address_option(iface
, cur
, true,
378 if ((cur
= tb
[OPT_IP6PREFIX
]))
379 if (parse_prefix_list(iface
, cur
) < 0)
382 if (n_v4
< 0 || n_v6
< 0)
385 if ((cur
= tb
[OPT_GATEWAY
])) {
386 if (n_v4
&& !parse_gateway_option(iface
, cur
, false))
390 if ((cur
= tb
[OPT_IP6GW
])) {
391 if (n_v6
&& !parse_gateway_option(iface
, cur
, true))
395 if ((cur
= tb
[OPT_IP6ASSIGN
]))
396 if (!parse_ip6assign_option(iface
, cur
))
402 interface_add_error(iface
, "proto", error
, NULL
, 0);
408 proto_apply_ip_settings(struct interface
*iface
, struct blob_attr
*attr
, bool ext
)
410 struct blob_attr
*tb
[__OPT_MAX
];
411 struct blob_attr
*cur
;
412 int n_v4
= 0, n_v6
= 0;
414 blobmsg_parse(proto_ip_attributes
, __OPT_MAX
, tb
, blob_data(attr
), blob_len(attr
));
416 if ((cur
= tb
[OPT_IPADDR
]))
417 n_v4
= parse_address_list(iface
, cur
, false, ext
);
419 if ((cur
= tb
[OPT_IP6ADDR
]))
420 n_v6
= parse_address_list(iface
, cur
, true, ext
);
422 if ((cur
= tb
[OPT_IP6PREFIX
]))
423 if (parse_prefix_list(iface
, cur
) < 0)
426 if (n_v4
< 0 || n_v6
< 0)
429 if ((cur
= tb
[OPT_GATEWAY
])) {
430 if (n_v4
&& !parse_gateway_option(iface
, cur
, false))
434 if ((cur
= tb
[OPT_IP6GW
])) {
435 if (n_v6
&& !parse_gateway_option(iface
, cur
, true))
439 if ((cur
= tb
[OPT_IP6ASSIGN
]))
440 if (!parse_ip6assign_option(iface
, cur
))
449 void add_proto_handler(struct proto_handler
*p
)
452 avl_init(&handlers
, avl_strcmp
, false, NULL
);
457 p
->avl
.key
= p
->name
;
458 avl_insert(&handlers
, &p
->avl
);
462 default_proto_free(struct interface_proto_state
*proto
)
468 invalid_proto_handler(struct interface_proto_state
*proto
,
469 enum interface_proto_cmd cmd
, bool force
)
475 no_proto_handler(struct interface_proto_state
*proto
,
476 enum interface_proto_cmd cmd
, bool force
)
481 static struct interface_proto_state
*
482 default_proto_attach(const struct proto_handler
*h
,
483 struct interface
*iface
, struct blob_attr
*attr
)
485 struct interface_proto_state
*proto
;
487 proto
= calloc(1, sizeof(*proto
));
488 proto
->free
= default_proto_free
;
489 proto
->cb
= no_proto_handler
;
494 static const struct proto_handler no_proto
= {
496 .flags
= PROTO_FLAG_IMMEDIATE
,
497 .attach
= default_proto_attach
,
500 static const struct proto_handler
*
501 get_proto_handler(const char *name
)
503 struct proto_handler
*proto
;
505 if (!strcmp(name
, "none"))
511 return avl_find_element(&handlers
, name
, proto
, avl
);
515 proto_dump_handlers(struct blob_buf
*b
)
517 struct proto_handler
*p
;
520 avl_for_each_element(&handlers
, p
, avl
) {
521 c
= blobmsg_open_table(b
, p
->name
);
522 blobmsg_add_u8(b
, "no_device", !!(p
->flags
& PROTO_FLAG_NODEV
));
523 blobmsg_close_table(b
, c
);
528 proto_init_interface(struct interface
*iface
, struct blob_attr
*attr
)
530 const struct proto_handler
*proto
= iface
->proto_handler
;
531 struct interface_proto_state
*state
= NULL
;
536 state
= proto
->attach(proto
, iface
, attr
);
538 state
= no_proto
.attach(&no_proto
, iface
, attr
);
539 state
->cb
= invalid_proto_handler
;
542 state
->handler
= proto
;
543 interface_set_proto_state(iface
, state
);
547 proto_attach_interface(struct interface
*iface
, const char *proto_name
)
549 const struct proto_handler
*proto
= &no_proto
;
552 proto
= get_proto_handler(proto_name
);
554 interface_add_error(iface
, "proto", "INVALID_PROTO", NULL
, 0);
559 iface
->proto_handler
= proto
;
563 interface_proto_event(struct interface_proto_state
*proto
,
564 enum interface_proto_cmd cmd
, bool force
)
566 enum interface_proto_event ev
;
569 ret
= proto
->cb(proto
, cmd
, force
);
570 if (ret
|| !(proto
->handler
->flags
& PROTO_FLAG_IMMEDIATE
))
574 case PROTO_CMD_SETUP
:
577 case PROTO_CMD_TEARDOWN
:
583 proto
->proto_event(proto
, ev
);