Пример #1
0
int
if_address(const struct interface *iface, const struct in_addr *address,
    const struct in_addr *netmask, const struct in_addr *broadcast,
    int action)
{
	int retval;
	struct ifaliasreq ifa;
	union {
		struct sockaddr *sa;
		struct sockaddr_in *sin;
	} _s;

	memset(&ifa, 0, sizeof(ifa));
	strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));

#define ADDADDR(_var, _addr) {						      \
		_s.sa = &_var;						      \
		_s.sin->sin_family = AF_INET;				      \
		_s.sin->sin_len = sizeof(*_s.sin);			      \
		memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr));   \
	}

	ADDADDR(ifa.ifra_addr, address);
	ADDADDR(ifa.ifra_mask, netmask);
	if (action >= 0 && broadcast) {
		ADDADDR(ifa.ifra_broadaddr, broadcast);
	}
#undef ADDADDR

	if (action < 0)
		retval = ifioctl(socket_afnet, SIOCDIFADDR, &ifa, curlwp);
	else
		retval = ifioctl(socket_afnet, SIOCAIFADDR, &ifa, curlwp);
	return retval;
}
Пример #2
0
static int do_address (const char *ifname, struct in_addr address,
                       struct in_addr netmask, struct in_addr broadcast, int del)
{
    int s;
    struct ifaliasreq ifa;

    if (! ifname)
        return -1;

    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        logger (LOG_ERR, "socket: %s", strerror (errno));
        return -1;
    }

    memset (&ifa, 0, sizeof (ifa));
    strcpy (ifa.ifra_name, ifname);

#define ADDADDR(_var, _addr) \
    { \
      union { struct sockaddr *sa; struct sockaddr_in *sin; } _s; \
      _s.sa = &_var; \
      _s.sin->sin_family = AF_INET; \
      _s.sin->sin_len = sizeof (struct sockaddr_in); \
      memcpy (&_s.sin->sin_addr, &_addr, sizeof (struct in_addr)); \
    }

    ADDADDR (ifa.ifra_addr, address);
    ADDADDR (ifa.ifra_mask, netmask);
    if (! del)
    {
        ADDADDR (ifa.ifra_broadaddr, broadcast);
    }

#undef ADDADDR

    if (ioctl (s, del ? SIOCDIFADDR : SIOCAIFADDR, &ifa) == -1)
    {
        logger (LOG_ERR, "ioctl %s: %s", del ? "SIOCDIFADDR" : "SIOCAIFADDR",
                strerror (errno));
        close (s);
        return -1;
    }

    close (s);
    return 0;
}
Пример #3
0
int
if_address6(const struct ipv6_addr *a, int action)
{
	int s, r;
	struct in6_aliasreq ifa;
	struct in6_addr mask;

	if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1)
		return -1;

	memset(&ifa, 0, sizeof(ifa));
	strlcpy(ifa.ifra_name, a->iface->name, sizeof(ifa.ifra_name));
	/*
	 * We should not set IN6_IFF_TENTATIVE as the kernel should be
	 * able to work out if it's a new address or not.
	 *
	 * We should set IN6_IFF_AUTOCONF, but the kernel won't let us.
	 * This is probably a safety measure, but still it's not entirely right
	 * either.
	 */
#if 0
	if (a->autoconf)
		ifa.ifra_flags |= IN6_IFF_AUTOCONF;
#endif

#define ADDADDR(v, addr) {						      \
		(v)->sin6_family = AF_INET6;				      \
		(v)->sin6_len = sizeof(*v);				      \
		(v)->sin6_addr = *addr;					      \
	}

	ADDADDR(&ifa.ifra_addr, &a->addr);
	ifa_scope(&ifa.ifra_addr, a->iface->index);
	ipv6_mask(&mask, a->prefix_len);
	ADDADDR(&ifa.ifra_prefixmask, &mask);
	ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime;
	ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime;
#undef ADDADDR

	r = ioctl(s, action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
	close(s);
	return r;
}
Пример #4
0
int
if_address(const struct interface *iface, const struct in_addr *address,
    const struct in_addr *netmask, const struct in_addr *broadcast,
    int action)
{
	int s, r;
	struct ifaliasreq ifa;
	union {
		struct sockaddr *sa;
		struct sockaddr_in *sin;
	} _s;

	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
		return -1;

	memset(&ifa, 0, sizeof(ifa));
	strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));

