Keeping this up.

On 19 March 2011 22:35, Christiano F. Haesbaert <haesba...@haesbaert.org>
wrote:
> Whoops, I made some last time changes which broke big-endian systems,
spotted by
> Mattew.
>
> Index: net/getaddrinfo.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/net/getaddrinfo.c,v
> retrieving revision 1.71
> diff -d -u -p -w -r1.71 getaddrinfo.c
> --- net/getaddrinfo.c   18 Nov 2009 07:43:22 -0000      1.71
> +++ net/getaddrinfo.c   20 Mar 2011 01:32:16 -0000
> @@ -235,6 +235,8 @@ static int res_searchN(const char *, str
>  static int res_querydomainN(const char *, const char *, struct res_target
*);
>  static struct addrinfo *_dns_getaddrinfo(const char *, const struct
addrinfo *,
>        const struct __res_state *);
> +static struct addrinfo *_mcast_getaddrinfo(const char *,
> +    const struct addrinfo *, const struct __res_state *);
>
>
>  /* XXX macros that make external reference is BAD. */
> @@ -523,6 +525,9 @@ explore_fqdn(const struct addrinfo *pai,
>                case 'f':
>                        result = _files_getaddrinfo(hostname, pai);
>                        break;
> +               case 'm':
> +                       result = _mcast_getaddrinfo(hostname, pai, _resp);
> +                       break;
>                }
>        }
>        _THREAD_PRIVATE_MUTEX_UNLOCK(_explore_mutex);
> @@ -1209,6 +1214,99 @@ _dns_getaddrinfo(const char *name, const
>                free(buf);
>                free(buf2);
>                return NULL;
> +       }
> +       ai = getanswer(buf, q.n, q.name, q.qtype, pai);
> +       if (ai) {
> +               cur->ai_next = ai;
> +               while (cur && cur->ai_next)
> +                       cur = cur->ai_next;
> +       }
> +       if (q.next) {
> +               ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
> +               if (ai)
> +                       cur->ai_next = ai;
> +       }
> +       free(buf);
> +       free(buf2);
> +       return sentinel.ai_next;
> +}
> +
> +static struct addrinfo *
> +_mcast_getaddrinfo(const char *name, const struct addrinfo *pai,
> +    const struct __res_state *_resp)
> +{
> +       struct addrinfo *ai;
> +       querybuf *buf, *buf2;
> +       struct addrinfo sentinel, *cur;
> +       struct res_target q, q2;
> +
> +       memset(&q, 0, sizeof(q));
> +       memset(&q2, 0, sizeof(q2));
> +       memset(&sentinel, 0, sizeof(sentinel));
> +       cur = &sentinel;
> +
> +       buf = malloc(sizeof(*buf));
> +       if (buf == NULL) {
> +               h_errno = NETDB_INTERNAL;
> +               return NULL;
> +       }
> +       buf2 = malloc(sizeof(*buf2));
> +       if (buf2 == NULL) {
> +               free(buf);
> +               h_errno = NETDB_INTERNAL;
> +               return NULL;
> +       }
> +
> +       switch (pai->ai_family) {
> +       case AF_UNSPEC:
> +               /* respect user supplied order */
> +               q.qclass = C_IN;
> +               q.qtype = (_resp->family[0] == AF_INET6) ? T_AAAA : T_A;
> +               q.answer = buf->buf;
> +               q.anslen = sizeof(buf->buf);
> +               q.next = &q2;
> +
> +               if (_resp->family[1] == -1) {
> +                       /* stop here if only one family was given */
> +                       q.next = NULL;
> +                       break;
> +               }
> +
> +               q2.qclass = C_IN;
> +               q2.qtype = (_resp->family[1] == AF_INET6) ? T_AAAA : T_A;
> +               q2.answer = buf2->buf;
> +               q2.anslen = sizeof(buf2->buf);
> +               break;
> +       case AF_INET:
> +               q.qclass = C_IN;
> +               q.qtype = T_A;
> +               q.answer = buf->buf;
> +               q.anslen = sizeof(buf->buf);
> +               break;
> +       case AF_INET6:
> +               q.qclass = C_IN;
> +               q.qtype = T_AAAA;
> +               q.answer = buf->buf;
> +               q.anslen = sizeof(buf->buf);
> +               break;
> +       default:
> +               free(buf);
> +               free(buf2);
> +               return NULL;
> +       }
> +       if ((q.n = res_search_mcast(name,
> +           q.qclass, q.qtype, q.answer, q.anslen)) < 0) {
> +               free(buf);
> +               free(buf2);
> +               return (NULL);
> +       }
> +       if (q.next != NULL) {
> +               if ((q2.n = res_search_mcast(name,
> +                   q2.qclass, q2.qtype, q2.answer, q2.anslen)) < 0) {
> +                       free(buf);
> +                       free(buf2);
> +                       return (NULL);
> +               }
>        }
>        ai = getanswer(buf, q.n, q.name, q.qtype, pai);
>        if (ai) {
> Index: net/gethostnamadr.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/net/gethostnamadr.c,v
> retrieving revision 1.73
> diff -d -u -p -w -r1.73 gethostnamadr.c
> --- net/gethostnamadr.c 18 Nov 2009 07:43:22 -0000      1.73
> +++ net/gethostnamadr.c 20 Mar 2011 01:32:16 -0000
> @@ -606,6 +606,7 @@ gethostbyname2(const char *name, int af)
>
>        hp = (struct hostent *)NULL;
>        for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
> +               size_t nlen;
>                switch (lookups[i]) {
>  #ifdef YP
>                case 'y':
> @@ -615,9 +616,10 @@ gethostbyname2(const char *name, int af)
>                        break;
>  #endif
>                case 'b':
> -                       buf = malloc(sizeof(*buf));
> -                       if (buf == NULL)
> +                       if ((buf = malloc(sizeof(*buf))) == NULL) {
> +                               h_errno = NETDB_INTERNAL;
>                                break;
> +                       }
>                        if ((n = res_search(name, C_IN, type, buf->buf,
>                            sizeof(buf->buf))) < 0) {
>                                free(buf);
> @@ -633,6 +635,23 @@ gethostbyname2(const char *name, int af)
>                case 'f':
>                        hp = _gethtbyname2(name, af);
>                        break;
> +               case 'm':
> +                       if ((buf = malloc(sizeof(*buf))) == NULL) {
> +                               h_errno = NETDB_INTERNAL;
> +                               break;
> +                       }
> +                       if ((n = res_search_mcast(name, C_IN, type,
buf->buf,
> +                           sizeof(buf->buf))) < 0) {
> +                               free(buf);
> +#ifdef DEBUG
> +                               if (_resp->options & RES_DEBUG)
> +                                       printf("res_search_mcast
failed\n");
> +#endif
> +                               break;
> +                       }
> +                       hp = getanswer(buf, n, name, type);
> +                       free(buf);
> +                       break;
>                }
>        }
>        /* XXX h_errno not correct in all cases... */
> Index: net/res_init.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/net/res_init.c,v
> retrieving revision 1.40
> diff -d -u -p -w -r1.40 res_init.c
> --- net/res_init.c      5 Jun 2009 09:52:26 -0000       1.40
> +++ net/res_init.c      20 Mar 2011 01:32:16 -0000
> @@ -361,14 +361,16 @@ _res_init(int usercall)
>                                    break;
>                            if ((*cp == '\0') || (*cp == '\n')) {
>                                    if (sp) {
> -                                           if (*sp=='y' || *sp=='b' ||
*sp=='f')
> +                                           if (*sp=='y' || *sp=='b' ||
> +                                               *sp=='f' || *sp=='m')
>                                                    _resp->lookups[n++] =
*sp;
>                                            sp = NULL;
>                                    }
>                                    break;
>                            } else if ((*cp == ' ') || (*cp == '\t') || (*cp
== ',')) {
>                                    if (sp) {
> -                                           if (*sp=='y' || *sp=='b' ||
*sp=='f')
> +                                           if (*sp=='y' || *sp=='b' ||
> +                                               *sp=='f' || *sp=='m')
>                                                    _resp->lookups[n++] =
*sp;
>                                            sp = NULL;
>                                    }
> Index: net/res_query.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/net/res_query.c,v
> retrieving revision 1.26
> diff -d -u -p -w -r1.26 res_query.c
> --- net/res_query.c     29 Jun 2010 21:08:54 -0000      1.26
> +++ net/res_query.c     20 Mar 2011 01:32:17 -0000
> @@ -52,6 +52,7 @@
>  */
>
>  #include <sys/types.h>
> +#include <sys/socket.h>
>  #include <sys/param.h>
>  #include <netinet/in.h>
>  #include <arpa/inet.h>
> @@ -65,6 +66,7 @@
>  #include <stdlib.h>
>  #include <string.h>
>  #include <unistd.h>
> +#include <poll.h>
>
>  #include "thread_private.h"
>
> @@ -400,4 +402,134 @@ hostalias(const char *name)
>        }
>        fclose(fp);
>        return (NULL);
> +}
> +
> +int
> +res_search_mcast(const char *name,
> +    int class,         /* domain name */
> +    int type,          /* class and type of query */
> +    u_char *answer,    /* buffer to put answer */
> +    int anslen)                /* size of answer */
> +{
> +#define ALL_MDNS_DEVICES "224.0.0.251"
> +#define MDNS_PORT 5353
> +       union {
> +               HEADER hdr;
> +               u_char buf[MAXPACKET];
> +       } buf;
> +       struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
> +       struct sockaddr_in msin, from;
> +       socklen_t msinlen, fromlen;
> +       size_t resplen, nlen;
> +       struct pollfd pfd;
> +       int timeout, try;
> +       int msock;
> +       int n;
> +       HEADER *hp = &buf.hdr;
> +       HEADER *anhp = (HEADER *) answer;
> +
> +       /*
> +        * Only names in the .local domain should be looked up in the mdns
> +        * network.
> +        */
> +       nlen = strlen(name);
> +       if (nlen < 7 || (strcmp(&name[nlen - 6], ".local") != 0))
> +               return (0);
> +
> +       if (_res_init(0) == -1) {
> +               h_errno = NETDB_INTERNAL;
> +               return (-1);
> +       }
> +       h_errno = HOST_NOT_FOUND;
> +
> +       n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
> +           buf.buf, sizeof(buf.buf));
> +       if (n <= 0) {
> +               h_errno = NO_RECOVERY;
> +#ifdef DEBUG
> +               if (_resp->options & RES_DEBUG)
> +                       printf(";; res_query: mkquery failed\n");
> +#endif
> +               return (n);
> +       }
> +
> +       bzero(&msin, sizeof(msin));
> +       bzero(&from, sizeof(from));
> +       msinlen = fromlen = sizeof(struct sockaddr_in);
> +       /* Initialize msin to send to mcast */
> +       msin.sin_family = AF_INET;
> +       msin.sin_port = htons(MDNS_PORT);
> +       inet_aton(ALL_MDNS_DEVICES, &msin.sin_addr);
> +
> +       if ((msock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
> +               h_errno = TRY_AGAIN;
> +               return (-1);
> +       }
> +
> +       if (sendto(msock, buf.buf, n, 0,
> +           (struct sockaddr *)&msin, msinlen) != n) {
> +               h_errno = TRY_AGAIN;
> +               close(msock);
> +               return (-1);
> +       }
> +       /*
> +        * Wait for reply
> +        */
> +       try = 3;
> +       timeout = 3000;
> +wait:
> +       if (try-- == 0) {
> +               close(msock);
> +               h_errno = HOST_NOT_FOUND;
> +               return (-1);
> +       }
> +       pfd.fd = msock;
> +       pfd.events = POLLIN;
> +       n = poll(&pfd, 1, timeout);
> +       if (n < 0) {
> +               if (errno == EINTR)
> +                       goto wait;
> +               h_errno = TRY_AGAIN;
> +               close(msock);
> +               return (-1);
> +       }
> +       if (n == 0) {
> +               /*
> +                * timeout
> +                */
> +               h_errno = HOST_NOT_FOUND;
> +               close(msock);
> +               return (0);
> +       }
> +       /* Got an answer */
> +       h_errno = NETDB_SUCCESS;
> +       resplen = recvfrom(msock, answer, anslen, 0,
> +           (struct sockaddr *)&from, &fromlen);
> +       if (resplen <= 0) {
> +               h_errno = TRY_AGAIN;
> +               close(msock);
> +               return (-1);
> +       }
> +       /* Make sure this is the answer for our question */
> +       if (hp->id != anhp->id) {
> +               /*
> +                * response from old query, ignore it.
> +                * XXX - potential security hazard could
> +                *       be detected here.
> +                */
> +               goto wait;
> +       }
> +       if (!res_queriesmatch(buf.buf, buf.buf + sizeof(buf.buf),
> +           answer, answer + anslen)) {
> +               /*
> +                * response contains wrong query? ignore it.
> +                * XXX - potential security hazard could
> +                *       be detected here.
> +                */
> +               goto wait;
> +       }
> +
> +       return (resplen);
> +#undef ALL_MDNS_DEVICES
> +#undef MDNS_PORT
>  }

Reply via email to