diff -Naur mtr-0.69.old/dns.c mtr-0.69.new/dns.c
--- mtr-0.69.old/dns.c	2005-01-11 09:32:42.000000000 +0100
+++ mtr-0.69.new/dns.c	2005-10-03 21:31:27.000000000 +0200
@@ -853,6 +853,507 @@
   fputs("\r",stderr);
 }
 
+#ifdef __UCLIBC__
+
+static const char       digits[] = "0123456789";
+#define __set_errno(e) (errno = (e))
+
+#define NS_PUT16(s, cp) do { \
+        register u_int16_t t_s = (u_int16_t)(s); \
+        register u_char *t_cp = (u_char *)(cp); \
+        *t_cp++ = t_s >> 8; \
+        *t_cp   = t_s; \
+        (cp) += NS_INT16SZ; \
+} while (0)
+
+
+
+#define NS_PUT32(l, cp) do { \
+        register u_int32_t t_l = (u_int32_t)(l); \
+        register u_char *t_cp = (u_char *)(cp); \
+        *t_cp++ = t_l >> 24; \
+        *t_cp++ = t_l >> 16; \
+        *t_cp++ = t_l >> 8; \
+        *t_cp   = t_l; \
+        (cp) += NS_INT32SZ; \
+} while (0)
+
+
+void
+ns_put16(u_int src, u_char *dst) {
+        NS_PUT16(src, dst);
+}
+
+void
+ns_put32(u_long src, u_char *dst) {
+        NS_PUT32(src, dst);
+}
+
+void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
+
+int
+mklower(int ch) {
+        if (ch >= 0x41 && ch <= 0x5A)
+                return (ch + 0x20);
+        return (ch);
+}
+
+
+static int
+dn_find(const u_char *domain, const u_char *msg,
+        const u_char * const *dnptrs,
+        const u_char * const *lastdnptr)
+{
+        const u_char *dn, *cp, *sp;
+        const u_char * const *cpp;
+        u_int n;
+
+        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+                sp = *cpp;
+                /*
+                 * terminate search on:
+                 * root label
+                 * compression pointer
+                 * unusable offset
+                 */
+                while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
+                       (sp - msg) < 0x4000) {
+                        dn = domain;
+                        cp = sp;
+                        while ((n = *cp++) != 0) {
+                                /*
+                                 * check for indirection
+                                 */
+                                switch (n & NS_CMPRSFLGS) {
+                                case 0:         /* normal case, n == len */
+                                        if (n != *dn++)
+                                                goto next;
+                                        for ((void)NULL; n > 0; n--)
+                                                if (mklower(*dn++) !=
+                                                    mklower(*cp++))
+                                                        goto next;
+                                        /* Is next root for both ? */
+                                        if (*dn == '\0' && *cp == '\0')
+                                                return (sp - msg);
+                                        if (*dn)
+                                                continue;
+                                        goto next;
+
+                                case NS_CMPRSFLGS:      /* indirection */
+                                        cp = msg + (((n & 0x3f) << 8) | *cp);
+                                        break;
+
+                                default:        /* illegal type */
+                                        __set_errno (EMSGSIZE);
+                                        return (-1);
+                                }
+                        }
+ next:
+                        sp += *sp + 1;
+                }
+        }
+        __set_errno (ENOENT);
+        return (-1);
+}
+
+
+int
+ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
+             const u_char **dnptrs, const u_char **lastdnptr)
+{
+        u_char *dstp;
+        const u_char **cpp, **lpp, *eob, *msg;
+        const u_char *srcp;
+        int n, l, first = 1;
+
+        srcp = src;
+        dstp = dst;
+        eob = dstp + dstsiz;
+        lpp = cpp = NULL;
+        if (dnptrs != NULL) {
+                if ((msg = *dnptrs++) != NULL) {
+                        for (cpp = dnptrs; *cpp != NULL; cpp++)
+                                (void)NULL;
+                        lpp = cpp;      /* end of list to search */
+                }
+        } else
+                msg = NULL;
+
+        /* make sure the domain we are about to add is legal */
+        l = 0;
+        do {
+                n = *srcp;
+                if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) {
+                        __set_errno (EMSGSIZE);
+                        return (-1);
+                }
+                if (n == 0x41)
+                        n = *++srcp / 8;
+                l += n + 1;
+                if (l > MAXCDNAME) {
+                        __set_errno (EMSGSIZE);
+                        return (-1);
+                }
+                srcp += n + 1;
+        } while (n != 0);
+
+        /* from here on we need to reset compression pointer array on error */
+        srcp = src;
+        do {
+                /* Look to see if we can use pointers. */
+                n = *srcp;
+                if (n != 0 && n != 0x41 && msg != NULL) {
+                        l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
+                                    (const u_char * const *)lpp);
+                        if (l >= 0) {
+                                if (dstp + 1 >= eob) {
+                                        goto cleanup;
+                                }
+                                *dstp++ = (l >> 8) | NS_CMPRSFLGS;
+                                *dstp++ = l % 256;
+                                return (dstp - dst);
+                        }
+                        /* Not found, save it. */
+                        if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+                            (dstp - msg) < 0x4000 && first) {
+                                *cpp++ = dstp;
+                                *cpp = NULL;
+                                first = 0;
+                        }
+                }
+                /* copy label to buffer */
+                if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) {             /* Should not happen. */
+                        goto cleanup;
+                }
+                if (n == 0x41) {
+                        n = *++srcp / 8;
+                        if (dstp + 1 >= eob)
+                                goto cleanup;
+                        *dstp++ = 0x41;
+                }
+                if (dstp + 1 + n >= eob) {
+                        goto cleanup;
+                }
+                memcpy(dstp, srcp, n + 1);
+                srcp += n + 1;
+                dstp += n + 1;
+        } while (n != 0);
+
+        if (dstp > eob) {
+cleanup:
+                if (msg != NULL)
+                        *lpp = NULL;
+                __set_errno (EMSGSIZE);
+                return (-1);
+        }
+        return (dstp - dst);
+}
+
+
+int
+ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
+        u_char *label, *bp, *eom;
+        int c, n, escaped;
+        char *cp;
+
+        escaped = 0;
+        bp = dst;
+        eom = dst + dstsiz;
+        label = bp++;
+
+        while ((c = *src++) != 0) {
+                if (escaped) {
+                        if ((cp = strchr(digits, c)) != NULL) {
+                                n = (cp - digits) * 100;
+                                if ((c = *src++) == 0 ||
+                                    (cp = strchr(digits, c)) == NULL) {
+                                        __set_errno (EMSGSIZE);
+                                        return (-1);
+                                }
+                                n += (cp - digits) * 10;
+                                if ((c = *src++) == 0 ||
+                                    (cp = strchr(digits, c)) == NULL) {
+                                        __set_errno (EMSGSIZE);
+                                        return (-1);
+                                }
+                                n += (cp - digits);
+                                if (n > 255) {
+                                        __set_errno (EMSGSIZE);
+                                        return (-1);
+                                }
+                                c = n;
+                        } else if (c == '[' && label == bp - 1 && *src == 'x') {
+                                /* Theoretically we would have to handle \[o
+                                   as well but we do not since we do not need
+                                   it internally.  */
+                                *label = 0x41;
+                                label = bp++;
+                                ++src;
+                                while (isxdigit (*src)) {
+                                        n = *src > '9' ? *src - 'a' + 10 : *src - '0';
+                                        ++src;
+                                        if (! isxdigit(*src)) {
+                                                __set_errno (EMSGSIZE);
+                                                return (-1);
+                                        }
+                                        n <<= 4;
+                                        n += *src > '9' ? *src - 'a' + 10 : *src - '0';
+                                        if (bp + 1 >= eom) {
+                                                __set_errno (EMSGSIZE);
+                                                return (-1);
+                                        }
+                                        *bp++ = n;
+                                        ++src;
+                                }
+                                *label = (bp - label - 1) * 8;
+                                if (*src++ != ']' || *src++ != '.') {
+                                        __set_errno (EMSGSIZE);
+                                        return (-1);
+                                }
+                                escaped = 0;
+                                label = bp++;
+                                if (bp >= eom) {
+                                        __set_errno (EMSGSIZE);
+                                        return (-1);
+                                }
+                                continue;
+                        }
+                        escaped = 0;
+                } else if (c == '\\') {
+                        escaped = 1;
+                        continue;
+                } else if (c == '.') {
+                        c = (bp - label - 1);
+                        if ((c & NS_CMPRSFLGS) != 0) {  /* Label too big. */
+                                __set_errno (EMSGSIZE);
+                                return (-1);
+                        }
+                        if (label >= eom) {
+                                __set_errno (EMSGSIZE);
+                                return (-1);
+                        }
+                        *label = c;
+                        /* Fully qualified ? */
+                        if (*src == '\0') {
+                                if (c != 0) {
+                                        if (bp >= eom) {
+                                                __set_errno (EMSGSIZE);
+                                                return (-1);
+                                        }
+                                        *bp++ = '\0';
+                                }
+                                if ((bp - dst) > MAXCDNAME) {
+                                        __set_errno (EMSGSIZE);
+                                        return (-1);
+                                }
+                                return (1);
+                        }
+                        if (c == 0 || *src == '.') {
+                                __set_errno (EMSGSIZE);
+                                return (-1);
+                        }
+                        label = bp++;
+                        continue;
+                }
+                if (bp >= eom) {
+                        __set_errno (EMSGSIZE);
+                        return (-1);
+                }
+                *bp++ = (u_char)c;
+        }
+        c = (bp - label - 1);
+        if ((c & NS_CMPRSFLGS) != 0) {          /* Label too big. */
+                __set_errno (EMSGSIZE);
+                return (-1);
+        }
+        if (label >= eom) {
+                __set_errno (EMSGSIZE);
+                return (-1);
+        }
+        *label = c;
+        if (c != 0) {
+                if (bp >= eom) {
+                        __set_errno (EMSGSIZE);
+                        return (-1);
+                }
+                *bp++ = 0;
+        }
+        if ((bp - dst) > MAXCDNAME) {   /* src too big */
+                __set_errno (EMSGSIZE);
+                return (-1);
+        }
+        return (0);
+}
+
+
+
+int
+ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
+                 const u_char **dnptrs, const u_char **lastdnptr)
+{
+        u_char tmp[NS_MAXCDNAME];
+
+        if (ns_name_pton(src, tmp, sizeof tmp) == -1)
+                return (-1);
+        return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
+}
+
+
+int
+dn_comp(const char *src, u_char *dst, int dstsiz,
+        u_char **dnptrs, u_char **lastdnptr)
+{
+        return (ns_name_compress(src, dst, (size_t)dstsiz,
+                                 (const u_char **)dnptrs,
+                                 (const u_char **)lastdnptr));
+}
+
+
+
+
+int
+res_nmkquery(res_state statp,
+             int op,                    /* opcode of query */
+             const char *dname,         /* domain name */
+             int class, int type,       /* class and type of query */
+             const u_char *data,        /* resource record data */
+             int datalen,               /* length of data */
+             const u_char *newrr_in,    /* new rr for modify or append */
+             u_char *buf,               /* buffer to put query */
+             int buflen)                /* size of buffer */
+{
+        register HEADER *hp;
+        register u_char *cp;
+        register int n;
+        u_char *dnptrs[20], **dpp, **lastdnptr;
+
+#ifdef DEBUG
+        if (statp->options & RES_DEBUG)
+                printf(";; res_nmkquery(%s, %s, %s, %s)\n",
+                       _res_opcodes[op], dname, p_class(class), p_type(type));
+#endif
+        /*
+         * Initialize header fields.
+         */
+        if ((buf == NULL) || (buflen < HFIXEDSZ))
+                return (-1);
+        memset(buf, 0, HFIXEDSZ);
+        hp = (HEADER *) buf;
+        /* We randomize the IDs every time.  The old code just
+           incremented by one after the initial randomization which
+           still predictable if the application does multiple
+           requests.  */
+#if 0
+        hp->id = htons(++statp->id);
+#else
+        hp->id = htons(statp->id);
+        int randombits;
+        do
+          {
+#ifdef RANDOM_BITS
+            RANDOM_BITS (randombits);
+#else
+            struct timeval tv;
+            gettimeofday (&tv, NULL);
+            randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
+#endif
+          }
+        while ((randombits & 0xffff) == 0);
+        statp->id = (statp->id + randombits) & 0xffff;
+#endif
+        hp->opcode = op;
+        hp->rd = (statp->options & RES_RECURSE) != 0;
+        hp->rcode = NOERROR;
+        cp = buf + HFIXEDSZ;
+        buflen -= HFIXEDSZ;
+        dpp = dnptrs;
+        *dpp++ = buf;
+        *dpp++ = NULL;
+        lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+        /*
+         * perform opcode specific processing
+         */
+        switch (op) {
+        case QUERY:     /*FALLTHROUGH*/
+        case NS_NOTIFY_OP:
+                if ((buflen -= QFIXEDSZ) < 0)
+                        return (-1);
+                if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+                        return (-1);
+                cp += n;
+                buflen -= n;
+                __putshort(type, cp);
+                cp += INT16SZ;
+                __putshort(class, cp);
+                cp += INT16SZ;
+                hp->qdcount = htons(1);
+                if (op == QUERY || data == NULL)
+                        break;
+                /*
+                 * Make an additional record for completion domain.
+                 */
+                buflen -= RRFIXEDSZ;
+                n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
+                if (n < 0)
+                        return (-1);
+                cp += n;
+                buflen -= n;
+                __putshort(T_NULL, cp);
+                cp += INT16SZ;
+                __putshort(class, cp);
+                cp += INT16SZ;
+                __putlong(0, cp);
+                cp += INT32SZ;
+                __putshort(0, cp);
+                cp += INT16SZ;
+                hp->arcount = htons(1);
+                break;
+
+        case IQUERY:
+                /*
+                 * Initialize answer section
+                 */
+                if (buflen < 1 + RRFIXEDSZ + datalen)
+                        return (-1);
+                *cp++ = '\0';   /* no domain name */
+                __putshort(type, cp);
+                cp += INT16SZ;
+                __putshort(class, cp);
+                cp += INT16SZ;
+                __putlong(0, cp);
+                cp += INT32SZ;
+                __putshort(datalen, cp);
+                cp += INT16SZ;
+                if (datalen) {
+                        memcpy(cp, data, datalen);
+                        cp += datalen;
+                }
+                hp->ancount = htons(1);
+                break;
+
+        default:
+                return (-1);
+        }
+        return (cp - buf);
+}
+
+int
+res_mkquery(int op,                     /* opcode of query */
+            const char *dname,          /* domain name */
+            int class, int type,        /* class and type of query */
+            const u_char *data,         /* resource record data */
+            int datalen,                /* length of data */
+            const u_char *newrr_in,     /* new rr for modify or append */
+            u_char *buf,                /* buffer to put query */
+            int buflen)                 /* size of buffer */
+{
+        return (res_nmkquery(&_res, op, dname, class, type,
+                             data, datalen,
+                             newrr_in, buf, buflen));
+}
+
+#endif
 
 void dorequest(char *s,int type,word id)
 {
