• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_res_mkquery.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1985, 1993
00003  *    The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
00032  *
00033  * Permission to use, copy, modify, and distribute this software for any
00034  * purpose with or without fee is hereby granted, provided that the above
00035  * copyright notice and this permission notice appear in all copies, and that
00036  * the name of Digital Equipment Corporation not be used in advertising or
00037  * publicity pertaining to distribution of the document or software without
00038  * specific, written prior permission.
00039  *
00040  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
00041  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
00042  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
00043  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00044  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00045  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00046  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00047  * SOFTWARE.
00048  */
00049 
00050 /*
00051  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
00052  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
00053  *
00054  * Permission to use, copy, modify, and distribute this software for any
00055  * purpose with or without fee is hereby granted, provided that the above
00056  * copyright notice and this permission notice appear in all copies.
00057  *
00058  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00059  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00060  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00061  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00062  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00063  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00064  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00065  */
00066 
00067 
00068 
00069 #include "ink_config.h"
00070 #include "ink_defs.h"
00071 
00072 #include <sys/types.h>
00073 #include <sys/param.h>
00074 #include <netinet/in.h>
00075 #include <arpa/nameser.h>
00076 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
00077 #include <arpa/nameser_compat.h>
00078 #endif
00079 #include <netdb.h>
00080 #include <resolv.h>
00081 #include <stdio.h>
00082 #include <string.h>
00083 
00084 #include "ink_error.h"
00085 #include "ink_resolver.h"
00086 
00087 #define SPRINTF(x) (sprintf x)
00088 
00089 /*%
00090  * Form all types of queries.
00091  * Returns the size of the result or -1.
00092  */
00093 int
00094 ink_res_mkquery(ink_res_state statp,
00095              int op,                    /*!< opcode of query  */
00096              const char *dname,         /*!< domain name  */
00097              int _class, int type,      /*!< _class and type of query  */
00098              const u_char *data,        /*!< resource record data  */
00099              int datalen,               /*!< length of data  */
00100              const u_char */* newrr_in  ATS_UNUSED */,  /*!< new rr for modify or append  */
00101              u_char *buf,               /*!< buffer to put query  */
00102              int buflen)                /*!< size of buffer  */
00103 {
00104         HEADER *hp;
00105         u_char *cp, *ep;
00106         int n;
00107         u_char *dnptrs[20], **dpp, **lastdnptr;
00108 
00109         /*
00110          * Initialize header fields.
00111          */
00112         if ((buf == NULL) || (buflen < HFIXEDSZ))
00113                 return (-1);
00114         memset(buf, 0, HFIXEDSZ);
00115         hp = (HEADER *) buf;
00116         hp->id = htons(++statp->id);
00117         hp->opcode = op;
00118         hp->rd = (statp->options & INK_RES_RECURSE) != 0U;
00119         hp->rcode = NOERROR;
00120         cp = buf + HFIXEDSZ;
00121         ep = buf + buflen;
00122         dpp = dnptrs;
00123         *dpp++ = buf;
00124         *dpp++ = NULL;
00125         lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
00126         /*
00127          * perform opcode specific processing
00128          */
00129         switch (op) {
00130         case QUERY:     /*FALLTHROUGH*/
00131         case NS_NOTIFY_OP:
00132                 if (ep - cp < QFIXEDSZ)
00133                         return (-1);
00134                 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
00135                     lastdnptr)) < 0)
00136                         return (-1);
00137                 cp += n;
00138                 NS_PUT16(type, cp);
00139                 NS_PUT16(_class, cp);
00140                 hp->qdcount = htons(1);
00141                 if (op == QUERY || data == NULL)
00142                         break;
00143                 /*
00144                  * Make an additional record for completion domain.
00145                  */
00146                 if ((ep - cp) < RRFIXEDSZ)
00147                         return (-1);
00148                 n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,
00149                             dnptrs, lastdnptr);
00150                 if (n < 0)
00151                         return (-1);
00152                 cp += n;
00153                 NS_PUT16(T_NULL, cp);
00154                 NS_PUT16(_class, cp);
00155                 NS_PUT32(0, cp);
00156                 NS_PUT16(0, cp);
00157                 hp->arcount = htons(1);
00158                 break;
00159 
00160         case IQUERY:
00161                 /*
00162                  * Initialize answer section
00163                  */
00164                 if (ep - cp < 1 + RRFIXEDSZ + datalen)
00165                         return (-1);
00166                 *cp++ = '\0';   /*%< no domain name */
00167                 NS_PUT16(type, cp);
00168                 NS_PUT16(_class, cp);
00169                 NS_PUT32(0, cp);
00170                 NS_PUT16(datalen, cp);
00171                 if (datalen) {
00172                         memcpy(cp, data, datalen);
00173                         cp += datalen;
00174                 }
00175                 hp->ancount = htons(1);
00176                 break;
00177 
00178         default:
00179                 return (-1);
00180         }
00181         return (cp - buf);
00182 }
00183 
00184 /* Public. */
00185 
00186 /*%
00187  *      Thinking in noninternationalized USASCII (per the DNS spec),
00188  *      is this character visible and not a space when printed ?
00189  *
00190  * return:
00191  *\li   boolean.
00192  */
00193 static int
00194 printable(int ch) {
00195         return (ch > 0x20 && ch < 0x7f);
00196 }
00197 
00198 static const char       digits[] = "0123456789";
00199 
00200 static int
00201 labellen(const u_char *lp)
00202 {
00203         int bitlen;
00204         u_char l = *lp;
00205 
00206         if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
00207                 /* should be avoided by the caller */
00208                 return(-1);
00209         }
00210 
00211         if ((l & NS_CMPRSFLGS) == INK_NS_TYPE_ELT) {
00212                 if (l == INK_DNS_LABELTYPE_BITSTRING) {
00213                         if ((bitlen = *(lp + 1)) == 0)
00214                                 bitlen = 256;
00215                         return((bitlen + 7 ) / 8 + 1);
00216                 }
00217                 return(-1);     /*%< unknwon ELT */
00218         }
00219         return(l);
00220 }
00221 
00222 static int
00223 decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
00224 {
00225         const unsigned char *cp = *cpp;
00226         char *beg = dn, tc;
00227         int b, blen, plen, i;
00228 
00229         if ((blen = (*cp & 0xff)) == 0)
00230                 blen = 256;
00231         plen = (blen + 3) / 4;
00232         plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
00233         if (dn + plen >= eom)
00234                 return(-1);
00235 
00236         cp++;
00237         i = SPRINTF((dn, "\\[x"));
00238         if (i < 0)
00239                 return (-1);
00240         dn += i;
00241         for (b = blen; b > 7; b -= 8, cp++) {
00242                 i = SPRINTF((dn, "%02x", *cp & 0xff));
00243                 if (i < 0)
00244                         return (-1);
00245                 dn += i;
00246         }
00247         if (b > 4) {
00248                 tc = *cp++;
00249                 i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
00250                 if (i < 0)
00251                         return (-1);
00252                 dn += i;
00253         } else if (b > 0) {
00254                 tc = *cp++;
00255                 i = SPRINTF((dn, "%1x",
00256                                ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
00257                 if (i < 0)
00258                         return (-1);
00259                 dn += i;
00260         }
00261         i = SPRINTF((dn, "/%d]", blen));
00262         if (i < 0)
00263                 return (-1);
00264         dn += i;
00265 
00266         *cpp = cp;
00267         return(dn - beg);
00268 }
00269 
00270 /*%
00271  *      Thinking in noninternationalized USASCII (per the DNS spec),
00272  *      is this characted special ("in need of quoting") ?
00273  *
00274  * return:
00275  *\li   boolean.
00276  */
00277 static int
00278 special(int ch) {
00279         switch (ch) {
00280         case 0x22: /*%< '"' */
00281         case 0x2E: /*%< '.' */
00282         case 0x3B: /*%< ';' */
00283         case 0x5C: /*%< '\\' */
00284         case 0x28: /*%< '(' */
00285         case 0x29: /*%< ')' */
00286         /* Special modifiers in zone files. */
00287         case 0x40: /*%< '@' */
00288         case 0x24: /*%< '$' */
00289                 return (1);
00290         default:
00291                 return (0);
00292         }
00293 }
00294 
00295 /*%
00296  *      Convert an encoded domain name to printable ascii as per RFC1035.
00297 
00298  * return:
00299  *\li   Number of bytes written to buffer, or -1 (with errno set)
00300  *
00301  * notes:
00302  *\li   The root is returned as "."
00303  *\li   All other domains are returned in non absolute form
00304  */
00305 int
00306 ink_ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
00307 {
00308         const u_char *cp;
00309         char *dn, *eom;
00310         u_char c;
00311         u_int n;
00312         int l;
00313 
00314         cp = src;
00315         dn = dst;
00316         eom = dst + dstsiz;
00317 
00318         while ((n = *cp++) != 0) {
00319                 if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
00320                         /* Some kind of compression pointer. */
00321                         errno = EMSGSIZE;
00322                         return (-1);
00323                 }
00324                 if (dn != dst) {
00325                         if (dn >= eom) {
00326                                 errno = EMSGSIZE;
00327                                 return (-1);
00328                         }
00329                         *dn++ = '.';
00330                 }
00331                 if ((l = labellen(cp - 1)) < 0) {
00332                         errno = EMSGSIZE; /*%< XXX */
00333                         return(-1);
00334                 }
00335                 if (dn + l >= eom) {
00336                         errno = EMSGSIZE;
00337                         return (-1);
00338                 }
00339                 if ((n & NS_CMPRSFLGS) == INK_NS_TYPE_ELT) {
00340                         int m;
00341 
00342                         if (n != INK_DNS_LABELTYPE_BITSTRING) {
00343                                 /* XXX: labellen should reject this case */
00344                                 errno = EINVAL;
00345                                 return(-1);
00346                         }
00347                         if ((m = decode_bitstring(&cp, dn, eom)) < 0)
00348                         {
00349                                 errno = EMSGSIZE;
00350                                 return(-1);
00351                         }
00352                         dn += m;
00353                         continue;
00354                 }
00355                 for ((void)NULL; l > 0; l--) {
00356                         c = *cp++;
00357                         if (special(c)) {
00358                                 if (dn + 1 >= eom) {
00359                                         errno = EMSGSIZE;
00360                                         return (-1);
00361                                 }
00362                                 *dn++ = '\\';
00363                                 *dn++ = (char)c;
00364                         } else if (!printable(c)) {
00365                                 if (dn + 3 >= eom) {
00366                                         errno = EMSGSIZE;
00367                                         return (-1);
00368                                 }
00369                                 *dn++ = '\\';
00370                                 *dn++ = digits[c / 100];
00371                                 *dn++ = digits[(c % 100) / 10];
00372                                 *dn++ = digits[c % 10];
00373                         } else {
00374                                 if (dn >= eom) {
00375                                         errno = EMSGSIZE;
00376                                         return (-1);
00377                                 }
00378                                 *dn++ = (char)c;
00379                         }
00380                 }
00381         }
00382         if (dn == dst) {
00383                 if (dn >= eom) {
00384                         errno = EMSGSIZE;
00385                         return (-1);
00386                 }
00387                 *dn++ = '.';
00388         }
00389         if (dn >= eom) {
00390                 errno = EMSGSIZE;
00391                 return (-1);
00392         }
00393         *dn++ = '\0';
00394         return (dn - dst);
00395 }
00396 
00397 /*%
00398  *      Convert an encoded domain name to printable ascii as per RFC1035.
00399 
00400  * return:
00401  *\li   Number of bytes written to buffer, or -1 (with errno set)
00402  *
00403  * notes:
00404  *\li   The root is returned as "."
00405  *\li   All other domains are returned in non absolute form
00406  */
00407 #if defined(linux)
00408 int
00409 ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) __THROW
00410 #else
00411 int
00412 ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
00413 #endif
00414 {
00415         const u_char *cp;
00416         char *dn, *eom;
00417         u_char c;
00418         u_int n;
00419         int l;
00420 
00421         cp = src;
00422         dn = dst;
00423         eom = dst + dstsiz;
00424 
00425         while ((n = *cp++) != 0) {
00426                 if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
00427                         /* Some kind of compression pointer. */
00428                         errno = EMSGSIZE;
00429                         return (-1);
00430                 }
00431                 if (dn != dst) {
00432                         if (dn >= eom) {
00433                                 errno = EMSGSIZE;
00434                                 return (-1);
00435                         }
00436                         *dn++ = '.';
00437                 }
00438                 if ((l = labellen(cp - 1)) < 0) {
00439                         errno = EMSGSIZE; /*%< XXX */
00440                         return(-1);
00441                 }
00442                 if (dn + l >= eom) {
00443                         errno = EMSGSIZE;
00444                         return (-1);
00445                 }
00446                 if ((n & NS_CMPRSFLGS) == INK_NS_TYPE_ELT) {
00447                         int m;
00448 
00449                         if (n != INK_DNS_LABELTYPE_BITSTRING) {
00450                                 /* XXX: labellen should reject this case */
00451                                 errno = EINVAL;
00452                                 return(-1);
00453                         }
00454                         if ((m = decode_bitstring(&cp, dn, eom)) < 0)
00455                         {
00456                                 errno = EMSGSIZE;
00457                                 return(-1);
00458                         }
00459                         dn += m;
00460                         continue;
00461                 }
00462                 for ((void)NULL; l > 0; l--) {
00463                         c = *cp++;
00464                         if (special(c)) {
00465                                 if (dn + 1 >= eom) {
00466                                         errno = EMSGSIZE;
00467                                         return (-1);
00468                                 }
00469                                 *dn++ = '\\';
00470                                 *dn++ = (char)c;
00471                         } else if (!printable(c)) {
00472                                 if (dn + 3 >= eom) {
00473                                         errno = EMSGSIZE;
00474                                         return (-1);
00475                                 }
00476                                 *dn++ = '\\';
00477                                 *dn++ = digits[c / 100];
00478                                 *dn++ = digits[(c % 100) / 10];
00479                                 *dn++ = digits[c % 10];
00480                         } else {
00481                                 if (dn >= eom) {
00482                                         errno = EMSGSIZE;
00483                                         return (-1);
00484                                 }
00485                                 *dn++ = (char)c;
00486                         }
00487                 }
00488         }
00489         if (dn == dst) {
00490                 if (dn >= eom) {
00491                         errno = EMSGSIZE;
00492                         return (-1);
00493                 }
00494                 *dn++ = '.';
00495         }
00496         if (dn >= eom) {
00497                 errno = EMSGSIZE;
00498                 return (-1);
00499         }
00500         *dn++ = '\0';
00501         return (dn - dst);
00502 }
00503 
00504 HostResStyle
00505 ats_host_res_from(int family, HostResPreferenceOrder order)
00506 {
00507   bool v4 = false, v6 = false;
00508   HostResPreference client = AF_INET6 == family ? HOST_RES_PREFER_IPV6 : HOST_RES_PREFER_IPV4;
00509 
00510   for ( int i = 0 ; i < N_HOST_RES_PREFERENCE_ORDER ; ++i ) {
00511     HostResPreference p = order[i];
00512     if (HOST_RES_PREFER_CLIENT == p) p = client; // CLIENT -> actual value
00513     if (HOST_RES_PREFER_IPV4 == p) {
00514       if (v6) return HOST_RES_IPV6;
00515       else v4 = true;
00516     } else if (HOST_RES_PREFER_IPV6 == p) {
00517       if (v4) return HOST_RES_IPV4;
00518       else v6 = true;
00519     } else {
00520       break;
00521     }
00522   }
00523   if (v4) return HOST_RES_IPV4_ONLY;
00524   else if (v6) return HOST_RES_IPV6_ONLY;
00525   return HOST_RES_NONE;
00526 }
00527 
00528 HostResStyle
00529 ats_host_res_match(sockaddr const* addr)
00530 {
00531   HostResStyle zret = HOST_RES_NONE;
00532   if (ats_is_ip6(addr))
00533     zret = HOST_RES_IPV6_ONLY;
00534   else if (ats_is_ip4(addr))
00535     zret = HOST_RES_IPV4_ONLY;
00536   return zret;
00537 }

Generated by  doxygen 1.7.1