/** 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; }
bool BNetworkAddress::IsMulticastNodeLocal() const { switch (fAddress.ss_family) { case AF_INET6: return IN6_IS_ADDR_MC_NODELOCAL( &((sockaddr_in6&)fAddress).sin6_addr); default: return false; } }
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()); }
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); } }
/* * 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); }
static const char * fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) { static char workbuf[128]; const char *cp; switch(sa->sa_family) { case AF_INET: { struct sockaddr_in *sockin = (struct sockaddr_in *)sa; if ((sockin->sin_addr.s_addr == INADDR_ANY) && mask && ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) ==0L) cp = "default" ; else if (flags & RTF_HOST) cp = routename(sockin->sin_addr.s_addr); else if (mask) cp = netname(sockin->sin_addr.s_addr, ntohl(((struct sockaddr_in *)mask) ->sin_addr.s_addr)); else cp = netname(sockin->sin_addr.s_addr, 0L); break; } #ifdef INET6 case AF_INET6: { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; struct in6_addr *in6 = &sa6->sin6_addr; /* * XXX: This is a special workaround for KAME kernels. * sin6_scope_id field of SA should be set in the future. */ if (IN6_IS_ADDR_LINKLOCAL(in6) || IN6_IS_ADDR_MC_LINKLOCAL(in6) || IN6_IS_ADDR_MC_NODELOCAL(in6)) { /* XXX: override is ok? */ sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]); *(u_short *)&in6->s6_addr[2] = 0; } if (flags & RTF_HOST) cp = routename6(sa6); else if (mask) cp = netname6(sa6, &((struct sockaddr_in6 *)mask)->sin6_addr); else { cp = netname6(sa6, NULL); } break; } #endif /*INET6*/ case AF_IPX: { struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; if (ipx_nullnet(satoipx_addr(work))) cp = "default"; else cp = ipx_print(sa); break; } case AF_APPLETALK: { if (!(flags & RTF_HOST) && mask) cp = atalk_print2(sa,mask,9); else cp = atalk_print(sa,11); break; } case AF_NETGRAPH: { printf("%s", ((struct sockaddr_ng *)sa)->sg_data); break; } case AF_LINK: { struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { (void) sprintf(workbuf, "link#%d", sdl->sdl_index); cp = workbuf; } else switch (sdl->sdl_type) { case IFT_ETHER: case IFT_L2VLAN: if (sdl->sdl_alen == ETHER_ADDR_LEN) { cp = ether_ntoa((struct ether_addr *) (sdl->sdl_data + sdl->sdl_nlen)); break; } /* FALLTHROUGH */ default: cp = link_ntoa(sdl); break; } break; } default: { u_char *s = (u_char *)sa->sa_data, *slim; char *cq, *cqlim; cq = workbuf; slim = sa->sa_len + (u_char *) sa; cqlim = cq + sizeof(workbuf) - 6; cq += sprintf(cq, "(%d)", sa->sa_family); while (s < slim && cq < cqlim) { cq += sprintf(cq, " %02x", *s++); if (s < slim) cq += sprintf(cq, "%02x", *s++); } cp = workbuf; } } return (cp); }
static int imp_verify_multicast_addr(pi_addr *p_pia) { if(p_pia->ss.ss_family == AF_INET6) { if (!IN6_IS_ADDR_MULTICAST(p_pia->v6.sin6_addr.s6_addr)) { IMP_LOG_ERROR("Address %s isn't multicast address\n", imp_pi_ntoa(p_pia)); return -1; } /* Interface-Local scope spans only a single interface on a node * and is useful only for loopback transmission of multicast. * * Link-Local multicast scope spans the same topological region as * the corresponding unicast scope. * [RFC 4291 section 2.7] */ if (IN6_IS_ADDR_MC_LINKLOCAL(p_pia->v6.sin6_addr.s6_addr) || IN6_IS_ADDR_MC_NODELOCAL(p_pia->v6.sin6_addr.s6_addr)) { IMP_LOG_WARNING("Group address %s is link-local multicast address\n", imp_pi_ntoa(p_pia)); return -1; } /* * Nodes must not originate a packet to a multicast address whose scop * field contains the reserved value 0; if such a packet is received, it * must be silently dropped. Nodes should not originate a packet to a * multicast address whose scop field contains the reserved value F; if * such a packet is sent or received, it must be treated the same as * packets destined to a global (scop E) multicast address. * [RFC 4291 section 2.7] */ if ((p_pia->v6.sin6_addr.s6_addr[1] & 0x0f) == 0) { IMP_LOG_WARNING("group address %s's scope is 0, Ignore it.\n", imp_pi_ntoa(p_pia)); return -1; } } else if(p_pia->ss.ss_family == AF_INET) { if (!IN_MULTICAST(p_pia->v4.sin_addr.s_addr)) { IMP_LOG_ERROR("group address %s isn't multicast adddress\n", imp_pi_ntoa(p_pia)); return -1; } /* * Address Range Size Designation * ------------- ---- ----------- * 224.0.0.0 - 224.0.0.255 (/24) Local Network Control Block * * Addresses in the Local Network Control Block are used for protocol * control traffic that is not forwarded off link. * [RFC 5771 section 4] */ if (IN_LOCAL_CONTROL_BLOCK(p_pia->v4.sin_addr.s_addr)) { IMP_LOG_INFO("Group address %s is Local Network Control Block\n", imp_pi_ntoa(p_pia)); return -1; } /* 239.255.0.0/16 is defined to be the IPv4 Local Scope. * [RFC 2365 section 6.1] */ if (IN_LOCAL_SCOPE_BLOCK(p_pia->v4.sin_addr.s_addr)) { IMP_LOG_INFO("Group address %s belongs to IPv4 Local Scope.\n", imp_pi_ntoa(p_pia)); return -1; } }else return -1; return 0; }
/* * getnameinfo * * We handle some "trival" cases locally. If the caller passes * NI_NUMERICHOST (only), then this call turns into a getservbyport * to get the service name + inet_pton() to create a host string. * If the caller passes NI_NUMERICSERV (only), then we zero out the port * number, complete the getnameinfo, and use printf() to create a service * string. If the caller specifies both NI_NUMERICHOST and NI_NUMERICSERV, * we inet_ntop() and printf() and return the results. */ si_item_t * si_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, const char *interface, uint32_t *err) { si_item_t *out = NULL; const struct sockaddr *lookup_sa; struct sockaddr_in s4; struct in_addr a4; struct in6_addr a6; const uint32_t unused = 0; void *addr = NULL; char *host = NULL; char *serv = NULL; uint32_t ifnum = 0; uint16_t port = 0; int do_host_lookup = ((flags & NI_NUMERICHOST) == 0); int do_serv_lookup = ((flags & NI_NUMERICSERV) == 0); /* check input */ if ((si == NULL) || (sa == NULL)) { if (err != NULL) *err = SI_STATUS_EAI_FAIL; return NULL; } if (err != NULL) *err = SI_STATUS_NO_ERROR; lookup_sa = sa; if (sa->sa_family == AF_INET) { struct sockaddr_in *s4 = (struct sockaddr_in *)sa; memcpy(&a4, &s4->sin_addr, sizeof(a4)); port = s4->sin_port; addr = &a4; } else if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)sa; memcpy(&a6, &s6->sin6_addr, sizeof(a6)); port = s6->sin6_port; /* Look for scope id in IPv6 Link Local, Multicast Node Local, and Multicast Link Local */ if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&s6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&s6->sin6_addr)) { ifnum = ntohs(a6.__u6_addr.__u6_addr16[1]); if (ifnum == 0) { ifnum = s6->sin6_scope_id; a6.__u6_addr.__u6_addr16[1] = htons(ifnum); } if ((ifnum != s6->sin6_scope_id) && (s6->sin6_scope_id != 0)) { if (err != NULL) *err = SI_STATUS_EAI_FAIL; return NULL; } } /* v4 mapped and compat addresses are converted to plain v4 */ if (IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&s6->sin6_addr)) { memcpy(&a4, &s6->sin6_addr.s6_addr[12], sizeof(a4)); addr = &a4; memset(&s4, 0, sizeof(s4)); s4.sin_len = sizeof(s4); s4.sin_family = AF_INET; s4.sin_port = port; memcpy(&s4.sin_addr, &a4, sizeof(s4.sin_addr)); lookup_sa = (const struct sockaddr *)&s4; } else { addr = &a6; } } else { if (err != NULL) *err = SI_STATUS_EAI_FAMILY; return NULL; } if (do_host_lookup == 1) { si_item_t *item = si_host_byaddr(si, addr, lookup_sa->sa_family, interface, NULL); if (item != NULL) { struct hostent *h; h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); host = strdup(h->h_name); si_item_release(item); if (host == NULL) { if (err != NULL) *err = SI_STATUS_EAI_MEMORY; return NULL; } } } if ((do_serv_lookup == 1) && (port != 0)) { si_item_t *item = si_service_byport(si, port, NULL); if (item != NULL) { struct servent *s; s = (struct servent *)((uintptr_t)item + sizeof(si_item_t)); serv = strdup(s->s_name); si_item_release(item); if (serv == NULL) { free(host); if (err != NULL) *err = SI_STATUS_EAI_MEMORY; return NULL; } } } /* * Return numeric host name for NI_NUMERICHOST or if lookup failed, but not * if NI_NAMEREQD is specified (so that we later fail with EAI_NONAME). */ if ((host == NULL) && ((flags & NI_NAMEREQD) == 0)) { char tmp[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1]; tmp[0] = '\0'; if (sa->sa_family == AF_INET) { char buf[INET_ADDRSTRLEN]; if (inet_ntop(AF_INET, &a4, buf, sizeof(buf)) != 0) { host = strdup(buf); } } else if (sa->sa_family == AF_INET6) { char buf[INET6_ADDRSTRLEN]; /* zero the embedded scope ID */ if (ifnum != 0) { a6.__u6_addr.__u6_addr16[1] = 0; } if (inet_ntop(AF_INET6, &a6, buf, sizeof(buf)) != 0) { if (ifnum != 0) { char ifname[IF_NAMESIZE]; if (if_indextoname(ifnum, ifname) != NULL) { asprintf(&host, "%s%%%s", buf, ifname); } else { /* ENXIO */ if (err != NULL) *err = SI_STATUS_EAI_FAIL; return NULL; } } else { host = strdup(buf); } } } } /* Return numeric service name for NI_NUMERICSERV or if lookup failed. */ if (serv == NULL) { asprintf(&serv, "%hu", ntohs(port)); } if ((host == NULL) || (serv == NULL)) { if (err != NULL) { if ((flags & NI_NAMEREQD) != 0) { *err = SI_STATUS_EAI_NONAME; } else { *err = SI_STATUS_EAI_MEMORY; } } } else { out = (si_item_t *)LI_ils_create("L4444ss", (unsigned long)si, CATEGORY_NAMEINFO, 1, unused, unused, host, serv); } free(host); free(serv); return out; }