]> git.saurik.com Git - apple/libinfo.git/commitdiff
Libinfo-129.4.tar.gz mac-os-x-1023 mac-os-x-1024 mac-os-x-1025 mac-os-x-1026 mac-os-x-1027 mac-os-x-1028 mac-os-x-1028g5 v129.4
authorApple <opensource@apple.com>
Tue, 19 Nov 2002 01:20:51 +0000 (01:20 +0000)
committerApple <opensource@apple.com>
Tue, 19 Nov 2002 01:20:51 +0000 (01:20 +0000)
dns.subproj/getnetnamadr.c
dns.subproj/res_data.c
dns.subproj/res_init.c
dns.subproj/res_send.c

index 40bc224bb5ba59fdd759e5abb0d283a4c4d2721f..7676e4f06acfe05d00bf89d0fd91f089da8345f2 100644 (file)
@@ -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 <sys/param.h>
@@ -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;
                }
index 93d648d6c6f20ba5884ecae10cd4c0536bb4c257..41def8cd82bdda31c4618c436af356e094ab2605 100644 (file)
@@ -38,6 +38,7 @@
 /* From res_init.c */
 
 struct __res_state _res = {0};
+__private_extern__ struct __res_state _res_shadow = {0};
 
 /* From getnetent.c */
 
index f9e8ad21ec77e92ba075769ed7a7d13fab28cae4..94fb0f8ff7cebd5df2b1d0dce1726cb296e02fcb 100644 (file)
@@ -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 <sys/param.h>
@@ -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);
 }
 
index b1c3a086f12db99b709d26065c3bf340544c9083..7be2204b669f4525a5953b012fa168ba08fc81f8 100644 (file)
@@ -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 <netinet/in.h>
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <net/if.h>
 
 #include <stdio.h>
 #include <netdb.h>
@@ -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