📄 gethostent.c
字号:
cplim = buf + lifc.lifc_len; /* skip over if's with big ifr_addr's */ for (cp = buf; (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; cp += cpsize) { memcpy(&lifreq, cp, sizeof lifreq);#ifdef HAVE_SA_LEN#ifdef FIX_ZERO_SA_LEN if (lifreq.lifr_addr.sa_len == 0) lifreq.lifr_addr.sa_len = 16;#endif#ifdef HAVE_MINIMUM_IFREQ cpsize = sizeof lifreq; if (lifreq.lifr_addr.sa_len > sizeof (struct sockaddr)) cpsize += (int)lifreq.lifr_addr.sa_len - (int)(sizeof (struct sockaddr));#else cpsize = sizeof lifreq.lifr_name + lifreq.lifr_addr.sa_len;#endif /* HAVE_MINIMUM_IFREQ */#elif defined SIOCGIFCONF_ADDR cpsize = sizeof lifreq;#else cpsize = sizeof lifreq.lifr_name; /* XXX maybe this should be a hard error? */ if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0) continue;#endif switch (lifreq.lifr_addr.ss_family) { case AF_INET: if (*have_v4 == 0) { memcpy(&in4, &((struct sockaddr_in *) &lifreq.lifr_addr)->sin_addr, sizeof in4); if (in4.s_addr == INADDR_ANY) break; n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); if (n < 0) break; if ((lifreq.lifr_flags & IFF_UP) == 0) break; *have_v4 = 1; } break; case AF_INET6: if (*have_v6 == 0) { memcpy(&in6, &((struct sockaddr_in6 *) &lifreq.lifr_addr)->sin6_addr, sizeof in6); if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) break; n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); if (n < 0) break; if ((lifreq.lifr_flags & IFF_UP) == 0) break; *have_v6 = 1; } break; } } if (buf != NULL) memput(buf, bufsiz); close(s); /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ return; cleanup: if (buf != NULL) memput(buf, bufsiz); if (s != -1) close(s); /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ return;}#endif#ifdef __linux#ifndef IF_NAMESIZE# ifdef IFNAMSIZ# define IF_NAMESIZE IFNAMSIZ# else# define IF_NAMESIZE 16# endif#endifstatic voidscan_linux6(int *have_v6) { FILE *proc = NULL; char address[33]; char name[IF_NAMESIZE+1]; int ifindex, prefix, flag3, flag4; proc = fopen("/proc/net/if_inet6", "r"); if (proc == NULL) return; if (fscanf(proc, "%32[a-f0-9] %x %x %x %x %16s\n", address, &ifindex, &prefix, &flag3, &flag4, name) == 6) *have_v6 = 1; fclose(proc); return;}#endifstatic intscan_interfaces(int *have_v4, int *have_v6) { struct ifconf ifc; union { char _pad[256]; /* leave space for IPv6 addresses */ struct ifreq ifreq; } u; struct in_addr in4; struct in6_addr in6; char *buf = NULL, *cp, *cplim; static unsigned int bufsiz = 4095; int s, n; size_t cpsize; /* Set to zero. Used as loop terminators below. */ *have_v4 = *have_v6 = 0;#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \ !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF) /* * Try to scan the interfaces using IPv6 ioctls(). */ scan_interfaces6(have_v4, have_v6); if (*have_v4 != 0 && *have_v6 != 0) return (0);#endif#ifdef __linux scan_linux6(have_v6);#endif /* Get interface list from system. */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) goto err_ret; /* * Grow buffer until large enough to contain all interface * descriptions. */ for (;;) { buf = memget(bufsiz); if (buf == NULL) goto err_ret; ifc.ifc_len = bufsiz; ifc.ifc_buf = buf;#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF /* * This is a fix for IRIX OS in which the call to ioctl with * the flag SIOCGIFCONF may not return an entry for all the * interfaces like most flavors of Unix. */ if (emul_ioctl(&ifc) >= 0) break;#else if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) { /* * Some OS's just return what will fit rather * than set EINVAL if the buffer is too small * to fit all the interfaces in. If * ifc.ifc_len is too near to the end of the * buffer we will grow it just in case and * retry. */ if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz) break; }#endif if ((n == -1) && errno != EINVAL) goto err_ret; if (bufsiz > 1000000) goto err_ret; memput(buf, bufsiz); bufsiz += 4096; } /* Parse system's interface list. */ cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */ for (cp = buf; (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; cp += cpsize) { memcpy(&u.ifreq, cp, sizeof u.ifreq);#ifdef HAVE_SA_LEN#ifdef FIX_ZERO_SA_LEN if (u.ifreq.ifr_addr.sa_len == 0) u.ifreq.ifr_addr.sa_len = 16;#endif#ifdef HAVE_MINIMUM_IFREQ cpsize = sizeof u.ifreq; if (u.ifreq.ifr_addr.sa_len > sizeof (struct sockaddr)) cpsize += (int)u.ifreq.ifr_addr.sa_len - (int)(sizeof (struct sockaddr));#else cpsize = sizeof u.ifreq.ifr_name + u.ifreq.ifr_addr.sa_len;#endif /* HAVE_MINIMUM_IFREQ */ if (cpsize > sizeof u.ifreq && cpsize <= sizeof u) memcpy(&u.ifreq, cp, cpsize);#elif defined SIOCGIFCONF_ADDR cpsize = sizeof u.ifreq;#else cpsize = sizeof u.ifreq.ifr_name; /* XXX maybe this should be a hard error? */ if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0) continue;#endif switch (u.ifreq.ifr_addr.sa_family) { case AF_INET: if (*have_v4 == 0) { memcpy(&in4, &((struct sockaddr_in *) &u.ifreq.ifr_addr)->sin_addr, sizeof in4); if (in4.s_addr == INADDR_ANY) break; n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq); if (n < 0) break; if ((u.ifreq.ifr_flags & IFF_UP) == 0) break; *have_v4 = 1; } break; case AF_INET6: if (*have_v6 == 0) { memcpy(&in6, &((struct sockaddr_in6 *) &u.ifreq.ifr_addr)->sin6_addr, sizeof in6); if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) break; n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq); if (n < 0) break; if ((u.ifreq.ifr_flags & IFF_UP) == 0) break; *have_v6 = 1; } break; } } if (buf != NULL) memput(buf, bufsiz); close(s); /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ return (0); err_ret: if (buf != NULL) memput(buf, bufsiz); if (s != -1) close(s); /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ return (-1);}static struct hostent *copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) { struct hostent *he = NULL; int addresses = 1; /* NULL terminator */ int names = 1; /* NULL terminator */ int len = 0; char **cpp, **npp; /* * Work out array sizes; */ if (he1 != NULL) { cpp = he1->h_addr_list; while (*cpp != NULL) { addresses++; cpp++; } cpp = he1->h_aliases; while (*cpp != NULL) { names++; cpp++; } } if (he2 != NULL) { cpp = he2->h_addr_list; while (*cpp != NULL) { addresses++; cpp++; } if (he1 == NULL) { cpp = he2->h_aliases; while (*cpp != NULL) { names++; cpp++; } } } if (addresses == 1) { *error_num = NO_ADDRESS; return (NULL); } he = memget(sizeof *he); if (he == NULL) goto no_recovery; he->h_addr_list = memget(sizeof(char *) * (addresses)); if (he->h_addr_list == NULL) goto cleanup0; memset(he->h_addr_list, 0, sizeof(char *) * (addresses)); /* copy addresses */ npp = he->h_addr_list; if (he1 != NULL) { cpp = he1->h_addr_list; while (*cpp != NULL) { *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); if (*npp == NULL) goto cleanup1; /* convert to mapped if required */ if (af == AF_INET6 && he1->h_addrtype == AF_INET) { memcpy(*npp, in6addr_mapped, sizeof in6addr_mapped); memcpy(*npp + sizeof in6addr_mapped, *cpp, INADDRSZ); } else { memcpy(*npp, *cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); } cpp++; npp++; } } if (he2 != NULL) { cpp = he2->h_addr_list; while (*cpp != NULL) { *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); if (*npp == NULL) goto cleanup1; /* convert to mapped if required */ if (af == AF_INET6 && he2->h_addrtype == AF_INET) { memcpy(*npp, in6addr_mapped, sizeof in6addr_mapped); memcpy(*npp + sizeof in6addr_mapped, *cpp, INADDRSZ); } else { memcpy(*npp, *cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); } cpp++; npp++; } } he->h_aliases = memget(sizeof(char *) * (names)); if (he->h_aliases == NULL) goto cleanup1; memset(he->h_aliases, 0, sizeof(char *) * (names)); /* copy aliases */ npp = he->h_aliases; cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases; while (*cpp != NULL) { len = strlen (*cpp) + 1; *npp = memget(len); if (*npp == NULL) goto cleanup2; strcpy(*npp, *cpp); npp++; cpp++; } /* copy hostname */ he->h_name = memget(strlen((he1 != NULL) ? he1->h_name : he2->h_name) + 1); if (he->h_name == NULL) goto cleanup2; strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name); /* set address type and length */ he->h_addrtype = af; he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ; return(he); cleanup2: cpp = he->h_aliases; while (*cpp != NULL) { memput(*cpp, strlen(*cpp) + 1); cpp++; } memput(he->h_aliases, sizeof(char *) * (names)); cleanup1: cpp = he->h_addr_list; while (*cpp != NULL) { memput(*cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); *cpp = NULL; cpp++; } memput(he->h_addr_list, sizeof(char *) * (addresses)); cleanup0: memput(he, sizeof *he); no_recovery: *error_num = NO_RECOVERY; return (NULL);}static struct net_data *init() { struct net_data *net_data; if (!(net_data = net_data_init(NULL))) goto error; if (!net_data->ho) { net_data->ho = (*net_data->irs->ho_map)(net_data->irs); if (!net_data->ho || !net_data->res) { error: errno = EIO; if (net_data && net_data->res) RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); return (NULL); } (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); } return (net_data);}static voidfreepvt(struct net_data *net_data) { if (net_data->ho_data) { free(net_data->ho_data); net_data->ho_data = NULL; }}static struct hostent *fakeaddr(const char *name, int af, struct net_data *net_data) { struct pvt *pvt; freepvt(net_data); net_data->ho_data = malloc(sizeof (struct pvt)); if (!net_data->ho_data) { errno = ENOMEM; RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); return (NULL); } pvt = net_data->ho_data;#ifndef __bsdi__ /* * Unlike its forebear(inet_aton), our friendly inet_pton() is strict * in its interpretation of its input, and it will only return "1" if * the input string is a formally valid(and thus unambiguous with * respect to host names) internet address specification for this AF. * * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now. */ if (inet_pton(af, name, pvt->addr) != 1) {#else /* BSDI XXX * We put this back to inet_aton -- we really want the old behavior * Long live 127.1... */ if ((af != AF_INET || inet_aton(name, (struct in_addr *)pvt->addr) != 1) && inet_pton(af, name, pvt->addr) != 1) {#endif RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); return (NULL); } strncpy(pvt->name, name, NS_MAXDNAME); pvt->name[NS_MAXDNAME] = '\0'; if (af == AF_INET && (net_data->res->options & RES_USE_INET6) != 0U) { map_v4v6_address(pvt->addr, pvt->addr); af = AF_INET6; } pvt->host.h_addrtype = af; switch(af) { case AF_INET: pvt->host.h_length = NS_INADDRSZ; break; case AF_INET6: pvt->host.h_length = NS_IN6ADDRSZ; break; default: errno = EAFNOSUPPORT; RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); return (NULL); } pvt->host.h_name = pvt->name; pvt->host.h_aliases = pvt->aliases; pvt->aliases[0] = NULL; pvt->addrs[0] = (char *)pvt->addr; pvt->addrs[1] = NULL; pvt->host.h_addr_list = pvt->addrs; RES_SET_H_ERRNO(net_data->res, NETDB_SUCCESS); return (&pvt->host);}#ifdef grot /* for future use in gethostbyaddr(), for "SUNSECURITY" */ struct hostent *rhp; char **haddr; u_long old_options; char hname2[MAXDNAME+1]; if (af == AF_INET) { /* * turn off search as the name should be absolute, * 'localhost' should be matched by defnames */ strncpy(hname2, hp->h_name, MAXDNAME); hname2[MAXDNAME] = '\0'; old_options = net_data->res->options; net_data->res->options &= ~RES_DNSRCH; net_data->res->options |= RES_DEFNAMES; if (!(rhp = gethostbyname(hname2))) { net_data->res->options = old_options; RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); return (NULL); } net_data->res->options = old_options; for (haddr = rhp->h_addr_list; *haddr; haddr++) if (!memcmp(*haddr, addr, INADDRSZ)) break; if (!*haddr) { RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); return (NULL); } }#endif /* grot */#endif /*__BIND_NOSTATIC*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -