delete_address(struct interface *iface)
{
int retval;
+
syslog(LOG_DEBUG, "%s: deleting IP address %s/%d",
iface->name,
inet_ntoa(iface->addr),
#ifdef __linux__
struct in_addr dest;
struct in_addr gate;
- struct rt *rt = NULL;
#endif
/* Grab our IP config */
net.s_addr = get_netmask(addr.s_addr);
if (get_option_addr(&brd.s_addr, dhcp, DHO_BROADCAST) == -1)
brd.s_addr = addr.s_addr | ~net.s_addr;
+#ifdef __linux__
+ dest.s_addr = addr.s_addr & net.s_addr;
+ gate.s_addr = 0;
+#endif
} else {
/* Only reset things if we had set them before */
if (iface->addr.s_addr != 0) {
#ifdef __linux__
/* On linux, we need to change the subnet route to have our metric. */
- if (iface->addr.s_addr != iface->state->lease.addr.s_addr &&
- iface->metric > 0 &&
- net.s_addr != INADDR_BROADCAST)
+ if (iface->metric > 0 &&
+ (net.s_addr != iface->net.s_addr ||
+ dest.s_addr != (iface->addr.s_addr & iface->net.s_addr)))
{
- dest.s_addr = addr.s_addr & net.s_addr;
- gate.s_addr = 0;
- add_route(iface, &dest, &net, &gate, iface->metric);
+ iface->addr.s_addr = addr.s_addr;
+ iface->net.s_addr = net.s_addr;
+ change_route(iface, &dest, &net, &gate, iface->metric);
del_route(iface, &dest, &net, &gate, 0);
- rt = xmalloc(sizeof(*rt));
- rt->dest.s_addr = dest.s_addr;
- rt->net.s_addr = net.s_addr;
- rt->gate.s_addr = gate.s_addr;
}
#endif
- configure_routes(iface, dhcp);
iface->addr.s_addr = addr.s_addr;
iface->net.s_addr = net.s_addr;
-
-#ifdef __linux__
- if (rt) {
- rt->next = iface->routes;
- iface->routes = rt;
- }
-#endif
+ configure_routes(iface, dhcp);
if (!iface->state->lease.frominfo)
if (write_lease(iface, dhcp) == -1)
nlm->hdr.nlmsg_type = RTM_NEWROUTE;
if (action == 0)
nlm->hdr.nlmsg_flags = NLM_F_REPLACE;
- else if (action > 0)
+ else if (action == 1)
nlm->hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
else
nlm->hdr.nlmsg_type = RTM_DELROUTE;
nlm->rt.rtm_family = AF_INET;
nlm->rt.rtm_table = RT_TABLE_MAIN;
- if (action < 0)
+ if (action == -1 || action == -2)
nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
else {
nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
- nlm->rt.rtm_protocol = RTPROT_BOOT;
+ /* We only change route metrics for kernel routes */
+ nlm->rt.rtm_protocol = action ? RTPROT_BOOT : RTPROT_KERNEL;
if (gateway->s_addr == INADDR_ANY)
nlm->rt.rtm_scope = RT_SCOPE_LINK;
else
nlm->rt.rtm_dst_len = inet_ntocidr(*netmask);
add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST,
&destination->s_addr, sizeof(destination->s_addr));
+ if (action != 1) {
+ add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC,
+ &iface->addr.s_addr, sizeof(iface->addr.s_addr));
+ }
add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY,
&gateway->s_addr, sizeof(gateway->s_addr));
if_route(iface, dest, mask, gate, metric, 0)
#define del_route(iface, dest, mask, gate, metric) \
if_route(iface, dest, mask, gate, metric, -1)
+#define del_src_route(iface, dest, mask, gate, metric) \
+ if_route(iface, dest, mask, gate, metric, -2)
void free_routes(struct rt *);
int open_udp_socket(struct interface *);