int net_ipv6_send(netif_t *net, const uint8 *data, size_t data_size, int hop_limit, int proto, const struct in6_addr *src, const struct in6_addr *dst) { ipv6_hdr_t hdr; if(!net) { net = net_default_dev; if(!net) { errno = ENETDOWN; return -1; } } /* Set up the hop limit. We need to do this here, in case we end up passing this off to the IPv4 code, otherwise we could end up with a 0 down there for the ttl, which would be bad. */ if(!hop_limit) { if(net->hop_limit) hop_limit = net->hop_limit; else hop_limit = 255; } /* If this is actually going both to and from an IPv4 address, use the IPv4 send function to do the rest. Note that only V4-mapped addresses are supported here (::ffff:x.y.z.w) */ if(IN6_IS_ADDR_V4MAPPED(src) && IN6_IS_ADDR_V4MAPPED(dst)) { return net_ipv4_send(net, data, data_size, -1, hop_limit, proto, src->__s6_addr.__s6_addr32[3], dst->__s6_addr.__s6_addr32[3]); } else if(IN6_IS_ADDR_V4MAPPED(src) || IN6_IS_ADDR_V4MAPPED(dst) || IN6_IS_ADDR_V4COMPAT(src) || IN6_IS_ADDR_V4COMPAT(dst)) { return -1; } hdr.version_lclass = 0x60; hdr.hclass_lflow = 0; hdr.lclass = 0; hdr.length = ntohs(data_size); hdr.next_header = proto; hdr.hop_limit = hop_limit; hdr.src_addr = *src; hdr.dst_addr = *dst; /* XXXX: Handle fragmentation... */ return net_ipv6_send_packet(net, &hdr, data, data_size); }
void server_unicast_option(dhcp_smach_t *dsmp, PKT_LIST *plp) { const dhcpv6_option_t *d6o; uint_t olen; d6o = dhcpv6_pkt_option(plp, NULL, DHCPV6_OPT_UNICAST, &olen); olen -= sizeof (*d6o); /* LINTED: no consequent */ if (d6o == NULL) { /* No Server Unicast option specified */ } else if (olen != sizeof (dsmp->dsm_server)) { dhcpmsg(MSG_WARNING, "server_unicast_option: %s has Server " "Unicast option with bad length", pkt_type_to_string(pkt_recv_type(plp), B_TRUE)); } else { in6_addr_t addr; (void) memcpy(&addr, d6o + 1, olen); if (IN6_IS_ADDR_UNSPECIFIED(&addr)) { dhcpmsg(MSG_WARNING, "server_unicast_option: unicast " "to unspecified address ignored"); } else if (IN6_IS_ADDR_MULTICAST(&addr)) { dhcpmsg(MSG_WARNING, "server_unicast_option: unicast " "to multicast address ignored"); } else if (IN6_IS_ADDR_V4COMPAT(&addr) || IN6_IS_ADDR_V4MAPPED(&addr)) { dhcpmsg(MSG_WARNING, "server_unicast_option: unicast " "to invalid address ignored"); } else { dsmp->dsm_server = addr; } } }
// Return the 4-byte IP address, converting it into host byte order. ACE_UINT32 ACE_INET_Addr::get_ip_address (void) const { ACE_TRACE ("ACE_INET_Addr::get_ip_address"); #if defined (ACE_HAS_IPV6) if (this->get_type () == AF_INET6) { if (IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr) || IN6_IS_ADDR_V4COMPAT (&this->inet_addr_.in6_.sin6_addr) ) { ACE_UINT32 addr; // Return the last 32 bits of the address char *thisaddrptr = (char*)this->ip_addr_pointer (); thisaddrptr += 128/8 - 32/8; ACE_OS::memcpy (&addr, thisaddrptr, sizeof (addr)); return ACE_NTOHL (addr); } ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("ACE_INET_Addr::get_ip_address: address is a IPv6 address not IPv4\n"))); errno = EAFNOSUPPORT; return 0; } #endif /* ACE_HAS_IPV6 */ return ntohl (ACE_UINT32 (this->inet_addr_.in4_.sin_addr.s_addr)); }
int get_host_addr(void *addr, unsigned int addrlen, const char *host, unsigned short port) { struct addrinfo hint = {0}; struct addrinfo *addrlink = NULL; struct addrinfo *tmp = NULL; unsigned short *lpport = (unsigned short *)((char*)addr + 1 + sizeof(unsigned short)); hint.ai_flags = AI_CANONNAME; if(getaddrinfo(host, NULL, &hint, &addrlink) != 0) { return -1; } for(tmp = addrlink; tmp != NULL; tmp = tmp->ai_next) { if(tmp->ai_family == AF_INET6) { if(IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) || IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) || IN6_IS_ADDR_SITELOCAL(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) || IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) ) { continue; } } ((char*)addr)[0] = (char)(tmp->ai_addrlen > addrlen ? addrlen : tmp->ai_addrlen); memcpy((char*)addr+1, tmp->ai_addr, ((char*)addr)[0]); *lpport = htons(port); break; } freeaddrinfo(addrlink); return 0; }
int isns_portal_to_sockaddr(const isns_portal_info_t *portal, struct sockaddr_storage *addr) { const struct sockaddr_in6 *six = &portal->addr; struct sockaddr_in *sin; /* Check if this is really a v4 address is disguise. * If so, explicitly use an AF_INET socket - the * stack may not support IPv6. */ if (IN6_IS_ADDR_V4MAPPED(&six->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&six->sin6_addr)) { sin = (struct sockaddr_in *) addr; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_addr.s_addr = six->sin6_addr.s6_addr32[3]; sin->sin_port = six->sin6_port; return sizeof(*sin); } /* This is the genuine article */ memcpy(addr, six, sizeof(*six)); return sizeof(*six); }
/** \brief Convert libnf IP address to string. * * Without conversion, IP address is converted to * UINT[0]:UINT[1]:UINT[2]:UINT[3]. If IPv4 is present, first three UINTs are * zero. With conversion, inet_ntop() is used to convert binary representation * to string. * * \param[in] addr Binary IP address representation. * \return String IP address representation. Static memory. */ static const char * mylnf_addr_to_str(const lnf_ip_t *addr) { const char *ret; switch (output_params.ip_addr_conv) { case OUTPUT_IP_ADDR_CONV_NONE: snprintf(global_str, sizeof (global_str), "%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":%" PRIu32, ntohl(addr->data[0]), ntohl(addr->data[1]), ntohl(addr->data[2]), ntohl(addr->data[3])); break; case OUTPUT_IP_ADDR_CONV_STR: if (IN6_IS_ADDR_V4COMPAT(addr->data)) { //IPv4 compatibile ret = inet_ntop(AF_INET, addr->data + 3, global_str, INET_ADDRSTRLEN); } else { //IPv6 ret = inet_ntop(AF_INET6, addr->data, global_str, INET6_ADDRSTRLEN); } assert(ret != NULL); break; default: assert(!"unknown IP address conversion"); } return global_str; }
bool SocketAddress::isCompatIpv6(void) const { if (AF_INET6 == data_.base_.sa_family) { return IN6_IS_ADDR_V4COMPAT(&data_.in6_.sin6_addr); } return false; }
/* function for IPv4/IPv6 address */ static void format_addr(char *buff, char *data) { lnf_ip_t *addr = (lnf_ip_t *)data; if (IN6_IS_ADDR_V4COMPAT((struct in6_addr *)addr)) { inet_ntop(AF_INET, (char *)&(addr->data[3]), buff, MAX_STR); } else { inet_ntop(AF_INET6, addr, buff, MAX_STR); } }
static krb5_boolean ipv6_uninteresting (const struct sockaddr *sa) { const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr; return IN6_IS_ADDR_LINKLOCAL(in6) || IN6_IS_ADDR_V4COMPAT(in6); }
// Constructs an address corresponding to 'ss' that's compatible with 'fd'. CompatibleSocketAddress(int fd, const sockaddr_storage& ss, bool mapUnspecified) { const int desiredFamily = getSocketAddressFamily(fd); if (ss.ss_family == AF_INET6) { if (desiredFamily == AF_INET6) { // Nothing to do. mCompatibleAddress = reinterpret_cast<const sockaddr*>(&ss); } else { sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&mTmp); const sockaddr_in6* sin6 = reinterpret_cast<const sockaddr_in6*>(&ss); memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_port = sin6->sin6_port; if (IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr)) { // We have an IPv6-mapped IPv4 address, but need plain old IPv4. // Unmap the mapped address in ss into an IPv6 address in mTmp. memcpy(&sin->sin_addr.s_addr, &sin6->sin6_addr.s6_addr[12], 4); mCompatibleAddress = reinterpret_cast<const sockaddr*>(&mTmp); } else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) { // Translate the IPv6 loopback address to the IPv4 one. sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); mCompatibleAddress = reinterpret_cast<const sockaddr*>(&mTmp); } else { // We can't help you. We return what you gave us, and assume you'll // get a sensible error when you use the address. mCompatibleAddress = reinterpret_cast<const sockaddr*>(&ss); } } } else /* ss.ss_family == AF_INET */ { if (desiredFamily == AF_INET) { // Nothing to do. mCompatibleAddress = reinterpret_cast<const sockaddr*>(&ss); } else { // We have IPv4 and need IPv6. // Map the IPv4 address in ss into an IPv6 address in mTmp. const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(&ss); sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(&mTmp); memset(sin6, 0, sizeof(*sin6)); sin6->sin6_family = AF_INET6; sin6->sin6_port = sin->sin_port; // TODO: mapUnspecified was introduced because kernels < 2.6.31 don't allow // you to bind to ::ffff:0.0.0.0. When we move to something >= 2.6.31, we // should make the code behave as if mapUnspecified were always true, and // remove the parameter. if (sin->sin_addr.s_addr != 0 || mapUnspecified) { memset(&(sin6->sin6_addr.s6_addr[10]), 0xff, 2); } memcpy(&sin6->sin6_addr.s6_addr[12], &sin->sin_addr.s_addr, 4); mCompatibleAddress = reinterpret_cast<const sockaddr*>(&mTmp); } } }
/** 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; }
/* char * * inetntop(af, src, dst, size) * convert a network format address to presentation format. * return: * pointer to presentation format address (`dst'), or NULL (see errno). * author: * Paul Vixie, 1996. */ const char * inetntop(int af, const void *src, char *dst, unsigned int size) { switch (af) { case AF_INET: return inet_ntop4(src, dst, size); #ifdef IPV6 case AF_INET6: if (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src) || IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) return inet_ntop4((unsigned char *)&((const struct in6_addr *)src)->s6_addr[12], dst, size); else return inet_ntop6(src, dst, size); #endif default: return NULL; } /* NOTREACHED */ }
const char * inet_ntop6(const struct in6_addr *addr, char *dst, size_t size) { char hexa[8][5], tmp[MAX_V6_ADDR_LEN]; int zr[8]; size_t len; int32_t i, j, k, skip; uint8_t x8, hx8; uint16_t x16; struct in_addr a4; if (addr == NULL) return NULL; memset(tmp, 0, MAX_V6_ADDR_LEN); /* check for mapped or compat addresses */ i = IN6_IS_ADDR_V4MAPPED(addr); j = IN6_IS_ADDR_V4COMPAT(addr); if ((i != 0) || (j != 0)) { a4.s_addr = addr->__u6_addr.__u6_addr32[3]; sprintf(tmp, "::%s%s", (i != 0) ? "ffff:" : "", inet_ntoa(a4)); len = strlen(tmp) + 1; if (len > size) return NULL; memcpy(dst, tmp, len); return dst; } k = 0; for (i = 0; i < 16; i += 2) { j = 0; skip = 1; memset(hexa[k], 0, 5); x8 = addr->__u6_addr.__u6_addr8[i]; hx8 = x8 >> 4; if (hx8 != 0) { skip = 0; hexa[k][j++] = hexchars[hx8]; } hx8 = x8 & 0x0f; if ((skip == 0) || ((skip == 1) && (hx8 != 0))) { skip = 0; hexa[k][j++] = hexchars[hx8]; } x8 = addr->__u6_addr.__u6_addr8[i + 1]; hx8 = x8 >> 4; if ((skip == 0) || ((skip == 1) && (hx8 != 0))) { hexa[k][j++] = hexchars[hx8]; } hx8 = x8 & 0x0f; hexa[k][j++] = hexchars[hx8]; k++; } /* find runs of zeros for :: convention */ j = 0; for (i = 7; i >= 0; i--) { zr[i] = j; x16 = addr->__u6_addr.__u6_addr16[i]; if (x16 == 0) j++; else j = 0; zr[i] = j; } /* find longest run of zeros */ k = -1; j = 0; for(i = 0; i < 8; i++) { if (zr[i] > j) { k = i; j = zr[i]; } } for(i = 0; i < 8; i++) { if (i != k) zr[i] = 0; } len = 0; for (i = 0; i < 8; i++) { if (zr[i] != 0) { /* check for leading zero */ if (i == 0) tmp[len++] = ':'; tmp[len++] = ':'; i += (zr[i] - 1); continue; } for (j = 0; hexa[i][j] != '\0'; j++) tmp[len++] = hexa[i][j]; if (i != 7) tmp[len++] = ':'; } /* trailing NULL */ len++; if (len > size) return NULL; memcpy(dst, tmp, len); return dst; }
/** Build a list of local IPv6 addresses and append it to *return_result. */ static int localinfo6(su_localinfo_t const *hints, su_localinfo_t **return_result) { su_localinfo_t *li = NULL; su_sockaddr_t su[1] = {{ 0 }}, *addr; int error = ELI_NOADDRESS; char *canonname = NULL; char line[80]; FILE *f; if ((f = fopen("/proc/net/if_inet6", "r"))) { for (;error;) { struct in6_addr in6; unsigned if_index, prefix_len, scope, flags; int addrlen, if_namelen; char ifname[16]; if (!fgets(line, sizeof(line), f)) { if (feof(f)) error = ELI_NOERROR; break; } if (sscanf(line, "%08x%08x%08x%08x %2x %2x %2x %02x %016s\n", &in6.s6_addr32[0], &in6.s6_addr32[1], &in6.s6_addr32[2], &in6.s6_addr32[3], &if_index, &prefix_len, &scope, &flags, ifname) != 9) break; flags = 0; /* Fix global scope (it is 0) */ if (!scope) scope = LI_SCOPE_GLOBAL; in6.s6_addr32[0] = htonl(in6.s6_addr32[0]); in6.s6_addr32[1] = htonl(in6.s6_addr32[1]); in6.s6_addr32[2] = htonl(in6.s6_addr32[2]); in6.s6_addr32[3] = htonl(in6.s6_addr32[3]); if (IN6_IS_ADDR_V4MAPPED(&in6) || IN6_IS_ADDR_V4COMPAT(&in6)) { uint32_t ip4 = *(uint32_t *)(in6.s6_addr + 12); scope = li_scope4(ip4); } if ((hints->li_scope && (hints->li_scope & scope) == 0) || (hints->li_index && hints->li_index != if_index) || (hints->li_ifname && strcmp(hints->li_ifname, ifname) != 0)) continue; su->su_family = AF_INET6; su->su_sin6.sin6_addr = in6; addrlen = su_sockaddr_size(su); if ((error = li_name(hints, 0, su, &canonname)) < 0) break; else if (error > 0) continue; else error = ELI_NOADDRESS; if (canonname && (strchr(canonname, ':') || strspn(canonname, "0123456789.") == strlen(canonname))) flags |= LI_NUMERIC; if (hints->li_flags & LI_IFNAME) if_namelen = strlen(ifname) + 1; else if_namelen = 0; if ((li = calloc(1, sizeof *li + addrlen + if_namelen)) == NULL) { error = ELI_MEMORY; break; } addr = (su_sockaddr_t*)memcpy((li + 1), su, addrlen); *return_result = li; return_result = &li->li_next; li->li_flags = flags; li->li_family = AF_INET6; li->li_scope = scope; li->li_index = if_index; li->li_addr = addr; li->li_addrlen = addrlen; li->li_canonname = canonname; if (if_namelen) li->li_ifname = memcpy(addrlen + (char *)addr, ifname, if_namelen); canonname = NULL; } fclose(f); } if (canonname) free(canonname); return error; }
/* * Get a new connection request and initialize 'cp' appropriately */ static status_e get_connection( struct service *sp, connection_s *cp ) { struct service_config *scp = SVC_CONF( sp ); socklen_t sin_len; const char *func = "get_connection" ; int on = 1; if( SC_IPV4(scp) ) sin_len = sizeof(struct sockaddr_in); if( SC_IPV6(scp) ) sin_len = sizeof(struct sockaddr_in6); if ( SVC_SOCKET_TYPE( sp ) == SOCK_STREAM ) { /* If it's a TCP socket, and we're set to wait, the accept is * done by the child process. Don't set NEW_DESCRIPTOR, since * there isn't one. The descriptor will be/was removed from * the descriptor set in svc_suspend and re-enabled in svc_resume. */ if( SC_WAITS( scp ) ) { cp->co_descriptor = SVC_FD( sp ); } else { cp->co_descriptor = accept( SVC_FD( sp ), &(cp->co_remote_address.sa), &sin_len ) ; if (cp->co_descriptor != -1) M_SET( cp->co_flags, COF_NEW_DESCRIPTOR ) ; } if ( cp->co_descriptor == -1 ) { if ((errno == EMFILE) || (errno == ENFILE)) cps_service_stop(sp, "no available descriptors"); else msg( LOG_ERR, func, "service %s, accept: %m", SVC_ID( sp ) ) ; return( FAILED ) ; } if( SC_NODELAY( scp ) && (SC_PROTOVAL( scp ) == IPPROTO_TCP) ) if( setsockopt(SVC_FD(sp), IPPROTO_TCP, TCP_NODELAY, (char *)&on, sizeof( on ) ) < 0 ) msg( LOG_WARNING, func, "service %s, setsockopt: %m", SVC_ID(sp)); if( SC_KEEPALIVE( scp ) && (SC_PROTOVAL( scp ) == IPPROTO_TCP) ) { if( setsockopt(SVC_FD(sp), SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof( on ) ) < 0 ) msg( LOG_WARNING, func, "service %s, setsockopt: %m", SVC_ID(sp)); } if( SC_IPV6(scp) && !(SC_V6ONLY( scp )) && (IN6_IS_ADDR_V4MAPPED(&cp->co_remote_address.sa_in6.sin6_addr) || IN6_IS_ADDR_V4COMPAT(&cp->co_remote_address.sa_in6.sin6_addr)) ) { int af = AF_INET; if( setsockopt(cp->co_descriptor, IPPROTO_IPV6, IPV6_ADDRFORM, &af, sizeof( af ) ) ) { if( debug.on ) msg( LOG_WARNING, func, "service %s, IPV6_ADDRFORM setsockopt() failed: %m", SVC_ID( sp) ); } } M_SET( cp->co_flags, COF_HAVE_ADDRESS ) ; } else { if ( SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM ) { char t_ch ; ssize_t val; /* * This trick is done to get the remote address. * select(2) guaranteed that we won't block on the recvfrom */ val = recvfrom( SVC_FD( sp ), &t_ch, 1, MSG_PEEK, &cp->co_remote_address.sa, &sin_len ); if ( val == (ssize_t)-1 ) { msg( LOG_ERR, func, "service %s, recvfrom: %m", SVC_ID( sp ) ) ; return( FAILED ) ; } M_SET( cp->co_flags, COF_HAVE_ADDRESS ) ; } cp->co_descriptor = SVC_FD( sp ) ; } return( OK ) ; }
static void tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type, uint8_t tflags) { char *p, *pp; int mask, af; struct in6_addr *paddr, tmp; struct tflow_entry *tfe; uint32_t key, *pkey; uint16_t port; struct protoent *pent; struct servent *sent; int masklen; masklen = 0; af = 0; paddr = (struct in6_addr *)&tentry->k; switch (type) { case IPFW_TABLE_ADDR: /* Remove / if exists */ if ((p = strchr(arg, '/')) != NULL) { *p = '\0'; mask = atoi(p + 1); } if (inet_pton(AF_INET, arg, paddr) == 1) { if (p != NULL && mask > 32) errx(EX_DATAERR, "bad IPv4 mask width: %s", p + 1); masklen = p ? mask : 32; af = AF_INET; } else if (inet_pton(AF_INET6, arg, paddr) == 1) { if (IN6_IS_ADDR_V4COMPAT(paddr)) errx(EX_DATAERR, "Use IPv4 instead of v4-compatible"); if (p != NULL && mask > 128) errx(EX_DATAERR, "bad IPv6 mask width: %s", p + 1); masklen = p ? mask : 128; af = AF_INET6; } else { /* Assume FQDN */ if (lookup_host(arg, (struct in_addr *)paddr) != 0) errx(EX_NOHOST, "hostname ``%s'' unknown", arg); masklen = 32; type = IPFW_TABLE_ADDR; af = AF_INET; } break; case IPFW_TABLE_INTERFACE: /* Assume interface name. Copy significant data only */ mask = MIN(strlen(arg), IF_NAMESIZE - 1); memcpy(paddr, arg, mask); /* Set mask to exact match */ masklen = 8 * IF_NAMESIZE; break; case IPFW_TABLE_NUMBER: /* Port or any other key */ key = strtol(arg, &p, 10); if (*p != '\0') errx(EX_DATAERR, "Invalid number: %s", arg); pkey = (uint32_t *)paddr; *pkey = key; masklen = 32; break; case IPFW_TABLE_FLOW: /* Assume [src-ip][,proto][,src-port][,dst-ip][,dst-port] */ tfe = &tentry->k.flow; af = 0; /* Handle <ipv4|ipv6> */ if ((tflags & IPFW_TFFLAG_SRCIP) != 0) { if ((p = strchr(arg, ',')) != NULL) *p++ = '\0'; /* Determine family using temporary storage */ if (inet_pton(AF_INET, arg, &tmp) == 1) { if (af != 0 && af != AF_INET) errx(EX_DATAERR, "Inconsistent address family\n"); af = AF_INET; memcpy(&tfe->a.a4.sip, &tmp, 4); } else if (inet_pton(AF_INET6, arg, &tmp) == 1) { if (af != 0 && af != AF_INET6) errx(EX_DATAERR, "Inconsistent address family\n"); af = AF_INET6; memcpy(&tfe->a.a6.sip6, &tmp, 16); } arg = p; } /* Handle <proto-num|proto-name> */ if ((tflags & IPFW_TFFLAG_PROTO) != 0) { if (arg == NULL) errx(EX_DATAERR, "invalid key: proto missing"); if ((p = strchr(arg, ',')) != NULL) *p++ = '\0'; key = strtol(arg, &pp, 10); if (*pp != '\0') { if ((pent = getprotobyname(arg)) == NULL) errx(EX_DATAERR, "Unknown proto: %s", arg); else key = pent->p_proto; } if (key > 255) errx(EX_DATAERR, "Bad protocol number: %u",key); tfe->proto = key; arg = p; } /* Handle <port-num|service-name> */ if ((tflags & IPFW_TFFLAG_SRCPORT) != 0) { if (arg == NULL) errx(EX_DATAERR, "invalid key: src port missing"); if ((p = strchr(arg, ',')) != NULL) *p++ = '\0'; if ((port = htons(strtol(arg, NULL, 10))) == 0) { if ((sent = getservbyname(arg, NULL)) == NULL) errx(EX_DATAERR, "Unknown service: %s", arg); else key = sent->s_port; } tfe->sport = port; arg = p; } /* Handle <ipv4|ipv6>*/ if ((tflags & IPFW_TFFLAG_DSTIP) != 0) { if (arg == NULL) errx(EX_DATAERR, "invalid key: dst ip missing"); if ((p = strchr(arg, ',')) != NULL) *p++ = '\0'; /* Determine family using temporary storage */ if (inet_pton(AF_INET, arg, &tmp) == 1) { if (af != 0 && af != AF_INET) errx(EX_DATAERR, "Inconsistent address family"); af = AF_INET; memcpy(&tfe->a.a4.dip, &tmp, 4); } else if (inet_pton(AF_INET6, arg, &tmp) == 1) { if (af != 0 && af != AF_INET6) errx(EX_DATAERR, "Inconsistent address family"); af = AF_INET6; memcpy(&tfe->a.a6.dip6, &tmp, 16); } arg = p; } /* Handle <port-num|service-name> */ if ((tflags & IPFW_TFFLAG_DSTPORT) != 0) { if (arg == NULL) errx(EX_DATAERR, "invalid key: dst port missing"); if ((p = strchr(arg, ',')) != NULL) *p++ = '\0'; if ((port = htons(strtol(arg, NULL, 10))) == 0) { if ((sent = getservbyname(arg, NULL)) == NULL) errx(EX_DATAERR, "Unknown service: %s", arg); else key = sent->s_port; } tfe->dport = port; arg = p; } tfe->af = af; break; default: errx(EX_DATAERR, "Unsupported table type: %d", type); } tentry->subtype = af; tentry->masklen = masklen; }
/* ARGSUSED */ char * inet_ntop(int af, const void *addr, char *buf, int addrlen) { static char local_buf[INET6_ADDRSTRLEN]; static char *err_buf1 = "<badaddr>"; static char *err_buf2 = "<badfamily>"; in6_addr_t *v6addr; uchar_t *v4addr; char *caddr; /* * We don't allow thread unsafe inet_ntop calls, they * must pass a non-null buffer pointer. For DEBUG mode * we use the ASSERT() and for non-debug kernel it will * silently allow it for now. Someday we should remove * the static buffer from this function. */ ASSERT(buf != NULL); if (buf == NULL) buf = local_buf; buf[0] = '\0'; /* Let user know politely not to send NULL or unaligned addr */ if (addr == NULL || !(OK_32PTR(addr))) { #ifdef DEBUG cmn_err(CE_WARN, "inet_ntop: addr is <null> or unaligned"); #endif return (err_buf1); } #define UC(b) (((int)b) & 0xff) switch (af) { case AF_INET: ASSERT(addrlen >= INET_ADDRSTRLEN); v4addr = (uchar_t *)addr; (void) sprintf(buf, "%03d.%03d.%03d.%03d", UC(v4addr[0]), UC(v4addr[1]), UC(v4addr[2]), UC(v4addr[3])); return (buf); case AF_INET6: ASSERT(addrlen >= INET6_ADDRSTRLEN); v6addr = (in6_addr_t *)addr; if (IN6_IS_ADDR_V4MAPPED(v6addr)) { caddr = (char *)addr; (void) sprintf(buf, "::ffff:%d.%d.%d.%d", UC(caddr[12]), UC(caddr[13]), UC(caddr[14]), UC(caddr[15])); } else if (IN6_IS_ADDR_V4COMPAT(v6addr)) { caddr = (char *)addr; (void) sprintf(buf, "::%d.%d.%d.%d", UC(caddr[12]), UC(caddr[13]), UC(caddr[14]), UC(caddr[15])); } else if (IN6_IS_ADDR_UNSPECIFIED(v6addr)) { (void) sprintf(buf, "::"); } else { convert2ascii(buf, v6addr); } return (buf); default: return (err_buf2); } #undef UC }
struct hostent * getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { struct hostent *he1, *he2; struct net_data *net_data = init(); /* Sanity Checks. */ if (src == NULL) { *error_num = NO_RECOVERY; return (NULL); } switch (af) { case AF_INET: if (len != (size_t)INADDRSZ) { *error_num = NO_RECOVERY; return (NULL); } break; case AF_INET6: if (len != (size_t)IN6ADDRSZ) { *error_num = NO_RECOVERY; return (NULL); } break; default: *error_num = NO_RECOVERY; return (NULL); } /* * Lookup IPv4 and IPv4 mapped/compatible addresses */ if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) || (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) || (af == AF_INET)) { const char *cp = src; if (af == AF_INET6) cp += 12; he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data); if (he1 == NULL) { *error_num = net_data->res->res_h_errno; return (NULL); } he2 = copyandmerge(he1, NULL, af, error_num); if (he2 == NULL) return (NULL); /* * Restore original address if mapped/compatible. */ if (af == AF_INET6) memcpy(he1->h_addr, src, len); return (he2); } /* * Lookup IPv6 address. */ if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) { *error_num = HOST_NOT_FOUND; return (NULL); } he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data); if (he1 == NULL) { *error_num = net_data->res->res_h_errno; return (NULL); } return (copyandmerge(he1, NULL, af, error_num)); }
struct hostent * W32_CALL getipnodebyaddr (const void *src, size_t len, int af, int *error) { struct hostent *he1, *he2; const BYTE *cp = (const BYTE*) src; SOCK_DEBUGF (("\ngetipnodebyaddr: ")); if (!src) { *error = NO_RECOVERY; return (NULL); } switch (af) { case AF_INET: if (len < INADDRSZ) { *error = NO_RECOVERY; return (NULL); } break; #if defined(USE_IPV6) case AF_INET6: if (len < IN6ADDRSZ) { *error = NO_RECOVERY; return (NULL); } break; #endif default: *error = NO_RECOVERY; return (NULL); } /* Look up IPv4 and IPv4 mapped/compatible addresses. */ if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(cp)) || (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(cp)) || (af == AF_INET)) { if (af == AF_INET6) cp += 12; SOCK_ENTER_SCOPE(); he1 = gethostbyaddr ((const char*)cp, 4, AF_INET); SOCK_LEAVE_SCOPE(); if (af == AF_INET) goto ret_copy; /* Convert from AF_INET to AF_INET6. */ he2 = copyandmerge (he1, NULL, af, error); if (he2) { memcpy (he2->h_addr, src, len); /* Restore original address */ SOCK_DEBUGF (("%s", af == AF_INET ? inet_ntoa(*(struct in_addr*)&he2->h_addr) : _inet6_ntoa(he2->h_addr))); } return (he2); } he1 = gethostbyaddr (src, len, AF_INET6); /* Lookup IPv6 address */ ret_copy: if (!he1) { *error = HOST_NOT_FOUND; return (NULL); } return copyandmerge (he1, NULL, af, error); }
/* * 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; }
void cXVDRServer::NewClientConnected(int fd) { struct sockaddr_storage sin; socklen_t len = sizeof(sin); in_addr_t *ipv4_addr = NULL; if (getpeername(fd, (struct sockaddr *)&sin, &len)) { ERRORLOG("getpeername() failed, dropping new incoming connection %d", m_IdCnt); close(fd); return; } if (!m_IPv4Fallback) { if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&sin)->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&((struct sockaddr_in6 *)&sin)->sin6_addr)) ipv4_addr = &((struct sockaddr_in6 *)&sin)->sin6_addr.s6_addr32[3]; } else ipv4_addr = &((struct sockaddr_in *)&sin)->sin_addr.s_addr; // Acceptable() method only supports in_addr_t argument so we're currently checking IPv4 hosts only if (ipv4_addr) { cAllowedHosts AllowedHosts(m_AllowedHostsFile); if (!AllowedHosts.Acceptable(*ipv4_addr)) { ERRORLOG("Address not allowed to connect (%s)", *m_AllowedHostsFile); close(fd); return; } } if (fcntl(fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK) == -1) { ERRORLOG("Error setting control socket to nonblocking mode"); close(fd); return; } int val = 1; setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); #ifndef __FreeBSD__ val = 30; setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &val, sizeof(val)); val = 15; setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &val, sizeof(val)); val = 5; setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &val, sizeof(val)); #endif val = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); if (!m_IPv4Fallback) INFOLOG("Client %s:%i with ID %d connected.", xvdr_inet_ntoa(((struct sockaddr_in6 *)&sin)->sin6_addr), ((struct sockaddr_in6 *)&sin)->sin6_port, m_IdCnt); else INFOLOG("Client %s:%i with ID %d connected.", inet_ntoa(((struct sockaddr_in *)&sin)->sin_addr), ((struct sockaddr_in *)&sin)->sin_port, m_IdCnt); cXVDRClient *connection = new cXVDRClient(fd, m_IdCnt); m_clients.push_back(connection); m_IdCnt++; }
/* * Type0 routing header processing * * RFC2292 backward compatibility warning: no support for strict/loose bitmap, * as it was dropped between RFC1883 and RFC2460. */ static int ip6_rthdr0(struct mbuf *m, struct ip6_hdr *ip6, struct ip6_rthdr0 *rh0) { int addrs, index; struct in6_addr *nextaddr, tmpaddr; const struct ip6aux *ip6a; if (rh0->ip6r0_segleft == 0) return (0); if (rh0->ip6r0_len % 2 #ifdef COMPAT_RFC1883 || rh0->ip6r0_len > 46 #endif ) { /* * Type 0 routing header can't contain more than 23 addresses. * RFC 2462: this limitation was removed since strict/loose * bitmap field was deleted. */ IP6_STATINC(IP6_STAT_BADOPTIONS); icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, (char *)&rh0->ip6r0_len - (char *)ip6); return (-1); } if ((addrs = rh0->ip6r0_len / 2) < rh0->ip6r0_segleft) { IP6_STATINC(IP6_STAT_BADOPTIONS); icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, (char *)&rh0->ip6r0_segleft - (char *)ip6); return (-1); } index = addrs - rh0->ip6r0_segleft; rh0->ip6r0_segleft--; nextaddr = ((struct in6_addr *)(rh0 + 1)) + index; /* * reject invalid addresses. be proactive about malicious use of * IPv4 mapped/compat address. * XXX need more checks? */ if (IN6_IS_ADDR_MULTICAST(nextaddr) || IN6_IS_ADDR_UNSPECIFIED(nextaddr) || IN6_IS_ADDR_V4MAPPED(nextaddr) || IN6_IS_ADDR_V4COMPAT(nextaddr)) { p6stat[IP6_STAT_BADOPTIONS]++; goto bad; } if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst) || IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst) || IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { IP6_STATINC(IP6_STAT_BADOPTIONS); goto bad; } /* * Determine the scope zone of the next hop, based on the interface * of the current hop. [RFC4007, Section 9] * Then disambiguate the scope zone for the next hop (if necessary). */ if ((ip6a = ip6_getdstifaddr(m)) == NULL) goto bad; if (in6_setzoneid(nextaddr, ip6a->ip6a_scope_id) != 0) { IP6_STATINC(IP6_STAT_BADSCOPE); goto bad; } /* * Swap the IPv6 destination address and nextaddr. Forward the packet. */ tmpaddr = *nextaddr; *nextaddr = ip6->ip6_dst; in6_clearscope(nextaddr); /* XXX */ ip6->ip6_dst = tmpaddr; #ifdef COMPAT_RFC1883 if (rh0->ip6r0_slmap[index / 8] & (1 << (7 - (index % 8)))) ip6_forward(m, IPV6_SRCRT_NEIGHBOR); else ip6_forward(m, IPV6_SRCRT_NOTNEIGHBOR); #else ip6_forward(m, 1); #endif return (-1); /* m would be freed in ip6_forward() */ bad: m_freem(m); return (-1); }
static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; struct net_device_stats *stats = &tunnel->stat; struct iphdr *tiph = &tunnel->parms.iph; u8 tos = tunnel->parms.iph.tos; u16 df = tiph->frag_off; struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ struct iphdr *old_iph = skb->nh.iph; #ifdef CONFIG_NET_IPIP_IPV6 struct ipv6hdr *iph6 = skb->nh.ipv6h; #endif struct iphdr *iph; /* Our new IP header */ int max_headroom; /* The extra header space needed */ u32 dst = tiph->daddr; int mtu; u8 protocol = 0; switch (skb->protocol) { case __constant_htons(ETH_P_IP): protocol = IPPROTO_IPIP; break; #ifdef CONFIG_NET_IPIP_IPV6 case __constant_htons(ETH_P_IPV6): protocol = IPPROTO_IPV6; break; #endif } if (tunnel->recursion++) { tunnel->stat.collisions++; goto tx_error; } switch(skb->protocol) { case __constant_htons(ETH_P_IP): if (tunnel->parms.iph.protocol && tunnel->parms.iph.protocol != IPPROTO_IPIP) goto tx_error; if (tos&1) tos = old_iph->tos; break; #ifdef CONFIG_NET_IPIP_IPV6 case __constant_htons(ETH_P_IPV6): if (tunnel->parms.iph.protocol && tunnel->parms.iph.protocol != IPPROTO_IPV6) goto tx_error; break; #endif default: goto tx_error; } if (!dst) { switch(skb->protocol){ case __constant_htons(ETH_P_IP): /* NBMA tunnel */ if ((rt = (struct rtable*)skb->dst) == NULL) { tunnel->stat.tx_fifo_errors++; goto tx_error; } dst = rt->rt_gateway; break; #ifdef CONFIG_NET_IPIP_IPV6 case __constant_htons(ETH_P_IPV6): { struct in6_addr *addr6 = &iph6->daddr; if (addr6->s6_addr16[0] == htons(0x2002)) { memcpy(&dst, &addr6->s6_addr16[1], 4); } else { /* dst is zero */ struct neighbour *neigh = NULL; if (skb->dst) neigh = skb->dst->neighbour; if (neigh == NULL) { printk(KERN_DEBUG "tunl: nexthop == NULL\n"); goto tx_error; } addr6 = (struct in6_addr*)&neigh->primary_key; if (IN6_IS_ADDR_UNSPECIFIED(addr6)) addr6 = &skb->nh.ipv6h->daddr; if (IN6_IS_ADDR_V4COMPAT(addr6)) dst = addr6->s6_addr32[3]; #ifdef CONFIG_IPV6_6TO4_NEXTHOP else if (addr6->s6_addr16[0] == htons(0x2002)) memcpy(&dst, &addr6->s6_addr16[1], 4); #endif else goto tx_error_icmp; } break; } #endif } if (!dst) goto tx_error_icmp; } if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) { tunnel->stat.tx_carrier_errors++; goto tx_error_icmp; } tdev = rt->u.dst.dev; if (tdev == dev) { ip_rt_put(rt); tunnel->stat.collisions++; goto tx_error; } if (tiph->frag_off) mtu = rt->u.dst.pmtu - sizeof(struct iphdr); else mtu = skb->dst ? skb->dst->pmtu : dev->mtu; if (mtu < 68) { tunnel->stat.collisions++; ip_rt_put(rt); goto tx_error; } switch(skb->protocol){ case __constant_htons(ETH_P_IP): if (skb->dst && mtu < skb->dst->pmtu) skb->dst->pmtu = mtu; df |= (old_iph->frag_off&htons(IP_DF)); if ((old_iph->frag_off&htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); ip_rt_put(rt); goto tx_error; } break; #ifdef CONFIG_NET_IPIP_IPV6 case __constant_htons(ETH_P_IPV6): #if 0 if (mtu < IPV6_MIN_MTU) { /* XXX: too small; we should fragment this packet? */ tunnel->stat.tx_carrier_errors++; goto tx_error_icmp; } #endif if (skb->len > mtu && mtu > IPV6_MIN_MTU) { icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); ip_rt_put(rt); goto tx_error; } df = mtu > IPV6_MIN_MTU ? htons(IP_DF) : 0; break; #endif } if (tunnel->err_count > 0) { if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { tunnel->err_count--; dst_link_failure(skb); } else tunnel->err_count = 0; } /* * Okay, now see if we can stuff it in the buffer as-is. */ max_headroom = (((tdev->hard_header_len+15)&~15)+sizeof(struct iphdr)); if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); if (!new_skb) { ip_rt_put(rt); stats->tx_dropped++; dev_kfree_skb(skb); tunnel->recursion--; return 0; } if (skb->sk) skb_set_owner_w(new_skb, skb->sk); dev_kfree_skb(skb); skb = new_skb; old_iph = skb->nh.iph; } skb->h.raw = skb->nh.raw; skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); dst_release(skb->dst); skb->dst = &rt->u.dst; /* * Push down and install the IPIP header. */ iph = skb->nh.iph; iph->version = 4; iph->ihl = sizeof(struct iphdr)>>2; iph->daddr = rt->rt_dst; iph->saddr = rt->rt_src; iph->ttl = tiph->ttl; iph->frag_off = df; switch(skb->protocol){ case __constant_htons(ETH_P_IP): iph->protocol = protocol; iph->tos = INET_ECN_encapsulate(tos, old_iph->tos); if (iph->ttl == 0) iph->ttl = old_iph->ttl; break; #ifdef CONFIG_NET_IPIP_IPV6 case __constant_htons(ETH_P_IPV6): iph->protocol = protocol; iph->tos = INET_ECN_encapsulate(tos, ip6_get_dsfield(iph6)); if (iph->ttl == 0) iph->ttl = iph6->hop_limit; break; #endif } nf_reset(skb); IPTUNNEL_XMIT(); tunnel->recursion--; return 0; tx_error_icmp: dst_link_failure(skb); tx_error: stats->tx_errors++; dev_kfree_skb(skb); tunnel->recursion--; return 0; }
static int lc_local_addresses(lua_State *L) { #ifndef _WIN32 /* Link-local IPv4 addresses; see RFC 3927 and RFC 5735 */ const long ip4_linklocal = htonl(0xa9fe0000); /* 169.254.0.0 */ const long ip4_mask = htonl(0xffff0000); struct ifaddrs *addr = NULL, *a; #endif int n = 1; int type = luaL_checkoption(L, 1, "both", type_strings); const char link_local = lua_toboolean(L, 2); /* defaults to 0 (false) */ const char ipv4 = (type == 0 || type == 1); const char ipv6 = (type == 0 || type == 2); #ifndef _WIN32 if (getifaddrs(&addr) < 0) { lua_pushnil(L); lua_pushfstring(L, "getifaddrs failed (%d): %s", errno, strerror(errno)); return 2; } #endif lua_newtable(L); #ifndef _WIN32 for (a = addr; a; a = a->ifa_next) { int family; char ipaddr[INET6_ADDRSTRLEN]; const char *tmp = NULL; if (a->ifa_addr == NULL || a->ifa_flags & IFF_LOOPBACK) continue; family = a->ifa_addr->sa_family; if (ipv4 && family == AF_INET) { struct sockaddr_in *sa = (struct sockaddr_in *)a->ifa_addr; if (!link_local &&((sa->sin_addr.s_addr & ip4_mask) == ip4_linklocal)) continue; tmp = inet_ntop(family, &sa->sin_addr, ipaddr, sizeof(ipaddr)); } else if (ipv6 && family == AF_INET6) { struct sockaddr_in6 *sa = (struct sockaddr_in6 *)a->ifa_addr; if (!link_local && IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) continue; if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&sa->sin6_addr)) continue; tmp = inet_ntop(family, &sa->sin6_addr, ipaddr, sizeof(ipaddr)); } if (tmp != NULL) { lua_pushstring(L, tmp); lua_rawseti(L, -2, n++); } /* TODO: Error reporting? */ } freeifaddrs(addr); #else if (ipv4) { lua_pushstring(L, "0.0.0.0"); lua_rawseti(L, -2, n++); } if (ipv6) { lua_pushstring(L, "::"); lua_rawseti(L, -2, n++); } #endif return 1; }
struct hostent * getipnodebyaddr(const void *src, size_t len, int af, int *errp) { struct hostent *hp; int rval; #ifdef INET6 struct in6_addr addrbuf; #else struct in_addr addrbuf; #endif static const ns_dtab dtab[] = { NS_FILES_CB(_files_ghbyaddr, NULL) { NSSRC_DNS, _dns_ghbyaddr, NULL }, NS_NIS_CB(_nis_ghbyaddr, NULL) #ifdef ICMPNL { NSSRC_ICMP, _icmp_ghbyaddr, NULL }, #endif { 0 } }; *errp = HOST_NOT_FOUND; switch (af) { case AF_INET: if (len != sizeof(struct in_addr)) { *errp = NO_RECOVERY; return NULL; } if ((long)src & ~(sizeof(struct in_addr) - 1)) { memcpy(&addrbuf, src, len); src = &addrbuf; } if (((struct in_addr *)src)->s_addr == 0) return NULL; break; #ifdef INET6 case AF_INET6: if (len != sizeof(struct in6_addr)) { *errp = NO_RECOVERY; return NULL; } if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/ memcpy(&addrbuf, src, len); src = &addrbuf; } if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src)) return NULL; if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src) || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) { src = (char *)src + (sizeof(struct in6_addr) - sizeof(struct in_addr)); af = AF_INET; len = sizeof(struct in_addr); } break; #endif default: *errp = NO_RECOVERY; return NULL; } rval = nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyaddr", default_src, src, len, af, errp); return (rval == NS_SUCCESS) ? hp : NULL; }
static void accept_connection(int pfd, void *data) { static time_t last_oper_notice = 0; struct irc_sockaddr sai; struct irc_inaddr addr; int fd; int pe; struct Listener * listener = data; assert(listener != NULL); if(listener == NULL) return; /* * There may be many reasons for error return, but * in otherwise correctly working environment the * probable cause is running out of file descriptors * (EMFILE, ENFILE or others?). The man pages for * accept don't seem to list these as possible, * although it's obvious that it may happen here. * Thus no specific errors are tested at this * point, just assume that connections cannot * be accepted until some old is closed first. */ fd = comm_accept(listener->fd, &sai); copy_s_addr(IN_ADDR(addr), S_ADDR(sai)); #ifdef IPV6 if((IN6_IS_ADDR_V4MAPPED(&IN_ADDR2(addr))) || (IN6_IS_ADDR_V4COMPAT(&IN_ADDR2(addr)))) { memmove(&addr.sins.sin.s_addr, addr.sins.sin6.s6_addr+12, sizeof(struct in_addr)); sai.sins.sin.sin_family = AF_INET; } #endif if (fd < 0) { /* Re-register a new IO request for the next accept .. */ comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ, accept_connection, listener, 0); return; } /* * check for connection limit */ if ((MAXCONNECTIONS - 10) < fd) { ++ServerStats->is_ref; /* * slow down the whining to opers bit */ if((last_oper_notice + 20) <= CurrentTime) { sendto_realops_flags(UMODE_ALL, L_ALL,"All connections in use. (%s)", get_listener_name(listener)); last_oper_notice = CurrentTime; } send(fd, "ERROR :All connections in use\r\n", 32, 0); fd_close(fd); /* Re-register a new IO request for the next accept .. */ comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ, accept_connection, listener, 0); return; } /* Do an initial check we aren't connecting too fast or with too many * from this IP... */ if ((pe = conf_connect_allowed(&addr, sai.sins.sin.sin_family)) != 0) { ServerStats->is_ref++; /* XXX - this can only be BANNED_CLIENT? */ switch (pe) { case BANNED_CLIENT: send(fd, DLINE_WARNING, sizeof(DLINE_WARNING)-1, 0); break; } fd_close(fd); /* Re-register a new IO request for the next accept .. */ comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ, accept_connection, listener, 0); return; } ServerStats->is_ac++; add_connection(listener, fd); /* Re-register a new IO request for the next accept .. */ comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ, accept_connection, listener, 0); }
/*% performs a reverse lookup of address src which is len bytes long. af denotes the protocol family, typically #PF_INET or PF_INET6. */ struct hostent * lwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { struct hostent *he1, *he2; lwres_context_t *lwrctx = NULL; lwres_gnbaresponse_t *by = NULL; lwres_result_t n; union { const void *konst; struct in6_addr *in6; } u; /* * Sanity checks. */ if (src == NULL) { *error_num = NO_RECOVERY; return (NULL); } switch (af) { case AF_INET: if (len != (unsigned int)INADDRSZ) { *error_num = NO_RECOVERY; return (NULL); } break; case AF_INET6: if (len != (unsigned int)IN6ADDRSZ) { *error_num = NO_RECOVERY; return (NULL); } break; default: *error_num = NO_RECOVERY; return (NULL); } /* * The de-"const"-ing game is done because at least one * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_* * macros in such a way that they discard the const with * internal casting, and gcc ends up complaining. Rather * than replacing their own (possibly optimized) definitions * with our own, cleanly discarding the const is the easiest * thing to do. */ u.konst = src; /* * Look up IPv4 and IPv4 mapped/compatible addresses. */ if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) || (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) || (af == AF_INET)) { const unsigned char *cp = src; if (af == AF_INET6) cp += 12; n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (n == LWRES_R_SUCCESS) (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (n == LWRES_R_SUCCESS) n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4, INADDRSZ, cp, &by); if (n != LWRES_R_SUCCESS) { lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); if (n == LWRES_R_NOTFOUND) *error_num = HOST_NOT_FOUND; else *error_num = NO_RECOVERY; return (NULL); } he1 = hostfromaddr(by, AF_INET, cp); lwres_gnbaresponse_free(lwrctx, &by); lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); if (af != AF_INET6) return (he1); /* * Convert from AF_INET to AF_INET6. */ he2 = copyandmerge(he1, NULL, af, error_num); lwres_freehostent(he1); if (he2 == NULL) return (NULL); /* * Restore original address. */ memcpy(he2->h_addr, src, len); return (he2); } /* * Lookup IPv6 address. */ if (memcmp(src, &in6addr_any, IN6ADDRSZ) == 0) { *error_num = HOST_NOT_FOUND; return (NULL); } n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (n == LWRES_R_SUCCESS) (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (n == LWRES_R_SUCCESS) n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ, src, &by); if (n != 0) { lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); if (n == LWRES_R_NOTFOUND) *error_num = HOST_NOT_FOUND; else *error_num = NO_RECOVERY; return (NULL); } he1 = hostfromaddr(by, AF_INET6, src); lwres_gnbaresponse_free(lwrctx, &by); if (he1 == NULL) *error_num = NO_RECOVERY; lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); return (he1); }
/* * This is the IPv6 interface for "gethostbyaddr". */ struct hostent * getipnodebyaddr(const void *src, size_t len, int type, int *error_num) { struct in6_addr *addr6 = 0; struct in_addr *addr4 = 0; nss_XbyY_buf_t *buf = 0; nss_XbyY_buf_t *res = 0; struct netconfig *nconf; struct hostent *hp = 0; struct nss_netdirbyaddr_in nssin; union nss_netdirbyaddr_out nssout; int neterr; char tmpbuf[64]; if (type == AF_INET6) { if ((addr6 = (struct in6_addr *)src) == NULL) { *error_num = HOST_NOT_FOUND; return (NULL); } } else if (type == AF_INET) { if ((addr4 = (struct in_addr *)src) == NULL) { *error_num = HOST_NOT_FOUND; return (NULL); } } else { *error_num = HOST_NOT_FOUND; return (NULL); } /* * Specific case: query for "::" */ if (type == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(addr6)) { *error_num = HOST_NOT_FOUND; return (NULL); } /* * Step 1: IPv4-mapped address or IPv4 Compat */ if ((type == AF_INET6 && len == 16) && ((IN6_IS_ADDR_V4MAPPED(addr6)) || (IN6_IS_ADDR_V4COMPAT(addr6)))) { if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) { *error_num = NO_RECOVERY; return (NULL); } if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) { *error_num = NO_RECOVERY; __IPv6_cleanup(buf); return (NULL); } nssin.op_t = NSS_HOST6; if (IN6_IS_ADDR_V4COMPAT(addr6)) { (void) memcpy(tmpbuf, addr6, sizeof (*addr6)); tmpbuf[10] = 0xffU; tmpbuf[11] = 0xffU; nssin.arg.nss.host.addr = (const char *)tmpbuf; } else { nssin.arg.nss.host.addr = (const char *)addr6; } nssin.arg.nss.host.len = sizeof (struct in6_addr); nssin.arg.nss.host.type = AF_INET6; nssin.arg.nss.host.buf = buf->buffer; nssin.arg.nss.host.buflen = buf->buflen; nssout.nss.host.hent = buf->result; nssout.nss.host.herrno_p = error_num; /* * We pass in nconf and let the implementation of the * long-named func decide whether to use the switch based on * nc_nlookups. */ neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout); (void) freenetconfigent(nconf); if (neterr != ND_OK) { /* Failover case, try hosts db for v4 address */ if (!gethostbyaddr_r(((char *)addr6) + 12, sizeof (in_addr_t), AF_INET, buf->result, buf->buffer, buf->buflen, error_num)) { __IPv6_cleanup(buf); return (NULL); } /* Found one, now format it into mapped/compat addr */ if ((res = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) { __IPv6_cleanup(buf); *error_num = NO_RECOVERY; return (NULL); } /* Convert IPv4 to mapped/compat address w/name */ hp = res->result; (void) __mapv4tov6(buf->result, 0, res, IN6_IS_ADDR_V4MAPPED(addr6)); __IPv6_cleanup(buf); free(res); return (hp); } /* * At this point, we'll have a v4mapped hostent. If that's * what was passed in, just return. If the request was a compat, * twiggle the two bytes to make the mapped address a compat. */ hp = buf->result; if (IN6_IS_ADDR_V4COMPAT(addr6)) { /* LINTED pointer cast */ addr6 = (struct in6_addr *)hp->h_addr_list[0]; addr6->s6_addr[10] = 0; addr6->s6_addr[11] = 0; } free(buf); return (hp); } /* * Step 2: AF_INET, v4 lookup. Since we're going to search the * ipnodes (v6) path first, we need to treat this as a v4mapped * address. nscd(1m) caches v4 from ipnodes as mapped v6's. The * switch backend knows to lookup v4's (not v4mapped) from the * name services. */ if (type == AF_INET) { struct in6_addr v4mapbuf; addr6 = &v4mapbuf; IN6_INADDR_TO_V4MAPPED(addr4, addr6); if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) { *error_num = NO_RECOVERY; return (NULL); } if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) { *error_num = NO_RECOVERY; freenetconfigent(nconf); return (NULL); } nssin.op_t = NSS_HOST6; nssin.arg.nss.host.addr = (const char *)addr6; nssin.arg.nss.host.len = sizeof (struct in6_addr); nssin.arg.nss.host.type = AF_INET6; nssin.arg.nss.host.buf = buf->buffer; nssin.arg.nss.host.buflen = buf->buflen; nssout.nss.host.hent = buf->result; nssout.nss.host.herrno_p = error_num; /* * We pass in nconf and let the implementation of the * long-named func decide whether to use the switch based on * nc_nlookups. */ neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout); (void) freenetconfigent(nconf); if (neterr != ND_OK) { /* Failover case, try hosts db for v4 address */ hp = buf->result; if (!gethostbyaddr_r(src, len, type, buf->result, buf->buffer, buf->buflen, error_num)) { __IPv6_cleanup(buf); return (NULL); } free(buf); return (hp); } if ((hp = __mappedtov4(buf->result, error_num)) == NULL) { __IPv6_cleanup(buf); return (NULL); } __IPv6_cleanup(buf); return (hp); } /* * Step 3: AF_INET6, plain vanilla v6 getipnodebyaddr() call. */ if (type == AF_INET6) { if ((nconf = __rpc_getconfip("udp")) == NULL && (nconf = __rpc_getconfip("tcp")) == NULL) { *error_num = NO_RECOVERY; return (NULL); } if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) { *error_num = NO_RECOVERY; freenetconfigent(nconf); return (NULL); } nssin.op_t = NSS_HOST6; nssin.arg.nss.host.addr = (const char *)addr6; nssin.arg.nss.host.len = len; nssin.arg.nss.host.type = type; nssin.arg.nss.host.buf = buf->buffer; nssin.arg.nss.host.buflen = buf->buflen; nssout.nss.host.hent = buf->result; nssout.nss.host.herrno_p = error_num; /* * We pass in nconf and let the implementation of the * long-named func decide whether to use the switch based on * nc_nlookups. */ neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout); (void) freenetconfigent(nconf); if (neterr != ND_OK) { __IPv6_cleanup(buf); return (NULL); } free(buf); return (nssout.nss.host.hent); } /* * If we got here, unknown type. */ *error_num = HOST_NOT_FOUND; return (NULL); }
/* * Reads a linux sockaddr and does any necessary translation. * Linux sockaddrs don't have a length field, only a family. * Copy the osockaddr structure pointed to by osa to kernel, adjust * family and convert to sockaddr. */ static int linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int salen) { struct sockaddr *sa; struct osockaddr *kosa; #ifdef INET6 struct sockaddr_in6 *sin6; int oldv6size; #endif char *name; int bdom, error, hdrlen, namelen; if (salen < 2 || salen > UCHAR_MAX || !osa) return (EINVAL); #ifdef INET6 oldv6size = 0; /* * Check for old (pre-RFC2553) sockaddr_in6. We may accept it * if it's a v4-mapped address, so reserve the proper space * for it. */ if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) { salen += sizeof(uint32_t); oldv6size = 1; } #endif kosa = malloc(salen, M_SONAME, M_WAITOK); if ((error = copyin(osa, kosa, salen))) goto out; bdom = linux_to_bsd_domain(kosa->sa_family); if (bdom == -1) { error = EAFNOSUPPORT; goto out; } #ifdef INET6 /* * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, * which lacks the scope id compared with RFC2553 one. If we detect * the situation, reject the address and write a message to system log. * * Still accept addresses for which the scope id is not used. */ if (oldv6size) { if (bdom == AF_INET6) { sin6 = (struct sockaddr_in6 *)kosa; if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { sin6->sin6_scope_id = 0; } else { log(LOG_DEBUG, "obsolete pre-RFC2553 sockaddr_in6 rejected\n"); error = EINVAL; goto out; } } else salen -= sizeof(uint32_t); } #endif if (bdom == AF_INET) { if (salen < sizeof(struct sockaddr_in)) { error = EINVAL; goto out; } salen = sizeof(struct sockaddr_in); } if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) { hdrlen = offsetof(struct sockaddr_un, sun_path); name = ((struct sockaddr_un *)kosa)->sun_path; if (*name == '\0') { /* * Linux abstract namespace starts with a NULL byte. * XXX We do not support abstract namespace yet. */ namelen = strnlen(name + 1, salen - hdrlen - 1) + 1; } else namelen = strnlen(name, salen - hdrlen); salen = hdrlen + namelen; if (salen > sizeof(struct sockaddr_un)) { error = ENAMETOOLONG; goto out; } }
/* * Copy the osockaddr structure pointed to by osa to kernel, adjust * family and convert to sockaddr. */ static int do_sa_get(struct sockaddr **sap, const struct osockaddr *osa, int *osalen, struct malloc_type *mtype) { int error=0, bdom; struct sockaddr *sa; struct osockaddr *kosa; int alloclen; #ifdef INET6 int oldv6size; struct sockaddr_in6 *sin6; #endif if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) return (EINVAL); alloclen = *osalen; #ifdef INET6 oldv6size = 0; /* * Check for old (pre-RFC2553) sockaddr_in6. We may accept it * if it's a v4-mapped address, so reserve the proper space * for it. */ if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) { alloclen = sizeof (struct sockaddr_in6); oldv6size = 1; } #endif kosa = malloc(alloclen, mtype, M_WAITOK); if ((error = copyin(osa, kosa, *osalen))) goto out; bdom = linux_to_bsd_domain(kosa->sa_family); if (bdom == -1) { error = EAFNOSUPPORT; goto out; } #ifdef INET6 /* * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, * which lacks the scope id compared with RFC2553 one. If we detect * the situation, reject the address and write a message to system log. * * Still accept addresses for which the scope id is not used. */ if (oldv6size && bdom == AF_INET6) { sin6 = (struct sockaddr_in6 *)kosa; if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { sin6->sin6_scope_id = 0; } else { log(LOG_DEBUG, "obsolete pre-RFC2553 sockaddr_in6 rejected\n"); error = EINVAL; goto out; } } else #endif if (bdom == AF_INET) { alloclen = sizeof(struct sockaddr_in); if (*osalen < alloclen) { error = EINVAL; goto out; } } sa = (struct sockaddr *) kosa; sa->sa_family = bdom; sa->sa_len = alloclen; *sap = sa; *osalen = alloclen; return (0); out: free(kosa, mtype); return (error); }