static u_long ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf) { ngx_addr_t addr; ngx_array_t *xfwd; struct sockaddr_in *sin; addr.sockaddr = r->connection->sockaddr; addr.socklen = r->connection->socklen; /* addr.name = r->connection->addr_text; */ xfwd = &r->headers_in.x_forwarded_for; if (xfwd->nelts > 0 && gcf->proxies != NULL) { (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL, gcf->proxies, gcf->proxy_recursive); } #if (NGX_HAVE_INET6) if (addr.sockaddr->sa_family == AF_INET6) { u_char *p; in_addr_t inaddr; struct in6_addr *inaddr6; inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr; if (IN6_IS_ADDR_V4MAPPED(inaddr6)) { p = inaddr6->s6_addr; inaddr = p[12] << 24; inaddr += p[13] << 16; inaddr += p[14] << 8; inaddr += p[15]; return inaddr; } } #endif if (addr.sockaddr->sa_family != AF_INET) { return INADDR_NONE; } sin = (struct sockaddr_in *) addr.sockaddr; return ntohl(sin->sin_addr.s_addr); }
char * sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error) { #if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)sa; struct sockaddr_in a4; #endif int ret; char host[NI_MAXHOST], serv[NI_MAXSERV]; #if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) if (sa->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) { /* convert "::ffff:127.0.0.1" to "127.0.0.1" */ memset(&a4, 0, sizeof(a4)); a4.sin_family = AF_INET; memcpy(&a4.sin_addr, ((const char *)&a6->sin6_addr) + 12, sizeof(a4.sin_addr)); a4.sin_port = a6->sin6_port; sa = (const struct sockaddr *)&a4; length = sizeof(a4); } #endif ret = getnameinfo(sa, length, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV); if (ret != 0) { g_set_error(error, g_quark_from_static_string("netdb"), ret, "%s", gai_strerror(ret)); return NULL; } #ifdef HAVE_UN if (sa->sa_family == AF_UNIX) /* "serv" contains corrupt information with unix sockets */ return g_strdup(host); #endif #ifdef HAVE_IPV6 if (strchr(host, ':') != NULL) return g_strconcat("[", host, "]:", serv, NULL); #endif return g_strconcat(host, ":", serv, NULL); }
static void udp6_connect(netmsg_t msg) { struct socket *so = msg->connect.base.nm_so; struct sockaddr *nam = msg->connect.nm_nam; struct thread *td = msg->connect.nm_td; struct sockaddr_in6 *sin6_p; struct inpcb *inp; int error; inp = so->so_pcb; if (inp == NULL) { error = EINVAL; goto out; } sin6_p = (struct sockaddr_in6 *)nam; if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { error = EADDRNOTAVAIL; goto out; } if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { error = EISCONN; goto out; } if (inp->inp_flags & INP_WILDCARD) in_pcbremwildcardhash(inp); if (!prison_remote_ip(td, nam)) { error = EAFNOSUPPORT; /* IPv4 only jail */ goto out; } error = in6_pcbconnect(inp, nam, td); if (error == 0) { soisconnected(so); } else if (error == EAFNOSUPPORT) { /* connection dissolved */ /* * Follow traditional BSD behavior and retain * the local port binding. But, fix the old misbehavior * of overwriting any previously bound local address. */ if (!(inp->inp_flags & INP_WASBOUND_NOTANY)) inp->in6p_laddr = kin6addr_any; in_pcbinswildcardhash(inp); } out: lwkt_replymsg(&msg->connect.base.lmsg, error); }
unsigned int isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { unsigned int length = 0; const unsigned char *s = NULL; unsigned int h = 0; unsigned int g; unsigned int p = 0; const struct in6_addr *in6; REQUIRE(sockaddr != NULL); switch (sockaddr->type.sa.sa_family) { case AF_INET: s = (const unsigned char *)&sockaddr->type.sin.sin_addr; p = ntohs(sockaddr->type.sin.sin_port); length = sizeof(sockaddr->type.sin.sin_addr.s_addr); break; case AF_INET6: in6 = &sockaddr->type.sin6.sin6_addr; s = (const unsigned char *)in6; if (IN6_IS_ADDR_V4MAPPED(in6)) { s += 12; length = sizeof(sockaddr->type.sin.sin_addr.s_addr); } else length = sizeof(sockaddr->type.sin6.sin6_addr); p = ntohs(sockaddr->type.sin6.sin6_port); break; default: UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, ISC_MSG_UNKNOWNFAMILY, "unknown address family: %d"), (int)sockaddr->type.sa.sa_family); s = (const unsigned char *)&sockaddr->type; length = sockaddr->length; p = 0; } h = isc_hash_calc(s, length, ISC_TRUE); if (!address_only) { g = isc_hash_calc((const unsigned char *)&p, sizeof(p), ISC_TRUE); h = h ^ g; /* XXX: we should concatenate h and p first */ } return (h); }
/** Return IPv6 address scope */ static int li_scope6(struct in6_addr const *ip6) { if (IN6_IS_ADDR_V4MAPPED(ip6) || IN6_IS_ADDR_V4COMPAT(ip6)) { uint32_t ip4 = *(uint32_t *)(ip6->s6_addr + 12); return li_scope4(ip4); } else if (IN6_IS_ADDR_LOOPBACK(ip6)) return LI_SCOPE_HOST; else if (IN6_IS_ADDR_LINKLOCAL(ip6)) return LI_SCOPE_LINK; else if (IN6_IS_ADDR_SITELOCAL(ip6)) return LI_SCOPE_SITE; else return LI_SCOPE_GLOBAL; }
/* * Opening a UDP socket is a little more tricky, since * UDP works in a way which is different from TCP... * * Our goal is to hide this difference for the end-user */ tree_cell * nasl_open_sock_udp (lex_ctxt * lexic) { int soc; tree_cell *retc; int port; struct sockaddr_in soca; struct sockaddr_in6 soca6; struct arglist *script_infos = lexic->script_infos; struct in6_addr *ia; port = get_int_var_by_num (lexic, 0, -1); if (port < 0) return NULL; ia = plug_get_host_ip (script_infos); if (ia == NULL) return NULL; if (IN6_IS_ADDR_V4MAPPED (ia)) { bzero (&soca, sizeof (soca)); soca.sin_addr.s_addr = ia->s6_addr32[3]; soca.sin_port = htons (port); soca.sin_family = AF_INET; soc = socket (AF_INET, SOCK_DGRAM, 0); openvas_source_set_socket (soc, 0, AF_INET); connect (soc, (struct sockaddr *) &soca, sizeof (soca)); } else { bzero (&soca6, sizeof (soca6)); memcpy (&soca6.sin6_addr, ia, sizeof (struct in6_addr)); soca6.sin6_port = htons (port); soca6.sin6_family = AF_INET6; soc = socket (AF_INET6, SOCK_DGRAM, 0); openvas_source_set_socket (soc, 0, AF_INET6); connect (soc, (struct sockaddr *) &soca6, sizeof (soca6)); } retc = alloc_tree_cell (0, NULL); retc->type = CONST_INT; retc->x.i_val = soc < 0 ? 0 : soc; return retc; }
/* Convert IPv4 compatible IPv6 address to IPv4 address. */ static void sockunion_normalise_mapped (union sockunion *su) { struct sockaddr_in sin; #ifdef HAVE_IPV6 if (su->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr)) { memset (&sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = su->sin6.sin6_port; memcpy (&sin.sin_addr, ((char *)&su->sin6.sin6_addr) + 12, 4); memcpy (su, &sin, sizeof (struct sockaddr_in)); } #endif /* HAVE_IPV6 */ }
void mappedtov4(union sockunion *sa) { struct sockaddr_in sin; struct sockaddr_in6 *sin6 = &sa->sa6; byte_zero(&sin, sizeof(sin)); if (sin6->sin6_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ) { byte_copy(&sin.sin_addr, sizeof(sin.sin_addr), sin6->sin6_addr.s6_addr+12); sin.sin_port = sin6->sin6_port; sin.sin_family = AF_INET; #ifdef HASSALEN sin.sin_len = sizeof(sin); #endif byte_copy(&sa->sa4, sizeof(sin), &sin); } }
static sockaddr_union * unmap_v4mapped( sockaddr_union *sa, sockaddr_union *tmp) { if (SU_GET_FAMILY(sa) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) { SU_INIT(tmp, AF_INET); SU_SET_PORT(tmp, SU_GET_PORT(sa)); /* extract the v4 address from byte 12 of the v6 address */ memcpy(&tmp->sin.sin_addr.s_addr, &sa->sin6.sin6_addr.s6_addr[12], sizeof(struct in_addr)); return tmp; } return sa; }
uint32_t addrConvert(struct sockaddr *pAddr) { uint32_t ipv4; if (AF_INET6 == pAddr->sa_family) { if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)pAddr)->sin6_addr)) ipv4 = ((Addr6 *) & ((struct sockaddr_in6 *)pAddr)->sin6_addr)->m_addrs[3]; else { Addr6 *a6 = (Addr6 *) & ((struct sockaddr_in6 *)pAddr)->sin6_addr; ipv4 = a6->m_addrs[0] ^ a6->m_addrs[1] ^ a6->m_addrs[2] ^ a6->m_addrs[3]; } } else ipv4 = ((struct sockaddr_in *)pAddr)->sin_addr.s_addr; return ipv4; }
static apr_status_t parse_ip(apr_ipsubnet_t *ipsub, const char *ipstr, int network_allowed) { /* supported flavors of IP: * * . IPv6 numeric address string (e.g., "fe80::1") * * IMPORTANT: Don't store IPv4-mapped IPv6 address as an IPv6 address. * * . IPv4 numeric address string (e.g., "127.0.0.1") * * . IPv4 network string (e.g., "9.67") * * IMPORTANT: This network form is only allowed if network_allowed is on. */ int rc; #if APR_HAVE_IPV6 rc = apr_inet_pton(AF_INET6, ipstr, ipsub->sub); if (rc == 1) { if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ipsub->sub)) { /* apr_ipsubnet_test() assumes that we don't create IPv4-mapped IPv6 * addresses; this of course forces the user to specify IPv4 addresses * in a.b.c.d style instead of ::ffff:a.b.c.d style. */ return APR_EBADIP; } ipsub->family = AF_INET6; } else #endif { rc = apr_inet_pton(AF_INET, ipstr, ipsub->sub); if (rc == 1) { ipsub->family = AF_INET; } } if (rc != 1) { if (network_allowed) { return parse_network(ipsub, ipstr); } else { return APR_EBADIP; } } return APR_SUCCESS; }
static ngx_int_t ngx_limit_tcp_find(ngx_connection_t *c) { struct sockaddr_in *sin; ngx_limit_tcp_conf_t *ltcf; #if (NGX_HAVE_INET6) u_char *p; in_addr_t addr; struct sockaddr_in6 *sin6; #endif ltcf = (ngx_limit_tcp_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ngx_limit_tcp_module); switch (c->sockaddr->sa_family) { case AF_INET: if (ltcf->rules) { sin = (struct sockaddr_in *) c->sockaddr; return ngx_limit_tcp_inet(c, ltcf, sin->sin_addr.s_addr); } break; #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) c->sockaddr; p = sin6->sin6_addr.s6_addr; if (ltcf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { addr = p[12] << 24; addr += p[13] << 16; addr += p[14] << 8; addr += p[15]; return ngx_limit_tcp_inet(c, ltcf, htonl(addr)); } if (ltcf->rules6) { return ngx_limit_tcp_inet6(c, ltcf, p); } #endif } return NGX_OK; }
static void tcp6_usr_connect(netmsg_t msg) { struct socket *so = msg->connect.base.nm_so; struct sockaddr *nam = msg->connect.nm_nam; struct thread *td = msg->connect.nm_td; int error = 0; struct inpcb *inp; struct tcpcb *tp; struct sockaddr_in6 *sin6p; COMMON_START(so, inp, 0); /* * Must disallow TCP ``connections'' to multicast addresses. */ sin6p = (struct sockaddr_in6 *)nam; if (sin6p->sin6_family == AF_INET6 && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { error = EAFNOSUPPORT; goto out; } if (!prison_remote_ip(td, nam)) { error = EAFNOSUPPORT; /* IPv4 only jail */ goto out; } /* Reject v4-mapped address */ if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { error = EADDRNOTAVAIL; goto out; } inp->inp_inc.inc_isipv6 = 1; tcp6_connect(msg); /* msg is invalid now */ return; out: if (msg->connect.nm_m) { m_freem(msg->connect.nm_m); msg->connect.nm_m = NULL; } lwkt_replymsg(&msg->lmsg, error); }
static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r) { struct sockaddr_in *sin; ngx_http_access_loc_conf_t *alcf; #if (NGX_HAVE_INET6) u_char *p; in_addr_t addr; struct sockaddr_in6 *sin6; #endif alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module); switch (r->connection->sockaddr->sa_family) { case AF_INET: if (alcf->rules) { sin = (struct sockaddr_in *) r->connection->sockaddr; return ngx_http_access_inet(r, alcf, sin->sin_addr.s_addr); } break; #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) r->connection->sockaddr; p = sin6->sin6_addr.s6_addr; if (alcf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { addr = p[12] << 24; addr += p[13] << 16; addr += p[14] << 8; addr += p[15]; return ngx_http_access_inet(r, alcf, htonl(addr)); } if (alcf->rules6) { return ngx_http_access_inet6(r, alcf, p); } #endif } return NGX_DECLINED; }
/* return 0 if ip is a LAN ip. * return -1 if it is not. */ int LAN_ip(IP ip) { if (ip.family == AF_INET) { IP4 ip4 = ip.ip4; /* Loopback. */ if (ip4.uint8[0] == 127) return 0; /* 10.0.0.0 to 10.255.255.255 range. */ if (ip4.uint8[0] == 10) return 0; /* 172.16.0.0 to 172.31.255.255 range. */ if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) return 0; /* 192.168.0.0 to 192.168.255.255 range. */ if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) return 0; /* 169.254.1.0 to 169.254.254.255 range. */ if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0 && ip4.uint8[2] != 255) return 0; } else if (ip.family == AF_INET6) { /* autogenerated for each interface: FE80::* (up to FEBF::*) FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) || ((ip.ip6.uint8[0] == 0xFE) && ((ip.ip6.uint8[1] & 0xC0) == 0x80))) return 0; /* embedded IPv4-in-IPv6 */ if (IN6_IS_ADDR_V4MAPPED(&ip.ip6.in6_addr)) { IP ip4; ip4.family = AF_INET; ip4.ip4.uint32 = ip.ip6.uint32[3]; return LAN_ip(ip4); } } return -1; }
int HttpListener::checkAccess( struct conn_data * pData ) { struct sockaddr * pPeer = ( struct sockaddr *) pData->achPeerAddr; if (( AF_INET6 == pPeer->sa_family )&& ( IN6_IS_ADDR_V4MAPPED( &((struct sockaddr_in6 *)pPeer)->sin6_addr )) ) { pPeer->sa_family = AF_INET; ((struct sockaddr_in *)pPeer)->sin_addr.s_addr = *((in_addr_t *)&pData->achPeerAddr[20]); } ClientInfo * pInfo = HttpGlobals::getClientCache()->getClientInfo( pPeer ); pData->pInfo = pInfo; if ( D_ENABLED( DL_MORE )) LOG_D(( "[%s] New connection from %s:%d.", getAddrStr(), pInfo->getAddrString(), ntohs( ((struct sockaddr_in*)pPeer)->sin_port) )); return pInfo->checkAccess(); }
/* * NAME: conn->accept6() * DESCRIPTION: accept a new ipv6 connection */ static connection *conn_accept6(int portfd, int port) { int fd; unsigned int len; struct sockaddr_in6 sin6; in46addr addr; connection *conn; if (!FD_ISSET(portfd, &readfds)) { return (connection *) NULL; } len = sizeof(sin6); fd = accept(portfd, (struct sockaddr *) &sin6, &len); if (fd < 0) { FD_CLR(portfd, &readfds); return (connection *) NULL; } fcntl(fd, F_SETFL, FNDELAY); conn = flist; flist = (connection *) conn->chain.next; conn->chain.name = (char *) NULL; conn->fd = fd; conn->udpbuf = (char *) NULL; if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) { /* convert to IPv4 address */ addr.in.addr = *(struct in_addr *) &sin6.sin6_addr.s6_addr[12]; addr.ipv6 = FALSE; } else { addr.in.addr6 = sin6.sin6_addr; addr.ipv6 = TRUE; } conn->addr = ipa_new(&addr); conn->at = port; FD_SET(fd, &infds); FD_SET(fd, &outfds); FD_CLR(fd, &readfds); FD_SET(fd, &writefds); if (fd > maxfd) { maxfd = fd; } return conn; }
/* Return a numerical IP address and port for the given socket info */ PUBLIC int socketAddress(struct sockaddr *addr, int addrlen, char *ip, int ipLen, int *port) { #if (ME_UNIX_LIKE || WINDOWS) char service[NI_MAXSERV]; #ifdef IN6_IS_ADDR_V4MAPPED if (addr->sa_family == AF_INET6) { struct sockaddr_in6* addr6 = (struct sockaddr_in6*) addr; if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) { struct sockaddr_in addr4; memset(&addr4, 0, sizeof(addr4)); addr4.sin_family = AF_INET; addr4.sin_port = addr6->sin6_port; memcpy(&addr4.sin_addr.s_addr, addr6->sin6_addr.s6_addr + 12, sizeof(addr4.sin_addr.s_addr)); memcpy(addr, &addr4, sizeof(addr4)); addrlen = sizeof(addr4); } } #endif if (getnameinfo(addr, addrlen, ip, ipLen, service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN)) { return -1; } if (port) { *port = atoi(service); } #else struct sockaddr_in *sa; #if HAVE_NTOA_R sa = (struct sockaddr_in*) addr; inet_ntoa_r(sa->sin_addr, ip, ipLen); #else uchar *cp; sa = (struct sockaddr_in*) addr; cp = (uchar*) &sa->sin_addr; fmt(ip, ipLen, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); #endif if (port) { *port = ntohs(sa->sin_port); } #endif return 0; }
int is_loopback(struct netbuf *nbuf) { struct sockaddr *addr = (struct sockaddr *)nbuf->buf; struct sockaddr_in *sin; #ifdef INET6 struct sockaddr_in6 *sin6; #endif switch (addr->sa_family) { case AF_INET: if (!oldstyle_local) return 0; sin = (struct sockaddr_in *)addr; #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "Checking caller's adress (port = %d)\n", ntohs(sin->sin_port)); #endif return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)); #ifdef INET6 case AF_INET6: if (!oldstyle_local) return 0; sin6 = (struct sockaddr_in6 *)addr; #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "Checking caller's adress (port = %d)\n", ntohs(sin6->sin6_port)); #endif return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) || (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) && sin6->sin6_addr.s6_addr32[3] == htonl(INADDR_LOOPBACK))); #endif case AF_LOCAL: return 1; default: break; } return 0; }
static int udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { struct inpcb *inp; struct inpcbinfo *pcbinfo; int error; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_bind: inp == NULL")); INP_WLOCK(inp); INP_HASH_WLOCK(pcbinfo); inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { struct sockaddr_in6 *sin6_p; sin6_p = (struct sockaddr_in6 *)nam; if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) inp->inp_vflag |= INP_IPV4; #ifdef INET else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { struct sockaddr_in sin; in6_sin6_2_sin(&sin, sin6_p); inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; error = in_pcbbind(inp, (struct sockaddr *)&sin, td->td_ucred); goto out; } #endif } error = in6_pcbbind(inp, nam, td->td_ucred); #ifdef INET out: #endif INP_HASH_WUNLOCK(pcbinfo); INP_WUNLOCK(inp); return (error); }
void bctbx_sockaddr_remove_v4_mapping(const struct sockaddr *v6, struct sockaddr *result, socklen_t *result_len) { if (v6->sa_family == AF_INET6) { struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)v6; if (IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr)) { struct sockaddr_in *in = (struct sockaddr_in *)result; result->sa_family = AF_INET; in->sin_addr.s_addr = IN6_GET_ADDR_V4MAPPED(&in6->sin6_addr); in->sin_port = in6->sin6_port; *result_len = sizeof(struct sockaddr_in); } else { if (v6 != result) memcpy(result, v6, sizeof(struct sockaddr_in6)); *result_len = sizeof(struct sockaddr_in6); } } else { *result_len = sizeof(struct sockaddr_in); if (v6 != result) memcpy(result, v6, sizeof(struct sockaddr_in)); } }
/* translate IPv4 mapped IPv6 address to IPv4 address */ void unmappedaddr(struct sockaddr_in6 *sin6) { struct sockaddr_in *sin4; u_int32_t addr; int port; if (sin6->sin6_family != AF_INET6 || !IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) return; sin4 = (struct sockaddr_in *)sin6; memcpy(&addr, &sin6->sin6_addr.s6_addr[12], sizeof(addr)); port = sin6->sin6_port; memset(sin4, 0, sizeof(struct sockaddr_in)); sin4->sin_addr.s_addr = addr; sin4->sin_port = port; sin4->sin_family = AF_INET; sin4->sin_len = sizeof(struct sockaddr_in); }
static int tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p) { int s = splnet(); int error = 0; struct inpcb *inp = sotoinpcb(so); struct tcpcb *tp; struct sockaddr_in6 *sin6p; COMMON_START(); /* * Must disallow TCP ``connections'' to multicast addresses. */ sin6p = (struct sockaddr_in6 *)nam; if (sin6p->sin6_family == AF_INET6 && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { error = EAFNOSUPPORT; goto out; } if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { struct sockaddr_in sin; if (!ip6_mapped_addr_on || (inp->inp_flags & IN6P_IPV6_V6ONLY)) return(EINVAL); in6_sin6_2_sin(&sin, sin6p); inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; if ((error = tcp_connect(tp, (struct sockaddr *)&sin, p)) != 0) goto out; error = tcp_output(tp); goto out; } inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; if ((error = tcp6_connect(tp, nam, p)) != 0) goto out; error = tcp_output(tp); COMMON_END(PRU_CONNECT); }
static void merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src, const char *iface) { guint32 num, i; num = nm_ip6_config_get_num_nameservers (src); for (i = 0; i < num; i++) { const struct in6_addr *addr; char buf[INET6_ADDRSTRLEN]; addr = nm_ip6_config_get_nameserver (src, i); /* inet_ntop is probably supposed to do this for us, but it doesn't */ if (IN6_IS_ADDR_V4MAPPED (addr)) { if (inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, INET_ADDRSTRLEN) > 0) add_string_item (rc->nameservers, buf); } else { if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0) { if (IN6_IS_ADDR_LINKLOCAL (addr) && strchr (buf, '%') == NULL) { char *tmp; tmp = g_strdup_printf ("%s%%%s", buf, iface); add_string_item (rc->nameservers, tmp); g_free (tmp); } else add_string_item (rc->nameservers, buf); } } } num = nm_ip6_config_get_num_domains (src); for (i = 0; i < num; i++) { const char *domain; domain = nm_ip6_config_get_domain (src, i); if (!rc->domain) rc->domain = domain; add_string_item (rc->searches, domain); } num = nm_ip6_config_get_num_searches (src); for (i = 0; i < num; i++) add_string_item (rc->searches, nm_ip6_config_get_search (src, i)); }
/* * This is called for the -h option, initializes cxt->{hostname,hostaddress}. */ static void init_remote_info(struct login_context *cxt, char *remotehost) { const char *domain; char *p; struct addrinfo hints, *info = NULL; cxt->remote = 1; get_thishost(cxt, &domain); if (domain && (p = strchr(remotehost, '.')) && strcasecmp(p + 1, domain) == 0) *p = '\0'; cxt->hostname = xstrdup(remotehost); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_ADDRCONFIG; cxt->hostaddress[0] = 0; if (getaddrinfo(cxt->hostname, NULL, &hints, &info) == 0 && info) { if (info->ai_family == AF_INET) { struct sockaddr_in *sa = (struct sockaddr_in *) info->ai_addr; memcpy(cxt->hostaddress, &(sa->sin_addr), sizeof(sa->sin_addr)); } else if (info->ai_family == AF_INET6) { struct sockaddr_in6 *sa = (struct sockaddr_in6 *) info->ai_addr; #ifdef IN6_IS_ADDR_V4MAPPED if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr)) { const uint8_t *bytes = sa->sin6_addr.s6_addr; struct in_addr addr = { *(const in_addr_t *) (bytes + 12) }; memcpy(cxt->hostaddress, &addr, sizeof(struct in_addr)); } else #endif memcpy(cxt->hostaddress, &(sa->sin6_addr), sizeof(sa->sin6_addr)); } freeaddrinfo(info); } }
/* * Taken from inetd.c * This is a wrapper function for inet_ntop(). In case the af is AF_INET6 * and the address pointed by src is a IPv4-mapped IPv6 address, it * returns printable IPv4 address, not IPv4-mapped IPv6 address. In other cases * it behaves just like inet_ntop(). */ static const char * inet_ntop_native(int af, const void *src, char *dst, size_t size) { struct in_addr src4; const char *result; if (af == AF_INET6) { if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)) { IN6_V4MAPPED_TO_INADDR((struct in6_addr *)src, &src4); result = inet_ntop(AF_INET, &src4, dst, size); } else { result = inet_ntop(AF_INET6, src, dst, size); } } else { result = inet_ntop(af, src, dst, size); } return (result); }
static void udp6_send(netmsg_t msg) { struct socket *so = msg->send.base.nm_so; struct mbuf *m = msg->send.nm_m; struct sockaddr *addr = msg->send.nm_addr; struct mbuf *control = msg->send.nm_control; struct thread *td = msg->send.nm_td; struct inpcb *inp; int error = 0; inp = so->so_pcb; if (inp == NULL) { error = EINVAL; goto bad; } if (addr) { struct sockaddr_in6 *sin6; if (addr->sa_len != sizeof(struct sockaddr_in6)) { error = EINVAL; goto bad; } if (addr->sa_family != AF_INET6) { error = EAFNOSUPPORT; goto bad; } sin6 = (struct sockaddr_in6 *)addr; if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { error = EADDRNOTAVAIL; goto bad; } } error = udp6_output(inp, m, addr, control, td); lwkt_replymsg(&msg->send.base.lmsg, error); return; bad: m_freem(m); lwkt_replymsg(&msg->send.base.lmsg, error); }
static void tcp6_usr_bind(netmsg_t msg) { struct socket *so = msg->bind.base.nm_so; struct sockaddr *nam = msg->bind.nm_nam; struct thread *td = msg->bind.nm_td; int error = 0; struct inpcb *inp; struct tcpcb *tp; struct sockaddr_in6 *sin6p; COMMON_START(so, inp, 0); /* * Must check for multicast addresses and disallow binding * to them. */ sin6p = (struct sockaddr_in6 *)nam; if (sin6p->sin6_family == AF_INET6 && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { error = EAFNOSUPPORT; goto out; } inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr)) inp->inp_vflag |= INP_IPV4; else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { struct sockaddr_in sin; in6_sin6_2_sin(&sin, sin6p); inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; error = in_pcbbind(inp, (struct sockaddr *)&sin, td); goto out; } } error = in6_pcbbind(inp, nam, td); if (error) goto out; COMMON_END(PRU_BIND); }
void mangle_mapped_sockaddr(struct sockaddr *in) { struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in; if(in->sa_family == AF_INET) return; if(in->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr)) { struct sockaddr_in in4; memset(&in4, 0, sizeof(struct sockaddr_in)); in4.sin_family = AF_INET; in4.sin_port = in6->sin6_port; in4.sin_addr.s_addr = ((uint32_t *)&in6->sin6_addr)[3]; memcpy(in, &in4, sizeof(struct sockaddr_in)); } return; }
static void mappedtov4(struct sockaddr *ss) { struct sockaddr_in sin; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ss; debug(DEBUGLEVEL_INFO, "mappedtov4 %p\n", ss); if (ss->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ) { memcpy(&sin.sin_addr, sin6->sin6_addr.s6_addr+12, sizeof(sin.sin_addr)); sin.sin_port = ((struct sockaddr_in6 *)ss)->sin6_port; sin.sin_family = AF_INET; #ifdef SIN6_LEN sin.sin_len = 16; #endif memcpy(ss, &sin, sizeof(sin)); } }