#define ADDADDR(_var, _addr) {						      \
		_s.sa = &_var;						      \
		_s.sin->sin_family = AF_INET;				      \
		_s.sin->sin_len = sizeof(*_s.sin);			      \
		memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr));   \
	}

	ADDADDR(ifa.ifra_addr, address);
	ADDADDR(ifa.ifra_mask, netmask);
	if (action >= 0 && broadcast) {
		ADDADDR(ifa.ifra_broadaddr, broadcast);
	}
#undef ADDADDR

	r = ioctl(s,
	    action < 0 ? SIOCDIFADDR :
	    action == 2 ? SIOCSIFADDR :  SIOCAIFADDR, &ifa);
	close(s);
	return r;
}
Пример #5
0
/* ARGSUSED4 */
int
if_route(const struct interface *iface, const struct in_addr *dest,
    const struct in_addr *net, const struct in_addr *gate,
    int metric, int action)
{
	int error;

	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in sin;
#ifdef INET6
		struct sockaddr_in6 sin6;
#endif
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	struct rtm 
	{
		struct rt_msghdr hdr;
		char buffer[sizeof(su) * 4];
	} rtm;
	char *bp = rtm.buffer, *p;
	size_t l;
	struct mbuf *m;

#define ADDSU(_su) {							      \
		l = RT_ROUNDUP(_su.sa.sa_len);				      \
		memcpy(bp, &(_su), l);					      \
		bp += l;						      \
	}
#define ADDADDR(_a) {							      \
		memset (&su, 0, sizeof(su));				      \
		su.sin.sin_family = AF_INET;				      \
		su.sin.sin_len = sizeof(su.sin);			      \
		memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr));	      \
		ADDSU(su);						      \
	}

	memset(&rtm, 0, sizeof(rtm));
	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = 1;
	if (action == 0)
		rtm.hdr.rtm_type = RTM_CHANGE;
	else if (action > 0)
		rtm.hdr.rtm_type = RTM_ADD;
	else {
		rtm.hdr.rtm_type = RTM_DELETE;
		/* shortcircuit a bit for now */
		return 0;
	}
	rtm.hdr.rtm_flags = RTF_UP;
	/* None interface subnet routes are static. */
	if (gate->s_addr != INADDR_ANY ||
	    net->s_addr != iface->net.s_addr ||
	    dest->s_addr != (iface->addr.s_addr & iface->net.s_addr))
		rtm.hdr.rtm_flags |= RTF_STATIC;
	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
	if (dest->s_addr == gate->s_addr && net->s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST;
	else {
		rtm.hdr.rtm_addrs |= RTA_NETMASK;
		if (rtm.hdr.rtm_flags & RTF_STATIC)
			rtm.hdr.rtm_flags |= RTF_GATEWAY;
		if (action >= 0)
			rtm.hdr.rtm_addrs |= RTA_IFA;
	}

	ADDADDR(dest);
	if (rtm.hdr.rtm_flags & RTF_HOST ||
	    !(rtm.hdr.rtm_flags & RTF_STATIC))
	{
		/* Make us a link layer socket for the host gateway */
		memset(&su, 0, sizeof(su));
		memcpy(&su.sdl, iface->ifp->if_sadl, sizeof(su.sdl));
		ADDSU(su);
	} else {
		ADDADDR(gate);
	}

	if (rtm.hdr.rtm_addrs & RTA_NETMASK) {
		/* Ensure that netmask is set correctly */
		memset(&su, 0, sizeof(su));
		su.sin.sin_family = AF_INET;
		su.sin.sin_len = sizeof(su.sin);
		memcpy(&su.sin.sin_addr, &net->s_addr, sizeof(su.sin.sin_addr));
		p = su.sa.sa_len + (char *)&su;
		for (su.sa.sa_len = 0; p > (char *)&su;)
			if (*--p != 0) {
				su.sa.sa_len = 1 + p - (char *)&su;
				break;
			}
		ADDSU(su);
	}

	if (rtm.hdr.rtm_addrs & RTA_IFA)
		ADDADDR(&iface->addr);

	m = m_gethdr(M_WAIT, MT_DATA);
	m->m_pkthdr.len = rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
	m->m_len = 0;
	m_copyback(m, 0, l, &rtm);

	/* XXX: no check */
	solock(routeso);
#if __NetBSD_Prereq__(7,99,26)
	error = routeso->so_proto->pr_usrreqs->pr_send(routeso,
	    m, NULL, NULL, curlwp);
#else
	error = routeso->so_proto->pr_output(m, routeso);
#endif
	sounlock(routeso);

	return error;
}
Пример #6
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)
{
    int s;
    char *dstd;
    char *gend;
    struct rtm
    {
        struct rt_msghdr hdr;
        struct sockaddr_in destination;
        union
        {
            struct sockaddr sa;
            struct sockaddr_in sin;
            struct sockaddr_dl sdl;
            struct sockaddr_storage sss; /* added to avoid memory overrun */
        } gateway;
        struct sockaddr_in netmask;
    } rtm;
    static int seq;

    if (! ifname)
        return -1;

    /* Do something with metric to satisfy compiler warnings */
    metric = 0;

    dstd = strdup (inet_ntoa (destination));
    if (gateway.s_addr == destination.s_addr)
        logger (LOG_INFO, "%s route to %s/%d",
                change ? "changing" : del ? "removing" : "adding",
                dstd, gend, inet_ntocidr (netmask));
    else if (destination.s_addr == INADDR_ANY && netmask.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)) < 0)
    {
        logger (LOG_ERR, "socket: %s", strerror (errno));
        return -1;
    }

    memset (&rtm, 0, sizeof (struct rtm));

    rtm.hdr.rtm_version = RTM_VERSION;
    rtm.hdr.rtm_seq = ++seq;
    rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD;

    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;

    rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;

