00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
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 
00091 
00092 
00093 int
00094 ink_res_mkquery(ink_res_state statp,
00095              int op,                    
00096              const char *dname,         
00097              int _class, int type,      
00098              const u_char *data,        
00099              int datalen,               
00100              const u_char *,  
00101              u_char *buf,               
00102              int buflen)                
00103 {
00104         HEADER *hp;
00105         u_char *cp, *ep;
00106         int n;
00107         u_char *dnptrs[20], **dpp, **lastdnptr;
00108 
00109         
00110 
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 
00128 
00129         switch (op) {
00130         case QUERY:     
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 
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 
00163 
00164                 if (ep - cp < 1 + RRFIXEDSZ + datalen)
00165                         return (-1);
00166                 *cp++ = '\0';   
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 
00185 
00186 
00187 
00188 
00189 
00190 
00191 
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                 
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);     
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 
00272 
00273 
00274 
00275 
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         
00287         case 0x40: 
00288         case 0x24: 
00289                 return (1);
00290         default:
00291                 return (0);
00292         }
00293 }
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
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                         
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; 
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                                 
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 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
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                         
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; 
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                                 
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; 
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 }