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;
}
예제 #2
0
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);
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}