#define ADDADDR(_var, _addr) \
  _var.sin_family = AF_INET; \
  _var.sin_len = sizeof (struct sockaddr_in); \
  memcpy (&_var.sin_addr, &_addr, sizeof (struct in_addr));

    ADDADDR (rtm.destination, destination);
    if (netmask.s_addr == INADDR_BROADCAST)
    {
        struct ifaddrs *ifap, *ifa;
        union
        {
            struct sockaddr *sa;
            struct sockaddr_dl *sdl;
        } us;

        if (getifaddrs (&ifap))
        {
            logger (LOG_ERR, "getifaddrs: %s", strerror (errno));
            return -1;
        }

        for (ifa = ifap; ifa; ifa = ifa->ifa_next)
        {
            if (ifa->ifa_addr->sa_family != AF_LINK)
                continue;

            if (strcmp (ifname, ifa->ifa_name))
                continue;

            us.sa = ifa->ifa_addr;
            memcpy (&rtm.gateway.sdl, us.sdl, us.sdl->sdl_len);
            break;
        }
        freeifaddrs (ifap);
    }
    else
    {
        ADDADDR (rtm.gateway.sin, gateway);
    }

    ADDADDR (rtm.netmask, netmask);

#undef ADDADDR

    rtm.hdr.rtm_msglen = sizeof (rtm);

    if (write(s, &rtm, sizeof (rtm)) < 0)
    {
        /* Don't report error about routes already existing */
        if (errno != EEXIST)
            logger (LOG_ERR, "write: %s", strerror (errno));
        close (s);
        return -1;
    }

    close (s);
    return 0;
}
Пример #7
0
/* ARGSUSED4 */
int
if_route(const struct interface *iface, const struct in_addr *dest,
    const struct in_addr *net, const struct in_addr *gate,
    _unused int metric, int action)
{
	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in sin;
#ifdef INET6
		struct sockaddr_in6 sin6;
#endif
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	struct rtm 
	{
		struct rt_msghdr hdr;
		char buffer[sizeof(su) * 4];
	} rtm;
	char *bp = rtm.buffer, *p;
	size_t l;
	int retval = 0;

#define ADDSU(_su) {							      \
		l = ROUNDUP(_su.sa.sa_len);				      \
		memcpy(bp, &(_su), l);					      \
		bp += l;						      \
	}
