|
|
return (r == 0 ? 0 : -1); | return (r == 0 ? 0 : -1); |
} | } |
| |
|
static void log_route( |
|
struct in_addr destination, |
|
struct in_addr netmask, |
|
struct in_addr gateway, |
|
int metric, |
|
int change, int del) |
|
{ |
|
char *dstd = xstrdup (inet_ntoa (destination)); |
|
|
|
#ifdef __linux__ |
|
#define METRIC " metric %d" |
|
#else |
|
#define METRIC "" |
|
metric = 0; |
|
#endif |
|
|
|
if (gateway.s_addr == destination.s_addr) |
|
logger (LOG_INFO, "%s route to %s/%d" METRIC, |
|
change ? "changing" : del ? "removing" : "adding", |
|
dstd, inet_ntocidr (netmask) |
|
#ifdef __linux__ |
|
, metric |
|
#endif |
|
); |
|
else if (destination.s_addr == INADDR_ANY) |
|
logger (LOG_INFO, "%s default route via %s" METRIC, |
|
change ? "changing" : del ? "removing" : "adding", |
|
inet_ntoa (gateway) |
|
|
|
#ifdef __linux__ |
|
, metric |
|
#endif |
|
); |
|
else |
|
logger (LOG_INFO, "%s route to %s/%d via %s" METRIC, |
|
change ? "changing" : del ? "removing" : "adding", |
|
dstd, inet_ntocidr (netmask), inet_ntoa (gateway) |
|
#ifdef __linux__ |
|
, metric |
|
#endif |
|
); |
|
|
|
free (dstd); |
|
} |
|
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) \ | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) \ |
|| defined(__APPLE__) | || defined(__APPLE__) |
static int do_address (const char *ifname, struct in_addr address, | static int do_address (const char *ifname, struct in_addr address, |
|
|
int change, int del) | int change, int del) |
{ | { |
int s; | int s; |
char *dstd; |
|
struct rtm | struct rtm |
{ | { |
struct rt_msghdr hdr; | struct rt_msghdr hdr; |
|
|
if (! ifname) | if (! ifname) |
return -1; | return -1; |
| |
/* Do something with metric to satisfy compiler warnings */ |
log_route (destination, netmask, gateway, metric, change, del); |
metric = 0; |
|
| |
dstd = xstrdup (inet_ntoa (destination)); |
|
if (gateway.s_addr == destination.s_addr) |
|
logger (LOG_INFO, "%s route to %s/%d", |
|
change ? "changing" : del ? "removing" : "adding", |
|
dstd, inet_ntocidr (netmask)); |
|
else if (destination.s_addr == INADDR_ANY) |
|
logger (LOG_INFO, "%s default route via %s", |
|
change ? "changing" : del ? "removing" : "adding", |
|
inet_ntoa (gateway)); |
|
else |
|
logger (LOG_INFO, "%s route to %s/%d via %s", |
|
change ? "changing" : del ? "removing" : "adding", |
|
dstd, inet_ntocidr (netmask), inet_ntoa (gateway)); |
|
if (dstd) |
|
free (dstd); |
|
|
|
if ((s = socket (PF_ROUTE, SOCK_RAW, 0)) == -1) { | if ((s = socket (PF_ROUTE, SOCK_RAW, 0)) == -1) { |
logger (LOG_ERR, "socket: %s", strerror (errno)); | logger (LOG_ERR, "socket: %s", strerror (errno)); |
return -1; | return -1; |
|
|
rtm.hdr.rtm_version = RTM_VERSION; | rtm.hdr.rtm_version = RTM_VERSION; |
rtm.hdr.rtm_seq = ++seq; | rtm.hdr.rtm_seq = ++seq; |
rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD; | rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD; |
|
|
rtm.hdr.rtm_flags = RTF_UP | RTF_STATIC; | rtm.hdr.rtm_flags = RTF_UP | RTF_STATIC; |
if (netmask.s_addr == INADDR_BROADCAST) |
|
rtm.hdr.rtm_flags |= RTF_HOST; |
|
else |
|
rtm.hdr.rtm_flags |= RTF_GATEWAY; |
|
| |
/* This order is important */ | /* This order is important */ |
rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; | rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; |
|
|
l = SA_SIZE (&(su.sa)); | l = SA_SIZE (&(su.sa)); |
memcpy (bp, &su, l); | memcpy (bp, &su, l); |
bp += l; | bp += l; |
|
|
|
rtm.hdr.rtm_flags |= RTF_HOST; |
} else { | } else { |
ADDADDR (gateway); | ADDADDR (gateway); |
|
rtm.hdr.rtm_flags |= RTF_GATEWAY; |
} | } |
| |
ADDADDR (netmask); | ADDADDR (netmask); |
|
|
struct in_addr gateway, | struct in_addr gateway, |
int metric, int change, int del) | int metric, int change, int del) |
{ | { |
char *dstd; |
|
unsigned int ifindex; | unsigned int ifindex; |
struct | struct |
{ | { |
|
|
char buffer[256]; | char buffer[256]; |
} | } |
nlm; | nlm; |
int cidr = inet_ntocidr (netmask); |
|
| |
if (! ifname) | if (! ifname) |
return -1; | return -1; |
| |
dstd = xstrdup (inet_ntoa (destination)); |
log_route (destination, netmask, gateway, metric, change, del); |
if (gateway.s_addr == destination.s_addr) |
|
logger (LOG_INFO, "%s route to %s/%d metric %d", |
|
change ? "changing" : del ? "removing" : "adding", |
|
dstd, cidr, metric); |
|
else if (destination.s_addr == INADDR_ANY && netmask.s_addr == INADDR_ANY) |
|
logger (LOG_INFO, "%s default route via %s metric %d", |
|
change ? "changing" : del ? "removing" : "adding", |
|
inet_ntoa (gateway), metric); |
|
else |
|
logger (LOG_INFO, "%s route to %s/%d via %s metric %d", |
|
change ? "changing" : del ? "removing" : "adding", |
|
dstd, cidr, inet_ntoa (gateway), metric); |
|
if (dstd) |
|
free (dstd); |
|
| |
memset (&nlm, 0, sizeof (nlm)); | memset (&nlm, 0, sizeof (nlm)); |
| |
|
|
else { | else { |
nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; | nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; |
nlm.rt.rtm_protocol = RTPROT_BOOT; | nlm.rt.rtm_protocol = RTPROT_BOOT; |
if (gateway.s_addr == INADDR_ANY) |
if (netmask.s_addr == INADDR_BROADCAST) |
nlm.rt.rtm_scope = RT_SCOPE_LINK; | nlm.rt.rtm_scope = RT_SCOPE_LINK; |
else | else |
nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE; | nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE; |
|
|
nlm.rt.rtm_dst_len = inet_ntocidr (netmask); | nlm.rt.rtm_dst_len = inet_ntocidr (netmask); |
add_attr_l (&nlm.hdr, sizeof (nlm), RTA_DST, &destination.s_addr, | add_attr_l (&nlm.hdr, sizeof (nlm), RTA_DST, &destination.s_addr, |
sizeof (destination.s_addr)); | sizeof (destination.s_addr)); |
if (gateway.s_addr != INADDR_ANY && gateway.s_addr != destination.s_addr) |
if (netmask.s_addr != INADDR_BROADCAST) |
add_attr_l (&nlm.hdr, sizeof (nlm), RTA_GATEWAY, &gateway.s_addr, | add_attr_l (&nlm.hdr, sizeof (nlm), RTA_GATEWAY, &gateway.s_addr, |
sizeof (gateway.s_addr)); | sizeof (gateway.s_addr)); |
| |