From owner-freebsd-arch Thu Oct 17 21:47: 4 2002 Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D437537B4DF for ; Thu, 17 Oct 2002 21:46:53 -0700 (PDT) Received: from pirzyk.org (dsl-65-184-181-29.telocity.com [65.184.181.29]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9C05943E88 for ; Thu, 17 Oct 2002 21:46:52 -0700 (PDT) (envelope-from jim@pirzyk.org) Received: from snoopy (snoopy.pirzyk.org [10.26.0.4]) by pirzyk.org (8.12.3/8.12.3) with ESMTP id g9I4iFaw007027 for ; Thu, 17 Oct 2002 21:44:16 -0700 (PDT) (envelope-from jim@pirzyk.org) From: Jim Pirzyk Subject: Fwd: getnetbyname broken for DNS case? Date: Thu, 17 Oct 2002 21:46:48 -0700 User-Agent: KMail/1.4.3 To: freebsd-arch@freebsd.org MIME-Version: 1.0 Message-Id: <200210172143.59341.jim@pirzyk.org> Content-Type: Multipart/Mixed; boundary="------------Boundary-00=_0MU5PT6WIZBMNQMHKSST" Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG --------------Boundary-00=_0MU5PT6WIZBMNQMHKSST Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable So I have developed a patch to use gethostbydns* in the getnetbydns* case. I did not get any comments from -net on this original question, so I thought to change the audience. Comments, questions, etc. - JimP ---------- Forwarded Message ---------- Subject: getnetbyname broken for DNS case? Date: Wed, 18 Sep 2002 00:32:11 -0700 From: Jim Pirzyk To: freebsd-net@freebsd.org Hi, I am trying to debug a problem that I have with /etc/exports. I cannot put in the symbolic name for my network (10.26.0.0) without putting it in /etc/networks. It is currently in DNS, but it looks like the getnetby= name is not working correctly for the DNS case. The functions that are broken is _getnetbydnsname() and getnetanswer(). The _getnetbydnsname() is easily fixed by changing T_PTR to T_A in res_query(), but getnetanswer() is harder to solve. It is not parsing= the format of the result correctly. First I had to put some code in to test "type" being T_PTR only if "net_i" is set to BYADDR and T_A if "net_= i" is set to BYNAME. When I go into the res_hnok() test, it is assumed by the code that it IP address is in ascii format, which it is not (it is in network binar= y order). If I remove the res_hnok() test, then it does not load the netent.n_net address correctly. The code is broken for both -CURRENT and -STABLE. So my question is then, can I rewrite getnetbyname() to use gethostbyname= () call and massage the result to a netent entry? This would solve the DNS result parsing problem and would also get us T_AAA (IPv6) network name addresses. I would also implement getnetbyaddr() in terms of gethostbyad= dr() too. - JimP --- @(#) $Id: dot.signature,v 1.10 2001/05/17 23:38:49 Jim.Pirzyk Exp $ __o jim@pirzyk.org ----------------------------------------------- _'\<,_ (*)/ (*) ------------------------------------------------------- --=20 --- @(#) $Id: dot.signature,v 1.10 2001/05/17 23:38:49 Jim.Pirzyk Exp $ __o jim@pirzyk.org ----------------------------------------------- _'\<,_ =20 (*)/ (*) =20 --------------Boundary-00=_0MU5PT6WIZBMNQMHKSST Content-Type: text/x-diff; charset="iso-8859-1"; name="getnetbydns.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="getnetbydns.patch" *** lib/libc/net/getnetbydns.c.orig Thu Sep 19 08:58:31 2002 --- lib/libc/net/getnetbydns.c Sat Sep 21 09:52:14 2002 *************** *** 81,88 **** extern int h_errno; - #define BYADDR 0 - #define BYNAME 1 #define MAXALIASES 35 #if PACKETSZ > 1024 --- 81,86 ---- *************** *** 91,222 **** #define MAXPACKET 1024 #endif ! typedef union { ! HEADER hdr; ! u_char buf[MAXPACKET]; ! } querybuf; ! ! typedef union { ! long al; ! char ac; ! } align; static struct netent * ! getnetanswer(answer, anslen, net_i) ! querybuf *answer; ! int anslen; ! int net_i; { - register HEADER *hp; - register u_char *cp; - register int n; - u_char *eom; - int type, class, buflen, ancount, qdcount, haveanswer, i, nchar; - char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN]; - char *in, *st, *pauxt, *bp, **ap; - char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0; static struct netent net_entry; ! static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; ! /* ! * find first satisfactory answer ! * ! * answer --> +------------+ ( MESSAGE ) ! * | Header | ! * +------------+ ! * | Question | the question for the name server ! * +------------+ ! * | Answer | RRs answering the question ! * +------------+ ! * | Authority | RRs pointing toward an authority ! * | Additional | RRs holding additional information ! * +------------+ ! */ ! eom = answer->buf + anslen; ! hp = &answer->hdr; ! ancount = ntohs(hp->ancount); /* #/records in the answer section */ ! qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ ! bp = netbuf; ! buflen = sizeof(netbuf); ! cp = answer->buf + HFIXEDSZ; ! if (!qdcount) { ! if (hp->aa) ! h_errno = HOST_NOT_FOUND; ! else ! h_errno = TRY_AGAIN; ! return (NULL); } - while (qdcount-- > 0) - cp += __dn_skipname(cp, eom) + QFIXEDSZ; - ap = net_aliases; - *ap = NULL; net_entry.n_aliases = net_aliases; ! haveanswer = 0; ! while (--ancount >= 0 && cp < eom) { ! n = dn_expand(answer->buf, eom, cp, bp, buflen); ! if ((n < 0) || !res_dnok(bp)) ! break; ! cp += n; ! ans[0] = '\0'; ! (void)strncpy(&ans[0], bp, sizeof(ans) - 1); ! ans[sizeof(ans) - 1] = '\0'; ! GETSHORT(type, cp); ! GETSHORT(class, cp); ! cp += INT32SZ; /* TTL */ ! GETSHORT(n, cp); ! if (class == C_IN && type == T_PTR) { ! n = dn_expand(answer->buf, eom, cp, bp, buflen); ! if ((n < 0) || !res_hnok(bp)) { ! cp += n; ! return (NULL); ! } ! cp += n; ! *ap++ = bp; ! n = strlen(bp) + 1; ! bp += n; ! buflen -= n; ! net_entry.n_addrtype = ! (class == C_IN) ? AF_INET : AF_UNSPEC; ! haveanswer++; ! } ! } ! if (haveanswer) { ! *ap = NULL; ! switch (net_i) { ! case BYADDR: ! net_entry.n_name = *net_entry.n_aliases; ! net_entry.n_net = 0L; ! break; ! case BYNAME: ! in = *net_entry.n_aliases; ! net_entry.n_name = &ans[0]; ! aux2[0] = '\0'; ! for (i = 0; i < 4; i++) { ! for (st = in, nchar = 0; ! *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; ! } ! in = ++st; ! } ! net_entry.n_net = inet_network(paux2); ! break; ! } ! net_entry.n_aliases++; ! return (&net_entry); ! } ! h_errno = TRY_AGAIN; ! return (NULL); } struct netent * --- 89,132 ---- #define MAXPACKET 1024 #endif ! struct hostent * _gethostbydnsaddr(const char *, int, int); ! struct hostent * _gethostbydnsname(const char *, int); static struct netent * ! getnetanswer(answer) ! struct hostent *answer; { static struct netent net_entry; ! static char *net_aliases[MAXALIASES]; ! u_long net; ! int i; ! /* Check to make sure we found a hostent */ ! if ( !answer ) return (NULL); ! ! net_entry.n_name = answer->h_name; ! ! for (i = 0; answer->h_aliases[i] && i < MAXALIASES; i++) { ! net_aliases[i] = answer->h_aliases[i]; } net_entry.n_aliases = net_aliases; ! ! net_entry.n_addrtype = answer->h_addrtype; ! ! /* One difference between gethostby* and getnetby* is the */ ! /* address for the former is in network byte order and the */ ! /* latter is in machine byte order :( */ ! /* Do the memcpy instead of a cast to make sure we have */ ! /* aligned memory for a u_long */ ! memcpy (&net, answer->h_addr, sizeof (net)); ! net_entry.n_net = ntohl(net); ! ! /* Strip trailing zeros */ ! while ((net_entry.n_net & 0xff) == 0 && net_entry.n_net != 0) ! net_entry.n_net >>= 8; ! ! return (&net_entry); } struct netent * *************** *** 224,301 **** register unsigned long net; register int net_type; { ! unsigned int netbr[4]; ! int nn, anslen; ! querybuf buf; ! char qbuf[MAXDNAME]; ! unsigned long net2; ! struct netent *net_entry; ! ! if (net_type != AF_INET) ! return (NULL); ! ! for (nn = 4, net2 = net; net2; net2 >>= 8) ! netbr[--nn] = net2 & 0xff; ! switch (nn) { ! case 3: /* Class A */ ! sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]); ! break; ! case 2: /* Class B */ ! sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]); ! break; ! case 1: /* Class C */ ! sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], ! netbr[1]); ! break; ! case 0: /* Class D - E */ ! sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], ! netbr[1], netbr[0]); ! break; ! } ! anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf)); ! if (anslen < 0) { ! #ifdef DEBUG ! if (_res.options & RES_DEBUG) ! printf("res_query failed\n"); ! #endif ! return (NULL); ! } ! net_entry = getnetanswer(&buf, anslen, BYADDR); ! if (net_entry) { ! unsigned u_net = net; /* maybe net should be unsigned ? */ ! ! /* Strip trailing zeros */ ! while ((u_net & 0xff) == 0 && u_net != 0) ! u_net >>= 8; ! net_entry->n_net = u_net; ! return (net_entry); ! } ! return (NULL); } struct netent * _getnetbydnsname(net) register const char *net; { ! int anslen; ! querybuf buf; ! char qbuf[MAXDNAME]; ! ! if ((_res.options & RES_INIT) == 0 && res_init() == -1) { ! h_errno = NETDB_INTERNAL; ! return (NULL); ! } ! strncpy(qbuf, net, sizeof(qbuf) - 1); ! qbuf[sizeof(qbuf) - 1] = '\0'; ! anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf)); ! if (anslen < 0) { ! #ifdef DEBUG ! if (_res.options & RES_DEBUG) ! printf("res_query failed\n"); ! #endif ! return (NULL); ! } ! return getnetanswer(&buf, anslen, BYNAME); } void --- 134,194 ---- register unsigned long net; register int net_type; { ! unsigned int netbr[4]; ! int nn, anslen; ! char qbuf[MAXDNAME]; ! unsigned long net2; ! struct hostent *buf; ! ! for (nn = 4, net2 = net; net2; net2 >>= 8) ! netbr[--nn] = net2 & 0xff; ! switch (nn) { ! case 3: /* Class A */ ! sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]); ! break; ! case 2: /* Class B */ ! sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]); ! break; ! case 1: /* Class C */ ! sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], ! netbr[1]); ! break; ! case 0: /* Class D - E */ ! sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], ! netbr[1], netbr[0]); ! break; ! } ! ! anslen = strlen(qbuf); ! ! if ((_res.options & RES_INIT) == 0 && res_init() == -1) { ! h_errno = NETDB_INTERNAL; ! return (NULL); ! } ! if (_res.options & RES_USE_INET6) { /* XXX */ ! buf = _gethostbydnsaddr(qbuf, anslen, AF_INET6); /* XXX */ ! if (buf) /* XXX */ ! return (getnetanswer(buf)); /* XXX */ ! } /* XXX */ ! return getnetanswer(_gethostbydnsaddr(qbuf, anslen, AF_INET)); } struct netent * _getnetbydnsname(net) register const char *net; { ! struct hostent *hp; ! ! if ((_res.options & RES_INIT) == 0 && res_init() == -1) { ! h_errno = NETDB_INTERNAL; ! return (NULL); ! } ! if (_res.options & RES_USE_INET6) { /* XXX */ ! hp = _gethostbydnsname(net, AF_INET6); /* XXX */ ! if (hp) /* XXX */ ! return (getnetanswer(hp)); /* XXX */ ! } /* XXX */ ! return getnetanswer(_gethostbydnsname(net, AF_INET)); } void --------------Boundary-00=_0MU5PT6WIZBMNQMHKSST-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message