#define ADDADDR(_a) {							      \
		memset (&su, 0, sizeof(su));				      \
		su.sin.sin_family = AF_INET;				      \
		su.sin.sin_len = sizeof(su.sin);			      \
		memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr));	      \
		ADDSU(su);						      \
	}

	memset(&rtm, 0, sizeof(rtm));
	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = 1;
	if (action == 0)
		rtm.hdr.rtm_type = RTM_CHANGE;
	else if (action > 0)
		rtm.hdr.rtm_type = RTM_ADD;
	else
		rtm.hdr.rtm_type = RTM_DELETE;
	rtm.hdr.rtm_flags = RTF_UP;
	/* None interface subnet routes are static. */
	if (gate->s_addr != INADDR_ANY ||
	    net->s_addr != iface->net.s_addr ||
	    dest->s_addr != (iface->addr.s_addr & iface->net.s_addr))
		rtm.hdr.rtm_flags |= RTF_STATIC;
	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
	if (dest->s_addr == gate->s_addr && net->s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST;
	else {
		rtm.hdr.rtm_addrs |= RTA_NETMASK;
		if (rtm.hdr.rtm_flags & RTF_STATIC)
			rtm.hdr.rtm_flags |= RTF_GATEWAY;
		if (action >= 0)
			rtm.hdr.rtm_addrs |= RTA_IFA;
	}

	ADDADDR(dest);
	if (rtm.hdr.rtm_flags & RTF_HOST ||
	    !(rtm.hdr.rtm_flags & RTF_STATIC))
	{
		/* Make us a link layer socket for the host gateway */
		memset(&su, 0, sizeof(su));
		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
		link_addr(iface->name, &su.sdl);
		ADDSU(su);
	} else
		ADDADDR(gate);

	if (rtm.hdr.rtm_addrs & RTA_NETMASK) {
		/* Ensure that netmask is set correctly */
		memset(&su, 0, sizeof(su));
		su.sin.sin_family = AF_INET;
		su.sin.sin_len = sizeof(su.sin);
		memcpy(&su.sin.sin_addr, &net->s_addr, sizeof(su.sin.sin_addr));
		p = su.sa.sa_len + (char *)&su;
		for (su.sa.sa_len = 0; p > (char *)&su;)
			if (*--p != 0) {
				su.sa.sa_len = 1 + p - (char *)&su;
				break;
			}
		ADDSU(su);
	}

	if (rtm.hdr.rtm_addrs & RTA_IFA)
		ADDADDR(&iface->addr);

	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
	if (write(r_fd, &rtm, l) == -1)
		retval = -1;
	return retval;
}
Пример #8
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)
{
  if (! ifname)
    return -1;

  char *destd = strdup (inet_ntoa (destination));
  char *gend = strdup (inet_ntoa (netmask));
  logger (LOG_INFO, "%s route to %s (%s) via %s",
	  change ? "changing" : del ? "removing" : "adding",
	  destd, gend, inet_ntoa(gateway));
  if (destd)
    free (destd);
  if (gend)
    free (gend);

  int s;
  if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) 
    {
      logger (LOG_ERR, "socket: %s", strerror (errno));
      return -1;
    }

  struct rtm
    {
      struct rt_msghdr hdr;
      struct sockaddr_in destination;
      struct sockaddr_in gateway;
      struct sockaddr_in netmask;
    } rtm;
  memset (&rtm, 0, sizeof (struct rtm));

  rtm.hdr.rtm_version = RTM_VERSION;
  static int seq;
  rtm.hdr.rtm_seq = ++seq;
  rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD;

  rtm.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
  if (netmask.s_addr == 0xffffffff)
    rtm.hdr.rtm_flags |= RTF_HOST;

  rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;

#define ADDADDR(_var, _addr) \
  _var.sin_family = AF_INET; \
  _var.sin_len = sizeof (struct sockaddr_in); \
  memcpy (&_var.sin_addr, &_addr, sizeof (struct in_addr));

  ADDADDR (rtm.destination, destination);
  ADDADDR (rtm.gateway, gateway);
  ADDADDR (rtm.netmask, netmask);

