示例#1
0
const char *
inet6_n2a(struct in6_addr *p)
{
	static char buf[NI_MAXHOST];
	struct sockaddr_in6 sin6;
	u_int32_t scopeid;
#ifdef NI_WITHSCOPEID
	const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
#else
	const int niflags = NI_NUMERICHOST;
#endif

	memset(&sin6, 0, sizeof(sin6));
	sin6.sin6_family = AF_INET6;
	sin6.sin6_len = sizeof(struct sockaddr_in6);
	sin6.sin6_addr = *p;
	if (IN6_IS_ADDR_LINKLOCAL(p) || IN6_IS_ADDR_MC_LINKLOCAL(p)) {
		scopeid = ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
		if (scopeid) {
			sin6.sin6_scope_id = scopeid;
			sin6.sin6_addr.s6_addr[2] = 0;
			sin6.sin6_addr.s6_addr[3] = 0;
		}
	}
	if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
			buf, sizeof(buf), NULL, 0, niflags) == 0)
		return buf;
	else
		return "(invalid)";
}
示例#2
0
/** Determines the IPv6 scope of a specified address.
 *
 * @param[in] v6Addr - The IPv6 address to be checked.
 *
 * @return The ipv6 scope of the address.
 *
 * @remarks The @p v6Addr parameter must be pointer to a 16-byte IPv6 
 *    address in binary form.
 * 
 * @internal
 */
static int setScopeFromAddress(const struct in6_addr * v6Addr)
{
   if (IN6_IS_ADDR_MULTICAST(v6Addr))
   {
      if (IN6_IS_ADDR_MC_GLOBAL(v6Addr))
         return SLP_SCOPE_GLOBAL;

      if (IN6_IS_ADDR_MC_ORGLOCAL(v6Addr))
         return SLP_SCOPE_ORG_LOCAL;

      if (IN6_IS_ADDR_MC_SITELOCAL(v6Addr))
         return SLP_SCOPE_SITE_LOCAL;

      if (IN6_IS_ADDR_MC_NODELOCAL(v6Addr))
         return SLP_SCOPE_NODE_LOCAL;

      if (IN6_IS_ADDR_MC_LINKLOCAL(v6Addr))
         return SLP_SCOPE_LINK_LOCAL;
   }
   if (IN6_IS_ADDR_SITELOCAL(v6Addr))
      return SLP_SCOPE_SITE_LOCAL;

   if (SLP_IN6_IS_ADDR_LOOPBACK(v6Addr))
      return SLP_SCOPE_NODE_LOCAL;

   if (IN6_IS_ADDR_LINKLOCAL(v6Addr))
      return SLP_SCOPE_LINK_LOCAL;

   return 0;
}
示例#3
0
static void 
ifa_make_sockaddr(sa_family_t family, 
		  struct sockaddr *sa, 
		  void *p, size_t len,
		  uint32_t scope, uint32_t scopeid)
{
  if (sa == NULL) return;
  switch(family){
  case AF_INET:
    memcpy(&((struct sockaddr_in*)sa)->sin_addr, (char *)p, len);
    break;
  case AF_INET6:
    memcpy(&((struct sockaddr_in6*)sa)->sin6_addr, (char *)p, len);
    if (IN6_IS_ADDR_LINKLOCAL(p) ||
	IN6_IS_ADDR_MC_LINKLOCAL(p)){
      ((struct sockaddr_in6*)sa)->sin6_scope_id = scopeid;
    }
    break;
  case AF_PACKET:
    memcpy(((struct sockaddr_ll*)sa)->sll_addr, (char *)p, len);
    ((struct sockaddr_ll*)sa)->sll_halen = len;
    break;
  default:
    memcpy(sa->sa_data, p, len);	/*XXX*/
    break;
  }
  sa->sa_family = family;
#ifdef HAVE_SOCKADDR_SA_LEN
  sa->sa_len = ifa_sa_len(family, len);
#endif
}
示例#4
0
static void copy_addr(struct sockaddr** r,
                      int af,
                      union sockany* sa,
                      void* addr,
                      size_t addrlen,
                      int ifindex) {
  uint8_t* dst;
  int len;

  switch (af) {
    case AF_INET:
      dst = (uint8_t*)&sa->v4.sin_addr;
      len = 4;
      break;
    case AF_INET6:
      dst = (uint8_t*)&sa->v6.sin6_addr;
      len = 16;
      if (IN6_IS_ADDR_LINKLOCAL(addr) || IN6_IS_ADDR_MC_LINKLOCAL(addr))
        sa->v6.sin6_scope_id = ifindex;
      break;
    default:
      return;
  }
  if (addrlen < len)
    return;
  sa->sa.sa_family = af;
  memcpy(dst, addr, len);
  *r = &sa->sa;
}
示例#5
0
/* Parse SOURCE as a scope ID for ADDRESS.  Return 0 on success and -1
   on error.  */
