/* Linux DNS client library implementation Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> Copyright (C) 2006 Gerald Carter <jerry@samba.org> ** NOTE! The following LGPL license applies to the libaddns ** library. This does NOT imply that all of Samba is released ** under the LGPL This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #ifndef _DNS_H #define _DNS_H #include "../replace/replace.h" #include "system/network.h" /* make sure we have included the correct config.h */ #ifndef NO_CONFIG_H /* for some tests */ #ifndef CONFIG_H_IS_FROM_SAMBA #error "make sure you have removed all config.h files from standalone builds!" #error "the included config.h isn't from samba!" #endif #endif /* NO_CONFIG_H */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <time.h> #include <string.h> #include <errno.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdarg.h> #ifdef HAVE_UUID_UUID_H #include <uuid/uuid.h> #endif #ifdef HAVE_KRB5_H #include <krb5.h> #endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> #ifndef int16 #define int16 int16_t #endif #ifndef uint16 #define uint16 uint16_t #endif #ifndef int32 #define int32 int32_t #endif #ifndef uint32 #define uint32 uint32_t #endif #endif #ifdef HAVE_KRB5_H #include <krb5.h> #endif #if HAVE_GSSAPI_GSSAPI_H #include <gssapi/gssapi.h> #elif HAVE_GSSAPI_GSSAPI_GENERIC_H #include <gssapi/gssapi_generic.h> #elif HAVE_GSSAPI_H #include <gssapi.h> #endif #if defined(HAVE_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_GENERIC_H) #define HAVE_GSSAPI_SUPPORT 1 #endif #include <talloc.h> #if 0 Disable these now we have checked all code paths and ensured NULL returns on zero request. JRA. void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name); void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name); void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name); void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name); void *talloc_zeronull(const void *context, size_t size, const char *name); #define TALLOC(ctx, size) talloc_zeronull(ctx, size, __location__) #define TALLOC_P(ctx, type) (type *)talloc_zeronull(ctx, sizeof(type), #type) #define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array_zeronull(ctx, sizeof(type), count, #type) #define TALLOC_MEMDUP(ctx, ptr, size) _talloc_memdup_zeronull(ctx, ptr, size, __location__) #define TALLOC_ZERO(ctx, size) _talloc_zero_zeronull(ctx, size, __location__) #define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero_zeronull(ctx, sizeof(type), #type) #define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array_zeronull(ctx, sizeof(type), count, #type) #define TALLOC_SIZE(ctx, size) talloc_zeronull(ctx, size, __location__) #define TALLOC_ZERO_SIZE(ctx, size) _talloc_zero_zeronull(ctx, size, __location__) #else #define TALLOC(ctx, size) talloc_named_const(ctx, size, __location__) #define TALLOC_P(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) #define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) #define TALLOC_MEMDUP(ctx, ptr, size) _talloc_memdup(ctx, ptr, size, __location__) #define TALLOC_ZERO(ctx, size) _talloc_zero(ctx, size, __location__) #define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) #define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) #define TALLOC_SIZE(ctx, size) talloc_named_const(ctx, size, __location__) #define TALLOC_ZERO_SIZE(ctx, size) _talloc_zero(ctx, size, __location__) #endif #define TALLOC_REALLOC(ctx, ptr, count) _talloc_realloc(ctx, ptr, count, __location__) #define TALLOC_REALLOC_ARRAY(ctx, ptr, type, count) (type *)_talloc_realloc_array(ctx, ptr, sizeof(type), count, #type) #define talloc_destroy(ctx) talloc_free(ctx) #ifndef TALLOC_FREE #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) #endif /******************************************************************* Type definitions for int16, int32, uint16 and uint32. Needed for Samba coding style *******************************************************************/ #ifndef uint8 # define uint8 unsigned char #endif #if !defined(int16) && !defined(HAVE_INT16_FROM_RPC_RPC_H) # if (SIZEOF_SHORT == 4) # define int16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; # else /* SIZEOF_SHORT != 4 */ # define int16 short # endif /* SIZEOF_SHORT != 4 */ /* needed to work around compile issue on HP-UX 11.x */ # define _INT16 1 #endif /* * Note we duplicate the size tests in the unsigned * case as int16 may be a typedef from rpc/rpc.h */ #if !defined(uint16) && !defined(HAVE_UINT16_FROM_RPC_RPC_H) # if (SIZEOF_SHORT == 4) # define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; # else /* SIZEOF_SHORT != 4 */ # define uint16 unsigned short # endif /* SIZEOF_SHORT != 4 */ #endif #if !defined(int32) && !defined(HAVE_INT32_FROM_RPC_RPC_H) # if (SIZEOF_INT == 4) # define int32 int # elif (SIZEOF_LONG == 4) # define int32 long # elif (SIZEOF_SHORT == 4) # define int32 short # else /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */ # define int32 int # endif # ifndef _INT32 /* needed to work around compile issue on HP-UX 11.x */ # define _INT32 1 # endif #endif /* * Note we duplicate the size tests in the unsigned * case as int32 may be a typedef from rpc/rpc.h */ #if !defined(uint32) && !defined(HAVE_UINT32_FROM_RPC_RPC_H) # if (SIZEOF_INT == 4) # define uint32 unsigned int # elif (SIZEOF_LONG == 4) # define uint32 unsigned long # elif (SIZEOF_SHORT == 4) # define uint32 unsigned short # else /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */ # define uint32 unsigned # endif #endif /* * check for 8 byte long long */ #if !defined(uint64) # if (SIZEOF_LONG == 8) # define uint64 unsigned long # elif (SIZEOF_LONG_LONG == 8) # define uint64 unsigned long long # endif /* don't lie. If we don't have it, then don't use it */ #endif /* needed on Sun boxes */ #ifndef INADDR_NONE #define INADDR_NONE 0xFFFFFFFF #endif #include "dnserr.h" #define DNS_TCP 1 #define DNS_UDP 2 #define DNS_OPCODE_UPDATE 1 /* DNS Class Types */ #define DNS_CLASS_IN 1 #define DNS_CLASS_ANY 255 #define DNS_CLASS_NONE 254 /* DNS RR Types */ #define DNS_RR_A 1 #define DNS_TCP_PORT 53 #define DNS_UDP_PORT 53 #define QTYPE_A 1 #define QTYPE_NS 2 #define QTYPE_MD 3 #define QTYPE_CNAME 5 #define QTYPE_SOA 6 #define QTYPE_ANY 255 #define QTYPE_TKEY 249 #define QTYPE_TSIG 250 /* MF 4 a mail forwarder (Obsolete - use MX) CNAME 5 the canonical name for an alias SOA 6 marks the start of a zone of authority MB 7 a mailbox domain name (EXPERIMENTAL) MG 8 a mail group member (EXPERIMENTAL) MR 9 a mail rename domain name (EXPERIMENTAL) NULL 10 a null RR (EXPERIMENTAL) WKS 11 a well known service description PTR 12 a domain name pointer HINFO 13 host information MINFO 14 mailbox or mail list information MX 15 mail exchange TXT 16 text strings */ #define QR_QUERY 0x0000 #define QR_RESPONSE 0x0001 #define OPCODE_QUERY 0x00 #define OPCODE_IQUERY 0x01 #define OPCODE_STATUS 0x02 #define AA 1 #define RECURSION_DESIRED 0x01 #define RCODE_NOERROR 0 #define RCODE_FORMATERROR 1 #define RCODE_SERVER_FAILURE 2 #define RCODE_NAME_ERROR 3 #define RCODE_NOTIMPLEMENTED 4 #define RCODE_REFUSED 5 #define SENDBUFFER_SIZE 65536 #define RECVBUFFER_SIZE 65536 /* * TKEY Modes from rfc2930 */ #define DNS_TKEY_MODE_SERVER 1 #define DNS_TKEY_MODE_DH 2 #define DNS_TKEY_MODE_GSSAPI 3 #define DNS_TKEY_MODE_RESOLVER 4 #define DNS_TKEY_MODE_DELETE 5 #define DNS_ONE_DAY_IN_SECS 86400 #define DNS_TEN_HOURS_IN_SECS 36000 #define SOCKET_ERROR -1 #define INVALID_SOCKET -1 #define DNS_NO_ERROR 0 #define DNS_FORMAT_ERROR 1 #define DNS_SERVER_FAILURE 2 #define DNS_NAME_ERROR 3 #define DNS_NOT_IMPLEMENTED 4 #define DNS_REFUSED 5 typedef long HANDLE; enum dns_ServerType { DNS_SRV_ANY, DNS_SRV_WIN2000, DNS_SRV_WIN2003 }; struct dns_domain_label { struct dns_domain_label *next; char *label; size_t len; }; struct dns_domain_name { struct dns_domain_label *pLabelList; }; struct dns_question { struct dns_domain_name *name; uint16 q_type; uint16 q_class; }; /* * Before changing the definition of dns_zone, look * dns_marshall_update_request(), we rely on this being the same as * dns_question right now. */ struct dns_zone { struct dns_domain_name *name; uint16 z_type; uint16 z_class; }; struct dns_rrec { struct dns_domain_name *name; uint16 type; uint16 r_class; uint32 ttl; uint16 data_length; uint8 *data; }; struct dns_tkey_record { struct dns_domain_name *algorithm; time_t inception; time_t expiration; uint16 mode; uint16 error; uint16 key_length; uint8 *key; }; struct dns_request { uint16 id; uint16 flags; uint16 num_questions; uint16 num_answers; uint16 num_auths; uint16 num_additionals; struct dns_question **questions; struct dns_rrec **answers; struct dns_rrec **auths; struct dns_rrec **additionals; }; /* * Before changing the definition of dns_update_request, look * dns_marshall_update_request(), we rely on this being the same as * dns_request right now. */ struct dns_update_request { uint16 id; uint16 flags; uint16 num_zones; uint16 num_preqs; uint16 num_updates; uint16 num_additionals; struct dns_zone **zones; struct dns_rrec **preqs; struct dns_rrec **updates; struct dns_rrec **additionals; }; struct dns_connection { int32 hType; int s; struct sockaddr RecvAddr; }; struct dns_buffer { uint8 *data; size_t size; size_t offset; DNS_ERROR error; }; /* from dnsutils.c */ DNS_ERROR dns_domain_name_from_string( TALLOC_CTX *mem_ctx, const char *pszDomainName, struct dns_domain_name **presult ); char *dns_generate_keyname( TALLOC_CTX *mem_ctx ); /* from dnsrecord.c */ DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name, uint16 q_type, uint16 q_class, struct dns_request **preq ); DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name, struct dns_update_request **preq ); DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone, const char *host, int num_ips, const struct sockaddr_storage *sslist, struct dns_update_request **preq); DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name, uint16 type, uint16 r_class, uint32 ttl, uint16 data_length, uint8 *data, struct dns_rrec **prec); DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, uint16 *num_records, struct dns_rrec ***records); DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname, const char *algorithm_name, time_t inception, time_t expiration, uint16 mode, uint16 error, uint16 key_length, const uint8 *key, struct dns_rrec **prec); DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx, const char *name, const struct sockaddr_storage *ip, struct dns_rrec **prec); DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name, uint16 type, uint16 r_class, struct dns_rrec **prec); DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx, const char *name, uint32 type, struct dns_rrec **prec); DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host, uint32 ttl, const struct sockaddr_storage *pss, struct dns_rrec **prec); DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, struct dns_tkey_record **ptkey); DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname, const char *algorithm_name, time_t time_signed, uint16 fudge, uint16 mac_length, const uint8 *mac, uint16 original_id, uint16 error, struct dns_rrec **prec); DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, uint16 *num_records, struct dns_rrec ***records); DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx, const char *domainname, const char *hostname, const struct sockaddr_storage *ip_addr, size_t num_adds, struct dns_update_request **preq); /* from dnssock.c */ DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType, TALLOC_CTX *mem_ctx, struct dns_connection **conn ); DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf); DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn, struct dns_buffer **presult); DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn, const struct dns_request *req, struct dns_request **resp); DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn, struct dns_update_request *up_req, struct dns_update_request **up_resp); /* from dnsmarshall.c */ struct dns_buffer *dns_create_buffer(TALLOC_CTX *mem_ctx); void dns_marshall_buffer(struct dns_buffer *buf, const uint8 *data, size_t len); void dns_marshall_uint16(struct dns_buffer *buf, uint16 val); void dns_marshall_uint32(struct dns_buffer *buf, uint32 val); void dns_unmarshall_buffer(struct dns_buffer *buf, uint8 *data, size_t len); void dns_unmarshall_uint16(struct dns_buffer *buf, uint16 *val); void dns_unmarshall_uint32(struct dns_buffer *buf, uint32 *val); void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx, struct dns_buffer *buf, struct dns_domain_name **pname); void dns_marshall_domain_name(struct dns_buffer *buf, const struct dns_domain_name *name); void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx, struct dns_buffer *buf, struct dns_domain_name **pname); DNS_ERROR dns_marshall_request(TALLOC_CTX *mem_ctx, const struct dns_request *req, struct dns_buffer **pbuf); DNS_ERROR dns_unmarshall_request(TALLOC_CTX *mem_ctx, struct dns_buffer *buf, struct dns_request **preq); DNS_ERROR dns_marshall_update_request(TALLOC_CTX *mem_ctx, struct dns_update_request *update, struct dns_buffer **pbuf); DNS_ERROR dns_unmarshall_update_request(TALLOC_CTX *mem_ctx, struct dns_buffer *buf, struct dns_update_request **pupreq); struct dns_request *dns_update2request(struct dns_update_request *update); struct dns_update_request *dns_request2update(struct dns_request *request); uint16 dns_response_code(uint16 flags); /* from dnsgss.c */ #ifdef HAVE_GSSAPI_SUPPORT void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat ); DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm, const char *servername, const char *keyname, gss_ctx_id_t *gss_ctx, enum dns_ServerType srv_type ); DNS_ERROR dns_sign_update(struct dns_update_request *req, gss_ctx_id_t gss_ctx, const char *keyname, const char *algorithmname, time_t time_signed, uint16 fudge); #endif /* HAVE_GSSAPI_SUPPORT */ #endif /* _DNS_H */