#undef ADDADDR

  rtm.hdr.rtm_msglen = sizeof (rtm);

  if (write(s, &rtm, sizeof (rtm)) < 0)
    {
      /* Don't report error about routes already existing */
      if (errno != EEXIST)
	logger (LOG_ERR, "write: %s", strerror (errno));
      close (s);
      return -1;
    }

  close (s);
  return 0;
}
Пример #9
0
int
if_route6(const struct rt6 *rt, int action)
{
	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in6 sin;
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	struct rtm
	{
		struct rt_msghdr hdr;
		char buffer[sizeof(su) * 4];
	} rtm;
	char *bp = rtm.buffer;
	size_t l;
	int retval = 0;
	const struct ipv6_addr_l *lla;

/* KAME based systems want to store the scope inside the sin6_addr
 * for link local addreses */
#ifdef __KAME__
#define SCOPE {								      \
		if (IN6_IS_ADDR_LINKLOCAL(&su.sin.sin6_addr)) {		      \
			uint16_t scope = htons(su.sin.sin6_scope_id);	      \
			memcpy(&su.sin.sin6_addr.s6_addr[2], &scope,	      \
			    sizeof(scope));				      \
			su.sin.sin6_scope_id = 0;			      \
		}							      \
	}
#else
#define SCOPE
#endif

#define ADDSU {								      \
		l = RT_ROUNDUP(su.sa.sa_len);				      \
		memcpy(bp, &su, l);					      \
		bp += l;						      \
	}
#define ADDADDRS(addr, scope) {						      \
		memset(&su, 0, sizeof(su));				      \
		su.sin.sin6_family = AF_INET6;				      \
		su.sin.sin6_len = sizeof(su.sin);			      \
		(&su.sin)->sin6_addr = *addr;				      \
		su.sin.sin6_scope_id = scope;				      \
		SCOPE;							      \
		ADDSU;							      \
	}
#define ADDADDR(addr) ADDADDRS(addr, 0)

	memset(&rtm, 0, sizeof(rtm));
	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = 1;
	if (action == 0)
		rtm.hdr.rtm_type = RTM_CHANGE;
	else if (action > 0)
		rtm.hdr.rtm_type = RTM_ADD;
	else
		rtm.hdr.rtm_type = RTM_DELETE;

	rtm.hdr.rtm_flags = RTF_UP;
	/* None interface subnet routes are static. */
	if (IN6_IS_ADDR_UNSPECIFIED(&rt->dest) &&
	    IN6_IS_ADDR_UNSPECIFIED(&rt->net))
		rtm.hdr.rtm_flags |= RTF_GATEWAY;
#ifdef RTF_CLONING
	else
		rtm.hdr.rtm_flags |= RTF_CLONING;
#endif

	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
	if (action >= 0)
		rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;

	ADDADDR(&rt->dest);
	if (!(rtm.hdr.rtm_flags & RTF_GATEWAY)) {
		lla = ipv6_linklocal(rt->iface);
		if (lla == NULL) /* unlikely as we need a LL to get here */
			return -1;
		ADDADDRS(&lla->addr, rt->iface->index);
	} else {
		lla = NULL;
		ADDADDRS(&rt->gate, rt->iface->index);
	}

	if (rtm.hdr.rtm_addrs & RTA_NETMASK) {
		if (rtm.hdr.rtm_flags & RTF_GATEWAY) {
			memset(&su, 0, sizeof(su));
			su.sin.sin6_family = AF_INET6;
			ADDSU;
		} else
			ADDADDR(&rt->net);
	}

	if (rtm.hdr.rtm_addrs & RTA_IFP) {
		/* Make us a link layer socket for the host gateway */
		memset(&su, 0, sizeof(su));
		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
		link_addr(rt->iface->name, &su.sdl);
		ADDSU;
	}

	if (rtm.hdr.rtm_addrs & RTA_IFA) {
		if (lla == NULL) {
			lla = ipv6_linklocal(rt->iface);
			if (lla == NULL) /* unlikely */
				return -1;
		}
		ADDADDRS(&lla->addr, rt->iface->index);
	}

