/* * Solaris Kerberos: * krb5int_address_get_realm() given an address (either IPv4 or IPv6) tries to * find a realm based on the DNS name of that address. Assumes that its being * used as a callback for krb5int_foreach_localaddr(). */ static int krb5int_address_get_realm(void *data, struct sockaddr *addr) { krb5_context context = data; struct hostent *he = NULL; switch (addr->sa_family) { case AF_INET: he = res_gethostbyaddr((char*)(&sa2sin(addr)->sin_addr), sizeof(sa2sin(addr)->sin_addr), AF_INET); break; case AF_INET6: he = res_gethostbyaddr( (char*)(&sa2sin6(addr)->sin6_addr), sizeof(sa2sin6(addr)->sin6_addr), AF_INET6); break; } if (he) { /* Try to find realm using returned DNS name */ krb5int_fqdn_get_realm(context, he->h_name, &context->default_realm); /* If a realm was found return 1 to immediately halt * krb5int_foreach_localaddr() */ if (context->default_realm != 0) { return (1); } } return (0); }
static int addr_eq (struct sockaddr *s1, struct sockaddr *s2) { if (s1->sa_family != s2->sa_family) return 0; switch (s1->sa_family) { case AF_INET: return !memcmp(&sa2sin(s1)->sin_addr, &sa2sin(s2)->sin_addr, sizeof(sa2sin(s1)->sin_addr)); case AF_INET6: return !memcmp(&sa2sin6(s1)->sin6_addr, &sa2sin6(s2)->sin6_addr, sizeof(sa2sin6(s1)->sin6_addr)); default: /* Err on side of duplicate listings. */ return 0; } }
static int getbroadcastnets( struct in_addr *addrs, int sock, /* any valid socket will do */ char *buf /* why allocxate more when we can use existing... */ ) { struct ifconf ifc; struct ifreq ifreq, *ifr; int n, i; ifc.ifc_len = GIFCONF_BUFSIZE; ifc.ifc_buf = buf; memset (buf, 0, GIFCONF_BUFSIZE); if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { perror("broadcast: ioctl (get interface configuration)"); return (0); } ifr = ifc.ifc_req; for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) { ifreq = *ifr; if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) { perror("broadcast: ioctl (get interface flags)"); continue; } if ((ifreq.ifr_flags & IFF_BROADCAST) && (ifreq.ifr_flags & IFF_UP) && ifr->ifr_addr.sa_family == AF_INET) { #ifdef SIOCGIFBRDADDR /* 4.3BSD */ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { addrs[i++].s_addr = INADDR_ANY; } else { addrs[i++] = sa2sin(&ifreq.ifr_addr)->sin_addr; } #else /* 4.2 BSD */ struct sockaddr_in *sockin; sockin = sa2sin(&ifr->ifr_addr); addrs[i++] = inet_makeaddr(inet_netof (sockin->sin_addr.s_addr), INADDR_ANY); #endif } } return (i); }
static int is_loopback_address(struct sockaddr *sa) { switch (sa->sa_family) { case AF_INET: { struct sockaddr_in *s4 = sa2sin(sa); return s4->sin_addr.s_addr == htonl(INADDR_LOOPBACK); } case AF_INET6: { struct sockaddr_in6 *s6 = sa2sin6(sa); return IN6_IS_ADDR_LOOPBACK(&s6->sin6_addr); } default: return 0; } }
/* Misc utility routines. */ static void set_sa_port(struct sockaddr *addr, int port) { switch (addr->sa_family) { case AF_INET: sa2sin(addr)->sin_port = port; break; #ifdef KRB5_USE_INET6 case AF_INET6: sa2sin6(addr)->sin6_port = port; break; #endif default: break; } }
krb5_error_code k5_os_hostaddr(krb5_context context, const char *name, krb5_address ***ret_addrs) { krb5_error_code retval; krb5_address **addrs; int i, j, r; struct addrinfo hints, *ai, *aip; if (!name) return KRB5_ERR_BAD_HOSTNAME; memset (&hints, 0, sizeof (hints)); hints.ai_flags = AI_NUMERICHOST | AI_ADDRCONFIG; /* We don't care what kind at this point, really, but without this, we can get back multiple sockaddrs per address, for SOCK_DGRAM, SOCK_STREAM, and SOCK_RAW. I haven't checked if that's what the spec indicates. */ hints.ai_socktype = SOCK_DGRAM; r = getaddrinfo (name, 0, &hints, &ai); if (r && AI_NUMERICHOST != 0) { hints.ai_flags &= ~AI_NUMERICHOST; r = getaddrinfo (name, 0, &hints, &ai); } if (r) return KRB5_ERR_BAD_HOSTNAME; for (i = 0, aip = ai; aip; aip = aip->ai_next) { switch (aip->ai_addr->sa_family) { case AF_INET: case AF_INET6: i++; default: /* Ignore addresses of unknown families. */ ; } } addrs = malloc ((i+1) * sizeof(*addrs)); if (!addrs) return ENOMEM; for (j = 0; j < i + 1; j++) addrs[j] = 0; for (i = 0, aip = ai; aip; aip = aip->ai_next) { void *ptr; size_t addrlen; int atype; switch (aip->ai_addr->sa_family) { case AF_INET: addrlen = sizeof (struct in_addr); ptr = &sa2sin(aip->ai_addr)->sin_addr; atype = ADDRTYPE_INET; break; case AF_INET6: addrlen = sizeof (struct in6_addr); ptr = &sa2sin6(aip->ai_addr)->sin6_addr; atype = ADDRTYPE_INET6; break; default: continue; } addrs[i] = (krb5_address *) malloc(sizeof(krb5_address)); if (!addrs[i]) { retval = ENOMEM; goto errout; } addrs[i]->magic = KV5M_ADDRESS; addrs[i]->addrtype = atype; addrs[i]->length = addrlen; addrs[i]->contents = k5memdup(ptr, addrlen, &retval); if (addrs[i]->contents == NULL) goto errout; i++; } *ret_addrs = addrs; if (ai) freeaddrinfo(ai); return 0; errout: if (addrs) { for (i = 0; addrs[i]; i++) { free (addrs[i]->contents); free (addrs[i]); } krb5_free_addresses(context, addrs); } if (ai) freeaddrinfo(ai); return retval; }