Back to index

glibc  2.9
res_data.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1995-1999 by Internet Software Consortium.
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
00009  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00010  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
00011  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00012  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00013  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00014  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00015  * SOFTWARE.
00016  */
00017 
00018 #if defined(LIBC_SCCS) && !defined(lint)
00019 static const char rcsid[] = "$BINDId: res_data.c,v 8.17 1999/10/13 17:11:31 vixie Exp $";
00020 #endif /* LIBC_SCCS and not lint */
00021 
00022 #include <sys/types.h>
00023 #include <sys/param.h>
00024 #include <sys/socket.h>
00025 #include <sys/time.h>
00026 
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 #include <arpa/nameser.h>
00030 
00031 #include <ctype.h>
00032 #include <netdb.h>
00033 #include <resolv.h>
00034 #ifdef BIND_UPDATE
00035 #include <res_update.h>
00036 #endif
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <unistd.h>
00041 
00042 const char *_res_opcodes[] = {
00043        "QUERY",
00044        "IQUERY",
00045        "CQUERYM",
00046        "CQUERYU",    /* experimental */
00047        "NOTIFY",     /* experimental */
00048        "UPDATE",
00049        "6",
00050        "7",
00051        "8",
00052        "9",
00053        "10",
00054        "11",
00055        "12",
00056        "13",
00057        "ZONEINIT",
00058        "ZONEREF",
00059 };
00060 libresolv_hidden_data_def (_res_opcodes)
00061 
00062 #ifdef BIND_UPDATE
00063 const char *_res_sectioncodes[] attribute_hidden = {
00064        "ZONE",
00065        "PREREQUISITES",
00066        "UPDATE",
00067        "ADDITIONAL",
00068 };
00069 #endif
00070 
00071 #ifndef __BIND_NOSTATIC
00072 #ifdef _LIBC
00073 /* The definition has been moved to res_libc.c.  */
00074 #else
00075 #undef _res
00076 struct __res_state _res
00077 # if defined(__BIND_RES_TEXT)
00078        = { RES_TIMEOUT, }   /* Motorola, et al. */
00079 # endif
00080         ;
00081 #endif
00082 
00083 /* Proto. */
00084 #ifndef _LIBC
00085 int  res_ourserver_p(const res_state, const struct sockaddr_in *);
00086 void res_pquery(const res_state, const u_char *, int, FILE *);
00087 #endif
00088 
00089 #ifndef _LIBC
00090 /* Moved to res_libc.c since res_init() should go into libc.so but the
00091    rest of this file not.  */
00092 int
00093 res_init(void) {
00094        extern int __res_vinit(res_state, int);
00095 
00096        /*
00097         * These three fields used to be statically initialized.  This made
00098         * it hard to use this code in a shared library.  It is necessary,
00099         * now that we're doing dynamic initialization here, that we preserve
00100         * the old semantics: if an application modifies one of these three
00101         * fields of _res before res_init() is called, res_init() will not
00102         * alter them.  Of course, if an application is setting them to
00103         * _zero_ before calling res_init(), hoping to override what used
00104         * to be the static default, we can't detect it and unexpected results
00105         * will follow.  Zero for any of these fields would make no sense,
00106         * so one can safely assume that the applications were already getting
00107         * unexpected results.
00108         *
00109         * _res.options is tricky since some apps were known to diddle the bits
00110         * before res_init() was first called. We can't replicate that semantic
00111         * with dynamic initialization (they may have turned bits off that are
00112         * set in RES_DEFAULT).  Our solution is to declare such applications
00113         * "broken".  They could fool us by setting RES_INIT but none do (yet).
00114         */
00115        if (!_res.retrans)
00116               _res.retrans = RES_TIMEOUT;
00117        if (!_res.retry)
00118               _res.retry = 4;
00119        if (!(_res.options & RES_INIT))
00120               _res.options = RES_DEFAULT;
00121 
00122        /*
00123         * This one used to initialize implicitly to zero, so unless the app
00124         * has set it to something in particular, we can randomize it now.
00125         */
00126        if (!_res.id)
00127               _res.id = res_randomid();
00128 
00129        return (__res_vinit(&_res, 1));
00130 }
00131 #endif
00132 
00133 void
00134 p_query(const u_char *msg) {
00135        fp_query(msg, stdout);
00136 }
00137 
00138 void
00139 fp_query(const u_char *msg, FILE *file) {
00140        fp_nquery(msg, PACKETSZ, file);
00141 }
00142 libresolv_hidden_def (fp_query)
00143 
00144 void
00145 fp_nquery(const u_char *msg, int len, FILE *file) {
00146        if (__res_maybe_init (&_res, 0) == -1)
00147               return;
00148 
00149        res_pquery(&_res, msg, len, file);
00150 }
00151 libresolv_hidden_def (fp_nquery)
00152 
00153 int
00154 res_mkquery(int op,                /* opcode of query */
00155            const char *dname,             /* domain name */
00156            int class, int type,    /* class and type of query */
00157            const u_char *data,            /* resource record data */
00158            int datalen,            /* length of data */
00159            const u_char *newrr_in, /* new rr for modify or append */
00160            u_char *buf,            /* buffer to put query */
00161            int buflen)                    /* size of buffer */
00162 {
00163        if (__res_maybe_init (&_res, 1) == -1) {
00164               RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
00165               return (-1);
00166        }
00167        return (res_nmkquery(&_res, op, dname, class, type,
00168                           data, datalen,
00169                           newrr_in, buf, buflen));
00170 }
00171 
00172 #ifdef BIND_UPDATE
00173 int
00174 res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
00175        if (__res_maybe_init (&_res, 1) == -1) {
00176               RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
00177               return (-1);
00178        }
00179 
00180        return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
00181 }
00182 #endif
00183 
00184 int
00185 res_query(const char *name, /* domain name */
00186          int class, int type,      /* class and type of query */
00187          u_char *answer,    /* buffer to put answer */
00188          int anslen)        /* size of answer buffer */
00189 {
00190        if (__res_maybe_init (&_res, 1) == -1) {
00191               RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
00192               return (-1);
00193        }
00194        return (res_nquery(&_res, name, class, type, answer, anslen));
00195 }
00196 
00197 void
00198 res_send_setqhook(res_send_qhook hook) {
00199        _res.qhook = hook;
00200 }
00201 
00202 void
00203 res_send_setrhook(res_send_rhook hook) {
00204        _res.rhook = hook;
00205 }
00206 
00207 int
00208 res_isourserver(const struct sockaddr_in *inp) {
00209        return (res_ourserver_p(&_res, (const struct sockaddr_in6 *) inp));
00210 }
00211 
00212 int
00213 res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
00214        if (__res_maybe_init (&_res, 1) == -1) {
00215               /* errno should have been set by res_init() in this case. */
00216               return (-1);
00217        }
00218 
00219        return (res_nsend(&_res, buf, buflen, ans, anssiz));
00220 }
00221 
00222 #ifndef _LIBC
00223 int
00224 res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
00225               u_char *ans, int anssiz)
00226 {
00227        if (__res_maybe_init (&_res, 1) == -1) {
00228               /* errno should have been set by res_init() in this case. */
00229               return (-1);
00230        }
00231 
00232        return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
00233 }
00234 #endif
00235 
00236 void
00237 res_close(void) {
00238 #ifdef _LIBC
00239        /*
00240         * Some stupid programs out there call res_close() before res_init().
00241         * Since _res._vcsock isn't explicitly initialized, these means that
00242         * we could do a close(0), which might lead to some security problems.
00243         * Therefore we check if res_init() was called before by looking at
00244         * the RES_INIT bit in _res.options.  If it hasn't been set we bail out
00245         * early.  */
00246        if ((_res.options & RES_INIT) == 0)
00247          return;
00248 #endif
00249        /* We don't free the name server addresses because we never
00250           did it and it would be done implicitly on shutdown.  */
00251        __res_iclose(&_res, false);
00252 }
00253 
00254 #ifdef BIND_UPDATE
00255 int
00256 res_update(ns_updrec *rrecp_in) {
00257        if (__res_maybe_init (&_res, 1) == -1) {
00258               RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
00259               return (-1);
00260        }
00261 
00262        return (res_nupdate(&_res, rrecp_in, NULL));
00263 }
00264 #endif
00265 
00266 int
00267 res_search(const char *name,       /* domain name */
00268           int class, int type,     /* class and type of query */
00269           u_char *answer,   /* buffer to put answer */
00270           int anslen)              /* size of answer */
00271 {
00272        if (__res_maybe_init (&_res, 1) == -1) {
00273               RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
00274               return (-1);
00275        }
00276 
00277        return (res_nsearch(&_res, name, class, type, answer, anslen));
00278 }
00279 
00280 int
00281 res_querydomain(const char *name,
00282               const char *domain,
00283               int class, int type, /* class and type of query */
00284               u_char *answer,             /* buffer to put answer */
00285               int anslen)          /* size of answer */
00286 {
00287        if (__res_maybe_init (&_res, 1) == -1) {
00288               RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
00289               return (-1);
00290        }
00291 
00292        return (res_nquerydomain(&_res, name, domain,
00293                              class, type,
00294                              answer, anslen));
00295 }
00296 
00297 const char *
00298 hostalias(const char *name) {
00299        static char abuf[MAXDNAME];
00300 
00301        return (res_hostalias(&_res, name, abuf, sizeof abuf));
00302 }
00303 libresolv_hidden_def (hostalias)
00304 
00305 #ifdef ultrix
00306 int
00307 local_hostname_length(const char *hostname) {
00308        int len_host, len_domain;
00309 
00310        if (!*_res.defdname)
00311               res_init();
00312        len_host = strlen(hostname);
00313        len_domain = strlen(_res.defdname);
00314        if (len_host > len_domain &&
00315            !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
00316            hostname[len_host - len_domain - 1] == '.')
00317               return (len_host - len_domain - 1);
00318        return (0);
00319 }
00320 #endif /*ultrix*/
00321 
00322 #endif
00323 
00324 
00325 #include <shlib-compat.h>
00326 
00327 #if SHLIB_COMPAT(libresolv, GLIBC_2_0, GLIBC_2_2)
00328 # undef res_mkquery
00329 # undef res_query
00330 # undef res_querydomain
00331 # undef res_search
00332 weak_alias (__res_mkquery, res_mkquery);
00333 weak_alias (__res_query, res_query);
00334 weak_alias (__res_querydomain, res_querydomain);
00335 weak_alias (__res_search, res_search);
00336 #endif