#undef ADDADDR
#undef ADDSU
#undef SCOPE

	if (action >= 0 && rt->mtu) {
		rtm.hdr.rtm_inits |= RTV_MTU;
		rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
	}

	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
	if (write(r_fd, &rtm, l) == -1)
		retval = -1;
	return retval;
}
Пример #10
0
int
if_route(const struct rt *rt, int action)
{
	const struct dhcp_state *state;
	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in sin;
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	struct rtm
	{
		struct rt_msghdr hdr;
		char buffer[sizeof(su) * 4];
	} rtm;
	char *bp = rtm.buffer;
	size_t l;
	int retval = 0;

#define ADDSU {								      \
		l = RT_ROUNDUP(su.sa.sa_len);				      \
		memcpy(bp, &su, l);					      \
		bp += l;						      \
	}
#define ADDADDR(addr) {							      \
		memset(&su, 0, sizeof(su));				      \
		su.sin.sin_family = AF_INET;				      \
		su.sin.sin_len = sizeof(su.sin);			      \
		(&su.sin)->sin_addr = *addr;				      \
		ADDSU;							      \
	}

	state = D_CSTATE(rt->iface);
	memset(&rtm, 0, sizeof(rtm));
	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = 1;
	if (action == 0)
		rtm.hdr.rtm_type = RTM_CHANGE;
	else if (action > 0)
		rtm.hdr.rtm_type = RTM_ADD;
	else
		rtm.hdr.rtm_type = RTM_DELETE;
	rtm.hdr.rtm_flags = RTF_UP;
	/* None interface subnet routes are static. */
	if (rt->gate.s_addr != INADDR_ANY ||
	    rt->net.s_addr != state->net.s_addr ||
	    rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr))
		rtm.hdr.rtm_flags |= RTF_STATIC;
	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
	if (rt->dest.s_addr == rt->gate.s_addr &&
	    rt->net.s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST;
	else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
	    rt->net.s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
	else {
		rtm.hdr.rtm_addrs |= RTA_NETMASK;
		if (rtm.hdr.rtm_flags & RTF_STATIC)
			rtm.hdr.rtm_flags |= RTF_GATEWAY;
		if (action >= 0)
			rtm.hdr.rtm_addrs |= RTA_IFA;
	}

	ADDADDR(&rt->dest);
	if ((rtm.hdr.rtm_flags & RTF_HOST &&
	    rt->gate.s_addr != htonl(INADDR_LOOPBACK)) ||
	    !(rtm.hdr.rtm_flags & RTF_STATIC))
	{
		/* Make us a link layer socket for the host gateway */
		memset(&su, 0, sizeof(su));
		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
		link_addr(rt->iface->name, &su.sdl);
		ADDSU;
	} else
		ADDADDR(&rt->gate);

	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
		ADDADDR(&rt->net);

	if (rtm.hdr.rtm_addrs & RTA_IFP) {
		/* Make us a link layer socket for the host gateway */
		memset(&su, 0, sizeof(su));
		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
		link_addr(rt->iface->name, &su.sdl);
		ADDSU;
	}

	if (rtm.hdr.rtm_addrs & RTA_IFA)
		ADDADDR(&state->addr);

#undef ADDADDR
#undef ADDSU

	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
	if (write(r_fd, &rtm, l) == -1)
		retval = -1;
	return retval;
}
Пример #11
0
int
if_route6(const struct rt6 *rt, int action)
{
	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in6 sin;
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	struct rtm
	{
		struct rt_msghdr hdr;
		char buffer[sizeof(su) * 5];
	} rtm;
	char *bp = rtm.buffer;
	size_t l;
	int s, retval;
	const struct ipv6_addr *lla;

	if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
		return -1;

#define ADDSU {								      \
		l = RT_ROUNDUP(su.sa.sa_len);				      \
		memcpy(bp, &su, l);					      \
		bp += l;						      \
	}
#define ADDADDRS(addr, scope) {						      \
		memset(&su, 0, sizeof(su));				      \
		su.sin.sin6_family = AF_INET6;				      \
		su.sin.sin6_len = sizeof(su.sin);			      \
		(&su.sin)->sin6_addr = *addr;				      \
		if (scope)						      \
			ifa_scope(&su.sin, scope);			      \
		ADDSU;							      \
	}
