/***********************************************************
        Copyright 1996 by Carnegie Mellon University

                      All Rights Reserved

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 CMU not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/

#include "config.h"
#ifndef DHCPD_H
#define DHCPD_H

#include "hash.h"
/* ANSI function prototypes or empty arg list? */
#ifdef  __STDC__
#define P(args) args
#else
#define P(args) ()
#endif

struct client_info {
	struct shared_bindata 	*cliid;
	struct shared_bindata 	*cliidhw;
	unsigned char 			*req_opts;
	unsigned int			max_len;
	unsigned int 			secs;
	struct in_addr			req_addr;
	struct in_addr			serv_addr;
	struct shared_bindata	*vend;
	struct shared_bindata	*user;
	char					*msg;
	unsigned				clhashcode;
	boolean					cliid_explicit;
	boolean					client_fqdn_option_present; /* the "Client FQDN" option was present (in a packet from client) */
};

struct link_list {
	char *data;
	struct link_list *next;
};


/* What access flags are associated with a pool of dynamic IP addrs? */
#define	DHCP_ACCESS		1
#define	BOOTP_ACCESS	2
#define	ROAMING_ACCESS	4
#define	REG_ACCESS		8
#define UNREG_ACCESS	16
#define	ANY				0x7f

struct cable {
	int						linkcount;
	struct shared_string	*name;
	unsigned long			net;
	unsigned long			mask;
	unsigned char			code;
	struct link_list 		*head;
	struct link_list 		*tail;
	int 					free;
};

struct shared_string_list {
	int 					linkcount,num;
	char					*str[1];
};

struct gateway {
	int						linkcount;
	struct in_addr			addr;
	unsigned long			mask;
	char  					**nets;
	int						num;
	struct in_addr			*proxyaddr;
	unsigned long			*proxymask;
	int						proxynum;
};

struct unknownhost {
	unsigned char 	hlen;
	unsigned char	htype;
	unsigned char 	haddr[BP_CHADDR_LEN];
	struct in_addr	giaddr;
	struct in_addr	from_ip;
	unsigned long	last_seen;
	struct unknownhost *next;
};

	


typedef int (*order_cmpfp) P((char *, char *));

#define DHCPDISCOVER	((unsigned char) 1)
#define DHCPOFFER		((unsigned char) 2)
#define DHCPREQUEST		((unsigned char) 3)
#define DHCPDECLINE		((unsigned char) 4)
#define DHCPACK			((unsigned char) 5)
#define DHCPNACK			((unsigned char) 6)
#define DHCPRELEASE		((unsigned char) 7)
#define DHCPINFORM		((unsigned char) 8)

/* how did the client get the ip address?
   UNKNOWN == not actually a legal value
   RESERVED_FLAG == static via dhcp
   DHCP_FLAG == dynamic via dhcp
   BOOTP_FLAG == dynamic via bootp
   ROAMING_FLAG = no longer used ?
   SYNCH_FLAG == no longer used ?
*/
#define UNKNOWN_FLAG	0x0
#define RESERVED_FLAG	0x1
#define DHCP_FLAG		0x2
#define BOOTP_FLAG		0x3
#define ROAMING_FLAG	0x4
#define SYNCH_FLAG		0x5
static char *codename[] = {
    "UNKNOWN", "RESERVED_FLAG", "DHCP_FLAG", "BOOTP_FLAG", "ROAMING_FLAG", "SYCH_FLAG"
}; 

#ifndef LASTBINDDIR
#define LASTBINDDIR		"/etc/bindings"
#endif
#define DEFAULT_LEASE		21600
#define TIME_OFFSET			60
#define	INFINITY			0xFFFFFFFF

/* flags that comprise the possible values of the :cf: (Client FQDN Option) tag:
    CF_DONT_ANSWER == the DHCP server should never send a Client FQDN option to the client.
	CF_STATIC == all IP addresses are static as far as Dynamic DNS is concerned.
			     The Client is not permitted to issue Dynamic DNS updates, and the
			     the DHCP server will not attempt to do so either (default).
	CF_ALL_FLAGS == all the nonzero flags OR'd together
*/
#define CF_DONT_ANSWER 0x0
#define CF_STATIC	0x1
/* add other CF_* flags here */
#define CF_ALL_FLAGS (CF_STATIC)

extern unsigned int discovers_received,offers_sent;
extern unsigned int requests_received,acks_sent,nacks_sent;
extern unsigned int declines_received;
extern unsigned int releases_received;
extern unsigned int informs_received;
extern unsigned int leases,ips_expired,ips_reclaimed;
extern unsigned int num_unknown;


extern char dhcp_msg_type();
extern boolean ipcmp P((hash_datum*, hash_datum*));
extern boolean cliidhwlookcmp P((hash_datum*, hash_datum*));
extern boolean boundcliidcmp P((hash_datum*, hash_datum*));
extern boolean cliidcmp P((hash_datum*, hash_datum*));
extern boolean inaddrcmp P((hash_datum *, hash_datum *));
extern void dhcp_garbage_collect();
extern void order_delete();
extern hash_tbl *boundhshtbl;
extern hash_tbl *ipboundhshtbl;
extern hash_tbl *known_serverids_hshtbl;
extern int known_serverids_hshtbl_inuse;
extern struct unknownhost *unknown;
extern unsigned long now;
extern unsigned long dhcp_alarm;
extern unsigned long gcinterval;
extern unsigned long expire_infinite_dynamics;
extern unsigned int delay_reply_dhcpoffer;
extern unsigned int delay_reply_dhcpack;
extern unsigned int delay_reply_dhcpnak;
extern unsigned int delay_reply_bootpreply;
extern unsigned int delay_reply_default;
extern void free_client_info();
extern void free_inaddr P((hash_datum *)); 
boolean is_known_server_identifier P((struct in_addr *));
extern ping();
extern pid_t pid;
extern unsigned long readtabinterval;
extern unsigned long readconfinterval;


#define BINDATA_EQ(a,b) (((a)->length)==((b)->length) && \
		!bcmp((a)->data,(b)->data,(a)->length))
#define CLIID_EQ BINDATA_EQ

#endif