internal_function int
__inet6_scopeid_pton (const struct in6_addr *address, const char *scope,
                      uint32_t *result)
{
  if (IN6_IS_ADDR_LINKLOCAL (address)
      || IN6_IS_ADDR_MC_LINKLOCAL (address))
    {
      uint32_t number = __if_nametoindex (scope);
      if (number != 0)
        {
          *result = number;
          return 0;
        }
    }

  if (isdigit_l (scope[0], _nl_C_locobj_ptr))
    {
      char *end;
      unsigned long long number
        = ____strtoull_l_internal (scope, &end, /*base */ 10, /* group */ 0,
                                   _nl_C_locobj_ptr);
      if (*end == '\0' && number <= UINT32_MAX)
        {
          *result = number;
          return 0;
        }
    }

  __set_errno (EINVAL);
  return -1;
}
示例#6
0
const char *
ACE_INET_Addr::get_host_addr (char *dst, int size) const
{
#if defined (ACE_HAS_IPV6)
  if (this->get_type () == AF_INET6)
    {
      // [email protected] - Aug-26, 2005
      // I don't think this should be done because it results in a decimal address
      // representation which is not distinguishable from the IPv4 form which makes
      // it impossible to resolve back to an IPv6 INET_Addr without prior knowledge
      // that this was such an address to begin with.

      //if (IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr))
      //{
      //  ACE_UINT32 addr;
      //  addr = this->get_ip_address();
      //  addr = ACE_HTONL (addr);
      //  return ACE_OS::inet_ntop (AF_INET, &addr, dst, size);
      //}

#  if defined (ACE_WIN32)
      if (0 == ::getnameinfo (reinterpret_cast<const sockaddr*> (&this->inet_addr_.in6_),
                              this->get_size (),
                              dst,
                              size,
                              0, 0,    // Don't want service name
                              NI_NUMERICHOST))
        return dst;
      ACE_OS::set_errno_to_wsa_last_error ();
      return 0;
#  else
      const char *ch = ACE_OS::inet_ntop (AF_INET6,
                                          &this->inet_addr_.in6_.sin6_addr,
                                          dst,
                                          size);
#if defined (__linux__)
      if ((IN6_IS_ADDR_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr) ||
           IN6_IS_ADDR_MC_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr)) &&
          this->inet_addr_.in6_.sin6_scope_id != 0)
        {
          char scope_buf[32];
          ACE_OS::sprintf (scope_buf, "%%%u", this->inet_addr_.in6_.sin6_scope_id);
          if ((ACE_OS::strlen (ch)+ACE_OS::strlen (scope_buf)) < (size_t)size)
            {
              ACE_OS::strcat (dst, scope_buf);
            }
        }
#endif
      return ch;
#  endif /* ACE_WIN32 */
    }
#endif /* ACE_HAS_IPV6 */

  return ACE_OS::inet_ntop (AF_INET,
          &this->inet_addr_.in4_.sin_addr,
          dst,
          size);
}
示例#7
0
struct sockaddr *
_SC_string_to_sockaddr(const char *str, sa_family_t af, void *buf, size_t bufLen)
{
	union {
		void			*buf;
		struct sockaddr		*sa;
		struct sockaddr_in	*sin;
		struct sockaddr_in6	*sin6;
	} addr;

	if (buf == NULL) {
		bufLen = sizeof(struct sockaddr_storage);
		addr.buf = CFAllocatorAllocate(NULL, bufLen, 0);
	} else {
		addr.buf = buf;
	}

	bzero(addr.buf, bufLen);
	if (((af == AF_UNSPEC) || (af == AF_INET)) &&
	    (bufLen >= sizeof(struct sockaddr_in)) &&
	    inet_aton(str, &addr.sin->sin_addr) == 1) {
		// if IPv4 address
		addr.sin->sin_len    = sizeof(struct sockaddr_in);
		addr.sin->sin_family = AF_INET;
	} else if (((af == AF_UNSPEC) || (af == AF_INET6)) &&
		   (bufLen >= sizeof(struct sockaddr_in6)) &&
		   inet_pton(AF_INET6, str, &addr.sin6->sin6_addr) == 1) {
		// if IPv6 address
		char	*p;

		addr.sin6->sin6_len    = sizeof(struct sockaddr_in6);
		addr.sin6->sin6_family = AF_INET6;

		p = strchr(buf, '%');
		if (p != NULL) {
			addr.sin6->sin6_scope_id = if_nametoindex(p + 1);
		}

		if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6->sin6_addr) ||
		    IN6_IS_ADDR_MC_LINKLOCAL(&addr.sin6->sin6_addr)) {
			uint16_t	if_index;

			if_index = ntohs(addr.sin6->sin6_addr.__u6_addr.__u6_addr16[1]);
			addr.sin6->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
			if (addr.sin6->sin6_scope_id == 0) {
				// use the scope id that was embedded in the [link local] IPv6 address
				addr.sin6->sin6_scope_id = if_index;
			}
		}
	} else {
		if (addr.buf != buf) {
			CFAllocatorDeallocate(NULL, addr.buf);
		}
		addr.buf = NULL;
	}

	return addr.sa;
}
示例#8
0
static int
parse_kernel_route(const struct rt_msghdr *rtm, struct kernel_route *route)
{

    void *rta = (void*)rtm + sizeof(struct rt_msghdr);
    struct sockaddr_in6 *sin6;
    char addr[INET6_ADDRSTRLEN];

    memset(route, 0, sizeof(*route));
    route->metric = 0;
    route->ifindex = rtm->rtm_index;

    if(!(rtm->rtm_addrs & RTA_DST))
        return -1;
    sin6 = (struct sockaddr_in6 *)rta;
    if(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) 
       || IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
        return -1;
    if((rtm->rtm_flags & RTF_PROTO2) != 0)
        return -1;
    memcpy(&route->prefix, &sin6->sin6_addr, 16);
    rta += ROUNDUP(sizeof(struct sockaddr_in6));
   
    if(!(rtm->rtm_addrs & RTA_GATEWAY))
        return -1;

    sin6 = (struct sockaddr_in6 *)rta;
    if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) {
        route->ifindex = IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr);
        SET_IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr, 0);
    }
    memcpy(&route->gw, &sin6->sin6_addr, 16);
    rta += ROUNDUP(sizeof(struct sockaddr_in6));

    if(!(rtm->rtm_addrs & RTA_NETMASK)) {
        route->plen = 0;
    } else {
        sin6 = (struct sockaddr_in6 *)rta;        
        route->plen = mask2len(&sin6->sin6_addr);
        inet_ntop(AF_INET6, &sin6->sin6_addr, addr, sizeof(addr));
        rta += ROUNDUP(sizeof(struct sockaddr_in6));
    }
    if (rtm->rtm_flags & RTF_HOST)
        route->plen = 128;

    if(ifindex_lo < 0) {
        ifindex_lo = if_nametoindex("lo0");
        if(ifindex_lo <= 0)
            return -1;
    }

    if(route->ifindex == ifindex_lo)
        return -1;

    return 0;

}
示例#9
0
/*
 * check validity of a router renumbering command packet
 * return 0 on success, 1 on failure
 */