#define ADDADDR(addr) ADDADDRS(addr, 0)

	memset(&rtm, 0, sizeof(rtm));
	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = 1;
	if (action == 0)
		rtm.hdr.rtm_type = RTM_CHANGE;
	else if (action > 0)
		rtm.hdr.rtm_type = RTM_ADD;
	else
		rtm.hdr.rtm_type = RTM_DELETE;
	rtm.hdr.rtm_flags = RTF_UP | (int)rt->flags;
#ifdef RTF_PINNED
	if (rtm.hdr.rtm_type != RTM_ADD)
		rtm.hdr.rtm_flags |= RTF_PINNED;
#endif
	rtm.hdr.rtm_addrs = RTA_DST | RTA_NETMASK;
#ifdef SIOCGIFPRIORITY
	rtm.hdr.rtm_priority = rt->metric;
#endif
	/* None interface subnet routes are static. */
	if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
#ifdef RTF_CLONING
		rtm.hdr.rtm_flags |= RTF_CLONING;
#endif
	 } else
		rtm.hdr.rtm_flags |= RTF_GATEWAY | RTF_STATIC;

	if (action >= 0) {
		rtm.hdr.rtm_addrs |= RTA_GATEWAY;
		if (!(rtm.hdr.rtm_flags & RTF_REJECT))
			rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;
	}

	ADDADDR(&rt->dest);
	lla = NULL;
	if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
		if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
			if_linkaddr(&su.sdl, rt->iface);
			ADDSU;
		} else {
			ADDADDRS(&rt->gate, rt->iface->index);
		}
	}

	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
		ADDADDR(&rt->net);

	if (rtm.hdr.rtm_addrs & RTA_IFP) {
		if_linkaddr(&su.sdl, rt->iface);
		ADDSU;
	}

	if (rtm.hdr.rtm_addrs & RTA_IFA) {
		if (lla == NULL) {
			lla = ipv6_linklocal(rt->iface);
			if (lla == NULL) /* unlikely */
				return -1;
		}
		ADDADDRS(&lla->addr, rt->iface->index);
	}

#undef ADDADDR
#undef ADDSU

	if (action >= 0 && rt->mtu) {
		rtm.hdr.rtm_inits |= RTV_MTU;
		rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
	}

	rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);

	retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
	close(s);
	return retval;
}
Пример #12
0
int
if_route(const struct rt *rt, int action)
{
	const struct dhcp_state *state;
	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in sin;
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	struct rtm
	{
		struct rt_msghdr hdr;
		char buffer[sizeof(su) * 5];
	} rtm;
	char *bp = rtm.buffer;
	size_t l;
	int s, retval;

	if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
		return -1;

#define ADDSU {								      \
		l = RT_ROUNDUP(su.sa.sa_len);				      \
		memcpy(bp, &su, l);					      \
		bp += l;						      \
	}
#define ADDADDR(addr) {							      \
		memset(&su, 0, sizeof(su));				      \
		su.sin.sin_family = AF_INET;				      \
		su.sin.sin_len = sizeof(su.sin);			      \
		(&su.sin)->sin_addr = *addr;				      \
		ADDSU;							      \
	}

	state = D_CSTATE(rt->iface);
	memset(&rtm, 0, sizeof(rtm));
	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = 1;
	rtm.hdr.rtm_addrs = RTA_DST;
	if (action == 0)
		rtm.hdr.rtm_type = RTM_CHANGE;
	else if (action > 0) {
		rtm.hdr.rtm_type = RTM_ADD;
		rtm.hdr.rtm_addrs |= RTA_GATEWAY;
	} else
		rtm.hdr.rtm_type = RTM_DELETE;
	rtm.hdr.rtm_flags = RTF_UP;
#ifdef RTF_PINNED
	if (rtm.hdr.rtm_type != RTM_ADD)
		rtm.hdr.rtm_flags |= RTF_PINNED;
#endif
#ifdef SIOCGIFPRIORITY
	rtm.hdr.rtm_priority = rt->metric;
