int main(int argc, char **argv) { struct hostent *he; int error; (void)argc; while (argv[1] != NULL) { he = gethostbyname(argv[1]); print_he(he, h_errno, "gethostbyname", argv[1]); he = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT|AI_ALL, &error); print_he(he, error, "getipnodebyname", argv[1]); if (he != NULL) freehostent(he); he = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT, &error); print_he(he, error, "getipnodebyname", argv[1]); if (he != NULL) freehostent(he); argv++; } return (0); }
static void test_getipnodebyname(const char *name, const char *address, int af, int v4map, int all) { struct hostent *hp; unsigned char addrbuf[16]; int len, ret; int error_num; int flags = 0; if (v4map) flags |= AI_V4MAPPED; if (all) flags |= AI_ALL; hp = getipnodebyname(name, af, flags, &error_num); if (hp == NULL) { if (address == NULL && error_num == HOST_NOT_FOUND) return; else if (error_num != HOST_NOT_FOUND) { printf("I:getipnodebyname(%s) failed: %d\n", name, error_num); fails++; return; } else { printf("I:getipnodebyname(%s) returned not found\n", name); fails++; return; } } else { if (af == AF_INET) len = 4; else len = 16; ret = inet_pton(af, address, addrbuf); assert(ret == 1); if (hp->h_addrtype != af) { printf("I:getipnodebyname(%s) returned wrong family\n", name); freehostent(hp); fails++; return; } if (len != (int)hp->h_length || memcmp(hp->h_addr_list[0], addrbuf, hp->h_length) != 0) { char outbuf[16]; (void)inet_ntop(af, hp->h_addr_list[0], outbuf, sizeof(outbuf)); printf("I:getipnodebyname(%s) returned %s, " "expected %s\n", name, outbuf, address); freehostent(hp); fails++; return; } freehostent(hp); } }
struct hostent * ROKEN_LIB_FUNCTION copyhostent (const struct hostent *h) { struct hostent *res; char **p; int i, n; res = malloc (sizeof (*res)); if (res == NULL) return NULL; res->h_name = NULL; res->h_aliases = NULL; res->h_addrtype = h->h_addrtype; res->h_length = h->h_length; res->h_addr_list = NULL; res->h_name = strdup (h->h_name); if (res->h_name == NULL) { freehostent (res); return NULL; } for (n = 0, p = h->h_aliases; *p != NULL; ++p) ++n; res->h_aliases = malloc ((n + 1) * sizeof(*res->h_aliases)); if (res->h_aliases == NULL) { freehostent (res); return NULL; } for (i = 0; i < n + 1; ++i) res->h_aliases[i] = NULL; for (i = 0; i < n; ++i) { res->h_aliases[i] = strdup (h->h_aliases[i]); if (res->h_aliases[i] == NULL) { freehostent (res); return NULL; } } for (n = 0, p = h->h_addr_list; *p != NULL; ++p) ++n; res->h_addr_list = malloc ((n + 1) * sizeof(*res->h_addr_list)); if (res->h_addr_list == NULL) { freehostent (res); return NULL; } for (i = 0; i < n + 1; ++i) { res->h_addr_list[i] = NULL; } for (i = 0; i < n; ++i) { res->h_addr_list[i] = malloc (h->h_length); if (res->h_addr_list[i] == NULL) { freehostent (res); return NULL; } memcpy (res->h_addr_list[i], h->h_addr_list[i], h->h_length); } return res; }
static char * myGetHostByAddr (char *addr, int len, int type) { struct hostent *hostEnt; char *result; #if HAVE_GETIPNODEBYADDR int error; hostEnt = getipnodebyaddr (addr, len, type, &error); #else hostEnt = gethostbyaddr (addr, len, type); #endif if (hostEnt) { result = malloc (128); /* out of a hat */ strncpy (result, hostEnt->h_name, 128); #if HAVE_GETIPNODEBYADDR freehostent (hostEnt); #endif } else result = NULL; return (result); }
static void __freehostent(struct hostent *he) { /* NOTE: checking for he != NULL - just in case */ if ((use_ipnode_functions != 0) && (he != NULL)) freehostent(he); }
static int spoolss_getservername(char *name, size_t namelen) { char hostname[MAXHOSTNAMELEN]; char ipstr[INET6_ADDRSTRLEN]; smb_inaddr_t ipaddr; struct hostent *h; const char *p; int error; if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) { smb_tracef("spoolss_s_GetPrinter: gethostname failed"); return (-1); } if ((h = smb_gethostbyname(hostname, &error)) == NULL) { smb_tracef("spoolss_s_GetPrinter: gethostbyname failed: %d", error); return (-1); } bcopy(h->h_addr, &ipaddr, h->h_length); ipaddr.a_family = h->h_addrtype; freehostent(h); p = smb_inet_ntop(&ipaddr, ipstr, SMB_IPSTRLEN(ipaddr.a_family)); if (p == NULL) { smb_tracef("spoolss_s_GetPrinter: inet_ntop failed"); return (-1); } (void) snprintf(name, namelen, "\\\\%s", ipstr); return (0); }
char * SamrftGetHostByAddr( void *addr, int af) { struct hostent *host_ent; char *host_name = NULL; char buffer[32]; int h_err = TRUE; int size; switch (af) { case AF_INET: size = sizeof (struct in_addr); break; case AF_INET6: size = sizeof (struct in6_addr); break; } host_ent = getipnodebyaddr((char *)addr, size, af, &h_err); if (host_ent != NULL) { SamStrdup(host_name, host_ent->h_name); freehostent(host_ent); } else { Trace(TR_ERR, "Samrft af %d address %s not found", af, inet_ntop(af, (char *)addr, buffer, 32)); } return (host_name); }
bool Util::safe_gethostbyname(const char *address, HostEnt &result) { #if defined(__APPLE__) struct hostent *hp = gethostbyname(address); if (!hp) { return false; } result.hostbuf = *hp; freehostent(hp); return true; #else struct hostent *hp; int res; size_t hstbuflen = 1024; result.tmphstbuf = (char*)malloc(hstbuflen); while ((res = gethostbyname_r(address, &result.hostbuf, result.tmphstbuf, hstbuflen, &hp, &result.herr)) == ERANGE) { hstbuflen *= 2; result.tmphstbuf = (char*)realloc(result.tmphstbuf, hstbuflen); } return !res && hp; #endif }
struct hostent * tds_gethostbyaddr_r(const char *addr, int len, int type, struct hostent *result, char *buffer, int buflen, int *h_errnop) { #if defined(NETDB_REENTRANT) return gethostbyaddr(addr, len, type); #elif defined(HAVE_GETIPNODEBYADDR) struct hostent *he = getipnodebyaddr(addr, len, type, h_errnop); if (!he) return NULL; if (tds_copy_hostent(he, result, buffer, buflen)) { errno = ENOMEM; if (h_errnop) *h_errnop = NETDB_INTERNAL; freehostent(he); return NULL; } freehostent(he); return result; #elif defined(HAVE_FUNC_GETHOSTBYADDR_R_8) if (gethostbyaddr_r(addr, len, type, result, buffer, buflen, &result, h_errnop)) return NULL; return result; #elif defined(HAVE_FUNC_GETHOSTBYADDR_R_7) result = gethostbyaddr_r(addr, len, type, result, buffer, buflen, h_errnop); return result; #elif defined(HAVE_FUNC_GETHOSTBYADDR_R_5) struct hostent_data *data = (struct hostent_data *) buffer; memset(buffer, 0, buflen); if (gethostbyaddr_r(addr, len, type, result, data)) { *h_errnop = 0; result = NULL; } return result; #elif defined(TDS_NO_THREADSAFE) return gethostbyaddr(addr, len, type); #else #error gethostbyaddr_r style unknown #endif }
struct hostent * tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop) { struct hostent *he = getipnodebyname(servername, AF_INET, 0, h_errnop); if (!he) return NULL; if (tds_copy_hostent(he, result, buffer, buflen)) { errno = ENOMEM; if (h_errnop) *h_errnop = NETDB_INTERNAL; freehostent(he); return NULL; } freehostent(he); return result; }
void free_ghbnctx (struct ghbnctx *ctx) { assert (ctx != NULL); if (ctx->hostent != NULL) freehostent (ctx->hostent); }
static int get_nodes (const char *nodename, const struct addrinfo *hints, int port, int protocol, int socktype, struct addrinfo **res) { struct addrinfo *first = NULL; struct addrinfo **current = &first; int family = PF_UNSPEC; int flags = 0; int ret = EAI_NONAME; int error; if (hints != NULL) { family = hints->ai_family; flags = hints->ai_flags; } #ifdef HAVE_IPV6 if (family == PF_INET6 || family == PF_UNSPEC) { struct hostent *he; he = getipnodebyname (nodename, PF_INET6, 0, &error); if (he != NULL) { ret = add_hostent (port, protocol, socktype, ¤t, const_v6, he, &flags); freehostent (he); } } #endif if (family == PF_INET || family == PF_UNSPEC) { struct hostent *he; he = getipnodebyname (nodename, PF_INET, 0, &error); if (he != NULL) { ret = add_hostent (port, protocol, socktype, ¤t, const_v4, he, &flags); freehostent (he); } } *res = first; return ret; }
struct hostent * tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop) { #if defined(NETDB_REENTRANT) return gethostbyname(servername); /* we have a better replacements */ #elif defined(HAVE_GETIPNODEBYNAME) struct hostent *he = getipnodebyname(servername, AF_INET, 0, h_errnop); if (!he) return NULL; if (tds_copy_hostent(he, result, buffer, buflen)) { errno = ENOMEM; if (h_errnop) *h_errnop = NETDB_INTERNAL; freehostent(he); return NULL; } freehostent(he); return result; #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_6) if (gethostbyname_r(servername, result, buffer, buflen, &result, h_errnop)) return NULL; return result; #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5) result = gethostbyname_r(servername, result, buffer, buflen, h_errnop); return result; #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3) struct hostent_data *data = (struct hostent_data *) buffer; memset(buffer, 0, buflen); if (gethostbyname_r(servername, result, data)) { *h_errnop = 0; result = NULL; } return result; #else #error gethostbyname_r style unknown #endif }
char * one_addr(krb5_address *a) { static char retstr[256]; struct hostent *h; int no_resolve = 1; retstr[0] = '\0'; if ((a->addrtype == ADDRTYPE_INET && a->length == 4) #ifdef AF_INET6 || (a->addrtype == ADDRTYPE_INET6 && a->length == 16) #endif ) { int af = AF_INET; #ifdef AF_INET6 if (a->addrtype == ADDRTYPE_INET6) af = AF_INET6; #endif if (!no_resolve) { #ifdef HAVE_GETIPNODEBYADDR int err; h = getipnodebyaddr(a->contents, a->length, af, &err); if (h) { wsprintf(retstr, "%s", h->h_name); freehostent(h); } #else h = gethostbyaddr(a->contents, a->length, af); if (h) { wsprintf(retstr,"%s", h->h_name); } #endif if (h) return(retstr); } if (no_resolve || !h) { #ifdef HAVE_INET_NTOP char buf[46]; const char *name = inet_ntop(a->addrtype, a->contents, buf, sizeof(buf)); if (name) { wsprintf(retstr,"%s", name); return; } #else if (a->addrtype == ADDRTYPE_INET) { wsprintf(retstr,"%d.%d.%d.%d", a->contents[0], a->contents[1], a->contents[2], a->contents[3]); return(retstr); } #endif } } wsprintf(retstr,"unknown addr type %d", a->addrtype); return(retstr); }
static void test_getipnodebyaddr(const char *address, int af, const char *name) { struct hostent *hp; char addrbuf[16]; int len, ret; int error_num; if (af == AF_INET) len = 4; else len = 16; ret = inet_pton(af, address, addrbuf); assert(ret == 1); hp = getipnodebyaddr(addrbuf, len, af, &error_num); if (hp == NULL) { if (name == NULL && error_num == HOST_NOT_FOUND) return; else if (error_num != HOST_NOT_FOUND) { printf("I:getipnodebyaddr(%s) failed: %d\n", address, error_num); fails++; return; } else { printf("I:getipnodebyaddr(%s) returned not found\n", address); fails++; return; } } else { if (name != NULL && strcmp(hp->h_name, name) != 0) { printf("I:getipnodebyaddr(%s) returned %s, " "expected %s\n", address, hp->h_name, name); freehostent(hp); fails++; return; } freehostent(hp); } }
/* * Frees host list - should be called while keeping auditd_mutex. */ static void freehostlist(hostlist_t **hostlist_ptr) { hostlist_t *h, *n; h = *hostlist_ptr; while (h != NULL) { n = h->next_host; freehostent(h->host); free(h); h = n; } *hostlist_ptr = NULL; }
/* * vs_eng_connect * open socket connection to remote scan engine * * Returns: sockfd or -1 (error) */ static int vs_eng_connect(char *host, int port) { int rc, sockfd, opt_nodelay, opt_keepalive, opt_reuseaddr, err_num; struct sockaddr_in addr; struct hostent *hp; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) return (-1); hp = getipnodebyname(host, AF_INET, 0, &err_num); if (hp == NULL) { (void) close(sockfd); return (-1); } (void) memset(&addr, 0, sizeof (addr)); (void) memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); addr.sin_port = htons(port); addr.sin_family = hp->h_addrtype; freehostent(hp); #ifdef FIONBIO /* Use non-blocking mode for connect. */ rc = nbio_connect(sockfd, (struct sockaddr *)&addr, sizeof (struct sockaddr)); #else rc = connect(sockfd, (struct sockaddr *)&addr, sizeof (struct sockaddr)); #endif opt_nodelay = 1; opt_keepalive = 1; opt_reuseaddr = 1; if ((rc < 0) || (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt_nodelay, sizeof (opt_nodelay)) < 0) || (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &opt_keepalive, sizeof (opt_keepalive)) < 0) || (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt_reuseaddr, sizeof (opt_reuseaddr)) < 0)) { (void) close(sockfd); return (-1); } return (sockfd); }
static int add_hostent (int port, int protocol, int socktype, struct addrinfo ***current, int (*func)(struct addrinfo *, void *data, int port), struct hostent *he, int *flags) { int ret; char *canonname = NULL; char **h; if (*flags & AI_CANONNAME) { struct hostent *he2 = NULL; const char *tmp_canon; tmp_canon = hostent_find_fqdn (he); if (strchr (tmp_canon, '.') == NULL) { int error; he2 = getipnodebyaddr (he->h_addr_list[0], he->h_length, he->h_addrtype, &error); if (he2 != NULL) { const char *tmp = hostent_find_fqdn (he2); if (strchr (tmp, '.') != NULL) tmp_canon = tmp; } } canonname = strdup (tmp_canon); if (he2 != NULL) freehostent (he2); if (canonname == NULL) return EAI_MEMORY; } for (h = he->h_addr_list; *h != NULL; ++h) { ret = add_one (port, protocol, socktype, current, func, *h, canonname); if (ret) return ret; if (*flags & AI_CANONNAME) { *flags &= ~AI_CANONNAME; canonname = NULL; } } return 0; }
static struct hostent * hostent_alloc(int family) { struct hostent *h; h = calloc(1, sizeof *h); if (h == NULL) return (NULL); h->h_aliases = calloc(MAXALIASES, sizeof *h->h_aliases); h->h_addr_list = calloc(MAXADDRS, sizeof *h->h_addr_list); if (h->h_aliases == NULL || h->h_addr_list == NULL) { freehostent(h); return (NULL); } h->h_addrtype = family; h->h_length = (family == AF_INET) ? 4 : 16; return (h); }
//----------------------------------------------------------------------------- // validate_ipstring //----------------------------------------------------------------------------- char* validate_ip_string(const char *inIPString, char *outIPString, size_t outSize) { int nErr ; char* outIP; if (!inIPString) return 0; if (!*inIPString) return 0; if (outSize < 16) return 0; // First, ask the system to look up the given name. struct hostent *hesp = getipnodebyname (inIPString, AF_INET, 0, &nErr); if (hesp == NULL) return 0; // Convert the returned info to dotted decimal string. outIP = (char*)inet_ntop(AF_INET, hesp->h_addr_list[0], outIPString, outSize); freehostent (hesp); return outIP; }
void printaddress (krb5_address address) { int af; char buf[46]; const char *addr_string = NULL; switch (address.addrtype) { case ADDRTYPE_INET: af = AF_INET; break; case ADDRTYPE_INET6: af = AF_INET6; break; default: printmsg ("unknown address type %d", address.addrtype); return; } if (!no_reverse_resolve_addresses) { struct hostent *h = NULL; int err; h = getipnodebyaddr (address.contents, address.length, af, &err); if (h != NULL) { printmsg ("%s", h->h_name); freehostent (h); return; } } /* either we aren't resolving addresses or we failed to do so */ addr_string = inet_ntop(af, address.contents, buf, sizeof(buf)); if (addr_string != NULL) { printmsg ("%s", addr_string); } }
int main(int argc, char **argv) { struct hostent *he; int error; struct in_addr in_addr; struct in6_addr in6_addr; void *addr; int af; size_t len; (void)argc; while (argv[1] != NULL) { if (inet_pton(AF_INET, argv[1], &in_addr) == 1) { af = AF_INET; addr = &in_addr; len = sizeof(in_addr); } else if (inet_pton(AF_INET6, argv[1], &in6_addr) == 1) { af = AF_INET6; addr = &in6_addr; len = sizeof(in6_addr); } else { printf("unable to convert \"%s\" to an address\n", argv[1]); argv++; continue; } he = gethostbyaddr(addr, len, af); print_he(he, h_errno, "gethostbyaddr", argv[1]); he = getipnodebyaddr(addr, len, af, &error); print_he(he, error, "getipnodebyaddr", argv[1]); if (he != NULL) freehostent(he); argv++; } return (0); }
/* * Get information about the Domain Controller in the joined resource domain. * * Returns NT status codes. */ uint32_t smb_get_dcinfo(char *namebuf, uint32_t namebuflen, smb_inaddr_t *ipaddr) { smb_string_t dcname; struct hostent *h; int rc; assert((namebuf != NULL) && (namebuflen != 0)); *namebuf = '\0'; bzero(&dcname, sizeof (smb_string_t)); rc = smb_door_call(SMB_DR_GET_DCINFO, NULL, NULL, &dcname, smb_string_xdr); if (rc != 0) { syslog(LOG_DEBUG, "smb_get_dcinfo: %m"); if (dcname.buf) xdr_free(smb_string_xdr, (char *)&dcname); return (NT_STATUS_INTERNAL_ERROR); } if (dcname.buf) { (void) strlcpy(namebuf, dcname.buf, namebuflen); if ((h = smb_gethostbyname(dcname.buf, &rc)) == NULL) { bzero(ipaddr, sizeof (smb_inaddr_t)); } else { (void) memcpy(ipaddr, h->h_addr, h->h_length); ipaddr->a_family = h->h_addrtype; freehostent(h); } xdr_free(smb_string_xdr, (char *)&dcname); } return (NT_STATUS_SUCCESS); }
/* getipnodebyname() internal routine for multiple query(PF_UNSPEC) support. */ struct hostent * _getipnodebyname_multi(const char *name, int af, int flags, int *errp) { struct hostent *hp; union inx_addr addrbuf; /* XXX: PF_UNSPEC is only supposed to be passed from getaddrinfo() */ if (af != AF_INET #ifdef INET6 && af != AF_INET6 #endif && af != PF_UNSPEC ) { *errp = NO_RECOVERY; return NULL; } #ifdef INET6 /* special case for literal address */ if (inet_pton(AF_INET6, name, &addrbuf) == 1) { if (af != AF_INET6) { *errp = HOST_NOT_FOUND; return NULL; } return _hpaddr(af, name, &addrbuf, errp); } #endif if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) { if (af != AF_INET) { if (MAPADDRENABLED(flags)) { MAPADDR(&addrbuf, &addrbuf.in_addr); } else { *errp = HOST_NOT_FOUND; return NULL; } } return _hpaddr(af, name, &addrbuf, errp); } *errp = HOST_NOT_FOUND; hp = _ghbyname(name, af, flags, errp); #ifdef INET6 if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) && (MAPADDRENABLED(flags))) { struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp); if (hp == NULL) hp = _hpmapv6(hp2, errp); else { if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) { freehostent(hp2); hp2 = NULL; } hp = _hpmerge(hp, hp2, errp); } } #endif return _hpsort(hp); }
int main(int argc, char *argv[]) { int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM }; char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep; int ch, i, on = 1, seq, rcvcmsglen, error, minlen; struct addrinfo hints, *res; static u_char *rcvcmsgbuf; u_long probe, hops, lport; struct hostent *hp; size_t size; uid_t uid; /* * Receive ICMP */ if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { perror("socket(ICMPv6)"); exit(5); } /* revoke privs */ uid = getuid(); if (setresuid(uid, uid, uid) == -1) err(1, "setresuid"); size = sizeof(i); (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0); max_hops = i; /* specify to tell receiving interface */ if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) err(1, "setsockopt(IPV6_RECVPKTINFO)"); /* specify to tell value of hoplimit field of received IP6 hdr */ if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on)) < 0) err(1, "setsockopt(IPV6_RECVHOPLIMIT)"); seq = 0; while ((ch = getopt(argc, argv, "df:g:Ilm:np:q:rs:w:v")) != -1) switch (ch) { case 'd': options |= SO_DEBUG; break; case 'f': ep = NULL; errno = 0; first_hop = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep|| first_hop > 255) { fprintf(stderr, "traceroute6: invalid min hoplimit.\n"); exit(1); } break; case 'g': hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno); if (hp == NULL) { fprintf(stderr, "traceroute6: unknown host %s\n", optarg); exit(1); } if (rth == NULL) { /* * XXX: We can't detect the number of * intermediate nodes yet. */ if ((rth = inet6_rth_init((void *)rtbuf, sizeof(rtbuf), IPV6_RTHDR_TYPE_0, 0)) == NULL) { fprintf(stderr, "inet6_rth_init failed.\n"); exit(1); } } if (inet6_rth_add((void *)rth, (struct in6_addr *)hp->h_addr)) { fprintf(stderr, "inet6_rth_add failed for %s\n", optarg); exit(1); } freehostent(hp); break; case 'I': useicmp++; ident = htons(getpid() & 0xffff); /* same as ping6 */ break; case 'l': lflag++; break; case 'm': ep = NULL; errno = 0; max_hops = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep || max_hops > 255) { fprintf(stderr, "traceroute6: invalid max hoplimit.\n"); exit(1); } break; case 'n': nflag++; break; case 'p': ep = NULL; errno = 0; lport = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep) { fprintf(stderr, "traceroute6: invalid port.\n"); exit(1); } if (lport == 0 || lport != (lport & 0xffff)) { fprintf(stderr, "traceroute6: port out of range.\n"); exit(1); } port = lport & 0xffff; break; case 'q': ep = NULL; errno = 0; nprobes = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep) { fprintf(stderr, "traceroute6: invalid nprobes.\n"); exit(1); } if (nprobes < 1) { fprintf(stderr, "traceroute6: nprobes must be >0.\n"); exit(1); } break; case 'r': options |= SO_DONTROUTE; break; case 's': /* * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ source = optarg; break; case 'v': verbose++; break; case 'w': ep = NULL; errno = 0; waittime = strtoul(optarg, &ep, 0); if (errno || !*optarg || *ep) { fprintf(stderr, "traceroute6: invalid wait time.\n"); exit(1); } if (waittime <= 1) { fprintf(stderr, "traceroute6: wait must be >1 sec.\n"); exit(1); } break; default: usage(); } argc -= optind; argv += optind; if (max_hops < first_hop) { fprintf(stderr, "traceroute6: max hoplimit must be larger than first hoplimit.\n"); exit(1); } if (argc < 1 || argc > 2) usage(); #if 1 setvbuf(stdout, NULL, _IOLBF, BUFSIZ); #else setlinebuf(stdout); #endif memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_INET6; hints.ai_socktype = SOCK_RAW; hints.ai_protocol = IPPROTO_ICMPV6; hints.ai_flags = AI_CANONNAME; error = getaddrinfo(*argv, NULL, &hints, &res); if (error) { fprintf(stderr, "traceroute6: %s\n", gai_strerror(error)); exit(1); } if (res->ai_addrlen != sizeof(Dst)) { fprintf(stderr, "traceroute6: size of sockaddr mismatch\n"); exit(1); } memcpy(&Dst, res->ai_addr, res->ai_addrlen); hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv; if (!hostname) { fprintf(stderr, "traceroute6: not enough core\n"); exit(1); } if (res->ai_next) { if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) strlcpy(hbuf, "?", sizeof(hbuf)); fprintf(stderr, "traceroute6: Warning: %s has multiple " "addresses; using %s\n", hostname, hbuf); } if (*++argv) { ep = NULL; errno = 0; datalen = strtoul(*argv, &ep, 0); if (errno || !*argv || *ep) { fprintf(stderr, "traceroute6: invalid packet length.\n"); exit(1); } } if (useicmp) minlen = ICMP6ECHOLEN + sizeof(struct tv32); else minlen = sizeof(struct opacket); if (datalen < minlen) datalen = minlen; else if (datalen >= MAXPACKET) { fprintf(stderr, "traceroute6: packet size must be %d <= s < %ld.\n", minlen, (long)MAXPACKET); exit(1); } outpacket = (struct opacket *)malloc((unsigned)datalen); if (!outpacket) { perror("malloc"); exit(1); } (void) bzero((char *)outpacket, datalen); /* initialize msghdr for receiving packets */ rcviov[0].iov_base = (caddr_t)packet; rcviov[0].iov_len = sizeof(packet); rcvmhdr.msg_name = (caddr_t)&Rcv; rcvmhdr.msg_namelen = sizeof(Rcv); rcvmhdr.msg_iov = rcviov; rcvmhdr.msg_iovlen = 1; rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)); if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) { fprintf(stderr, "traceroute6: malloc failed\n"); exit(1); } rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; rcvmhdr.msg_controllen = rcvcmsglen; if (options & SO_DEBUG) (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); if (options & SO_DONTROUTE) (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); /* * Send UDP or ICMP */ if (useicmp) { sndsock = rcvsock; } else { if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { perror("socket(SOCK_DGRAM)"); exit(5); } } #ifdef SO_SNDBUF i = datalen; if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof(i)) < 0) { perror("setsockopt(SO_SNDBUF)"); exit(6); } #endif /* SO_SNDBUF */ if (options & SO_DEBUG) (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); if (options & SO_DONTROUTE) (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); if (rth) {/* XXX: there is no library to finalize the header... */ rth->ip6r_len = rth->ip6r_segleft * 2; if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR, (void *)rth, (rth->ip6r_len + 1) << 3)) { fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n", strerror(errno)); exit(1); } } /* * Source selection */ bzero(&Src, sizeof(Src)); if (source) { struct addrinfo hints, *res; int error; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(source, "0", &hints, &res); if (error) { printf("traceroute6: %s: %s\n", source, gai_strerror(error)); exit(1); } if (res->ai_addrlen > sizeof(Src)) { printf("traceroute6: %s: %s\n", source, gai_strerror(error)); exit(1); } memcpy(&Src, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } else { struct sockaddr_in6 Nxt; int dummy; socklen_t len; Nxt = Dst; Nxt.sin6_port = htons(DUMMY_PORT); if (cmsg != NULL) bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr, sizeof(Nxt.sin6_addr)); if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(1); } if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) { perror("connect"); exit(1); } len = sizeof(Src); if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { perror("getsockname"); exit(1); } if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { fprintf(stderr, "getnameinfo failed for source\n"); exit(1); } source = src0; close(dummy); } Src.sin6_port = htons(0); if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) { perror("bind"); exit(1); } { socklen_t len; len = sizeof(Src); if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) { perror("getsockname"); exit(1); } srcport = ntohs(Src.sin6_port); } /* * Message to users */ if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) strlcpy(hbuf, "(invalid)", sizeof(hbuf)); fprintf(stderr, "traceroute6"); fprintf(stderr, " to %s (%s)", hostname, hbuf); if (source) fprintf(stderr, " from %s", source); fprintf(stderr, ", %lu hops max, %lu byte packets\n", max_hops, datalen); (void) fflush(stderr); if (first_hop > 1) printf("Skipping %lu intermediate hops\n", first_hop - 1); /* * Main loop */ for (hops = first_hop; hops <= max_hops; ++hops) { struct in6_addr lastaddr; int got_there = 0; int unreachable = 0; printf("%2lu ", hops); bzero(&lastaddr, sizeof(lastaddr)); for (probe = 0; probe < nprobes; ++probe) { int cc; struct timeval t1, t2; (void) gettimeofday(&t1, NULL); send_probe(++seq, hops); while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { (void) gettimeofday(&t2, NULL); if ((i = packet_ok(&rcvmhdr, cc, seq))) { if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr, &lastaddr)) { print(&rcvmhdr, cc); lastaddr = Rcv.sin6_addr; } printf(" %g ms", deltaT(&t1, &t2)); switch (i - 1) { case ICMP6_DST_UNREACH_NOROUTE: ++unreachable; printf(" !N"); break; case ICMP6_DST_UNREACH_ADMIN: ++unreachable; printf(" !P"); break; case ICMP6_DST_UNREACH_NOTNEIGHBOR: ++unreachable; printf(" !S"); break; case ICMP6_DST_UNREACH_ADDR: ++unreachable; printf(" !A"); break; case ICMP6_DST_UNREACH_NOPORT: if (rcvhlim >= 0 && rcvhlim <= 1) printf(" !"); ++got_there; break; } break; } } if (cc == 0) printf(" *"); (void) fflush(stdout); } putchar('\n'); if (got_there || (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) { exit(0); } } exit(0); }
static int gethostnamadr_async_run(struct async *as, struct async_res *ar) { struct hostent *e; int i, n, r, type; FILE *f; char *toks[MAXTOKEN], addr[16], dname[MAXDNAME], *data; next: switch(as->as_state) { case ASR_STATE_INIT: if (as->as.hostnamadr.family != AF_INET && as->as.hostnamadr.family != AF_INET6) { ar->ar_h_errno = NETDB_INTERNAL; ar->ar_errno = EAFNOSUPPORT; async_set_state(as, ASR_STATE_HALT); break; } if ((as->as.hostnamadr.family == AF_INET && as->as.hostnamadr.addrlen != INADDRSZ) || (as->as.hostnamadr.family == AF_INET6 && as->as.hostnamadr.addrlen != IN6ADDRSZ)) { ar->ar_h_errno = NETDB_INTERNAL; ar->ar_errno = EINVAL; async_set_state(as, ASR_STATE_HALT); break; } if (as->as_type == ASR_GETHOSTBYNAME) async_set_state(as, ASR_STATE_NEXT_DOMAIN); else async_set_state(as, ASR_STATE_NEXT_DB); break; case ASR_STATE_NEXT_DOMAIN: r = asr_iter_domain(as, as->as.hostnamadr.name, dname, sizeof(dname)); if (r == -1) { async_set_state(as, ASR_STATE_NOT_FOUND); break; } if (as->as.hostnamadr.dname) free(as->as.hostnamadr.dname); if ((as->as.hostnamadr.dname = strdup(dname)) == NULL) { ar->ar_h_errno = NETDB_INTERNAL; ar->ar_errno = errno; async_set_state(as, ASR_STATE_HALT); } as->as_db_idx = 0; async_set_state(as, ASR_STATE_NEXT_DB); break; case ASR_STATE_NEXT_DB: if (asr_iter_db(as) == -1) { if (as->as_type == ASR_GETHOSTBYNAME) async_set_state(as, ASR_STATE_NEXT_DOMAIN); else async_set_state(as, ASR_STATE_NOT_FOUND); break; } switch(AS_DB(as)) { case ASR_DB_DNS: /* Create a subquery to do the DNS lookup */ if (as->as_type == ASR_GETHOSTBYNAME) { type = (as->as.hostnamadr.family == AF_INET) ? T_A : T_AAAA; as->as.hostnamadr.subq = res_query_async_ctx( as->as.hostnamadr.dname, C_IN, type, NULL, 0, as->as_ctx); } else { addr_as_fqdn(as->as.hostnamadr.addr, as->as.hostnamadr.family, dname, sizeof(dname)); as->as.hostnamadr.subq = res_query_async_ctx( dname, C_IN, T_PTR, NULL, 0, as->as_ctx); } if (as->as.hostnamadr.subq == NULL) { ar->ar_errno = errno; ar->ar_h_errno = NETDB_INTERNAL; async_set_state(as, ASR_STATE_HALT); break; } async_set_state(as, ASR_STATE_SUBQUERY); break; case ASR_DB_FILE: /* Try to find a match in the host file */ if ((f = fopen(as->as_ctx->ac_hostfile, "r")) == NULL) break; if (as->as_type == ASR_GETHOSTBYNAME) data = as->as.hostnamadr.dname; else data = as->as.hostnamadr.addr; if (( n = hostent_file_match(f, as->as_type, as->as.hostnamadr.family, as->as.hostnamadr.addrlen, data, addr, toks, MAXTOKEN)) == -1) { fclose(f); break; } e = hostent_alloc(as->as.hostnamadr.family); if (e == NULL) { ar->ar_errno = errno; ar->ar_h_errno = NETDB_INTERNAL; async_set_state(as, ASR_STATE_HALT); break; } hostent_set_cname(e, toks[1], 0); for (i = 2; i < n; i ++) hostent_add_alias(e, toks[i], 0); hostent_add_addr(e, addr, e->h_length); fclose(f); ar->ar_h_errno = NETDB_SUCCESS; ar->ar_hostent = e; async_set_state(as, ASR_STATE_HALT); break; } break; case ASR_STATE_SUBQUERY: /* Run the DNS subquery. */ if ((r = async_run(as->as.hostnamadr.subq, ar)) == ASYNC_COND) return (ASYNC_COND); /* Done. */ as->as.hostnamadr.subq = NULL; if (ar->ar_datalen == -1) { async_set_state(as, ASR_STATE_NEXT_DB); break; } /* If we got a packet but no anwser, use the next DB. */ if (ar->ar_count == 0) { free(ar->ar_data); async_set_state(as, ASR_STATE_NEXT_DB); break; } /* Read the hostent from the packet. */ if ((e = hostent_alloc(as->as.hostnamadr.family)) == NULL) { ar->ar_errno = errno; ar->ar_h_errno = NETDB_INTERNAL; free(ar->ar_data); async_set_state(as, ASR_STATE_HALT); break; } if (as->as_type == ASR_GETHOSTBYADDR) { e->h_addr_list[0] = malloc(as->as.hostnamadr.addrlen); if (e->h_addr_list[0]) memmove(e->h_addr_list[0], as->as.hostnamadr.addr, as->as.hostnamadr.addrlen); } hostent_from_packet(e, as->as_type, ar->ar_data, ar->ar_datalen); free(ar->ar_data); /* * No address found in the dns packet. The blocking version * reports this as an error. */ if (as->as_type == ASR_GETHOSTBYNAME && e->h_addr_list[0] == NULL) { freehostent(e); async_set_state(as, ASR_STATE_NEXT_DB); break; } ar->ar_h_errno = NETDB_SUCCESS; ar->ar_hostent = e; async_set_state(as, ASR_STATE_HALT); break; case ASR_STATE_NOT_FOUND: ar->ar_errno = 0; ar->ar_h_errno = HOST_NOT_FOUND; async_set_state(as, ASR_STATE_HALT); break; case ASR_STATE_HALT: if (ar->ar_h_errno) ar->ar_hostent = NULL; else ar->ar_errno = 0; return (ASYNC_DONE); default: ar->ar_errno = EOPNOTSUPP; ar->ar_h_errno = NETDB_INTERNAL; ar->ar_gai_errno = EAI_SYSTEM; async_set_state(as, ASR_STATE_HALT); break; } goto next; }
/* * NAME: conn->init() * DESCRIPTION: initialize connection handling */ bool conn_init(int maxusers, char **thosts, char **bhosts, unsigned short *tports, unsigned short *bports, int ntports, int nbports) { # ifdef INET6 struct sockaddr_in6 sin6; # endif struct sockaddr_in sin; struct hostent *host; int n; connection *conn; bool ipv6, ipv4; int err; if (!ipa_init(maxusers)) { return FALSE; } #ifdef NETWORK_EXTENSIONS addrtype = PF_INET; #endif nusers = 0; maxfd = 0; FD_ZERO(&infds); FD_ZERO(&outfds); FD_ZERO(&waitfds); FD_SET(in, &infds); npackets = 0; closed = 0; #ifndef NETWORK_EXTENSIONS ntdescs = ntports; if (ntports != 0) { tdescs = ALLOC(portdesc, ntports); memset(tdescs, -1, ntports * sizeof(portdesc)); } nbdescs = nbports; if (nbports != 0) { bdescs = ALLOC(portdesc, nbports); memset(bdescs, -1, nbports * sizeof(portdesc)); udescs = ALLOC(portdesc, nbports); memset(udescs, -1, nbports * sizeof(portdesc)); } #endif # ifdef INET6 memset(&sin6, '\0', sizeof(sin6)); sin6.sin6_family = AF_INET6; # endif memset(&sin, '\0', sizeof(sin)); sin.sin_family = AF_INET; for (n = 0; n < ntdescs; n++) { /* telnet ports */ ipv6 = FALSE; ipv4 = FALSE; if (thosts[n] == (char *) NULL) { # ifdef INET6 sin6.sin6_addr = in6addr_any; ipv6 = TRUE; # endif sin.sin_addr.s_addr = INADDR_ANY; ipv4 = TRUE; } else { # ifdef INET6 if (inet_pton(AF_INET6, thosts[n], &sin6) > 0) { ipv6 = TRUE; } else { # ifdef AI_DEFAULT host = getipnodebyname(thosts[n], AF_INET6, 0, &err); if (host != (struct hostent *) NULL) { memcpy(&sin6.sin6_addr, host->h_addr, host->h_length); ipv6 = TRUE; freehostent(host); } # else host = gethostbyname2(thosts[n], AF_INET6); if (host != (struct hostent *) NULL) { memcpy(&sin6.sin6_addr, host->h_addr, host->h_length); ipv6 = TRUE; } # endif } # endif if ((sin.sin_addr.s_addr=inet_addr(thosts[n])) != INADDR_NONE) { ipv4 = TRUE; } else { host = gethostbyname(thosts[n]); if (host != (struct hostent *) NULL) { memcpy(&sin.sin_addr, host->h_addr, host->h_length); ipv4 = TRUE; } } } if (!ipv6 && !ipv4) { message("unknown host %s\012", thosts[n]); /* LF */ return FALSE; } # ifdef INET6 if (ipv6 && !conn_port6(&tdescs[n].in6, SOCK_STREAM, &sin6, tports[n])) { return FALSE; } # endif if (ipv4 && !conn_port(&tdescs[n].in4, SOCK_STREAM, &sin, tports[n])) { return FALSE; } } for (n = 0; n < nbdescs; n++) { /* binary ports */ ipv6 = FALSE; ipv4 = FALSE; if (bhosts[n] == (char *) NULL) { # ifdef INET6 sin6.sin6_addr = in6addr_any; ipv6 = TRUE; # endif sin.sin_addr.s_addr = INADDR_ANY; ipv4 = TRUE; } else { # ifdef INET6 if (inet_pton(AF_INET6, bhosts[n], &sin6) > 0) { ipv6 = TRUE; } else { # ifdef AI_DEFAULT host = getipnodebyname(bhosts[n], AF_INET6, 0, &err); if (host != (struct hostent *) NULL) { memcpy(&sin6.sin6_addr, host->h_addr, host->h_length); ipv6 = TRUE; freehostent(host); } # else host = gethostbyname2(bhosts[n], AF_INET6); if (host != (struct hostent *) NULL) { memcpy(&sin6.sin6_addr, host->h_addr, host->h_length); ipv6 = TRUE; } # endif } # endif if ((sin.sin_addr.s_addr=inet_addr(bhosts[n])) != INADDR_NONE) { ipv4 = TRUE; } else { host = gethostbyname(bhosts[n]); if (host != (struct hostent *) NULL) { memcpy(&sin.sin_addr, host->h_addr, host->h_length); ipv4 = TRUE; } } } if (!ipv6 && !ipv4) { message("unknown host %s\012", bhosts[n]); /* LF */ return FALSE; } # ifdef INET6 if (ipv6) { if (!conn_port6(&bdescs[n].in6, SOCK_STREAM, &sin6, bports[n])) { return FALSE; } if (!conn_port6(&udescs[n].in6, SOCK_DGRAM, &sin6, bports[n])) { return FALSE; } } # endif if (ipv4) { if (!conn_port(&bdescs[n].in4, SOCK_STREAM, &sin, bports[n])) { return FALSE; } if (!conn_port(&udescs[n].in4, SOCK_DGRAM, &sin, bports[n])) { return FALSE; } } } flist = (connection *) NULL; #ifndef NETWORK_EXTENSIONS connections = ALLOC(connection, nusers = maxusers); #else connections = ALLOC(connection, nusers = maxusers+1); #endif for (n = nusers, conn = connections; n > 0; --n, conn++) { conn->fd = -1; conn->chain.next = (hte *) flist; flist = conn; } #ifndef NETWORK_EXTENSIONS udphtab = ALLOC(connection*, udphtabsz = maxusers); memset(udphtab, '\0', udphtabsz * sizeof(connection*)); chtab = ht_new(maxusers, UDPHASHSZ, TRUE); #endif return TRUE; }
/* the ultimate(?) socat resolver function node: the address to be resolved; supported forms: 1.2.3.4 (IPv4 address) [::2] (IPv6 address) hostname (hostname resolving to IPv4 or IPv6 address) hostname.domain (fq hostname resolving to IPv4 or IPv6 address) service: the port specification; may be numeric or symbolic family: PF_INET, PF_INET6, or PF_UNSPEC permitting both socktype: SOCK_STREAM, SOCK_DGRAM protocol: IPPROTO_UDP, IPPROTO_TCP sau: an uninitialized storage for the resulting socket address returns: STAT_OK, STAT_RETRYLATER */ int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, union sockaddr_union *sau, socklen_t *socklen, unsigned long res_opts0, unsigned long res_opts1) { int port = -1; /* port number in network byte order */ char *numnode = NULL; size_t nodelen; unsigned long save_res_opts = 0; #if HAVE_GETADDRINFO struct addrinfo hints = {0}; struct addrinfo *res = NULL; #else /* HAVE_GETIPNODEBYNAME || nothing */ struct hostent *host; #endif int error_num; #if HAVE_RESOLV_H if (res_opts0 | res_opts1) { if (!(_res.options & RES_INIT)) { Res_init(); /*!!! returns -1 on error */ } save_res_opts = _res.options; _res.options &= ~res_opts0; _res.options |= res_opts1; Debug2("changed _res.options from 0x%lx to 0x%lx", save_res_opts, _res.options); } #endif /* HAVE_RESOLV_H */ memset(sau, 0, *socklen); sau->soa.sa_family = family; /* if service is numeric we don't want to have a lookup (might take long with NIS), so we handle this specially */ if (service && isdigit(service[0]&0xff)) { char *extra; port = htons(strtoul(service, &extra, 0)); if (*extra != '\0') { Warn2("xiogetaddrinfo(, \"%s\", ...): extra trailing data \"%s\"", service, extra); } service = NULL; } /* the resolver functions might handle numeric forms of node names by reverse lookup, that's not what we want. So we detect these and handle them specially */ if (node && isdigit(node[0]&0xff)) { #if HAVE_GETADDRINFO hints.ai_flags |= AI_NUMERICHOST; #endif /* HAVE_GETADDRINFO */ if (family == PF_UNSPEC) { family = PF_INET; #if HAVE_GETADDRINFO } else if (family == PF_INET6) { /* map "explicitely" into IPv6 address space; getipnodebyname() does this with AI_V4MAPPED, but not getaddrinfo() */ if ((numnode = Malloc(strlen(node)+7+1)) == NULL) { #if HAVE_RESOLV_H if (res_opts0 | res_opts1) { _res.options = (_res.options & (~res_opts0&~res_opts1) | save_res_opts& ( res_opts0| res_opts1)); } #endif return STAT_NORETRY; } sprintf(numnode, "::ffff:%s", node); node = numnode; hints.ai_flags |= AI_NUMERICHOST; #endif /* HAVE_GETADDRINFO */ } #if WITH_IP6 } else if (node && node[0] == '[' && node[(nodelen=strlen(node))-1]==']') { if ((numnode = Malloc(nodelen-1)) == NULL) { #if HAVE_RESOLV_H if (res_opts0 | res_opts1) { _res.options = (_res.options & (~res_opts0&~res_opts1) | save_res_opts& ( res_opts0| res_opts1)); } #endif return STAT_NORETRY; } strncpy(numnode, node+1, nodelen-2); numnode[nodelen-2] = '\0'; node = numnode; #if HAVE_GETADDRINFO hints.ai_flags |= AI_NUMERICHOST; #endif /* HAVE_GETADDRINFO */ if (family == PF_UNSPEC) family = PF_INET6; #endif /* WITH_IP6 */ } #if HAVE_GETADDRINFO if (node != NULL || service != NULL) { struct addrinfo *record; if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM) { /* actual socket type value is not supported - fallback to a good one */ socktype = SOCK_DGRAM; } if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) { /* actual protocol value is not supported - fallback to a good one */ if (socktype == SOCK_DGRAM) { protocol = IPPROTO_UDP; } else { protocol = IPPROTO_TCP; } } hints.ai_flags |= AI_PASSIVE; hints.ai_family = family; hints.ai_socktype = socktype; hints.ai_protocol = protocol; hints.ai_addrlen = 0; hints.ai_addr = NULL; hints.ai_canonname = NULL; hints.ai_next = NULL; if ((error_num = Getaddrinfo(node, service, &hints, &res)) != 0) { Error7("getaddrinfo(\"%s\", \"%s\", {%d,%d,%d,%d}, {}): %s", node, service, hints.ai_flags, hints.ai_family, hints.ai_socktype, hints.ai_protocol, (error_num == EAI_SYSTEM)? strerror(errno):gai_strerror(error_num)); if (res != NULL) freeaddrinfo(res); if (numnode) free(numnode); #if HAVE_RESOLV_H if (res_opts0 | res_opts1) { _res.options = (_res.options & (~res_opts0&~res_opts1) | save_res_opts& ( res_opts0| res_opts1)); } #endif return STAT_RETRYLATER; } service = NULL; /* do not resolve later again */ record = res; if (family == PF_UNSPEC && xioopts.preferred_ip == '0') { /* we just take the first result */ family = res[0].ai_addr->sa_family; } if (family == PF_UNSPEC) { int trypf; trypf = (xioopts.preferred_ip=='6'?PF_INET6:PF_INET); /* we must look for a matching entry */ while (record != NULL) { if (record->ai_family == trypf) { family = trypf; break; /* family and record set accordingly */ } record = record->ai_next; } if (record == NULL) { /* we did not find a "preferred" entry, take the first */ record = res; family = res[0].ai_addr->sa_family; } } switch (family) { #if WITH_IP4 case PF_INET: if (*socklen > record->ai_addrlen) { *socklen = record->ai_addrlen; } memcpy(&sau->ip4, record->ai_addr, *socklen); break; #endif /* WITH_IP4 */ #if WITH_IP6 case PF_INET6: #if _AIX /* older AIX versions pass wrong length, so we correct it */ record->ai_addr->sa_len = sizeof(struct sockaddr_in6); #endif if (*socklen > record->ai_addrlen) { *socklen = record->ai_addrlen; } memcpy(&sau->ip6, record->ai_addr, *socklen); break; #endif /* WITH_IP6 */ default: Error1("address resolved to unknown protocol family %d", record->ai_addr->sa_family); break; } freeaddrinfo(res); } else { switch (family) { #if WITH_IP4 case PF_INET: *socklen = sizeof(sau->ip4); break; #endif /* WITH_IP4 */ #if WITH_IP6 case PF_INET6: *socklen = sizeof(sau->ip6); break; #endif /* WITH_IP6 */ } } #elif HAVE_GETIPNODEBYNAME /* !HAVE_GETADDRINFO */ if (node != NULL) { /* first fallback is getipnodebyname() */ if (family == PF_UNSPEC) { #if WITH_IP4 && WITH_IP6 family = xioopts.default_ip=='6'?PF_INET6:PF_INET; #elif WITH_IP6 family = PF_INET6; #else family = PF_INET; #endif } host = Getipnodebyname(node, family, AI_V4MAPPED, &error_num); if (host == NULL) { const static char ai_host_not_found[] = "Host not found"; const static char ai_no_address[] = "No address"; const static char ai_no_recovery[] = "No recovery"; const static char ai_try_again[] = "Try again"; const char *error_msg = "Unknown error"; switch (error_num) { case HOST_NOT_FOUND: error_msg = ai_host_not_found; break; case NO_ADDRESS: error_msg = ai_no_address; case NO_RECOVERY: error_msg = ai_no_recovery; case TRY_AGAIN: error_msg = ai_try_again; } Error2("getipnodebyname(\"%s\", ...): %s", node, error_msg); } else { switch (family) { #if WITH_IP4 case PF_INET: *socklen = sizeof(sau->ip4); sau->soa.sa_family = PF_INET; memcpy(&sau->ip4.sin_addr, host->h_addr_list[0], 4); break; #endif #if WITH_IP6 case PF_INET6: *socklen = sizeof(sau->ip6); sau->soa.sa_family = PF_INET6; memcpy(&sau->ip6.sin6_addr, host->h_addr_list[0], 16); break; #endif } } freehostent(host); } #else /* !HAVE_GETIPNODEBYNAME */ if (node != NULL) { /* this is not a typical IP6 resolver function - but Linux "man gethostbyname" says that the only supported address type with this function is AF_INET _at present_, so maybe this fallback will be useful somewhere sometimesin a future even for IP6 */ if (family == PF_UNSPEC) { #if WITH_IP4 && WITH_IP6 family = xioopts.default_ip=='6'?PF_INET6:PF_INET; #elif WITH_IP6 family = PF_INET6; #else family = PF_INET; #endif } /*!!! try gethostbyname2 for IP6 */ if ((host = Gethostbyname(node)) == NULL) { Error2("gethostbyname(\"%s\"): %s", node, h_errno == NETDB_INTERNAL ? strerror(errno) : hstrerror(h_errno)); #if HAVE_RESOLV_H if (res_opts0 | res_opts1) { _res.options = (_res.options & (~res_opts0&~res_opts1) | save_res_opts& ( res_opts0| res_opts1)); } #endif return STAT_RETRYLATER; } if (host->h_addrtype != family) { Error2("xioaddrinfo(): \"%s\" does not resolve to %s", node, family==PF_INET?"IP4":"IP6"); } else { switch (family) { #if WITH_IP4 case PF_INET: *socklen = sizeof(sau->ip4); sau->soa.sa_family = PF_INET; memcpy(&sau->ip4.sin_addr, host->h_addr_list[0], 4); break; #endif /* WITH_IP4 */ #if WITH_IP6 case PF_INET6: *socklen = sizeof(sau->ip6); sau->soa.sa_family = PF_INET6; memcpy(&sau->ip6.sin6_addr, host->h_addr_list[0], 16); break; #endif /* WITH_IP6 */ } } } #endif #if WITH_TCP || WITH_UDP if (service) { port = parseport(service, protocol); } if (port >= 0) { switch (family) { #if WITH_IP4 case PF_INET: sau->ip4.sin_port = port; break; #endif /* WITH_IP4 */ #if WITH_IP6 case PF_INET6: sau->ip6.sin6_port = port; break; #endif /* WITH_IP6 */ } } #endif /* WITH_TCP || WITH_UDP */ if (numnode) free(numnode); #if HAVE_RESOLV_H if (res_opts0 | res_opts1) { _res.options = (_res.options & (~res_opts0&~res_opts1) | save_res_opts& ( res_opts0| res_opts1)); } #endif /* HAVE_RESOLV_H */ return STAT_OK; }
/* * _hpmerge: merge 2 hostent structure, arguments will be freed */ static struct hostent * _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) { int i, j; int naddr, nalias; char **pp; struct hostent *hp, hpbuf; char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1]; union inx_addr addrbuf[MAXADDRS]; if (hp1 == NULL) return hp2; if (hp2 == NULL) return hp1; #define HP(i) (i == 1 ? hp1 : hp2) hp = &hpbuf; hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name); hp->h_aliases = aliases; nalias = 0; for (i = 1; i <= 2; i++) { if ((pp = HP(i)->h_aliases) == NULL) continue; for (; nalias < MAXALIASES && *pp != NULL; pp++) { /* check duplicates */ for (j = 0; j < nalias; j++) if (strcasecmp(*pp, aliases[j]) == 0) break; if (j == nalias) aliases[nalias++] = *pp; } } aliases[nalias] = NULL; #ifdef INET6 if (hp1->h_length != hp2->h_length) { hp->h_addrtype = AF_INET6; hp->h_length = sizeof(struct in6_addr); } else { #endif hp->h_addrtype = hp1->h_addrtype; hp->h_length = hp1->h_length; #ifdef INET6 } #endif hp->h_addr_list = addrs; naddr = 0; for (i = 1; i <= 2; i++) { if ((pp = HP(i)->h_addr_list) == NULL) continue; if (HP(i)->h_length == hp->h_length) { while (naddr < MAXADDRS && *pp != NULL) addrs[naddr++] = *pp++; } else { /* copy IPv4 addr as mapped IPv6 addr */ while (naddr < MAXADDRS && *pp != NULL) { MAPADDR(&addrbuf[naddr], *pp++); addrs[naddr] = (char *)&addrbuf[naddr]; naddr++; } } } addrs[naddr] = NULL; hp = _hpcopy(hp, errp); freehostent(hp1); freehostent(hp2); return hp; }
//----------------------------------------------------------------------------- // process_server_prefs //----------------------------------------------------------------------------- static int process_server_prefs(struct vpn_params *params) { u_int32_t lval, len; u_char str[MAXPATHLEN]; int err ; struct hostent *hostent; get_int_option(params->serverRef, kRASEntServer, kRASPropServerMaximumSessions, &lval, 0); if (lval) params->max_sessions = lval; len = sizeof(str); get_str_option(params->serverRef, kRASEntServer, kRASPropServerLogfile, str, sizeof(str), &len, (u_char*)default_log_path); if (str[0]) memcpy(params->log_path, str, len + 1); get_int_option(params->serverRef, kRASEntServer, kRASPropServerVerboseLogging, &lval, 0); if (lval) params->log_verbose = lval; // Load balancing parameters get_int_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingEnabled, &lval, 0); if (lval) { params->lb_enable = 1; // will determine the interface from the cluster address //len = sizeof(str); //get_str_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingInterface, str, sizeof(str), &len, "en1"); //strncpy(params->lb_interface, str, sizeof(params->lb_interface)); // is priority really useful ? //get_int_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingPriority, &lval, 5); //if (lval < 1) lval = 1; //else if (lval > LB_MAX_PRIORITY) lval = LB_MAX_PRIORITY; //params->lb_priority = lval; get_int_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingPort, &lval, LB_DEFAULT_PORT); params->lb_port = htons(lval); len = sizeof(str); get_str_option(params->serverRef, kRASEntServer, kRASPropServerLoadBalancingAddress, str, sizeof(str), &len, empty_str); // ask the system to look up the given name. hostent = getipnodebyname ((char*)str, AF_INET, 0, &err); if (!hostent) { vpnlog(LOG_ERR, "Incorrect Load Balancing address found '%s'\n", str); params->lb_enable = 0; } else { struct sockaddr_in src, dst; params->lb_cluster_address = *(struct in_addr *)hostent->h_addr_list[0]; freehostent(hostent); bzero(&dst, sizeof(dst)); dst.sin_family = PF_INET; dst.sin_len = sizeof(dst); dst.sin_addr = params->lb_cluster_address; // look for the interface and primary address of the cluster address if (get_route_interface((struct sockaddr *)&src, (struct sockaddr *)&dst, params->lb_interface)) { vpnlog(LOG_ERR, "Cannot get load balancing redirect address and interface (errno = %d)\n", errno); params->lb_enable = 0; } params->lb_redirect_address = src.sin_addr; } } return 0; }