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
> }