static int
rr_command_check(int len, struct icmp6_router_renum *rr, struct in6_addr *from,
		 struct in6_addr *dst)
{
	char ntopbuf[INET6_ADDRSTRLEN];

	/* omit rr minimal length check. hope kernel have done it. */
	/* rr_command length check */
	if (len < (sizeof(struct icmp6_router_renum) +
		   sizeof(struct rr_pco_match))) {
		syslog(LOG_ERR,	"<%s> rr_command len %d is too short",
		       __func__, len);
		return 1;
	}

	/* destination check. only for multicast. omit unicast check. */
	if (IN6_IS_ADDR_MULTICAST(dst) && !IN6_IS_ADDR_MC_LINKLOCAL(dst) &&
	    !IN6_IS_ADDR_MC_SITELOCAL(dst)) {
		syslog(LOG_ERR,	"<%s> dst mcast addr %s is illegal",
		       __func__,
		       inet_ntop(AF_INET6, dst, ntopbuf, INET6_ADDRSTRLEN));
		return 1;
	}

	/* seqnum and segnum check */
	if (rro.rro_seqnum > rr->rr_seqnum) {
		syslog(LOG_WARNING,
		       "<%s> rcvd old seqnum %d from %s",
		       __func__, (u_int32_t)ntohl(rr->rr_seqnum),
		       inet_ntop(AF_INET6, from, ntopbuf, INET6_ADDRSTRLEN));
		return 1;
	}
	if (rro.rro_seqnum == rr->rr_seqnum &&
	    (rr->rr_flags & ICMP6_RR_FLAGS_TEST) == 0 &&
	    RR_ISSET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum)) {
		if ((rr->rr_flags & ICMP6_RR_FLAGS_REQRESULT) != 0)
			syslog(LOG_WARNING,
			       "<%s> rcvd duped segnum %d from %s",
			       __func__, rr->rr_segnum,
			       inet_ntop(AF_INET6, from, ntopbuf,
					 INET6_ADDRSTRLEN));
		return 0;
	}

	/* update seqnum */
	if (rro.rro_seqnum != rr->rr_seqnum) {
		/* then must be "<" */

		/* init rro_segnum_bits */
		memset(rro.rro_segnum_bits, 0,
		       sizeof(rro.rro_segnum_bits));
	}
	rro.rro_seqnum = rr->rr_seqnum;

	return 0;
}
示例#10
0
文件: inet6.c 项目: MarginC/kame
char *
inet6name(struct in6_addr *in6p)
{
	char *cp;
	static char line[NI_MAXHOST];
	struct hostent *hp;
	static char domain[MAXHOSTNAMELEN];
	static int first = 1;
	char hbuf[NI_MAXHOST];
	struct sockaddr_in6 sin6;
	const int niflag = NI_NUMERICHOST;

	if (first && !nflag) {
		first = 0;
		if (gethostname(domain, sizeof(domain)) == 0 &&
		    (cp = strchr(domain, '.')))
			(void) strlcpy(domain, cp + 1, sizeof domain);
		else
			domain[0] = '\0';
	}
	cp = 0;
	if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
		if (hp) {
			if ((cp = strchr(hp->h_name, '.')) &&
			    !strcmp(cp + 1, domain))
				*cp = 0;
			cp = hp->h_name;
		}
	}
	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
		strlcpy(line, "*", sizeof(line));
	else if (cp)
		strlcpy(line, cp, sizeof(line));
	else {
		memset(&sin6, 0, sizeof(sin6));
		sin6.sin6_len = sizeof(sin6);
		sin6.sin6_family = AF_INET6;
		sin6.sin6_addr = *in6p;
#ifdef __KAME__
		if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
		    IN6_IS_ADDR_MC_LINKLOCAL(in6p)) {
			sin6.sin6_scope_id =
			    ntohs(*(u_int16_t *)&in6p->s6_addr[2]);
			sin6.sin6_addr.s6_addr[2] = 0;
			sin6.sin6_addr.s6_addr[3] = 0;
		}
