Print this page
1926 libresolv evades compiler warnings


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*

  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 /*
  31  * University Copyright- Copyright (c) 1982, 1986, 1988
  32  * The Regents of the University of California
  33  * All Rights Reserved
  34  *
  35  * University Acknowledgment- Portions of this document are derived from
  36  * software developed by the University of California, Berkeley, and its
  37  * contributors.
  38  */
  39 
  40 #pragma ident   "%Z%%M% %I%     %E% SMI"
  41 
  42 #include <stdio.h>
  43 #include <sys/types.h>
  44 #include <sys/socket.h>
  45 #include <sys/stat.h>
  46 #include <netinet/in.h>
  47 #include <arpa/nameser.h>
  48 #include <resolv.h>



  49 #include <errno.h>
  50 #include <netdb.h>

  51 
  52 /*
  53  * Kludge to time out quickly if there is no /etc/resolv.conf
  54  * and a TCP connection to the local DNS server fails.
  55  *
  56  * Moved function from res_send.c to res_mkquery.c.  This
  57  * solves a long timeout problem with nslookup.
  58  *
  59  * __areweinnamed is needed because there is a possibility that the
  60  * user might do bad things to resolv.conf and cause in.named to call
  61  * _confcheck and deadlock the server.
  62  */
  63 
  64 int __areweinnamed()
  65 {
  66         return (0);
  67 }
  68 
  69 static int _confcheck()
  70 {


  80         if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) {
  81 
  82                 /* Next, we check to see if _res.nsaddr is set to loopback.
  83                  * If it isn't, it has been altered by the application
  84                  * explicitly and we then want to bail with success.
  85                  */
  86                 if (__areweinnamed())
  87                         return (0);
  88                 
  89                 if (_res.nsaddr.sin_addr.S_un.S_addr == htonl(INADDR_LOOPBACK)) {
  90 
  91                         /* Lastly, we try to connect to the TCP port of the
  92                          * nameserver.  If this fails, then we know that
  93                          * DNS is misconfigured and we can quickly exit.
  94                          */
  95                         ns = socket(AF_INET, SOCK_STREAM, 0);
  96                         IN_SET_LOOPBACK_ADDR(&ns_sin);
  97                         ns_sin.sin_port = htons(NAMESERVER_PORT);
  98                         if (connect(ns, (struct sockaddr *) &ns_sin,
  99                                     sizeof ns_sin) == -1) {
 100                                 close(ns);
 101                                 return(-1);
 102                         }
 103                         else {
 104                                 close(ns);
 105                                 return(0);
 106                         }
 107                 }
 108         
 109                 return(0);
 110         }
 111         
 112         return (0);
 113 }
 114 
 115 /*
 116  * Form all types of queries.
 117  * Returns the size of the result or -1.
 118  */
 119 int
 120 res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
 121         int op;                 /* opcode of query */
 122         char *dname;            /* domain name */
 123         int class, type;        /* class and type of query */
 124         char *data;             /* resource record data */
 125         int datalen;            /* length of data */
 126         struct rrec *newrr;     /* new rr for modify or append */
 127         char *buf;              /* buffer to put query */
 128         int buflen;             /* size of buffer */
 129 {
 130         register HEADER *hp;
 131         register char *cp;
 132         register int n;
 133         char *dnptrs[10], **dpp, **lastdnptr;
 134 
 135 #ifdef DEBUG
 136         if (_res.options & RES_DEBUG)
 137                 printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
 138 #endif /* DEBUG */
 139         
 140         /*
 141          * Check to see if we can bailout quickly.
 142          * Also rerun res_init if we failed in the past.
 143          */
 144 
 145         if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
 146                 h_errno = NO_RECOVERY;
 147                 return(-1);
 148         }
 149         
 150         if (_confcheck() == -1) {
 151                 _res.options &= ~RES_INIT;
 152                 h_errno = NO_RECOVERY;
 153                 return(-1);
 154         }
 155 
 156         /*
 157          * Initialize header fields.
 158          */
 159         if ((buf == NULL) || (buflen < sizeof (HEADER)))
 160                 return (-1);
 161 #ifdef SYSV
 162         memset(buf, 0, sizeof (HEADER));
 163 #else
 164         bzero(buf, sizeof (HEADER));
 165 #endif
 166         hp = (HEADER *) buf;
 167         hp->id = htons(++_res.id);
 168         hp->opcode = op;
 169         hp->pr = (_res.options & RES_PRIMARY) != 0;
 170         hp->rd = (_res.options & RES_RECURSE) != 0;
 171         hp->rcode = NOERROR;
 172         cp = buf + sizeof (HEADER);
 173         buflen -= sizeof (HEADER);
 174         dpp = dnptrs;
 175         *dpp++ = buf;
 176         *dpp++ = NULL;
 177         lastdnptr = dnptrs + sizeof (dnptrs) / sizeof (dnptrs[0]);
 178         /*
 179          * perform opcode specific processing
 180          */
 181         switch (op) {
 182         case QUERY:
 183                 if ((buflen -= QFIXEDSZ) < 0)
 184                         return (-1);
 185                 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)

 186                         return (-1);
 187                 cp += n;
 188                 buflen -= n;
 189                 putshort(type, cp);
 190                 cp += sizeof (u_short);
 191                 putshort(class, cp);
 192                 cp += sizeof (u_short);
 193                 hp->qdcount = htons(1);
 194                 if (op == QUERY || data == NULL)
 195                         break;
 196                 /*
 197                  * Make an additional record for completion domain.
 198                  */
 199                 buflen -= RRFIXEDSZ;
 200                 if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)

 201                         return (-1);
 202                 cp += n;
 203                 buflen -= n;
 204                 putshort(T_NULL, cp);
 205                 cp += sizeof (u_short);
 206                 putshort(class, cp);
 207                 cp += sizeof (u_short);
 208                 putlong(0, cp);
 209                 cp += sizeof (u_long);
 210                 putshort(0, cp);
 211                 cp += sizeof (u_short);
 212                 hp->arcount = htons(1);
 213                 break;
 214 
 215         case IQUERY:
 216                 /*
 217                  * Initialize answer section
 218                  */
 219                 if (buflen < 1 + RRFIXEDSZ + datalen)
 220                         return (-1);
 221                 *cp++ = '\0';   /* no domain name */
 222                 putshort(type, cp);
 223                 cp += sizeof (u_short);
 224                 putshort(class, cp);
 225                 cp += sizeof (u_short);
 226                 putlong(0, cp);
 227                 cp += sizeof (u_long);
 228                 putshort(datalen, cp);
 229                 cp += sizeof (u_short);
 230                 if (datalen) {
 231 #ifdef SYSV
 232                         memcpy((void *)cp, (void *)data, datalen);
 233 #else
 234                         bcopy(data, cp, datalen);
 235 #endif
 236                         cp += datalen;
 237                 }
 238                 hp->ancount = htons(1);
 239                 break;
 240 
 241 #ifdef ALLOW_UPDATES
 242         /*
 243          * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
 244          * (Record to be modified is followed by its replacement in msg.)
 245          */
 246         case UPDATEM:
 247         case UPDATEMA:
 248 
 249         case UPDATED:
 250                 /*
 251                  * The res code for UPDATED and UPDATEDA is the same; user
 252                  * calls them differently: specifies data for UPDATED; server
 253                  * ignores data if specified for UPDATEDA.
 254                  */
 255         case UPDATEDA:
 256                 buflen -= RRFIXEDSZ + datalen;
 257                 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)

 258                         return (-1);
 259                 cp += n;
 260                 putshort(type, cp);
 261                 cp += sizeof (u_short);
 262                 putshort(class, cp);
 263                 cp += sizeof (u_short);
 264                 putlong(0, cp);
 265                 cp += sizeof (u_long);
 266                 putshort(datalen, cp);
 267                 cp += sizeof (u_short);
 268                 if (datalen) {
 269 #ifdef SYSV
 270                         memcpy((void *)cp, (void *)data, datalen);
 271 #else
 272                         bcopy(data, cp, datalen);
 273 #endif
 274                         cp += datalen;
 275                 }
 276                 if ((op == UPDATED) || (op == UPDATEDA)) {
 277                         hp->ancount = htons(0);
 278                         break;
 279                 }
 280                 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
 281 
 282         case UPDATEA:   /* Add new resource record */
 283                 buflen -= RRFIXEDSZ + datalen;
 284                 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)

 285                         return (-1);
 286                 cp += n;
 287                 putshort(newrr->r_type, cp);
 288                 cp += sizeof (u_short);
 289                 putshort(newrr->r_class, cp);
 290                 cp += sizeof (u_short);
 291                 putlong(0, cp);
 292                 cp += sizeof (u_long);
 293                 putshort(newrr->r_size, cp);
 294                 cp += sizeof (u_short);
 295                 if (newrr->r_size) {
 296 #ifdef SYSV
 297                         memcpy((void *)cp, newrr->r_data, newrr->r_size);
 298 #else
 299                         bcopy(newrr->r_data, cp, newrr->r_size);
 300 #endif
 301                         cp += newrr->r_size;
 302                 }
 303                 hp->ancount = htons(0);
 304                 break;
 305 
 306 #endif /* ALLOW_UPDATES */
 307         }
 308         return (cp - buf);
 309 }


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2015 Gary Mills
  24  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  25  * Use is subject to license terms.
  26  */
  27 
  28 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  29 /*        All Rights Reserved   */
  30 
  31 /*
  32  * University Copyright- Copyright (c) 1982, 1986, 1988
  33  * The Regents of the University of California
  34  * All Rights Reserved
  35  *
  36  * University Acknowledgment- Portions of this document are derived from
  37  * software developed by the University of California, Berkeley, and its
  38  * contributors.
  39  */
  40 


  41 #include <stdio.h>
  42 #include <sys/types.h>
  43 #include <sys/socket.h>
  44 #include <sys/stat.h>
  45 #include <netinet/in.h>
  46 #include <arpa/nameser.h>
  47 #include <resolv.h>
  48 #include <string.h>
  49 #include <stdlib.h>
  50 #include <unistd.h>
  51 #include <errno.h>
  52 #include <netdb.h>
  53 #include "crossl.h"
  54 
  55 /*
  56  * Kludge to time out quickly if there is no /etc/resolv.conf
  57  * and a TCP connection to the local DNS server fails.
  58  *
  59  * Moved function from res_send.c to res_mkquery.c.  This
  60  * solves a long timeout problem with nslookup.
  61  *
  62  * __areweinnamed is needed because there is a possibility that the
  63  * user might do bad things to resolv.conf and cause in.named to call
  64  * _confcheck and deadlock the server.
  65  */
  66 
  67 int __areweinnamed()
  68 {
  69         return (0);
  70 }
  71 
  72 static int _confcheck()
  73 {


  83         if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) {
  84 
  85                 /* Next, we check to see if _res.nsaddr is set to loopback.
  86                  * If it isn't, it has been altered by the application
  87                  * explicitly and we then want to bail with success.
  88                  */
  89                 if (__areweinnamed())
  90                         return (0);
  91                 
  92                 if (_res.nsaddr.sin_addr.S_un.S_addr == htonl(INADDR_LOOPBACK)) {
  93 
  94                         /* Lastly, we try to connect to the TCP port of the
  95                          * nameserver.  If this fails, then we know that
  96                          * DNS is misconfigured and we can quickly exit.
  97                          */
  98                         ns = socket(AF_INET, SOCK_STREAM, 0);
  99                         IN_SET_LOOPBACK_ADDR(&ns_sin);
 100                         ns_sin.sin_port = htons(NAMESERVER_PORT);
 101                         if (connect(ns, (struct sockaddr *) &ns_sin,
 102                                     sizeof ns_sin) == -1) {
 103                                 (void) close(ns);
 104                                 return(-1);
 105                         }
 106                         else {
 107                                 (void) close(ns);
 108                                 return(0);
 109                         }
 110                 }
 111         
 112                 return(0);
 113         }
 114         
 115         return (0);
 116 }
 117 
 118 /*
 119  * Form all types of queries.
 120  * Returns the size of the result or -1.
 121  */
 122 int
 123 res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
 124         int op;                 /* opcode of query */
 125         char *dname;            /* domain name */
 126         int class, type;        /* class and type of query */
 127         char *data;             /* resource record data */
 128         int datalen;            /* length of data */
 129         struct rrec *newrr;     /* new rr for modify or append */
 130         char *buf;              /* buffer to put query */
 131         int buflen;             /* size of buffer */
 132 {
 133         register HEADER *hp;
 134         register u_char *cp;
 135         register int n;
 136         u_char *dnptrs[10], **dpp, **lastdnptr;
 137 
 138 #ifdef DEBUG
 139         if (_res.options & RES_DEBUG)
 140                 printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
 141 #endif /* DEBUG */
 142         
 143         /*
 144          * Check to see if we can bailout quickly.
 145          * Also rerun res_init if we failed in the past.
 146          */
 147 
 148         if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
 149                 h_errno = NO_RECOVERY;
 150                 return(-1);
 151         }
 152         
 153         if (_confcheck() == -1) {
 154                 _res.options &= ~RES_INIT;
 155                 h_errno = NO_RECOVERY;
 156                 return(-1);
 157         }
 158 
 159         /*
 160          * Initialize header fields.
 161          */
 162         if ((buf == NULL) || (buflen < sizeof (HEADER)))
 163                 return (-1);
 164 #ifdef SYSV
 165         (void) memset(buf, 0, sizeof (HEADER));
 166 #else
 167         bzero(buf, sizeof (HEADER));
 168 #endif
 169         hp = (HEADER *) buf;
 170         hp->id = htons(++_res.id);
 171         hp->opcode = op;
 172         hp->pr = (_res.options & RES_PRIMARY) != 0;
 173         hp->rd = (_res.options & RES_RECURSE) != 0;
 174         hp->rcode = NOERROR;
 175         cp = (u_char *)(buf + sizeof (HEADER));
 176         buflen -= sizeof (HEADER);
 177         dpp = dnptrs;
 178         *dpp++ = (u_char *)buf;
 179         *dpp++ = NULL;
 180         lastdnptr = dnptrs + sizeof (dnptrs) / sizeof (dnptrs[0]);
 181         /*
 182          * perform opcode specific processing
 183          */
 184         switch (op) {
 185         case QUERY:
 186                 if ((buflen -= QFIXEDSZ) < 0)
 187                         return (-1);
 188                 if ((n = dn_comp((u_char *)dname, cp, buflen,
 189                     dnptrs, lastdnptr)) < 0)
 190                         return (-1);
 191                 cp += n;
 192                 buflen -= n;
 193                 putshort(type, cp);
 194                 cp += sizeof (u_short);
 195                 putshort(class, cp);
 196                 cp += sizeof (u_short);
 197                 hp->qdcount = htons(1);
 198                 if (op == QUERY || data == NULL)
 199                         break;
 200                 /*
 201                  * Make an additional record for completion domain.
 202                  */
 203                 buflen -= RRFIXEDSZ;
 204                 if ((n = dn_comp((u_char *)data, cp, buflen,
 205                     dnptrs, lastdnptr)) < 0)
 206                         return (-1);
 207                 cp += n;
 208                 buflen -= n;
 209                 putshort(T_NULL, cp);
 210                 cp += sizeof (u_short);
 211                 putshort(class, cp);
 212                 cp += sizeof (u_short);
 213                 putlong(0, cp);
 214                 cp += sizeof (u_long);
 215                 putshort(0, cp);
 216                 cp += sizeof (u_short);
 217                 hp->arcount = htons(1);
 218                 break;
 219 
 220         case IQUERY:
 221                 /*
 222                  * Initialize answer section
 223                  */
 224                 if (buflen < 1 + RRFIXEDSZ + datalen)
 225                         return (-1);
 226                 *cp++ = '\0';   /* no domain name */
 227                 putshort(type, cp);
 228                 cp += sizeof (u_short);
 229                 putshort(class, cp);
 230                 cp += sizeof (u_short);
 231                 putlong(0, cp);
 232                 cp += sizeof (u_long);
 233                 putshort(datalen, cp);
 234                 cp += sizeof (u_short);
 235                 if (datalen) {
 236 #ifdef SYSV
 237                         (void) memcpy((void *)cp, (void *)data, datalen);
 238 #else
 239                         bcopy(data, cp, datalen);
 240 #endif
 241                         cp += datalen;
 242                 }
 243                 hp->ancount = htons(1);
 244                 break;
 245 
 246 #ifdef ALLOW_UPDATES
 247         /*
 248          * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
 249          * (Record to be modified is followed by its replacement in msg.)
 250          */
 251         case UPDATEM:
 252         case UPDATEMA:
 253 
 254         case UPDATED:
 255                 /*
 256                  * The res code for UPDATED and UPDATEDA is the same; user
 257                  * calls them differently: specifies data for UPDATED; server
 258                  * ignores data if specified for UPDATEDA.
 259                  */
 260         case UPDATEDA:
 261                 buflen -= RRFIXEDSZ + datalen;
 262                 if ((n = dn_comp((u_char *)dname, cp, buflen,
 263                     dnptrs, lastdnptr)) < 0)
 264                         return (-1);
 265                 cp += n;
 266                 putshort(type, cp);
 267                 cp += sizeof (u_short);
 268                 putshort(class, cp);
 269                 cp += sizeof (u_short);
 270                 putlong(0, cp);
 271                 cp += sizeof (u_long);
 272                 putshort(datalen, cp);
 273                 cp += sizeof (u_short);
 274                 if (datalen) {
 275 #ifdef SYSV
 276                         memcpy((void *)cp, (void *)data, datalen);
 277 #else
 278                         bcopy(data, cp, datalen);
 279 #endif
 280                         cp += datalen;
 281                 }
 282                 if ((op == UPDATED) || (op == UPDATEDA)) {
 283                         hp->ancount = htons(0);
 284                         break;
 285                 }
 286                 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
 287 
 288         case UPDATEA:   /* Add new resource record */
 289                 buflen -= RRFIXEDSZ + datalen;
 290                 if ((n = dn_comp((u_char *)dname, cp, buflen,
 291                     dnptrs, lastdnptr)) < 0)
 292                         return (-1);
 293                 cp += n;
 294                 putshort(newrr->r_type, cp);
 295                 cp += sizeof (u_short);
 296                 putshort(newrr->r_class, cp);
 297                 cp += sizeof (u_short);
 298                 putlong(0, cp);
 299                 cp += sizeof (u_long);
 300                 putshort(newrr->r_size, cp);
 301                 cp += sizeof (u_short);
 302                 if (newrr->r_size) {
 303 #ifdef SYSV
 304                         memcpy((void *)cp, newrr->r_data, newrr->r_size);
 305 #else
 306                         bcopy(newrr->r_data, cp, newrr->r_size);
 307 #endif
 308                         cp += newrr->r_size;
 309                 }
 310                 hp->ancount = htons(0);
 311                 break;
 312 
 313 #endif /* ALLOW_UPDATES */
 314         }
 315         return ((char *)cp - buf);
 316 }