}
static int
-delete_route(const char *iface, struct rt *rt, int metric)
+delete_route(const struct interface *iface, struct rt *rt, int metric)
{
char *addr;
int retval;
rt = reverse_routes(iface->routes);
while (rt) {
rtn = rt->next;
- retval += delete_route(iface->name, rt, metric);
+ retval += delete_route(iface, rt, metric);
free(rt);
rt = rtn;
}
iface->routes = reverse_routes(iface->routes);
for (rt = iface->routes; rt; rt = rt->next)
if (in_routes(ort, rt) != 0)
- delete_route(iface->name, rt, options->metric);
+ delete_route(iface, rt, options->metric);
for (rt = ort; rt; rt = rt->next) {
/* Don't set default routes if not asked to */
logger(LOG_DEBUG, "adding route to %s/%d via %s",
addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate));
free(addr);
- remember = add_route(iface->name, &rt->dest,
+ remember = add_route(iface, &rt->dest,
&rt->net, &rt->gate,
options->metric);
retval += remember;
{
dest.s_addr = addr.s_addr & net.s_addr;
gate.s_addr = 0;
- add_route(iface->name, &dest, &net, &gate, options->metric);
- del_route(iface->name, &dest, &net, &gate, 0);
+ add_route(iface, &dest, &net, &gate, options->metric);
+ del_route(iface, &dest, &net, &gate, 0);
}
#endif
}
int
-if_route(const char *ifname, const struct in_addr *destination,
+if_route(const struct interface *iface, const struct in_addr *destination,
const struct in_addr *netmask, const struct in_addr *gateway,
_unused int metric, int action)
{
memset(&su, 0, sizeof(su));
su.sdl.sdl_family = AF_LINK;
su.sdl.sdl_len = sizeof(su.sdl);
- link_addr(ifname, &su.sdl);
+ link_addr(iface->name, &su.sdl);
ADDSU(su);
rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
}
int
-if_route(const char *ifname,
+if_route(const struct interface *iface,
const struct in_addr *destination, const struct in_addr *netmask,
const struct in_addr *gateway, int metric, int action)
{
unsigned int ifindex;
int retval = 0;
- if (!(ifindex = if_nametoindex(ifname))) {
+ if (!(ifindex = if_nametoindex(iface->name))) {
errno = ENODEV;
return -1;
}
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 */
+ if (destination->s_addr ==
+ (iface->addr.s_addr & iface->net.s_addr) &&
+ netmask->s_addr == iface->net.s_addr)
+ nlm->rt.rtm_protocol = RTPROT_KERNEL;
+ else
+ nlm->rt.rtm_protocol = RTPROT_BOOT;
if (gateway->s_addr == INADDR_ANY ||
(gateway->s_addr == destination->s_addr &&
netmask->s_addr == INADDR_BROADCAST))
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 (nlm->rt.rtm_protocol == RTPROT_KERNEL) {
+ add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC,
+ &iface->addr.s_addr, sizeof(iface->addr.s_addr));
+ }
/* If destination == gateway then don't add the gateway */
if (destination->s_addr != gateway->s_addr ||
netmask->s_addr != INADDR_BROADCAST)
#define get_address(ifname, addr, net) \
do_interface(ifname, NULL, NULL, addr, net, 1)
-int if_route(const char *, const struct in_addr *, const struct in_addr *,
+int if_route(const struct interface *,
+ const struct in_addr *,const struct in_addr *,
const struct in_addr *, int, int);
-#define add_route(ifname, dest, mask, gate, metric) \
- if_route(ifname, dest, mask, gate, metric, 1)
-#define change_route(ifname, dest, mask, gate, metric) \
- if_route(ifname, dest, mask, gate, metric, 0)
-#define del_route(ifname, dest, mask, gate, metric) \
- if_route(ifname, dest, mask, gate, metric, -1)
+#define add_route(iface, dest, mask, gate, metric) \
+ if_route(iface, dest, mask, gate, metric, 1)
+#define change_route(iface, dest, mask, gate, metric) \
+ if_route(iface, dest, mask, gate, metric, 0)
+#define del_route(iface, dest, mask, gate, metric) \
+ if_route(iface, dest, mask, gate, metric, -1)
void free_routes(struct rt *);
int open_udp_socket(struct interface *);