#endif
		if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
		    hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
			strlcpy(hbuf, "?", sizeof hbuf);
		strlcpy(line, hbuf, sizeof(line));
	}
	return (line);
}
示例#11
0
bool
BNetworkAddress::IsMulticastLinkLocal() const
{
	switch (fAddress.ss_family) {
		case AF_INET6:
			return IN6_IS_ADDR_MC_LINKLOCAL(
				&((sockaddr_in6&)fAddress).sin6_addr);

		default:
			return false;
	}
}
示例#12
0
int svx_inetaddr_from_ipport(svx_inetaddr_t *self, const char *ip, uint16_t port)
{
    int   r = 0;
    char *ifname = NULL;
    char  ipv6[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1];

    if(NULL == self || NULL == ip) SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_INVAL, "self:%p, ip:%p\n", self, ip);
    
    memset(self, 0, sizeof(svx_inetaddr_t));

    if(!strchr(ip, ':'))
    {
        /* IPv4 */
        self->storage.addr4.sin_family = AF_INET;
        self->storage.addr4.sin_port = htons(port);
        if(1 != (r = inet_pton(AF_INET, ip, &(self->storage.addr4.sin_addr))))
            SVX_LOG_ERRNO_RETURN_ERR((0 == r ? SVX_ERRNO_INVAL : errno), "ip:%s\n", ip);
    }
    else
    {
        /* IPv6 */
        self->storage.addr6.sin6_family = AF_INET6;
        self->storage.addr6.sin6_port = htons(port);
        self->storage.addr6.sin6_flowinfo = 0; /* ignored, always 0 */
        self->storage.addr6.sin6_scope_id = 0; /* only used for link-local IPv6 address */

        strncpy(ipv6, ip, sizeof(ipv6));
        if(NULL != (ifname = strchr(ipv6, '%')))
        {
            *ifname = '\0';
            ifname++;
        }
        
        if(1 != (r = inet_pton(AF_INET6, ipv6, &(self->storage.addr6.sin6_addr))))
            SVX_LOG_ERRNO_RETURN_ERR((0 == r ? SVX_ERRNO_INVAL : errno), "ip:%s\n", ipv6);

        /* set scope id for link-local IPv6 address */
        /* man ipv6(7): Linux supports it only for link-local addresses, 
           in that case sin6_scope_id contains the interface index */
        if(IN6_IS_ADDR_LINKLOCAL(&(self->storage.addr6.sin6_addr)) || 
           IN6_IS_ADDR_MC_LINKLOCAL(&(self->storage.addr6.sin6_addr)))
        {
            if(NULL == ifname || '\0' == *ifname)
                SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_FORMAT, "IPv6 link-local address without interface: %s\n", ip);
            if(0 == (self->storage.addr6.sin6_scope_id = if_nametoindex(ifname)))
                SVX_LOG_ERRNO_RETURN_ERR(errno, "ifname:%s\n", ifname);
        }
    }

    return 0;
}
示例#13
0
int
inet6_uvif2scopeid(struct sockaddr_in6 *sa, struct uvif *v)
{
	if (IN6_IS_ADDR_MULTICAST(&sa->sin6_addr)) {
		if (IN6_IS_ADDR_MC_LINKLOCAL(&sa->sin6_addr))
			return(v->uv_ifindex);
	}
	else {
		if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr))
			return(v->uv_ifindex);
	}

	return(0);
}
示例#14
0
/*
 * Print the textual representation (as given by inet_ntop(3)) of the address
 * set in "sa".
 *
 * Return the total length of the string it tried to create or 0 if an error
 * occured, in which case errno is set.  On success, the constructed string
 * is guaranteed to be NUL-terminated.  Overflow must be detected by checking
 * the returned size against buflen.
 *
 */
