|
|
- --- a/dns.c
- +++ b/dns.c
- @@ -918,6 +918,507 @@ void restell(char *s)
- 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)
- {
|