10 #include "interface.h"
11 #include "interface-ip.h"
27 static const struct blobmsg_policy route_attr
[__ROUTE_LAST
] = {
28 [ROUTE_INTERFACE
] = { .name
= "interface", .type
= BLOBMSG_TYPE_STRING
},
29 [ROUTE_TARGET
] = { .name
= "target", .type
= BLOBMSG_TYPE_STRING
},
30 [ROUTE_MASK
] = { .name
= "netmask", .type
= BLOBMSG_TYPE_STRING
},
31 [ROUTE_GATEWAY
] = { .name
= "gateway", .type
= BLOBMSG_TYPE_STRING
},
32 [ROUTE_DEVICE
] = { .name
= "device", .type
= BLOBMSG_TYPE_STRING
},
33 [ROUTE_METRIC
] = { .name
= "metric", .type
= BLOBMSG_TYPE_INT32
},
34 [ROUTE_MTU
] = { .name
= "mtu", .type
= BLOBMSG_TYPE_INT32
},
38 interface_ip_add_route(struct interface
*iface
, struct blob_attr
*attr
, bool v6
)
40 struct interface_ip_settings
*ip
;
41 struct blob_attr
*tb
[__ROUTE_LAST
], *cur
;
42 struct device_route
*route
;
43 int af
= v6
? AF_INET6
: AF_INET
;
46 blobmsg_parse(route_attr
, __ROUTE_LAST
, tb
, blobmsg_data(attr
), blobmsg_data_len(attr
));
48 if (!tb
[ROUTE_GATEWAY
] && !tb
[ROUTE_DEVICE
])
52 if ((cur
= tb
[ROUTE_INTERFACE
]) == NULL
)
55 iface
= vlist_find(&interfaces
, blobmsg_data(cur
), iface
, node
);
59 ip
= &iface
->config_ip
;
62 ip
= &iface
->proto_ip
;
65 route
= calloc(1, sizeof(*route
));
69 route
->mask
= v6
? 128 : 32;
70 if ((cur
= tb
[ROUTE_MASK
]) != NULL
) {
71 route
->mask
= parse_netmask_string(blobmsg_data(cur
), v6
);
72 if (route
->mask
> (v6
? 128 : 32))
76 if ((cur
= tb
[ROUTE_TARGET
]) != NULL
) {
77 if (!inet_pton(af
, blobmsg_data(cur
), &route
->addr
)) {
78 DPRINTF("Failed to parse route target: %s\n", (char *) blobmsg_data(cur
));
83 if ((cur
= tb
[ROUTE_GATEWAY
]) != NULL
) {
84 if (!inet_pton(af
, blobmsg_data(cur
), &route
->nexthop
)) {
85 DPRINTF("Failed to parse route gateway: %s\n", (char *) blobmsg_data(cur
));
90 if ((cur
= tb
[ROUTE_METRIC
]) != NULL
)
91 route
->metric
= blobmsg_get_u32(cur
);
93 if ((cur
= tb
[ROUTE_MTU
]) != NULL
)
94 route
->mtu
= blobmsg_get_u32(cur
);
96 if (!config
&& (cur
= tb
[ROUTE_DEVICE
]) != NULL
)
97 route
->device
= device_get(blobmsg_data(cur
), true);
99 vlist_add(&ip
->route
, &route
->node
);
107 addr_cmp(const void *k1
, const void *k2
, void *ptr
)
109 return memcmp(k1
, k2
, sizeof(struct device_addr
) -
110 offsetof(struct device_addr
, mask
));
114 route_cmp(const void *k1
, const void *k2
, void *ptr
)
116 return memcmp(k1
, k2
, sizeof(struct device_route
) -
117 offsetof(struct device_route
, mask
));
121 interface_update_proto_addr(struct vlist_tree
*tree
,
122 struct vlist_node
*node_new
,
123 struct vlist_node
*node_old
)
125 struct interface_ip_settings
*ip
;
126 struct interface
*iface
;
128 struct device_addr
*addr
;
130 ip
= container_of(tree
, struct interface_ip_settings
, addr
);
132 dev
= iface
->l3_dev
->dev
;
135 addr
= container_of(node_old
, struct device_addr
, node
);
136 if (!(addr
->flags
& DEVADDR_EXTERNAL
) && addr
->enabled
)
137 system_del_address(dev
, addr
);
142 addr
= container_of(node_new
, struct device_addr
, node
);
143 if (!(addr
->flags
& DEVADDR_EXTERNAL
))
144 system_add_address(dev
, addr
);
145 addr
->enabled
= true;
150 interface_update_proto_route(struct vlist_tree
*tree
,
151 struct vlist_node
*node_new
,
152 struct vlist_node
*node_old
)
154 struct interface_ip_settings
*ip
;
155 struct interface
*iface
;
157 struct device_route
*route
;
159 ip
= container_of(tree
, struct interface_ip_settings
, route
);
161 dev
= iface
->l3_dev
->dev
;
164 route
= container_of(node_old
, struct device_route
, node
);
165 if (!(route
->flags
& DEVADDR_EXTERNAL
) && route
->enabled
)
166 system_del_route(dev
, route
);
171 route
= container_of(node_new
, struct device_route
, node
);
172 if (!(route
->flags
& DEVADDR_EXTERNAL
))
173 system_add_route(dev
, route
);
174 route
->enabled
= true;
179 interface_add_dns_server(struct interface_ip_settings
*ip
, const char *str
)
181 struct dns_server
*s
;
183 s
= calloc(1, sizeof(*s
));
185 if (inet_pton(s
->af
, str
, &s
->addr
.in
))
189 if (inet_pton(s
->af
, str
, &s
->addr
.in
))
196 D(INTERFACE
, "Add IPv%c DNS server: %s\n",
197 s
->af
== AF_INET6
? '6' : '4', str
);
198 list_add_tail(&s
->list
, &ip
->dns_servers
);
202 interface_add_dns_server_list(struct interface_ip_settings
*ip
, struct blob_attr
*list
)
204 struct blob_attr
*cur
;
207 blobmsg_for_each_attr(cur
, list
, rem
) {
208 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
211 if (!blobmsg_check_attr(cur
, NULL
))
214 interface_add_dns_server(ip
, blobmsg_data(cur
));
219 interface_add_dns_search_domain(struct interface_ip_settings
*ip
, const char *str
)
221 struct dns_search_domain
*s
;
222 int len
= strlen(str
);
224 s
= calloc(1, sizeof(*s
) + len
+ 1);
228 D(INTERFACE
, "Add DNS search domain: %s\n", str
);
229 memcpy(s
->name
, str
, len
);
230 list_add_tail(&s
->list
, &ip
->dns_search
);
234 interface_add_dns_search_list(struct interface_ip_settings
*ip
, struct blob_attr
*list
)
236 struct blob_attr
*cur
;
239 blobmsg_for_each_attr(cur
, list
, rem
) {
240 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
243 if (!blobmsg_check_attr(cur
, NULL
))
246 interface_add_dns_search_domain(ip
, blobmsg_data(cur
));
251 interface_clear_dns_servers(struct interface_ip_settings
*ip
)
253 struct dns_server
*s
, *tmp
;
255 list_for_each_entry_safe(s
, tmp
, &ip
->dns_servers
, list
) {
262 interface_clear_dns_search(struct interface_ip_settings
*ip
)
264 struct dns_search_domain
*s
, *tmp
;
266 list_for_each_entry_safe(s
, tmp
, &ip
->dns_search
, list
) {
273 interface_write_resolv_conf(void)
275 struct interface
*iface
;
276 struct dns_server
*s
;
277 struct dns_search_domain
*d
;
278 char *path
= alloca(strlen(resolv_conf
) + 5);
283 sprintf(path
, "%s.tmp", resolv_conf
);
285 f
= fopen(path
, "w");
287 D(INTERFACE
, "Failed to open %s for writing\n", path
);
291 vlist_for_each_element(&interfaces
, iface
, node
) {
292 if (iface
->state
!= IFS_UP
)
295 if (list_empty(&iface
->proto_ip
.dns_search
) &&
296 list_empty(&iface
->proto_ip
.dns_servers
))
299 fprintf(f
, "# Interface %s\n", iface
->name
);
300 list_for_each_entry(s
, &iface
->proto_ip
.dns_servers
, list
) {
301 str
= inet_ntop(s
->af
, &s
->addr
, buf
, sizeof(buf
));
305 fprintf(f
, "nameserver %s\n", str
);
308 list_for_each_entry(d
, &iface
->proto_ip
.dns_search
, list
) {
309 fprintf(f
, "search %s\n", d
->name
);
313 if (rename(path
, resolv_conf
) < 0) {
314 D(INTERFACE
, "Failed to replace %s\n", resolv_conf
);
319 void interface_ip_set_enabled(struct interface_ip_settings
*ip
, bool enabled
)
321 struct device_addr
*addr
;
322 struct device_route
*route
;
325 ip
->enabled
= enabled
;
326 dev
= ip
->iface
->l3_dev
->dev
;
330 vlist_for_each_element(&ip
->addr
, addr
, node
) {
331 if (addr
->enabled
== enabled
)
335 system_add_address(dev
, addr
);
337 system_del_address(dev
, addr
);
338 addr
->enabled
= enabled
;
341 vlist_for_each_element(&ip
->route
, route
, node
) {
342 if (route
->enabled
== enabled
)
346 system_add_route(dev
, route
);
348 system_del_route(dev
, route
);
349 route
->enabled
= enabled
;
354 interface_ip_update_start(struct interface_ip_settings
*ip
)
356 interface_clear_dns_servers(ip
);
357 interface_clear_dns_search(ip
);
358 vlist_update(&ip
->route
);
359 vlist_update(&ip
->addr
);
363 interface_ip_update_complete(struct interface_ip_settings
*ip
)
365 vlist_flush(&ip
->route
);
366 vlist_flush(&ip
->addr
);
370 interface_ip_flush(struct interface_ip_settings
*ip
)
372 interface_clear_dns_servers(ip
);
373 interface_clear_dns_search(ip
);
374 vlist_flush_all(&ip
->route
);
375 vlist_flush_all(&ip
->addr
);
379 interface_ip_init(struct interface_ip_settings
*ip
, struct interface
*iface
)
383 INIT_LIST_HEAD(&ip
->dns_search
);
384 INIT_LIST_HEAD(&ip
->dns_servers
);
385 vlist_init(&ip
->route
, route_cmp
, interface_update_proto_route
,
386 struct device_route
, node
, mask
);
387 vlist_init(&ip
->addr
, addr_cmp
, interface_update_proto_addr
,
388 struct device_addr
, node
, mask
);