static size_t
asr_print_addr(const struct sockaddr *sa, char *buf, size_t buflen)
{
	unsigned int ifidx;
	char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
	char scope[IF_NAMESIZE + 1], *ifname;
	const void *addr;
	size_t s;

	switch(sa->sa_family) {
	case AF_INET:
		addr = &SA_IN(sa)->sin_addr;
		break;
	case AF_INET6:
		addr = &SA_IN6(sa)->sin6_addr;
		break;
	default:
		errno = EINVAL;
		return (0);
	}

	if (inet_ntop(sa->sa_family, addr, tmp, sizeof(tmp)) == NULL)
		return (0); /* errno set */

	s = strlcpy(buf, tmp, buflen);

	if (sa->sa_family == AF_INET6 && SA_IN6(sa)->sin6_scope_id) {

		scope[0] = SCOPE_DELIMITER;
		scope[1] = '\0';

		ifidx = SA_IN6(sa)->sin6_scope_id;
		ifname = NULL;

		if (IN6_IS_ADDR_LINKLOCAL(&(SA_IN6(sa)->sin6_addr)) ||
		    IN6_IS_ADDR_MC_LINKLOCAL(&(SA_IN6(sa)->sin6_addr)) ||
		    IN6_IS_ADDR_MC_INTFACELOCAL(&(SA_IN6(sa)->sin6_addr)))
			ifname = if_indextoname(ifidx, scope + 1);

		if (ifname == NULL)
			(void)snprintf(scope + 1, sizeof(scope) - 1, "%u", ifidx);

		if (s < buflen)
			(void)strlcat(buf, scope, buflen);

		s += strlen(scope);
	}

	return (s);
}
示例#15
0
static struct sockaddr *
ifa_make_sockaddr_mask (sa_family_t family,
			struct sockaddr *sa, uint32_t prefixlen)
{
  int i;
  char *p = NULL, c;
  uint32_t max_prefixlen = 0;

  if (sa == NULL)
    return NULL;
  switch (family)
    {
    case AF_INET:
      memset (&((struct sockaddr_in *) sa)->sin_addr, 0,
	      sizeof (((struct sockaddr_in *) sa)->sin_addr));
      p = (char *) &((struct sockaddr_in *) sa)->sin_addr;
      max_prefixlen = 32;
      break;
    case AF_INET6:
      memset (&((struct sockaddr_in6 *) sa)->sin6_addr, 0,
	      sizeof (((struct sockaddr_in6 *) sa)->sin6_addr));
      p = (char *) &((struct sockaddr_in6 *) sa)->sin6_addr;
#if 0				/* XXX: fill scope-id? */
      if (IN6_IS_ADDR_LINKLOCAL (p) || IN6_IS_ADDR_MC_LINKLOCAL (p))
	{
	  ((struct sockaddr_in6 *) sa)->sin6_scope_id = scopeid;
	}
#endif
      max_prefixlen = 128;
      break;
    default:
      return NULL;
    }
  sa->sa_family = family;
#ifdef HAVE_SOCKADDR_SA_LEN
  sa->sa_len = ifa_sa_len (family, len);
#endif
  if (p)
    {
      if (prefixlen > max_prefixlen)
	prefixlen = max_prefixlen;
      for (i = 0; i < (prefixlen / 8); i++)
	*p++ = 0xff;
      c = 0xff;
      c <<= (8 - (prefixlen % 8));
      *p = c;
    }
  return sa;
}
示例#16
0
static void
add_scope(struct sockaddr *sa, int ifindex)
{
  struct sockaddr_in6 *sa6;

  if (sa->sa_family != AF_INET6)
    return;
  sa6 = (struct sockaddr_in6 *)sa;
  if (!IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) &&
      !IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr))
    return;
  if (*(u_int16_t *)&sa6->sin6_addr.s6_addr[2] != 0)
    return;
  *(u_int16_t *)&sa6->sin6_addr.s6_addr[2] = htons(ifindex);
}
示例#17
0
  sockaddr* CopyAddress(int family, const void* data, size_t byteCount, sockaddr_storage* ss) {
      // Netlink gives us the address family in the header, and the
      // sockaddr_in or sockaddr_in6 bytes as the payload. We need to
      // stitch the two bits together into the sockaddr that's part of
      // our portable interface.
      ss->ss_family = family;
      memcpy(SockaddrBytes(family, ss), data, byteCount);

      // For IPv6 we might also have to set the scope id.
      if (family == AF_INET6 && (IN6_IS_ADDR_LINKLOCAL(data) || IN6_IS_ADDR_MC_LINKLOCAL(data))) {
          reinterpret_cast<sockaddr_in6*>(ss)->sin6_scope_id = interface_index;
      }

      return reinterpret_cast<sockaddr*>(ss);
  }
