From: Apple Date: Tue, 19 Nov 2002 01:20:51 +0000 (+0000) Subject: Libinfo-129.4.tar.gz X-Git-Tag: mac-os-x-1023^0 X-Git-Url: https://git.saurik.com/apple/libinfo.git/commitdiff_plain/3e81ae21a7e2c2e07f2acbb16c9e9d1fd4a15b62?ds=sidebyside Libinfo-129.4.tar.gz --- diff --git a/dns.subproj/getnetnamadr.c b/dns.subproj/getnetnamadr.c index 40bc224..7676e4f 100644 --- a/dns.subproj/getnetnamadr.c +++ b/dns.subproj/getnetnamadr.c @@ -64,7 +64,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93"; static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03"; -static char rcsid[] = "$Id: getnetnamadr.c,v 1.3 2002/06/12 17:40:29 epeyton Exp $"; +static char rcsid[] = "$Id: getnetnamadr.c,v 1.3.44.1 2002/11/19 01:20:51 bbraun Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -122,10 +122,11 @@ getnetanswer(answer, anslen, net_i) register int n; u_char *eom; int type, class, buflen, ancount, qdcount, haveanswer, i, nchar; - char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap, + char aux1[30], aux2[30], *in, *st, *pauxt, *bp, **ap, *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0; -static struct netent net_entry; -static char *net_aliases[MAXALIASES], *netbuf = NULL; + static struct netent net_entry; + static char *net_aliases[MAXALIASES], *netbuf = NULL; + static char ans[MAXDNAME]; if (netbuf == NULL) { netbuf = malloc(BUFSIZ+1); @@ -161,8 +162,14 @@ static char *net_aliases[MAXALIASES], *netbuf = NULL; h_errno = TRY_AGAIN; return (NULL); } - while (qdcount-- > 0) - cp += __dn_skipname(cp, eom) + QFIXEDSZ; + while (qdcount-- > 0) { + n = __dn_skipname(cp, eom); + if (n < 0 || (cp + n + QFIXEDSZ) > eom) { + h_errno = NO_RECOVERY; + return(NULL); + } + cp += n + QFIXEDSZ; + } ap = net_aliases; *ap = NULL; net_entry.n_aliases = net_aliases; @@ -173,7 +180,7 @@ static char *net_aliases[MAXALIASES], *netbuf = NULL; break; cp += n; ans[0] = '\0'; - (void)strcpy(&ans[0], bp); + (void)strcpy(ans, bp); GETSHORT(type, cp); GETSHORT(class, cp); cp += INT32SZ; /* TTL */ @@ -185,11 +192,13 @@ static char *net_aliases[MAXALIASES], *netbuf = NULL; return (NULL); } cp += n; - *ap++ = bp; - bp += strlen(bp) + 1; - net_entry.n_addrtype = - (class == C_IN) ? AF_INET : AF_UNSPEC; - haveanswer++; + if ((ap + 2) < &net_aliases[MAXALIASES]) { + *ap++ = bp; + bp += strlen(bp) + 1; + net_entry.n_addrtype = + (class == C_IN) ? AF_INET : AF_UNSPEC; + haveanswer++; + } } } if (haveanswer) { @@ -200,26 +209,35 @@ static char *net_aliases[MAXALIASES], *netbuf = NULL; net_entry.n_net = 0L; break; case BYNAME: - in = *net_entry.n_aliases; - net_entry.n_name = &ans[0]; + ap = net_entry.n_aliases; + next_alias: + in = *ap++; + if (in == NULL) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + net_entry.n_name = ans; aux2[0] = '\0'; for (i = 0; i < 4; i++) { for (st = in, nchar = 0; - *st != '.'; + isdigit((unsigned char)*st); st++, nchar++) ; - if (nchar != 1 || *in != '0' || flag) { - flag = 1; - (void)strncpy(paux1, - (i==0) ? in : in-1, - (i==0) ?nchar : nchar+1); - paux1[(i==0) ? nchar : nchar+1] = '\0'; - pauxt = paux2; - paux2 = strcat(paux1, paux2); - paux1 = pauxt; - } + + if (*st != '.' || nchar == 0 || nchar > 3) + goto next_alias; + if (i != 0) + nchar++; + (void)strncpy(paux1, in, nchar); + paux1[nchar] = '\0'; + pauxt = paux2; + paux2 = strcat(paux1, paux2); + paux1 = pauxt; in = ++st; } + + if (strcasecmp(in, "IN-ADDR.ARPA") != 0) + goto next_alias; net_entry.n_net = inet_network(paux2); break; } diff --git a/dns.subproj/res_data.c b/dns.subproj/res_data.c index 93d648d..41def8c 100644 --- a/dns.subproj/res_data.c +++ b/dns.subproj/res_data.c @@ -38,6 +38,7 @@ /* From res_init.c */ struct __res_state _res = {0}; +__private_extern__ struct __res_state _res_shadow = {0}; /* From getnetent.c */ diff --git a/dns.subproj/res_init.c b/dns.subproj/res_init.c index f9e8ad2..94fb0f8 100644 --- a/dns.subproj/res_init.c +++ b/dns.subproj/res_init.c @@ -78,7 +78,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static char rcsid[] = "$Id: res_init.c,v 1.5 2002/03/26 20:12:06 ajn Exp $"; +static char rcsid[] = "$Id: res_init.c,v 1.5.88.1 2002/11/06 17:30:17 majka Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -152,6 +152,7 @@ static u_int32_t net_mask __P((struct in_addr)); extern #endif /* NeXT */ struct __res_state _res; +extern struct __res_state _res_shadow; /* * Set up default settings. If the configuration file exist, the values @@ -446,6 +447,7 @@ res_init() if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(cp, "env"); _res.options |= RES_INIT; + _res_shadow = _res; return (0); } diff --git a/dns.subproj/res_send.c b/dns.subproj/res_send.c index b1c3a08..7be2204 100644 --- a/dns.subproj/res_send.c +++ b/dns.subproj/res_send.c @@ -78,7 +78,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_send.c,v 1.2 1999/10/14 21:56:45 wsanchez Exp $"; +static char rcsid[] = "$Id: res_send.c,v 1.2.202.1 2002/11/06 17:30:17 majka Exp $"; #endif /* LIBC_SCCS and not lint */ /* change this to "0" @@ -99,6 +99,8 @@ static char rcsid[] = "$Id: res_send.c,v 1.2 1999/10/14 21:56:45 wsanchez Exp $" #include #include #include +#include +#include #include #include @@ -184,6 +186,8 @@ static int vc = 0; /* is the socket a virtual ciruit? */ } #endif +extern struct __res_state _res_shadow; + static res_send_qhook Qhook = NULL; static res_send_rhook Rhook = NULL; @@ -309,6 +313,85 @@ res_queriesmatch(buf1, eom1, buf2, eom2) return (1); } +static int res_using_defaults() +{ + int i; + + if (_res.nscount != _res_shadow.nscount) + return 0; + + for (i = 0; i < _res.nscount; i++) { + /* Check that the address and port have not changed */ + if ((_res.nsaddr_list[i].sin_addr.s_addr != + _res_shadow.nsaddr_list[i].sin_addr.s_addr) || + (_res.nsaddr_list[i].sin_port != + _res_shadow.nsaddr_list[i].sin_port)) { + return 0; + } + } + + return 1; +} + +/* Returns whether a dns encoded name should be sent to multicast or not */ +static int dns_is_local_name(const u_int8_t *name) +{ + const u_int8_t *d0 = NULL; // Top-Level Domain + const u_int8_t *d1 = NULL; // Second-Level Domain + const u_int8_t *d2 = NULL; // etc. + const u_int8_t *d3 = NULL; + + while (*name) + { + d3 = d2; + d2 = d1; + d1 = d0; + d0 = name; + name += 1 + *name; + } + + // "local" domains need to be resolved with multicast + // "local." + if (d0[0] == 5 && strncasecmp((char *)d0+1, "local", 5) == 0) return 1; + + // "local.arpa." + if (d1 && d1[0] == 5 && strncasecmp((char *)d1+1, "local", 5) == 0 && + d0[0] == 4 && strncasecmp((char *)d0+1, "arpa", 4) == 0) return 1; + + // "local.int." + if (d1 && d1[0] == 5 && strncasecmp((char *)d1+1, "local", 5) == 0 && + d0[0] == 3 && strncasecmp((char *)d0+1, "int", 3) == 0) return 1; + + // The network 169.254/16 is defined to be link-local, + // so lookups in 254.169.in-addr.arpa. also need to be resolved with local multicast + if (d3 && d3[0] == 3 && strncasecmp((char *)d3+1, "254", 3) == 0 && + d2 && d2[0] == 3 && strncasecmp((char *)d2+1, "169", 3) == 0 && + d1 && d1[0] == 7 && strncasecmp((char *)d1+1, "in-addr", 7) == 0 && + d0[0] == 4 && strncasecmp((char *)d0+1, "arpa", 4) == 0) return 1; + + return 0; +} + +#define DNS_LOCAL_DOMAIN_SERVICE_PORT 5353 +#define DNS_HEADER_SIZE 12 + +#if BYTE_ORDER == BIG_ENDIAN +#define my_htons(x) (x) +#define my_htonl(x) (x) +#else +#define my_htons(x) ((((u_int16_t)x) >> 8) | (((u_int16_t)x) << 8)) +#define my_htonl(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 16) | \ + (((x) & 0x0000FF00) << 16) | ((x) << 24)) +#endif + +static const struct sockaddr_in mDNS_addr = +{ + sizeof(mDNS_addr), + AF_INET, + my_htons(DNS_LOCAL_DOMAIN_SERVICE_PORT), + {my_htonl(0xE00000FB)} /* 224.0.0.251 */ +}; + int res_send(buf, buflen, ans, anssiz) const u_char *buf; @@ -320,7 +403,8 @@ res_send(buf, buflen, ans, anssiz) HEADER *anhp = (HEADER *) ans; int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; register int n; - u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ + u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ + int multicast; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { /* errno should have been set by res_init() in this case. */ @@ -334,12 +418,26 @@ res_send(buf, buflen, ans, anssiz) terrno = ETIMEDOUT; badns = 0; + if (res_using_defaults() && + dns_is_local_name((u_int8_t*)(buf + DNS_HEADER_SIZE))) { + multicast = 1; + v_circuit = 0; + } else { + multicast = 0; + } + + /* * Send request, RETRY times, or until successful */ for (try = 0; try < _res.retry; try++) { - for (ns = 0; ns < _res.nscount; ns++) { - struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; + for (ns = 0; (multicast == 0 && ns < _res.nscount) || + (multicast == 1 && ns < 1) ; ns++) { + struct sockaddr_in *nsap; + if (multicast == 0) + nsap = &_res.nsaddr_list[ns]; + else + nsap = (struct sockaddr_in*)&mDNS_addr; /* const cast */ same_ns: if (badns & (1 << ns)) { _res_close(); @@ -538,7 +636,7 @@ res_send(buf, buflen, ans, anssiz) * as we wish to receive answers from the first * server to respond. */ - if (_res.nscount == 1 || (try == 0 && ns == 0)) { + if ((_res.nscount == 1 || (try == 0 && ns == 0)) && multicast == 0) { /* * Connect only if we are sure we won't * receive a response from another server. @@ -590,14 +688,63 @@ res_send(buf, buflen, ans, anssiz) connected = 0; errno = 0; } - if (sendto(s, (char*)buf, buflen, 0, - (struct sockaddr *)nsap, - sizeof(struct sockaddr)) - != buflen) { - Aerror(stderr, "sendto", errno, *nsap); - badns |= (1 << ns); - _res_close(); - goto next_ns; + + if (multicast) { + struct ifaddrs* addrs; + struct ifaddrs* curAddr; + const int twofivefive = 255; + + // multicast packets with TTL 255 + if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive))) { + Perror(stderr, "setsocketopt - IP_MULTICAST_TTL", errno); + _res_close(); + return (0); + } + + if (getifaddrs(&addrs) != 0) + { + Perror(stderr, "getifaddrs", errno); + _res_close(); + return (0); + } + + /* multicast should send request on all multicast capable interfaces */ + for (curAddr = addrs; curAddr != NULL; curAddr = curAddr->ifa_next) { + if ((curAddr->ifa_addr->sa_family) == AF_INET && + (curAddr->ifa_flags & IFF_MULTICAST) != 0 && + (curAddr->ifa_flags & IFF_POINTOPOINT) == 0) { + struct in_addr* if_ip_addr = &((struct sockaddr_in*)curAddr->ifa_addr)->sin_addr; + + if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, + if_ip_addr, sizeof(*if_ip_addr)) != 0) { + freeifaddrs(addrs); + Perror(stderr, "setsocketopt - IP_MULTICAST_IF", errno); + _res_close(); + return (0); + } + + if (sendto(s, (char*)buf, buflen, 0, + (struct sockaddr *)nsap, sizeof *nsap) != buflen) + { + freeifaddrs(addrs); + Aerror(stderr, "sendto", errno, *nsap); + _res_close(); + return (0); + } + } + } + + freeifaddrs(addrs); + } else { + if (sendto(s, (char*)buf, buflen, 0, + (struct sockaddr *)nsap, + sizeof(struct sockaddr)) + != buflen) { + Aerror(stderr, "sendto", errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; + } } } @@ -607,7 +754,7 @@ res_send(buf, buflen, ans, anssiz) timeout.tv_sec = (_res.retrans << try); if (try > 0) timeout.tv_sec /= _res.nscount; - if ((long) timeout.tv_sec <= 0) + if ((long) timeout.tv_sec <= 0 || multicast) timeout.tv_sec = 1; timeout.tv_usec = 0; wait: @@ -654,7 +801,7 @@ res_send(buf, buflen, ans, anssiz) } #if CHECK_SRVR_ADDR if (!(_res.options & RES_INSECURE1) && - !res_isourserver(&from)) { + multicast == 0 && !res_isourserver(&from)) { /* * response from wrong server? ignore it. * XXX - potential security hazard could