/* 30Dec2004, Replaces GOTO 'waitmsgtx' label */ static void waitmsgtx (int s) { int index = 20; /* wait for I frame to be ACKed - K5JB/N5KNX */ while (socklen (s,1) > 0 && index--) j2pause(500L); close_s(s); return; }
/* * NAME: inet_ntostr * USAGE: Convert a "sockaddr name" (SA) into a Hostname/p-addr * PLAIN ENGLISH: Convert getpeername() into "foo.bar.com" * ARGS: name - The socket address, possibly returned by getpeername(). * retval - A string to store the hostname/paddr (RETURN VALUE) * size - The length of 'retval' in bytes * RETURN VALUE: "retval" is returned upon success * "empty_string" is returned for any error. * * NOTES: 'flags' should be set to NI_NAMEREQD if you don't want the remote * host's p-addr if it does not have a DNS hostname. */ int inet_ntostr (SA *name, char *host, int hsize, char *port, int psize, int flags) { int retval; socklen_t len; len = socklen(name); if ((retval = Getnameinfo(name, len, host, hsize, port, psize, flags | NI_NUMERICSERV))) { yell("Getnameinfo (sockaddr->p_addr): %s", gai_strerror(retval)); return retval; } return 0; }
/* * NAME: inet_remotesockaddr * USAGE: Get a sockaddr of the specified host and port. * ARGS: family - The family whose sockaddr info is to be retrieved * host - The host whose address shall be put in the sockaddr * port - The port to put into the sockaddr -- MUST BE IN HOST ORDER! * storage - Pointer to a sockaddr structure appropriate for family. */ static int inet_remotesockaddr (int family, const char *host, const char *port, SS *storage, socklen_t *len) { int err; ((SA *)storage)->sa_family = family; if ((err = inet_strton(host, port, (SA *)storage, 0))) return err; if ((*len = socklen((SA *)storage)) == 0) return -2; return 0; }
static int Connect (int fd, SA *addr) { int retval; set_non_blocking(fd); if ((retval = connect(fd, addr, socklen(addr)))) { if (errno != EINPROGRESS) syserr(-1, "Connect: connect(%d) failed: %s", fd, strerror(errno)); else retval = 0; } set_blocking(fd); return retval; }
void printaddr (struct sockaddr *sa) /*@modifies fileSystem@*/ { char buf[NI_MAXHOST]; int err; printf ("%p ", (void *) sa); err = getnameinfo (sa, socklen (sa), buf, sizeof (buf), 0, 0, NI_NUMERICHOST); if (err) printf ("<getnameinfo error %d: %s> family=%d", err, gai_strerror (err), sa->sa_family); else printf ("%s", buf); }
static const char *paddr (struct sockaddr *sa) { static char buf[100]; char portbuf[10]; if (getnameinfo(sa, socklen(sa), buf, sizeof(buf), portbuf, sizeof(portbuf), NI_NUMERICHOST|NI_NUMERICSERV)) strcpy(buf, "<unprintable>"); else { unsigned int len = sizeof(buf) - strlen(buf); char *p = buf + strlen(buf); if (len > 2+strlen(portbuf)) { *p++ = '.'; len--; strncpy(p, portbuf, len); } } return buf; }
/* * NAME: inet_vhostsockaddr * USAGE: Get the sockaddr of the current virtual host, if one is in use. * ARGS: family - The family whose sockaddr info is to be retrieved * storage - Pointer to a sockaddr structure appropriate for family. * len - This will be set to the size of the sockaddr structure that * was copied, or set to 0 if no virtual host is available in * the given family. * NOTES: If "len" is set to 0, do not attempt to bind() 'storage'! */ int inet_vhostsockaddr (int family, int port, SS *storage, socklen_t *len) { char p_port[12]; char *p = NULL; AI hints, *res; int err; /* * If port == -1, then this is a client connection, so we punt * if there is no virtual host name. But if port is NOT zero, then * the caller expects us to return a sockaddr they can bind() to, * so we need to use LocalHostName, even if it's NULL. If you * return *len == 0 for port != -1, then /dcc breaks. */ if (family == AF_UNIX || (port == -1 && !LocalHostName)) { *len = 0; return 0; /* No vhost needed */ } /* * Can it really be this simple? */ memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; if (port != -1) { hints.ai_flags = AI_PASSIVE; snprintf(p_port, 12, "%u", port); p = p_port; } if ((err = Getaddrinfo(LocalHostName, p, &hints, &res))) return -10; memcpy(storage, res->ai_addr, res->ai_addrlen); *len = socklen((SA *)storage); return 0; }
/* * Bind a socket to a privileged IP port */ int bindresvport_sa(int sd, struct sockaddr *sa) { int res; static short port; struct sockaddr_storage myaddr; socklen_t salen; int i; #define STARTPORT 600 #define ENDPORT (IPPORT_RESERVED - 1) #define NPORTS (ENDPORT - STARTPORT + 1) if (sa == NULL) { salen = sizeof(myaddr); sa = ss2sa(&myaddr); res = getsockname(sd, sa, &salen); if (res < 0) return (-1); } if (!sa_is_inet(sa)) { errno = EPFNOSUPPORT; return (-1); } if (port == 0) { port = (getpid() % NPORTS) + STARTPORT; } res = -1; errno = EADDRINUSE; for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) { sa_setport(sa, htons(port++)); if (port > ENDPORT) { port = STARTPORT; } res = bind(sd, sa, socklen(sa)); } return (res); }
/* * NAME: inet_vhostsockaddr * USAGE: Get the sockaddr of the current virtual host, if one is in use. * ARGS: family - The family whose sockaddr info is to be retrieved * storage - Pointer to a sockaddr structure appropriate for family. * len - This will be set to the size of the sockaddr structure that * was copied, or set to 0 if no virtual host is available in * the given family. * NOTES: If "len" is set to 0, do not attempt to bind() 'storage'! */ int inet_vhostsockaddr (int family, int port, const char *wanthost, SS *storage, socklen_t *len) { char p_port[12]; char *p = NULL; AI hints, *res; int err; const char *lhn; /* * If port == -1, AND "wanthost" is NULL, then this is a client connection, * so we punt if there is no virtual host name. But if port is NOT zero, * then the caller expects us to return a sockaddr they can bind() to, * so we need to use LocalIPv(4|6)HostName, even if it's NULL. If you * return *len == 0 for port != -1, then /dcc breaks. */ if ((family == AF_UNIX) || (family == AF_INET && port == -1 && empty(wanthost) && LocalIPv4HostName == NULL) #ifdef INET6 || (family == AF_INET6 && port == -1 && empty(wanthost) && LocalIPv6HostName == NULL) #endif ) { *len = 0; return 0; /* No vhost needed */ } if (wanthost && *wanthost) lhn = wanthost; else if (family == AF_INET) lhn = LocalIPv4HostName; #ifdef INET6 else if (family == AF_INET6) lhn = LocalIPv6HostName; #endif else lhn = NULL; /* * Can it really be this simple? */ memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; if (port != -1) { hints.ai_flags = AI_PASSIVE; snprintf(p_port, 12, "%d", port); p = p_port; } if ((err = my_getaddrinfo(lhn, p, &hints, &res))) { syserr(-1, "inet_vhostsockaddr: my_getaddrinfo(%s,%s) failed: %s", lhn, p, gai_strerror(err)); return -1; } memcpy(storage, res->ai_addr, res->ai_addrlen); my_freeaddrinfo(res); *len = socklen((SA *)storage); return 0; }
long pty_make_sane_hostname(const struct sockaddr *addr, int maxlen, int strip_ldomain, int always_ipaddr, char **out) { struct addrinfo *ai = 0; char addrbuf[NI_MAXHOST]; #ifdef HAVE_STRUCT_UTMP_UT_HOST struct utmp ut; #else struct utmpx utx; #endif char *cp, *domain; char lhost[MAXHOSTNAMELEN]; size_t ut_host_len; /* Note that on some systems (e.g., AIX 4.3.3), we may get an IPv6 address such as ::FFFF:18.18.1.71 when an IPv4 connection comes in. That's okay; at least on AIX, getnameinfo will deal with that properly. */ *out = NULL; if (maxlen && maxlen < 16) /* assume they meant 16, otherwise IPv4 addr won't fit */ maxlen = 16; #ifdef HAVE_STRUCT_UTMP_UT_HOST ut_host_len = sizeof (ut.ut_host); #else ut_host_len = sizeof (utx.ut_host); #endif if (maxlen == 0) maxlen = ut_host_len; *out = malloc(ut_host_len); if (*out == NULL) return ENOMEM; if (always_ipaddr) { use_ipaddr: if (getnameinfo (addr, socklen (addr), addrbuf, sizeof (addrbuf), (char *)0, 0, NI_NUMERICHOST) == 0) strncpy(*out, addrbuf, ut_host_len); else strncpy(*out, "??", ut_host_len); (*out)[ut_host_len - 1] = '\0'; return 0; } /* If we didn't want to chop off the local domain, this would be much simpler -- just a single getnameinfo call and a strncpy. */ if (getnameinfo(addr, socklen (addr), addrbuf, sizeof (addrbuf), (char *) NULL, 0, NI_NAMEREQD) != 0) goto use_ipaddr; downcase (addrbuf); if (strip_ldomain) { struct addrinfo hints; (void) gethostname(lhost, sizeof (lhost)); memset (&hints, 0, sizeof (hints)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_CANONNAME; if (getaddrinfo(lhost, (char *)NULL, &hints, &ai) == 0 && ai != NULL) { if (ai->ai_canonname != NULL) { downcase (ai->ai_canonname); domain = strchr (ai->ai_canonname, '.'); if (domain != NULL) { cp = strstr (addrbuf, domain); if (cp != NULL) *cp = '\0'; } } freeaddrinfo (ai); } } strncpy(*out, addrbuf, ut_host_len); (*out)[ut_host_len - 1] = '\0'; if (strlen(*out) >= maxlen) goto use_ipaddr; return 0; }
static int Connect (int fd, SA *addr) { return connect(fd, addr, socklen(addr)); }
/* * Solaris Kerberos * Same as krb5_sendto_kdc plus an extra arg to return the FQDN * of the KDC sent the request. * Caller (at top of stack) needs to free hostname_used. */ krb5_error_code krb5_sendto_kdc2 (krb5_context context, const krb5_data *message, const krb5_data *realm, krb5_data *reply, int *use_master, int tcp_only, char **hostname_used) { krb5_error_code retval, retval2; struct addrlist addrs = ADDRLIST_INIT; /* Solaris Kerberos */ int socktype1 = 0, socktype2 = 0, addr_used; /* * find KDC location(s) for realm */ /* * BUG: This code won't return "interesting" errors (e.g., out of mem, * bad config file) from locate_kdc. KRB5_REALM_CANT_RESOLVE can be * ignored from one query of two, but if only one query is done, or * both return that error, it should be returned to the caller. Also, * "interesting" errors (not KRB5_KDC_UNREACH) from sendto_{udp,tcp} * should probably be returned as well. */ /*LINTED*/ dprint("krb5_sendto_kdc(%d@%p, \"%D\", use_master=%d, tcp_only=%d)\n", /*LINTED*/ message->length, message->data, realm, *use_master, tcp_only); if (!tcp_only && context->udp_pref_limit < 0) { int tmp; retval = profile_get_integer(context->profile, "libdefaults", "udp_preference_limit", 0, DEFAULT_UDP_PREF_LIMIT, &tmp); if (retval) return retval; if (tmp < 0) tmp = DEFAULT_UDP_PREF_LIMIT; else if (tmp > HARD_UDP_LIMIT) /* In the unlikely case that a *really* big value is given, let 'em use as big as we think we can support. */ tmp = HARD_UDP_LIMIT; context->udp_pref_limit = tmp; } retval = (*use_master ? KRB5_KDC_UNREACH : KRB5_REALM_UNKNOWN); if (tcp_only) socktype1 = SOCK_STREAM, socktype2 = 0; else if (message->length <= context->udp_pref_limit) socktype1 = SOCK_DGRAM, socktype2 = SOCK_STREAM; else socktype1 = SOCK_STREAM, socktype2 = SOCK_DGRAM; retval = krb5_locate_kdc(context, realm, &addrs, *use_master, socktype1, 0); if (socktype2) { struct addrlist addrs2; retval2 = krb5_locate_kdc(context, realm, &addrs2, *use_master, socktype2, 0); #if 0 if (retval2 == 0) { (void) merge_addrlists(&addrs, &addrs2); krb5int_free_addrlist(&addrs2); retval = 0; } else if (retval == KRB5_REALM_CANT_RESOLVE) { retval = retval2; } #else retval = retval2; if (retval == 0) { (void) merge_addrlists(&addrs, &addrs2); krb5int_free_addrlist(&addrs2); } #endif } if (addrs.naddrs > 0) { krb5_error_code err = 0; retval = krb5int_sendto (context, message, &addrs, 0, reply, 0, 0, 0, 0, &addr_used, check_for_svc_unavailable, &err); switch (retval) { case 0: /* * Set use_master to 1 if we ended up talking to a master when * we didn't explicitly request to */ if (*use_master == 0) { struct addrlist addrs3; retval = krb5_locate_kdc(context, realm, &addrs3, 1, addrs.addrs[addr_used].ai->ai_socktype, addrs.addrs[addr_used].ai->ai_family); if (retval == 0) { if (in_addrlist(addrs.addrs[addr_used].ai, &addrs3)) *use_master = 1; krb5int_free_addrlist (&addrs3); } } if (hostname_used) { struct sockaddr *sa; char buf[NI_MAXHOST]; int err; *hostname_used = NULL; sa = addrs.addrs[addr_used].ai->ai_addr; err = getnameinfo (sa, socklen (sa), buf, sizeof (buf), 0, 0, AI_CANONNAME); if (err) err = getnameinfo (sa, socklen (sa), buf, sizeof (buf), 0, 0, NI_NUMERICHOST); if (!err) *hostname_used = strdup(buf); /* don't sweat strdup fail */ } krb5int_free_addrlist (&addrs); return 0; default: break; /* Cases here are for constructing useful error messages. */ case KRB5_KDC_UNREACH: if (err == KDC_ERR_SVC_UNAVAILABLE) { retval = KRB5KDC_ERR_SVC_UNAVAILABLE; } else { krb5_set_error_message(context, retval, dgettext(TEXT_DOMAIN, "Cannot contact any KDC for realm '%.*s'"), realm->length, realm->data); } break; } krb5int_free_addrlist (&addrs); } return retval; }