示例#18
0
int
ncprange_scopeid(const struct ncprange *range)
{
  const struct in6_addr *sin6;
  int scopeid = -1;

  if (range->ncprange_family == AF_INET6) {
    sin6 = &range->ncprange_ip6addr;
    if (IN6_IS_ADDR_LINKLOCAL(sin6) || IN6_IS_ADDR_MC_LINKLOCAL(sin6))
      if ((scopeid = ntohs(*(const u_short *)&sin6->s6_addr[2])) == 0)
        scopeid = -1;
  }

  return scopeid;
}
static void
foreach_route_cb (struct nl_object *object, void *user_data)
{
	ForeachRouteInfo *info = user_data;
	struct rtnl_route *route = (struct rtnl_route *) object;
	struct nl_addr *dst;

	if (info->out_route)
		return;

	if (nm_logging_level_enabled (LOGL_DEBUG))
		dump_route (route);

	if (   info->ifindex > 0
	    && rtnl_route_get_oif (route) != info->ifindex)
		return;

	if (   info->scope != RT_SCOPE_UNIVERSE
	    && rtnl_route_get_scope (route) != info->scope)
		return;

	if (   info->family != AF_UNSPEC
	    && rtnl_route_get_family (route) != info->family)
		return;

	dst = rtnl_route_get_dst (route);

	/* Check for IPv6 LL and MC routes that might need to be ignored */
	if (   (info->family == AF_INET6 || info->family == AF_UNSPEC)
	    && (rtnl_route_get_family (route) == AF_INET6)) {
		struct in6_addr *addr = NULL;

		if (dst)
			addr = nl_addr_get_binary_addr (dst);
		if (addr) {
			if (   IN6_IS_ADDR_LINKLOCAL (addr)
			    || IN6_IS_ADDR_MC_LINKLOCAL (addr)
			    || (IN6_IS_ADDR_MULTICAST (addr) && (nl_addr_get_prefixlen (dst) == 8)))
				return;
		}
	}

	info->out_route = info->callback (route, dst, info->iface, info->user_data);
	if (info->out_route) {
		/* Ref the route so it sticks around after the cache is cleared */
		rtnl_route_get (info->out_route);
	}
}
示例#20
0
static void
adjust_linklocal(struct sockaddr_in6 *sin6)
{
    /* XXX: ?????!?!?!!!!!  This is horrible ! */
    /*
     * The kernel does not understand sin6_scope_id for routing at this moment.
     * We should rather keep the embedded ID.
     * [email protected], 20011026
     */
    if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
        IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) {
      sin6->sin6_scope_id =
        ntohs(*(u_short *)&sin6->sin6_addr.s6_addr[2]);
      *(u_short *)&sin6->sin6_addr.s6_addr[2] = 0;
    }
}
示例#21
0
文件: icmp.cpp 项目: Distrotech/mrd6
bool icmp_base::send_icmp(const interface *intf, const in6_addr &dst,
			  int rta, icmp6_hdr *hdr, uint16_t len) const {
	if (IN6_IS_ADDR_LINKLOCAL(&dst) || IN6_IS_ADDR_MC_LINKLOCAL(&dst))
		return send_icmp(intf, *intf->linklocal(), dst, rta, hdr, len);
	else {
		if (intf->globals().empty()) {
			if (g_mrd->should_log(DEBUG)) {
				g_mrd->log().xprintf(
					"[ICMPv6] Failed to send message to "
					"%{addr}, no global address.\n", dst);
			}
			return false;
		}

		return send_icmp(intf, *intf->globals().begin(), dst, rta, hdr, len);
	}
}
示例#22
0
TEST(ifaddrs, inet6_scope_ids) {
  ifaddrs* addrs;
  ASSERT_EQ(0, getifaddrs(&addrs));

  for (ifaddrs* ifa = addrs; ifa != nullptr; ifa = ifa->ifa_next) {
    if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {
      sockaddr_in6* sa6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
      // Any link-local IPv6 address should have a scope id. (http://b/27219454.)
      // 0 isn't a valid interface index, so that would mean the scope id wasn't set.
      if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) {
        ASSERT_NE(sa6->sin6_scope_id, 0U);
      }
    }
  }

  freeifaddrs(addrs);
}
示例#23
0
文件: send.c 项目: jing-git/rt-n56u
int really_send(struct in6_addr const *dest, unsigned int if_index, struct in6_addr if_addr, unsigned char *buff, size_t len)
{
	char __attribute__ ((aligned(8))) chdr[CMSG_SPACE(sizeof(struct in6_pktinfo))];
	struct in6_pktinfo *pkt_info;
	struct msghdr mhdr;
	struct cmsghdr *cmsg;
	struct iovec iov;
	int err;
	struct sockaddr_in6 addr;

	memset((void *)&addr, 0, sizeof(addr));
	addr.sin6_family = AF_INET6;
	addr.sin6_port = htons(IPPROTO_ICMPV6);
	memcpy(&addr.sin6_addr, dest, sizeof(struct in6_addr));

	iov.iov_len = len;
	iov.iov_base = (caddr_t) buff;

	memset(chdr, 0, sizeof(chdr));
	cmsg = (struct cmsghdr *)chdr;

	cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
	cmsg->cmsg_level = IPPROTO_IPV6;
	cmsg->cmsg_type = IPV6_PKTINFO;

	pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
	pkt_info->ipi6_ifindex = if_index;
	memcpy(&pkt_info->ipi6_addr, &if_addr, sizeof(struct in6_addr));

#ifdef HAVE_SIN6_SCOPE_ID
	if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&addr.sin6_addr))
		addr.sin6_scope_id = if_index;
#endif

	memset(&mhdr, 0, sizeof(mhdr));
	mhdr.msg_name = (caddr_t) & addr;
	mhdr.msg_namelen = sizeof(struct sockaddr_in6);
	mhdr.msg_iov = &iov;
	mhdr.msg_iovlen = 1;
	mhdr.msg_control = (void *)cmsg;
	mhdr.msg_controllen = sizeof(chdr);

	err = sendmsg(sock, &mhdr, 0);

	return err;
}
示例#24
0
void mld_interface::handle_mldv1_membership_reduction(const in6_addr &src,
						      mldv1 *mldhdr) {
	m_stats.counter(ReductionCount, RX)++;
	mld->stats().counter(ReductionCount, RX)++;

	if (!IN6_IS_ADDR_MULTICAST(&mldhdr->mcaddr)) {
		m_stats.counter(ReductionCount, Bad)++;
		mld->stats().counter(ReductionCount, Bad)++;
		return;
	}

	if (IN6_IS_ADDR_MC_NODELOCAL(&mldhdr->mcaddr)
	    || IN6_IS_ADDR_MC_LINKLOCAL(&mldhdr->mcaddr))
		return;

	handle_mode_change_for_group(1, src, mldhdr->mcaddr,
				     MLD_SSM_CHANGE_TO_INCLUDE, address_set());
}
示例#25
0
文件: if.c 项目: yellowman/nsh
void
ipv6ll_db_store(struct sockaddr_in6 *sin6, struct sockaddr_in6 *sin6mask,
    int dbflag, char *ifname)
{
	/*
	 * If linklocal, store a version that will match conf output
	 * with no scope id, ifname in separate database field
	 */
	if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
	    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr) ||
	    IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr)) {
		sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
		sin6->sin6_scope_id = 0;
		db_delete_flag_x_ctl_data("ipv6linklocal", ifname,
		    netname6(sin6, sin6mask));
		if (dbflag != DB_X_REMOVE)
			db_insert_flag_x("ipv6linklocal", ifname, 0,
			    dbflag, netname6(sin6, sin6mask));
	}
}
示例#26
0
int svx_inetaddr_get_ipport(svx_inetaddr_t *self, char *ip, size_t ip_len, uint16_t *port)
{
    size_t len;

    if(NULL == self || ((NULL == ip || ip_len < SVX_INETADDR_STR_IP_LEN) && NULL == port))
        SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_INVAL, "self:%p, ip:%p, ip_len:%zu, port:%p\n", self, ip, ip_len, port);
    
    switch(self->storage.addr.sa_family)
    {
    case AF_INET:
        if(NULL != ip && ip_len >= SVX_INETADDR_STR_IP_LEN)
        {
            memset(ip, 0, ip_len);
            if(NULL == inet_ntop(AF_INET, &(self->storage.addr4.sin_addr), ip, (socklen_t)ip_len))
                SVX_LOG_ERRNO_RETURN_ERR(errno, NULL);
        }
        if(NULL != port) *port = ntohs(self->storage.addr4.sin_port);
        return 0;
    case AF_INET6:
        if(NULL != ip && ip_len >= SVX_INETADDR_STR_IP_LEN)
        {
            memset(ip, 0, ip_len);
            if(NULL == inet_ntop(AF_INET6, &(self->storage.addr6.sin6_addr), ip, (socklen_t)ip_len))
                SVX_LOG_ERRNO_RETURN_ERR(errno, NULL);
            
            /* append IPv6 link-local address interface name */
            if(IN6_IS_ADDR_LINKLOCAL(&(self->storage.addr6.sin6_addr)) || 
               IN6_IS_ADDR_MC_LINKLOCAL(&(self->storage.addr6.sin6_addr)))
            {
                len = strlen(ip);
                ip[len++] = '%';
                if(NULL == if_indextoname(self->storage.addr6.sin6_scope_id, ip + len))
                    SVX_LOG_ERRNO_RETURN_ERR(errno, NULL);
            }
        }
        if(NULL != port) *port = ntohs(self->storage.addr6.sin6_port);
        return 0;
    default:
        SVX_LOG_ERRNO_RETURN_ERR(SVX_ERRNO_NOTSPT, "family:%u\n", self->storage.addr.sa_family);
    }
}
示例#27
0
void mld_interface::handle_mldv2_membership_report(const in6_addr &src,
						   mldv2_report *mldhdr,
						   int len) {
	m_stats.counter(ReportV2Count, RX)++;
	mld->stats().counter(ReportV2Count, RX)++;

	mldv2_mrec *mrec = mldhdr->mrecs();
	int clen = 0;

	int reccount = ntoh(mldhdr->nmrecs());

	for (int i = 0; i < reccount && clen < len; i++, mrec = mrec->next()) {
		clen += sizeof(mldv2_mrec);
		if (clen <= len)
			clen += sizeof(in6_addr) * ntoh(mrec->nsrcs);
	}

	if (clen > len) {
		if (should_log(MESSAGE_ERR))
			log().writeline("Dropped badly formed MLDv2 Membership");

		m_stats.counter(ReportV2Count, Bad)++;
		mld->stats().counter(ReportV2Count, Bad)++;
		return;
	}

	mrec = mldhdr->mrecs();
	for (int i = 0; i < reccount; i++, mrec = mrec->next()) {
		if (!IN6_IS_ADDR_MULTICAST(&mrec->mca) ||
		     IN6_IS_ADDR_MC_NODELOCAL(&mrec->mca) ||
		     IN6_IS_ADDR_MC_LINKLOCAL(&mrec->mca))
			continue;

		address_set sources;
		in6_addr *srcs = mrec->sources();
		for (uint16_t j = 0; j < ntoh(mrec->nsrcs); j++)
			sources += srcs[j];

		handle_mode_change_for_group(2, src, mrec->mca, mrec->type, sources);
	}
}
示例#28
0
文件: send.c 项目: verrio/radvd
static int really_send(int sock, struct in6_addr const *dest, struct properties const *props, struct safe_buffer const *sb)
{
	struct sockaddr_in6 addr;
	memset((void *)&addr, 0, sizeof(addr));
	addr.sin6_family = AF_INET6;
	addr.sin6_port = htons(IPPROTO_ICMPV6);
	memcpy(&addr.sin6_addr, dest, sizeof(struct in6_addr));

	struct iovec iov;
	iov.iov_len = sb->used;
	iov.iov_base = (caddr_t)sb->buffer;

	char __attribute__ ((aligned(8))) chdr[CMSG_SPACE(sizeof(struct in6_pktinfo))];
	memset(chdr, 0, sizeof(chdr));
	struct cmsghdr *cmsg = (struct cmsghdr *)chdr;

	cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
	cmsg->cmsg_level = IPPROTO_IPV6;
	cmsg->cmsg_type = IPV6_PKTINFO;

	struct in6_pktinfo *pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
	pkt_info->ipi6_ifindex = props->if_index;
	memcpy(&pkt_info->ipi6_addr, &props->if_addr, sizeof(struct in6_addr));

#ifdef HAVE_SIN6_SCOPE_ID
	if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&addr.sin6_addr))
		addr.sin6_scope_id = props->if_index;
