/*
 * lib/krb5/os/dnsglue.h
 *
 * Copyright 2004 by the Massachusetts Institute of Technology.
 * All Rights Reserved.
 *
 * Export of this software from the United States of America may
 *   require a specific license from the United States Government.
 *   It is the responsibility of any person or organization contemplating
 *   export to obtain such a license before exporting.
 * 
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 * distribute this software and its documentation for any purpose and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of M.I.T. not be used in advertising or publicity pertaining
 * to distribution of the software without specific, written prior
 * permission.  Furthermore if you modify this software you must label
 * your software as modified software and not distribute it in such a
 * fashion that it might be confused with the original M.I.T. software.
 * M.I.T. makes no representations about the suitability of
 * this software for any purpose.  It is provided "as is" without express
 * or implied warranty.
 *
 * Glue layer for DNS resolver, to make parsing of replies easier
 * whether we are using BIND 4, 8, or 9.
 */

/*
 * BIND 4 doesn't have the ns_initparse() API, so we need to do some
 * manual parsing via the HEADER struct.  BIND 8 does have
 * ns_initparse(), but has enums for the various protocol constants
 * rather than the BIND 4 macros.  BIND 9 (at least on Mac OS X
 * Panther) appears to disable res_nsearch() if BIND_8_COMPAT is
 * defined (which is necessary to obtain the HEADER struct).
 *
 * We use ns_initparse() if available at all, and never define
 * BIND_8_COMPAT.  If there is no ns_initparse(), we do manual parsing
 * by using the HEADER struct.
 */

#ifndef KRB5_DNSGLUE_H
#define KRB5_DNSGLUE_H

#ifdef KRB5_DNS_LOOKUP

#define NEED_SOCKETS
#include "k5-int.h"
#include "os-proto.h"
#ifdef WSHELPER
#include <wshelper.h>
#else /* WSHELPER */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h>
#endif /* WSHELPER */

#if HAVE_SYS_PARAM_H
#include <sys/param.h>		/* for MAXHOSTNAMELEN */
#endif

#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64	/* if we can't find it elswhere */
#endif

#ifndef MAXDNAME

#ifdef NS_MAXDNAME
#define MAXDNAME NS_MAXDNAME
#else
#ifdef MAXLABEL
#define MAXDNAME (16 * MAXLABEL)
#else
#define MAXDNAME (16 * MAXHOSTNAMELEN)
#endif
#endif

#endif

#if HAVE_NS_INITPARSE
/*
 * Solaris 7 has ns_rr_cl rather than ns_rr_class.
 */
#if !defined(ns_rr_class) && defined(ns_rr_cl)
#define ns_rr_class ns_rr_cl
#endif
#endif

#if HAVE_RES_NSEARCH
/*
 * Some BIND 8 / BIND 9 implementations disable the BIND 4 style
 * constants.
 */
#ifndef C_IN
#define C_IN ns_c_in
#endif
#ifndef T_SRV
#define T_SRV ns_t_srv
#endif
#ifndef T_TXT
#define T_TXT ns_t_txt
#endif

#else  /* !HAVE_RES_NSEARCH */

/*
 * Some BIND implementations might be old enough to lack these.
 */
#ifndef T_TXT
#define T_TXT 15
#endif
#ifndef T_SRV
#define T_SRV 33
#endif

#endif /* HAVE_RES_NSEARCH */

/*
 * INCR_OK
 *
 * Given moving pointer PTR offset from BASE, return true if adding
 * INCR to PTR doesn't move it PTR than MAX bytes from BASE.
 */
#define INCR_OK(base, max, ptr, incr)				\
    ((incr) <= (max) - ((const unsigned char *)(ptr)		\
			- (const unsigned char *)(base)))

/*
 * SAFE_GETUINT16
 *
 * Given PTR offset from BASE, if at least INCR bytes are safe to
 * read, get network byte order uint16 into S, and increment PTR.  On
 * failure, goto LABEL.
 */

#define SAFE_GETUINT16(base, max, ptr, incr, s, label)	\
    do {						\
	if (!INCR_OK(base, max, ptr, incr)) goto label;	\
	(s) = (unsigned short)(p)[0] << 8		\
	    | (unsigned short)(p)[1];			\
	(p) += (incr);					\
    } while (0)

struct krb5int_dns_state;

int krb5int_dns_init(struct krb5int_dns_state **, char *, int, int);
int krb5int_dns_nextans(struct krb5int_dns_state *,
			const unsigned char **, int *);
int krb5int_dns_expand(struct krb5int_dns_state *,
		       const unsigned char *, char *, int);
void krb5int_dns_fini(struct krb5int_dns_state *);

#endif /* KRB5_DNS_LOOKUP */
#endif /* !defined(KRB5_DNSGLUE_H) */