#endif

	/* None interface subnet routes are static. */
	if (rt->gate.s_addr != INADDR_ANY ||
	    rt->net.s_addr != state->net.s_addr ||
	    rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr))
		rtm.hdr.rtm_flags |= RTF_STATIC;
	if (rt->dest.s_addr == rt->gate.s_addr &&
	    rt->net.s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST;
	else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
	    rt->net.s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
	else {
		rtm.hdr.rtm_addrs |= RTA_NETMASK;
		if (rtm.hdr.rtm_flags & RTF_STATIC)
			rtm.hdr.rtm_flags |= RTF_GATEWAY;
		if (action >= 0)
			rtm.hdr.rtm_addrs |= RTA_IFA;
	}

	ADDADDR(&rt->dest);
	if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
		if ((rtm.hdr.rtm_flags & RTF_HOST &&
		    rt->gate.s_addr != htonl(INADDR_LOOPBACK)) ||
		    !(rtm.hdr.rtm_flags & RTF_STATIC))
		{
			if_linkaddr(&su.sdl, rt->iface);
			ADDSU;
		} else
			ADDADDR(&rt->gate);
	}

	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
		ADDADDR(&rt->net);

	if (rtm.hdr.rtm_addrs & RTA_IFP) {
		if_linkaddr(&su.sdl, rt->iface);
		ADDSU;
	}

	if (rtm.hdr.rtm_addrs & RTA_IFA)
		ADDADDR(&state->addr);

#undef ADDADDR
#undef ADDSU

	rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);

	retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
	close(s);
	return retval;
}
Пример #13
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)
{
	int s;
	struct rtm 
	{
		struct rt_msghdr hdr;
		char buffer[sizeof (struct sockaddr_storage) * 3];
	} rtm;
	char *bp = rtm.buffer;
	static int seq;
	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in sin;
#ifdef INET6
		struct sockaddr_in6 sin6;
#endif
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	
	int l;

	if (! ifname)
		return -1;

	log_route (destination, netmask, gateway, metric, change, del);

	if ((s = socket (PF_ROUTE, SOCK_RAW, 0)) == -1) {
		logger (LOG_ERR, "socket: %s", strerror (errno));
		return -1;
	}

	memset (&rtm, 0, sizeof (struct rtm));

	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = ++seq;
	rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD;
	rtm.hdr.rtm_flags = RTF_UP | RTF_STATIC;

	/* This order is important */
	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;

#define ADDADDR(_addr) \
	memset (&su, 0, sizeof (struct sockaddr_storage)); \
	su.sin.sin_family = AF_INET; \
	su.sin.sin_len = sizeof (struct sockaddr_in); \
	memcpy (&su.sin.sin_addr, &_addr, sizeof (struct in_addr)); \
	l = SA_SIZE (&(su.sa)); \
	memcpy (bp, &(su), l); \
	bp += l;

	ADDADDR (destination);

	if (netmask.s_addr == INADDR_BROADCAST ||
		gateway.s_addr == INADDR_ANY)
	{
		/* Make us a link layer socket */
		unsigned char *hwaddr;
		int hwlen = 0;

		if (netmask.s_addr == INADDR_BROADCAST) 
			rtm.hdr.rtm_flags |= RTF_HOST;

		hwaddr = xmalloc (sizeof (unsigned char) * HWADDR_LEN);
		_do_interface (ifname, hwaddr, &hwlen, NULL, false, false);
		memset (&su, 0, sizeof (struct sockaddr_storage));
		su.sdl.sdl_len = sizeof (struct sockaddr_dl);
		su.sdl.sdl_family = AF_LINK;
		su.sdl.sdl_nlen = strlen (ifname);
		memcpy (&su.sdl.sdl_data, ifname, su.sdl.sdl_nlen);
		su.sdl.sdl_alen = hwlen;
		memcpy (((unsigned char *) &su.sdl.sdl_data) + su.sdl.sdl_nlen,
				hwaddr, su.sdl.sdl_alen);

		l = SA_SIZE (&(su.sa));
		memcpy (bp, &su, l);
		bp += l;
		free (hwaddr);
	} else {
		rtm.hdr.rtm_flags |= RTF_GATEWAY;
		ADDADDR (gateway);
	}

	ADDADDR (netmask);
#undef ADDADDR

	rtm.hdr.rtm_msglen = sizeof (rtm);
	if (write (s, &rtm, sizeof (rtm)) == -1) {
		/* Don't report error about routes already existing */
		if (errno != EEXIST)
			logger (LOG_ERR, "write: %s", strerror (errno));
		close (s);
		return -1;
	}

	close (s);
	return 0;
}