#endif

	struct msghdr mhdr;
	memset(&mhdr, 0, sizeof(mhdr));
	mhdr.msg_name = (caddr_t) & addr;
	mhdr.msg_namelen = sizeof(struct sockaddr_in6);
	mhdr.msg_iov = &iov;
	mhdr.msg_iovlen = 1;
	mhdr.msg_control = (void *)cmsg;
	mhdr.msg_controllen = sizeof(chdr);

	return sendmsg(sock, &mhdr, 0);
}
示例#29
0
// Forwards a packet on a specific interface
ssize_t relayd_forward_packet(int socket, struct sockaddr_in6 *dest,
		struct iovec *iov, size_t iov_len,
		const struct relayd_interface *iface)
{
	// Construct headers
	uint8_t cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {0};
	struct msghdr msg = {(void*)dest, sizeof(*dest), iov, iov_len,
				cmsg_buf, sizeof(cmsg_buf), 0};

	// Set control data (define destination interface)
	struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg);
	chdr->cmsg_level = IPPROTO_IPV6;
	chdr->cmsg_type = IPV6_PKTINFO;
	chdr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
	struct in6_pktinfo *pktinfo = (struct in6_pktinfo*)CMSG_DATA(chdr);
	pktinfo->ipi6_ifindex = iface->ifindex;

	// Also set scope ID if link-local
	if (IN6_IS_ADDR_LINKLOCAL(&dest->sin6_addr)
			|| IN6_IS_ADDR_MC_LINKLOCAL(&dest->sin6_addr))
		dest->sin6_scope_id = iface->ifindex;

	// IPV6_PKTINFO doesn't really work for IPv6-raw sockets (bug?)
	if (dest->sin6_port == 0) {
		msg.msg_control = NULL;
		msg.msg_controllen = 0;
	}

	char ipbuf[INET6_ADDRSTRLEN];
	inet_ntop(AF_INET6, &dest->sin6_addr, ipbuf, sizeof(ipbuf));

	ssize_t sent = sendmsg(socket, &msg, MSG_DONTWAIT);
	if (sent < 0)
		syslog(LOG_WARNING, "Failed to relay to %s%%%s (%s)",
				ipbuf, iface->ifname, strerror(errno));
	else
		syslog(LOG_NOTICE, "Relayed %li bytes to %s%%%s",
				(long)sent, ipbuf, iface->ifname);
	return sent;
}
示例#30
0
/*
 * Write the numeric address
 */
static int
_numerichost(struct asr_query *as)
{
	unsigned int	ifidx;
	char		scope[IF_NAMESIZE + 1], *ifname;
	void		*addr;
	char		*buf = as->as.ni.hostname;
	size_t		 buflen = as->as.ni.hostnamelen;

	if (as->as.ni.sa.sa.sa_family == AF_INET)
		addr = &as->as.ni.sa.sain.sin_addr;
	else
		addr = &as->as.ni.sa.sain6.sin6_addr;

	if (inet_ntop(as->as.ni.sa.sa.sa_family, addr, buf, buflen) == NULL)
		return (-1); /* errno set */

	if (as->as.ni.sa.sa.sa_family == AF_INET6 &&
	    as->as.ni.sa.sain6.sin6_scope_id) {

		scope[0] = SCOPE_DELIMITER;
		scope[1] = '\0';

		ifidx = as->as.ni.sa.sain6.sin6_scope_id;
		ifname = NULL;

		if (IN6_IS_ADDR_LINKLOCAL(&as->as.ni.sa.sain6.sin6_addr) ||
		    IN6_IS_ADDR_MC_LINKLOCAL(&as->as.ni.sa.sain6.sin6_addr) ||
		    IN6_IS_ADDR_MC_NODELOCAL(&as->as.ni.sa.sain6.sin6_addr))
			ifname = if_indextoname(ifidx, scope + 1);

		if (ifname == NULL)
			snprintf(scope + 1, sizeof(scope) - 1, "%u", ifidx);

		strlcat(buf, scope, buflen);
	}

	return (0);
}