static int do_address(const char *ifname, struct in_addr address, struct in_addr netmask, struct in_addr broadcast, int del) { struct { struct nlmsghdr hdr; struct ifaddrmsg ifa; char buffer[64]; } nlm; if (!ifname) return -1; memset (&nlm, 0, sizeof (nlm)); nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); nlm.hdr.nlmsg_flags = NLM_F_REQUEST; if (! del) nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; nlm.hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR; nlm.ifa.ifa_index = if_nametoindex (ifname); nlm.ifa.ifa_family = AF_INET; nlm.ifa.ifa_prefixlen = inet_ntocidr (netmask); add_attr_l (&nlm.hdr, sizeof (nlm), IFA_LOCAL, &address.s_addr, sizeof (address.s_addr)); if (! del) add_attr_l (&nlm.hdr, sizeof (nlm), IFA_BROADCAST, &broadcast.s_addr, sizeof (broadcast.s_addr)); return send_netlink (&nlm.hdr); }
int if_address(const struct interface *iface, const struct in_addr *address, const struct in_addr *netmask, const struct in_addr *broadcast, int action) { struct nlma *nlm; int retval = 0; nlm = calloc(1, sizeof(*nlm)); if (nlm == NULL) return -1; nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); nlm->hdr.nlmsg_flags = NLM_F_REQUEST; if (action >= 0) { nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; nlm->hdr.nlmsg_type = RTM_NEWADDR; } else nlm->hdr.nlmsg_type = RTM_DELADDR; nlm->ifa.ifa_index = iface->index; nlm->ifa.ifa_family = AF_INET; nlm->ifa.ifa_prefixlen = inet_ntocidr(*netmask); /* This creates the aliased interface */ add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL, iface->name, strlen(iface->name) + 1); add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL, &address->s_addr, sizeof(address->s_addr)); if (action >= 0 && broadcast) add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_BROADCAST, &broadcast->s_addr, sizeof(broadcast->s_addr)); if (send_netlink(&nlm->hdr) == -1) retval = -1; free(nlm); return retval; }
static int do_address(const char *ifname, struct in_addr address, struct in_addr netmask, struct in_addr broadcast, int del) { struct nlma *nlm; int retval; if (!ifname) return -1; nlm = xmalloc (sizeof (struct nlma)); memset (nlm, 0, sizeof (struct nlma)); nlm->hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); nlm->hdr.nlmsg_flags = NLM_F_REQUEST; if (! del) nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; nlm->hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR; if (! (nlm->ifa.ifa_index = if_nametoindex (ifname))) { logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'", ifname); free (nlm); return -1; } nlm->ifa.ifa_family = AF_INET; nlm->ifa.ifa_prefixlen = inet_ntocidr (netmask); /* This creates the aliased interface */ add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_LABEL, ifname, strlen (ifname) + 1); add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_LOCAL, &address.s_addr, sizeof (address.s_addr)); if (! del) add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_BROADCAST, &broadcast.s_addr, sizeof (broadcast.s_addr)); retval = send_netlink (&nlm->hdr); free (nlm); return retval; }
static int do_address(const char *ifname, struct in_addr address, struct in_addr netmask, struct in_addr broadcast, int del) { if (!ifname) return -1; struct { struct nlmsghdr hdr; struct ifaddrmsg ifa; char buffer[256]; } nlm; memset (&nlm, 0, sizeof (nlm)); nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); nlm.hdr.nlmsg_flags = NLM_F_REQUEST; nlm.hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR; nlm.ifa.ifa_index = if_nametoindex (ifname); nlm.ifa.ifa_family = AF_INET; /* Store the netmask in the prefix */ uint32_t mask = htonl (netmask.s_addr); while (mask) { nlm.ifa.ifa_prefixlen++; mask <<= 1; } add_attr_l (&nlm.hdr, sizeof (nlm), IFA_LOCAL, &address.s_addr, sizeof (address.s_addr)); if (! del) add_attr_l (&nlm.hdr, sizeof (nlm), IFA_BROADCAST, &broadcast.s_addr, sizeof (broadcast.s_addr)); return send_netlink (&nlm.hdr); }
int if_address6(const struct ipv6_addr *ap, int action) { struct nlma *nlm; struct ifa_cacheinfo cinfo; int retval = 0; nlm = calloc(1, sizeof(*nlm)); if (nlm == NULL) return -1; nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); nlm->hdr.nlmsg_flags = NLM_F_REQUEST; if (action >= 0) { nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; nlm->hdr.nlmsg_type = RTM_NEWADDR; } else nlm->hdr.nlmsg_type = RTM_DELADDR; nlm->ifa.ifa_index = ap->iface->index; nlm->ifa.ifa_family = AF_INET6; nlm->ifa.ifa_prefixlen = ap->prefix_len; /* This creates the aliased interface */ add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL, ap->iface->name, strlen(ap->iface->name) + 1); add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL, &ap->addr.s6_addr, sizeof(ap->addr.s6_addr)); if (action >= 0) { memset(&cinfo, 0, sizeof(cinfo)); cinfo.ifa_prefered = ap->prefix_pltime; cinfo.ifa_valid = ap->prefix_vltime; add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_CACHEINFO, &cinfo, sizeof(cinfo)); } if (send_netlink(&nlm->hdr) == -1) retval = -1; free(nlm); return retval; }
int if_route(const char *ifname, const struct in_addr *destination, const struct in_addr *netmask, const struct in_addr *gateway, int metric, int action) { struct nlmr *nlm; unsigned int ifindex; int retval = 0; if (!(ifindex = if_nametoindex(ifname))) { errno = ENODEV; return -1; } nlm = xzalloc(sizeof(*nlm)); nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlm->hdr.nlmsg_type = RTM_NEWROUTE; if (action == 0) nlm->hdr.nlmsg_flags = NLM_F_REPLACE; else if (action > 0) /* * ers@google: * commented out NLM_F_EXCL here and below. We * sometimes keep one interface up while we are * configuring the other one, and this flag * causes route addition to fail. */ nlm->hdr.nlmsg_flags = NLM_F_CREATE /* | NLM_F_EXCL */; else nlm->hdr.nlmsg_type = RTM_DELROUTE; nlm->hdr.nlmsg_flags |= NLM_F_REQUEST; nlm->rt.rtm_family = AF_INET; nlm->rt.rtm_table = RT_TABLE_MAIN; if (action < 0) nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; else { nlm->hdr.nlmsg_flags |= NLM_F_CREATE /*| NLM_F_EXCL*/; nlm->rt.rtm_protocol = RTPROT_BOOT; if (gateway->s_addr == INADDR_ANY) nlm->rt.rtm_scope = RT_SCOPE_LINK; else nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE; nlm->rt.rtm_type = RTN_UNICAST; } nlm->rt.rtm_dst_len = inet_ntocidr(*netmask); add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST, &destination->s_addr, sizeof(destination->s_addr)); add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY, &gateway->s_addr, sizeof(gateway->s_addr)); add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex); add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, metric); if (send_netlink(&nlm->hdr) == -1) retval = -1; free(nlm); return retval; }
static int do_route (const char *ifname, struct in_addr destination, struct in_addr netmask, struct in_addr gateway, int metric, int change, int del) { char *dstd; char *gend; struct { struct nlmsghdr hdr; struct rtmsg rt; char buffer[256]; } nlm; if (! ifname) return -1; dstd = strdup (inet_ntoa (destination)); gend = strdup (inet_ntoa (netmask)); if (gateway.s_addr == destination.s_addr) logger (LOG_INFO, "%s route to %s (%s) metric %d", change ? "changing" : del ? "removing" : "adding", dstd, gend, 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 (%s) via %s metric %d", change ? "changing" : del ? "removing" : "adding", dstd, gend, inet_ntoa (gateway), metric); if (dstd) free (dstd); if (gend) free (gend); memset (&nlm, 0, sizeof (nlm)); nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); if (change) nlm.hdr.nlmsg_flags = NLM_F_REPLACE; else if (! del) nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL; nlm.hdr.nlmsg_flags |= NLM_F_REQUEST; nlm.hdr.nlmsg_type = del ? RTM_DELROUTE : RTM_NEWROUTE; nlm.rt.rtm_family = AF_INET; nlm.rt.rtm_table = RT_TABLE_MAIN; if (del) nlm.rt.rtm_scope = RT_SCOPE_NOWHERE; else { nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; nlm.rt.rtm_protocol = RTPROT_BOOT; if (gateway.s_addr == INADDR_ANY || netmask.s_addr == INADDR_BROADCAST) nlm.rt.rtm_scope = RT_SCOPE_LINK; else nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE; nlm.rt.rtm_type = RTN_UNICAST; } 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 (gateway.s_addr != INADDR_ANY && gateway.s_addr != destination.s_addr) add_attr_l (&nlm.hdr, sizeof (nlm), RTA_GATEWAY, &gateway.s_addr, sizeof (gateway.s_addr)); add_attr_32 (&nlm.hdr, sizeof (nlm), RTA_OIF, if_nametoindex (ifname)); add_attr_32 (&nlm.hdr, sizeof (nlm), RTA_PRIORITY, metric); return send_netlink (&nlm.hdr); }
static int do_route (const char *ifname, struct in_addr destination, struct in_addr netmask, struct in_addr gateway, int metric, int change, int del) { struct nlmr *nlm; unsigned int ifindex; int retval; if (! ifname) return -1; log_route (destination, netmask, gateway, metric, change, del); if (! (ifindex = if_nametoindex (ifname))) { logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'", ifname); return -1; } nlm = xmalloc (sizeof (struct nlmr)); memset (nlm, 0, sizeof (struct nlmr)); nlm->hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); if (change) nlm->hdr.nlmsg_flags = NLM_F_REPLACE; else if (! del) nlm->hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL; nlm->hdr.nlmsg_flags |= NLM_F_REQUEST; nlm->hdr.nlmsg_type = del ? RTM_DELROUTE : RTM_NEWROUTE; nlm->rt.rtm_family = AF_INET; nlm->rt.rtm_table = RT_TABLE_MAIN; if (del) nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; else { nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; nlm->rt.rtm_protocol = RTPROT_BOOT; if (netmask.s_addr == INADDR_BROADCAST || gateway.s_addr == INADDR_ANY) nlm->rt.rtm_scope = RT_SCOPE_LINK; else nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE; nlm->rt.rtm_type = RTN_UNICAST; } nlm->rt.rtm_dst_len = inet_ntocidr (netmask); add_attr_l (&nlm->hdr, sizeof (struct nlmr), RTA_DST, &destination.s_addr, sizeof (destination.s_addr)); if (netmask.s_addr != INADDR_BROADCAST && destination.s_addr != gateway.s_addr) add_attr_l (&nlm->hdr, sizeof (struct nlmr), RTA_GATEWAY, &gateway.s_addr, sizeof (gateway.s_addr)); add_attr_32 (&nlm->hdr, sizeof (struct nlmr), RTA_OIF, ifindex); add_attr_32 (&nlm->hdr, sizeof (struct nlmr), RTA_PRIORITY, metric); retval = send_netlink (&nlm->hdr); free (nlm); return retval; }
int if_route6(const struct rt6 *rt, int action) { struct nlmr *nlm; char metricsbuf[32]; struct rtattr *metrics = (void *)metricsbuf; int retval = 0; nlm = calloc(1, sizeof(*nlm)); if (nlm == NULL) return -1; nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlm->hdr.nlmsg_type = RTM_NEWROUTE; nlm->hdr.nlmsg_flags = NLM_F_REQUEST; if (action == 0) nlm->hdr.nlmsg_flags |= NLM_F_REPLACE; 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_INET6; nlm->rt.rtm_table = RT_TABLE_MAIN; if (action == -1 || action == -2) nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; else { nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; /* None interface subnet routes are static. */ if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) { nlm->rt.rtm_protocol = RTPROT_KERNEL; nlm->rt.rtm_scope = RT_SCOPE_LINK; } else nlm->rt.rtm_protocol = RTPROT_BOOT; nlm->rt.rtm_type = RTN_UNICAST; } nlm->rt.rtm_dst_len = ipv6_prefixlen(&rt->net); add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST, &rt->dest.s6_addr, sizeof(rt->dest.s6_addr)); /* If destination == gateway then don't add the gateway */ if (!IN6_IS_ADDR_UNSPECIFIED(&rt->gate) && !IN6_ARE_ADDR_EQUAL(&rt->dest, &rt->gate)) add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY, &rt->gate.s6_addr, sizeof(rt->gate.s6_addr)); add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, rt->iface->index); add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric); if (rt->mtu) { metrics->rta_type = RTA_METRICS; metrics->rta_len = RTA_LENGTH(0); rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu); add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_METRICS, RTA_DATA(metrics), RTA_PAYLOAD(metrics)); } if (send_netlink(&nlm->hdr) == -1) retval = -1; free(nlm); return retval; errno = ENOTSUP; return -1; }
int if_route(const struct rt *rt, int action) { struct nlmr *nlm; int retval = 0; struct dhcp_state *state; nlm = calloc(1, sizeof(*nlm)); if (nlm == NULL) return -1; nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlm->hdr.nlmsg_type = RTM_NEWROUTE; if (action == 0) nlm->hdr.nlmsg_flags = NLM_F_REPLACE; else if (action == 1) nlm->hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL; else nlm->hdr.nlmsg_type = RTM_DELROUTE; nlm->hdr.nlmsg_flags |= NLM_F_REQUEST; nlm->rt.rtm_family = AF_INET; nlm->rt.rtm_table = RT_TABLE_MAIN; state = D_STATE(rt->iface); if (action == -1 || action == -2) nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; else { nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; /* We only change route metrics for kernel routes */ if (rt->dest.s_addr == (state->addr.s_addr & state->net.s_addr) && rt->net.s_addr == state->net.s_addr) nlm->rt.rtm_protocol = RTPROT_KERNEL; else nlm->rt.rtm_protocol = RTPROT_BOOT; if (rt->gate.s_addr == INADDR_ANY || (rt->gate.s_addr == rt->dest.s_addr && rt->net.s_addr == INADDR_BROADCAST)) nlm->rt.rtm_scope = RT_SCOPE_LINK; else nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE; nlm->rt.rtm_type = RTN_UNICAST; } nlm->rt.rtm_dst_len = inet_ntocidr(rt->net); add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST, &rt->dest.s_addr, sizeof(rt->dest.s_addr)); if (nlm->rt.rtm_protocol == RTPROT_KERNEL) { add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC, &state->addr.s_addr, sizeof(state->addr.s_addr)); } /* If destination == gateway then don't add the gateway */ if (rt->dest.s_addr != rt->gate.s_addr || rt->net.s_addr != INADDR_BROADCAST) add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY, &rt->gate.s_addr, sizeof(rt->gate.s_addr)); if (rt->gate.s_addr != htonl(INADDR_LOOPBACK)) add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, rt->iface->index); add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric); if (send_netlink(&nlm->hdr) == -1) retval = -1; free(nlm); return retval; }