mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-31 14:25:41 +00:00
DHCP Server Daemon
This commit is contained in:
197
common/alloc.c
Normal file
197
common/alloc.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/* alloc.c
|
||||
|
||||
Memory allocation...
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
|
||||
struct dhcp_packet *dhcp_free_list;
|
||||
struct packet *packet_free_list;
|
||||
|
||||
VOIDPTR dmalloc (size, name)
|
||||
int size;
|
||||
char *name;
|
||||
{
|
||||
VOIDPTR foo = (VOIDPTR)malloc (size);
|
||||
if (!foo)
|
||||
warn ("No memory for %s.\n");
|
||||
return foo;
|
||||
}
|
||||
|
||||
void dfree (ptr, name)
|
||||
VOIDPTR ptr;
|
||||
char *name;
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
struct packet *new_packet (name)
|
||||
char *name;
|
||||
{
|
||||
struct packet *rval;
|
||||
rval = (struct packet *)dmalloc (sizeof (struct packet), name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
struct dhcp_packet *new_dhcp_packet (name)
|
||||
char *name;
|
||||
{
|
||||
struct dhcp_packet *rval;
|
||||
rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet),
|
||||
name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
struct tree *new_tree (name)
|
||||
char *name;
|
||||
{
|
||||
struct tree *rval = dmalloc (sizeof (struct tree), name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
struct tree_cache *new_tree_cache (name)
|
||||
char *name;
|
||||
{
|
||||
struct tree_cache *rval = dmalloc (sizeof (struct tree_cache), name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
struct hash_table *new_hash_table (count, name)
|
||||
int count;
|
||||
char *name;
|
||||
{
|
||||
struct hash_table *rval = dmalloc (sizeof (struct hash_table)
|
||||
- (DEFAULT_HASH_SIZE
|
||||
* sizeof (struct hash_bucket *))
|
||||
+ (count
|
||||
* sizeof (struct hash_bucket *)),
|
||||
name);
|
||||
rval -> hash_count = count;
|
||||
return rval;
|
||||
}
|
||||
|
||||
struct hash_bucket *new_hash_bucket (name)
|
||||
char *name;
|
||||
{
|
||||
struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
struct lease *new_leases (n, name)
|
||||
int n;
|
||||
char *name;
|
||||
{
|
||||
struct lease *rval = dmalloc (n * sizeof (struct lease), name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
struct lease *new_lease (name)
|
||||
char *name;
|
||||
{
|
||||
struct lease *rval = dmalloc (sizeof (struct lease), name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
struct subnet *new_subnet (name)
|
||||
char *name;
|
||||
{
|
||||
struct subnet *rval = dmalloc (sizeof (struct subnet), name);
|
||||
return rval;
|
||||
}
|
||||
|
||||
void free_subnet (ptr, name)
|
||||
struct subnet *ptr;
|
||||
char *name;
|
||||
{
|
||||
dfree ((VOIDPTR)ptr, name);
|
||||
}
|
||||
|
||||
void free_lease (ptr, name)
|
||||
struct lease *ptr;
|
||||
char *name;
|
||||
{
|
||||
dfree ((VOIDPTR)ptr, name);
|
||||
}
|
||||
|
||||
void free_hash_bucket (ptr, name)
|
||||
struct hash_bucket *ptr;
|
||||
char *name;
|
||||
{
|
||||
dfree ((VOIDPTR)ptr, name);
|
||||
}
|
||||
|
||||
void free_hash_table (ptr, name)
|
||||
struct hash_table *ptr;
|
||||
char *name;
|
||||
{
|
||||
dfree ((VOIDPTR)ptr, name);
|
||||
}
|
||||
|
||||
void free_tree_cache (ptr, name)
|
||||
struct tree_cache *ptr;
|
||||
char *name;
|
||||
{
|
||||
dfree ((VOIDPTR)ptr, name);
|
||||
}
|
||||
|
||||
void free_packet (ptr, name)
|
||||
struct packet *ptr;
|
||||
char *name;
|
||||
{
|
||||
dfree ((VOIDPTR)ptr, name);
|
||||
}
|
||||
|
||||
void free_dhcp_packet (ptr, name)
|
||||
struct dhcp_packet *ptr;
|
||||
char *name;
|
||||
{
|
||||
dfree ((VOIDPTR)ptr, name);
|
||||
}
|
||||
|
||||
void free_tree (ptr, name)
|
||||
struct tree *ptr;
|
||||
char *name;
|
||||
{
|
||||
dfree ((VOIDPTR)ptr, name);
|
||||
}
|
280
common/conflex.c
Normal file
280
common/conflex.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/* conflex.c
|
||||
|
||||
Lexical scanner for dhcpd config file... */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
#include "dhctoken.h"
|
||||
#include <ctype.h>
|
||||
|
||||
static int line;
|
||||
static int lpos;
|
||||
int tlpos;
|
||||
int tline;
|
||||
static int token;
|
||||
static int ugflag;
|
||||
static char *tval;
|
||||
static char tokbuf [1500];
|
||||
|
||||
static int get_char PROTO ((FILE *));
|
||||
static int get_token PROTO ((FILE *));
|
||||
static void skip_to_eol PROTO ((FILE *));
|
||||
static int read_string PROTO ((FILE *));
|
||||
static int read_number PROTO ((int, FILE *));
|
||||
static int read_num_or_atom PROTO ((int, FILE *));
|
||||
static int intern PROTO ((char *, int));
|
||||
|
||||
static int get_char (cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
char c = getc (cfile);
|
||||
if (!ugflag) {
|
||||
if (c == EOL) {
|
||||
line++;
|
||||
lpos = 1;
|
||||
} else {
|
||||
lpos++;
|
||||
}
|
||||
} else
|
||||
ugflag = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int get_token (cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
int c;
|
||||
int i;
|
||||
int ttok;
|
||||
|
||||
do {
|
||||
c = get_char (cfile);
|
||||
if (isascii (c) && isspace (c))
|
||||
continue;
|
||||
if (c == '#') {
|
||||
skip_to_eol (cfile);
|
||||
continue;
|
||||
}
|
||||
tlpos = lpos;
|
||||
tline = line;
|
||||
if (c == '"') {
|
||||
ttok = read_string (cfile);
|
||||
break;
|
||||
}
|
||||
if (isascii (c) && isdigit (c)) {
|
||||
ttok = read_number (c, cfile);
|
||||
break;
|
||||
} else if (isascii (c) && isalpha (c)) {
|
||||
ttok = read_num_or_atom (c, cfile);
|
||||
break;
|
||||
} else {
|
||||
tval = 0;
|
||||
ttok = c;
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
return ttok;
|
||||
}
|
||||
|
||||
int next_token (rval, cfile)
|
||||
char **rval;
|
||||
FILE *cfile;
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (token) {
|
||||
rv = token;
|
||||
token = 0;
|
||||
} else {
|
||||
rv = get_token (cfile);
|
||||
}
|
||||
if (rval)
|
||||
*rval = tval;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int peek_token (rval, cfile)
|
||||
char **rval;
|
||||
FILE *cfile;
|
||||
{
|
||||
if (!token)
|
||||
token = get_token (cfile);
|
||||
if (rval)
|
||||
*rval = tval;
|
||||
return token;
|
||||
}
|
||||
|
||||
static void skip_to_eol (cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
int c;
|
||||
do {
|
||||
c = get_char (cfile);
|
||||
if (c == EOF)
|
||||
return;
|
||||
if (c == EOL) {
|
||||
ungetc (c, cfile);
|
||||
ugflag = 1;
|
||||
return;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static int read_string (cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
int i;
|
||||
int bs = 0;
|
||||
int c;
|
||||
|
||||
for (i = 0; i < sizeof tokbuf; i++) {
|
||||
c = get_char (cfile);
|
||||
if (c == EOF) {
|
||||
parse_warn ("eof in string constant");
|
||||
break;
|
||||
}
|
||||
if (bs) {
|
||||
bs = 0;
|
||||
tokbuf [i] = c;
|
||||
} else if (c == '\\')
|
||||
bs = 1;
|
||||
else if (c == '"')
|
||||
break;
|
||||
else
|
||||
tokbuf [i] = c;
|
||||
}
|
||||
/* Normally, I'd feel guilty about this, but we're talking about
|
||||
strings that'll fit in a DHCP packet here... */
|
||||
if (i == sizeof tokbuf) {
|
||||
parse_warn ("string constant larger than internal buffer");
|
||||
--i;
|
||||
}
|
||||
tokbuf [i] = 0;
|
||||
tval = tokbuf;
|
||||
return STRING;
|
||||
}
|
||||
|
||||
static int read_number (c, cfile)
|
||||
int c;
|
||||
FILE *cfile;
|
||||
{
|
||||
int seenx = 0;
|
||||
int i = 0;
|
||||
tokbuf [i++] = c;
|
||||
for (; i < sizeof tokbuf; i++) {
|
||||
c = get_char (cfile);
|
||||
if (!seenx && c == 'x')
|
||||
seenx = 1;
|
||||
else if (!isascii (c) || !isxdigit (c)) {
|
||||
ungetc (c, cfile);
|
||||
ugflag = 1;
|
||||
break;
|
||||
}
|
||||
tokbuf [i] = c;
|
||||
}
|
||||
if (i == sizeof tokbuf) {
|
||||
parse_warn ("numeric token larger than internal buffer");
|
||||
--i;
|
||||
}
|
||||
tokbuf [i] = 0;
|
||||
tval = tokbuf;
|
||||
return NUMBER;
|
||||
}
|
||||
|
||||
static int read_num_or_atom (c, cfile)
|
||||
int c;
|
||||
FILE *cfile;
|
||||
{
|
||||
int i = 0;
|
||||
int rv = NUMBER_OR_ATOM;
|
||||
tokbuf [i++] = c;
|
||||
for (; i < sizeof tokbuf; i++) {
|
||||
c = get_char (cfile);
|
||||
if (!isascii (c) ||
|
||||
(c != '-' && c != '_' && !isalnum (c))) {
|
||||
ungetc (c, cfile);
|
||||
ugflag = 1;
|
||||
break;
|
||||
}
|
||||
if (!isxdigit (c))
|
||||
rv = ATOM;
|
||||
tokbuf [i] = c;
|
||||
}
|
||||
if (i == sizeof tokbuf) {
|
||||
parse_warn ("token larger than internal buffer");
|
||||
--i;
|
||||
}
|
||||
tokbuf [i] = 0;
|
||||
tval = tokbuf;
|
||||
return intern (tval, rv);
|
||||
}
|
||||
|
||||
static int intern (atom, dfv)
|
||||
char *atom;
|
||||
int dfv;
|
||||
{
|
||||
switch (atom [0]) {
|
||||
case 'h':
|
||||
if (!strcasecmp (atom + 1, "ost"))
|
||||
return HOST;
|
||||
if (!strcasecmp (atom + 1, "ardware"))
|
||||
return HARDWARE;
|
||||
break;
|
||||
case 'f':
|
||||
if (!strcasecmp (atom + 1, "ilename"))
|
||||
return FILENAME;
|
||||
if (!strcasecmp (atom + 1, "ixed-address"))
|
||||
return FIXED_ADDR;
|
||||
break;
|
||||
case 'e':
|
||||
if (!strcasecmp (atom + 1, "thernet"))
|
||||
return ETHERNET;
|
||||
break;
|
||||
case 'o':
|
||||
if (!strcasecmp (atom + 1, "ption"))
|
||||
return OPTION;
|
||||
break;
|
||||
}
|
||||
return dfv;
|
||||
}
|
117
common/convert.c
Normal file
117
common/convert.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/* convert.c
|
||||
|
||||
Safe copying of option values into and out of the option buffer, which
|
||||
can't be assumed to be aligned. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
|
||||
unsigned long getULong (buf)
|
||||
unsigned char *buf;
|
||||
{
|
||||
unsigned long ibuf;
|
||||
|
||||
memcpy (&ibuf, buf, sizeof (unsigned long));
|
||||
return ntohl (ibuf);
|
||||
}
|
||||
|
||||
long getLong (buf)
|
||||
unsigned char *buf;
|
||||
{
|
||||
long ibuf;
|
||||
|
||||
memcpy (&ibuf, buf, sizeof (long));
|
||||
return ntohl (ibuf);
|
||||
}
|
||||
|
||||
unsigned short getUShort (buf)
|
||||
unsigned char *buf;
|
||||
{
|
||||
unsigned short ibuf;
|
||||
|
||||
memcpy (&ibuf, buf, sizeof (unsigned short));
|
||||
return ntohs (ibuf);
|
||||
}
|
||||
|
||||
short getShort (buf)
|
||||
unsigned char *buf;
|
||||
{
|
||||
short ibuf;
|
||||
|
||||
memcpy (&ibuf, buf, sizeof (short));
|
||||
return ntohs (ibuf);
|
||||
}
|
||||
|
||||
void putULong (obuf, val)
|
||||
unsigned char *obuf;
|
||||
unsigned long val;
|
||||
{
|
||||
unsigned long tmp = htonl (val);
|
||||
memcpy (obuf, &tmp, sizeof tmp);
|
||||
}
|
||||
|
||||
void putLong (obuf, val)
|
||||
unsigned char *obuf;
|
||||
long val;
|
||||
{
|
||||
long tmp = htonl (val);
|
||||
memcpy (obuf, &tmp, sizeof tmp);
|
||||
}
|
||||
|
||||
void putUShort (obuf, val)
|
||||
unsigned char *obuf;
|
||||
unsigned short val;
|
||||
{
|
||||
unsigned short tmp = htonl (val);
|
||||
memcpy (obuf, &tmp, sizeof tmp);
|
||||
}
|
||||
|
||||
void putShort (obuf, val)
|
||||
unsigned char *obuf;
|
||||
short val;
|
||||
{
|
||||
short tmp = htonl (val);
|
||||
memcpy (obuf, &tmp, sizeof tmp);
|
||||
}
|
||||
|
200
common/errwarn.c
Normal file
200
common/errwarn.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/* errwarn.c
|
||||
|
||||
Errors and warnings... */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 RadioMail Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of RadioMail Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY RADIOMAIL CORPORATION AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* RADIOMAIL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software was written for RadioMail Corporation by Ted Lemon
|
||||
* under a contract with Vixie Enterprises, and is based on an earlier
|
||||
* design by Paul Vixie.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 RadioMail Corporation. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
|
||||
static void do_percentm PROTO ((char *obuf, char *ibuf));
|
||||
|
||||
static char mbuf [1024];
|
||||
static char fbuf [1024];
|
||||
|
||||
/* Log an error message, then exit... */
|
||||
|
||||
int error (ANSI_DECL(char *) fmt, VA_DOTDOTDOT)
|
||||
KandR (char *fmt;)
|
||||
va_dcl
|
||||
{
|
||||
va_list list;
|
||||
extern int logged_in;
|
||||
|
||||
do_percentm (fbuf, fmt);
|
||||
|
||||
VA_start (list, fmt);
|
||||
vsnprintf (mbuf, sizeof mbuf, fbuf, list);
|
||||
va_end (list);
|
||||
#ifndef DEBUG
|
||||
syslog (LOG_ERR, mbuf);
|
||||
#else
|
||||
write (1, mbuf, strlen (mbuf));
|
||||
write (1, "\n", 1);
|
||||
#endif
|
||||
|
||||
cleanup ();
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Log a warning message... */
|
||||
|
||||
int warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
|
||||
KandR (char *fmt;)
|
||||
va_dcl
|
||||
{
|
||||
va_list list;
|
||||
|
||||
do_percentm (fbuf, fmt);
|
||||
|
||||
VA_start (list, fmt);
|
||||
vsnprintf (mbuf, sizeof mbuf, fbuf, list);
|
||||
va_end (list);
|
||||
#ifndef DEBUG
|
||||
syslog (LOG_ERR, mbuf);
|
||||
#else
|
||||
write (1, mbuf, strlen (mbuf));
|
||||
write (1, "\n", 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Log a note... */
|
||||
|
||||
int note (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
|
||||
KandR (char *fmt;)
|
||||
va_dcl
|
||||
{
|
||||
va_list list;
|
||||
|
||||
do_percentm (fbuf, fmt);
|
||||
|
||||
VA_start (list, fmt);
|
||||
vsnprintf (mbuf, sizeof mbuf, fbuf, list);
|
||||
va_end (list);
|
||||
#ifndef DEBUG
|
||||
syslog (LOG_INFO, mbuf);
|
||||
#else
|
||||
write (1, mbuf, strlen (mbuf));
|
||||
write (1, "\n", 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Log a debug message... */
|
||||
|
||||
int debug (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
|
||||
KandR (char *fmt;)
|
||||
va_dcl
|
||||
{
|
||||
va_list list;
|
||||
|
||||
do_percentm (fbuf, fmt);
|
||||
|
||||
VA_start (list, fmt);
|
||||
vsnprintf (mbuf, sizeof mbuf, fbuf, list);
|
||||
va_end (list);
|
||||
#ifndef DEBUG
|
||||
syslog (LOG_DEBUG, mbuf);
|
||||
#else
|
||||
write (1, mbuf, strlen (mbuf));
|
||||
write (1, "\n", 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find %m in the input string and substitute an error message string. */
|
||||
|
||||
static void do_percentm (obuf, ibuf)
|
||||
char *obuf;
|
||||
char *ibuf;
|
||||
{
|
||||
char *s = ibuf;
|
||||
char *p = obuf;
|
||||
int infmt = 0;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (infmt)
|
||||
{
|
||||
if (*s == 'm')
|
||||
{
|
||||
strcpy (p - 1, strerror (errno));
|
||||
p += strlen (p);
|
||||
++s;
|
||||
}
|
||||
else
|
||||
*p++ = *s++;
|
||||
infmt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*s == '%')
|
||||
infmt = 1;
|
||||
*p++ = *s++;
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
|
||||
int parse_warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
|
||||
KandR (char *fmt;)
|
||||
va_dcl
|
||||
{
|
||||
extern int tline, tlpos;
|
||||
va_list list;
|
||||
|
||||
do_percentm (mbuf, fmt);
|
||||
snprintf (fbuf, sizeof fbuf, "dhcpd.conf line %d char %d: %s",
|
||||
tline, tlpos, mbuf);
|
||||
|
||||
VA_start (list, fmt);
|
||||
vsnprintf (mbuf, sizeof mbuf, fbuf, list);
|
||||
va_end (list);
|
||||
#ifndef DEBUG
|
||||
syslog (LOG_ERROR, mbuf);
|
||||
#else
|
||||
write (1, mbuf, strlen (mbuf));
|
||||
write (1, "\n", 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
152
common/hash.c
Normal file
152
common/hash.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/* hash.c
|
||||
|
||||
Routines for manipulating hash tables... */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
|
||||
struct hash_table *new_hash ()
|
||||
{
|
||||
struct hash_table *rv = new_hash_table (DEFAULT_HASH_SIZE, "new_hash");
|
||||
if (!rv)
|
||||
return rv;
|
||||
memset (&rv -> buckets, 0,
|
||||
DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *));
|
||||
return rv;
|
||||
}
|
||||
|
||||
static INLINE do_hash (name, len, size)
|
||||
char *name;
|
||||
int len;
|
||||
int size;
|
||||
{
|
||||
register int accum = 0;
|
||||
register unsigned char *s = (unsigned char *)name;
|
||||
int i = len;
|
||||
if (i) {
|
||||
while (i--) {
|
||||
/* Add the character in... */
|
||||
accum += *s++;
|
||||
/* Add carry back in... */
|
||||
while (accum > 255) {
|
||||
accum = (accum & 255) + (accum >> 8);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (*s) {
|
||||
/* Add the character in... */
|
||||
accum += *s++;
|
||||
/* Add carry back in... */
|
||||
while (accum > 255) {
|
||||
accum = (accum & 255) + (accum >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
return accum % size;
|
||||
}
|
||||
|
||||
void add_hash (table, name, len, pointer)
|
||||
struct hash_table *table;
|
||||
int len;
|
||||
char *name;
|
||||
unsigned char *pointer;
|
||||
{
|
||||
int hashno = do_hash (name, len, table -> hash_count);
|
||||
struct hash_bucket *bp = new_hash_bucket ("add_hash");
|
||||
if (!bp) {
|
||||
warn ("Can't add %s to hash table.", name);
|
||||
return;
|
||||
}
|
||||
bp -> name = name;
|
||||
bp -> value = pointer;
|
||||
bp -> next = table -> buckets [hashno];
|
||||
table -> buckets [hashno] = bp;
|
||||
}
|
||||
|
||||
void delete_hash_entry (table, name, len)
|
||||
struct hash_table *table;
|
||||
int len;
|
||||
char *name;
|
||||
{
|
||||
int hashno = do_hash (name, len, table -> hash_count);
|
||||
struct hash_bucket *bp, *pbp = (struct hash_bucket *)0;
|
||||
|
||||
/* Go through the list looking for an entry that matches;
|
||||
if we find it, delete it. */
|
||||
for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
|
||||
if ((!bp -> len && !strcmp (bp -> name, name)) ||
|
||||
(bp -> len == len &&
|
||||
!memcmp (bp -> name, name, len))) {
|
||||
if (pbp) {
|
||||
pbp -> next = bp -> next;
|
||||
} else {
|
||||
table -> buckets [hashno] = bp -> next;
|
||||
}
|
||||
free_hash_bucket (bp, "delete_hash_entry");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *hash_lookup (table, name, len)
|
||||
struct hash_table *table;
|
||||
char *name;
|
||||
int len;
|
||||
{
|
||||
int hashno = do_hash (name, len, table -> hash_count);
|
||||
struct hash_bucket *bp;
|
||||
|
||||
if (len) {
|
||||
for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
|
||||
if (len == bp -> len
|
||||
&& !memcmp (bp -> name, name, len))
|
||||
return bp -> value;
|
||||
} else {
|
||||
for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
|
||||
if (!strcmp (bp -> name, name))
|
||||
return bp -> value;
|
||||
}
|
||||
return (unsigned char *)0;
|
||||
}
|
||||
|
395
common/memory.c
Normal file
395
common/memory.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/* memory.c
|
||||
|
||||
Memory-resident database... */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
|
||||
static struct host_decl *hosts;
|
||||
static struct hash_table *subnet_hash;
|
||||
static struct hash_table *lease_uid_hash;
|
||||
static struct hash_table *lease_ip_addr_hash;
|
||||
static struct hash_table *lease_hw_addr_hash;
|
||||
static struct lease *dangling_leases;
|
||||
|
||||
void enter_host (hd)
|
||||
struct host_decl *hd;
|
||||
{
|
||||
hd -> n_name = hosts;
|
||||
hd -> n_haddr = hosts;
|
||||
hd -> n_cid = hosts;
|
||||
|
||||
hosts = hd;
|
||||
}
|
||||
|
||||
struct host_decl *find_host_by_name (name)
|
||||
char *name;
|
||||
{
|
||||
struct host_decl *foo;
|
||||
|
||||
for (foo = hosts; foo; foo = foo -> n_name)
|
||||
if (!strcmp (name, foo -> name))
|
||||
return foo;
|
||||
return (struct host_decl *)0;
|
||||
}
|
||||
|
||||
struct host_decl *find_host_by_addr (htype, haddr, hlen)
|
||||
int htype;
|
||||
unsigned char *haddr;
|
||||
int hlen;
|
||||
{
|
||||
struct host_decl *foo;
|
||||
int i;
|
||||
|
||||
for (foo = hosts; foo; foo = foo -> n_haddr)
|
||||
for (i = 0; i < foo -> interface_count; i++)
|
||||
if (foo -> interfaces [i].htype == htype &&
|
||||
foo -> interfaces [i].hlen == hlen &&
|
||||
!memcmp (foo -> interfaces [i].haddr, haddr, hlen))
|
||||
return foo;
|
||||
return (struct host_decl *)0;
|
||||
}
|
||||
|
||||
void new_address_range (low, high, netmask)
|
||||
struct in_addr low, high, netmask;
|
||||
{
|
||||
struct lease *address_range, *lp, *plp;
|
||||
struct subnet *subnet;
|
||||
struct in_addr net;
|
||||
int i, max;
|
||||
char lowbuf [16], highbuf [16], netbuf [16];
|
||||
|
||||
/* Initialize the hash table if it hasn't been done yet. */
|
||||
if (!subnet_hash)
|
||||
subnet_hash = new_hash ();
|
||||
if (!lease_uid_hash)
|
||||
lease_uid_hash = new_hash ();
|
||||
if (!lease_ip_addr_hash)
|
||||
lease_ip_addr_hash = new_hash ();
|
||||
if (!lease_hw_addr_hash)
|
||||
lease_hw_addr_hash = new_hash ();
|
||||
|
||||
/* Make sure that high and low addresses are in same subnet. */
|
||||
net.s_addr = SUBNET (low, netmask);
|
||||
if (net.s_addr != SUBNET (high, netmask)) {
|
||||
strcpy (lowbuf, inet_ntoa (low));
|
||||
strcpy (highbuf, inet_ntoa (high));
|
||||
strcpy (netbuf, inet_ntoa (netmask));
|
||||
error ("Address range %s to %s, netmask %s spans %s!",
|
||||
lowbuf, highbuf, netbuf, "multiple subnets");
|
||||
}
|
||||
|
||||
/* See if this subnet is already known - if not, make a new one. */
|
||||
subnet = find_subnet (net);
|
||||
if (!subnet) {
|
||||
subnet = new_subnet ("new_address_range");
|
||||
if (!subnet)
|
||||
error ("No memory for new subnet");
|
||||
subnet -> net = net;
|
||||
subnet -> netmask = netmask;
|
||||
subnet -> leases = (struct lease *)0;
|
||||
enter_subnet (subnet);
|
||||
}
|
||||
|
||||
/* Get the high and low host addresses... */
|
||||
max = HOST_ADDR (high, netmask);
|
||||
i = HOST_ADDR (low, netmask);
|
||||
|
||||
/* Allow range to be specified high-to-low as well as low-to-high. */
|
||||
if (i > max) {
|
||||
max = i;
|
||||
i = HOST_ADDR (high, netmask);
|
||||
}
|
||||
|
||||
/* Get a lease structure for each address in the range. */
|
||||
address_range = new_leases (max - i + 1, "new_address_range");
|
||||
if (!address_range) {
|
||||
strcpy (lowbuf, inet_ntoa (low));
|
||||
strcpy (highbuf, inet_ntoa (high));
|
||||
error ("No memory for address range %s-%s.", lowbuf, highbuf);
|
||||
}
|
||||
memset (address_range, 0, (sizeof *address_range) * (max - i + 1));
|
||||
|
||||
/* Fill out the lease structures with some minimal information. */
|
||||
for (; i <= max; i++) {
|
||||
address_range [i].ip_addr.s_addr = IP_ADDR (subnet -> net, i);
|
||||
address_range [i].starts =
|
||||
address_range [i].timestamp = MIN_TIME;
|
||||
address_range [i].ends = MIN_TIME;
|
||||
address_range [i].contain = subnet;
|
||||
|
||||
/* Link this entry into the list. */
|
||||
address_range [i].next = subnet -> leases;
|
||||
address_range [i].prev = (struct lease *)0;
|
||||
subnet -> leases = &address_range [i];
|
||||
address_range [i].next -> prev = subnet -> leases;
|
||||
add_hash (lease_ip_addr_hash,
|
||||
(char *)&address_range [i].ip_addr,
|
||||
sizeof address_range [i].ip_addr,
|
||||
(unsigned char *)&address_range [i]);
|
||||
}
|
||||
|
||||
/* Find out if any dangling leases are in range... */
|
||||
plp = (struct lease *)0;
|
||||
for (lp = dangling_leases; lp; lp = lp -> next) {
|
||||
struct in_addr lnet;
|
||||
int lhost;
|
||||
|
||||
lnet.s_addr = SUBNET (lp -> ip_addr, subnet -> netmask);
|
||||
lhost = HOST_ADDR (lp -> ip_addr, subnet -> netmask);
|
||||
|
||||
/* If it's in range, fill in the real lease structure with
|
||||
the dangling lease's values, and remove the lease from
|
||||
the list of dangling leases. */
|
||||
if (lnet.s_addr == subnet -> net.s_addr &&
|
||||
lhost >= i && lhost <= max) {
|
||||
if (plp) {
|
||||
plp -> next = lp -> next;
|
||||
} else {
|
||||
dangling_leases = lp -> next;
|
||||
}
|
||||
lp -> next = (struct lease *)0;
|
||||
supersede_lease (&address_range [lhost - i], lp);
|
||||
free_lease (lp, "new_address_range");
|
||||
} else
|
||||
plp = lp;
|
||||
}
|
||||
}
|
||||
|
||||
struct subnet *find_subnet (subnet)
|
||||
struct in_addr subnet;
|
||||
{
|
||||
struct subnet *rv;
|
||||
|
||||
return (struct subnet *)hash_lookup (subnet_hash,
|
||||
(char *)&subnet, sizeof subnet);
|
||||
}
|
||||
|
||||
/* Enter a new subnet into the subnet hash. */
|
||||
|
||||
void enter_subnet (subnet)
|
||||
struct subnet *subnet;
|
||||
{
|
||||
add_hash (subnet_hash, (char *)&subnet -> net,
|
||||
sizeof subnet -> net, (unsigned char *)subnet);
|
||||
}
|
||||
|
||||
/* Enter a lease into the system. This is called by the parser each
|
||||
time it reads in a new lease. If the subnet for that lease has
|
||||
already been read in (usually the case), just update that lease;
|
||||
otherwise, allocate temporary storage for the lease and keep it around
|
||||
until we're done reading in the config file. */
|
||||
|
||||
void enter_lease (lease)
|
||||
struct lease *lease;
|
||||
{
|
||||
struct lease *comp = find_lease_by_ip_addr (lease -> ip_addr);
|
||||
|
||||
/* If we don't have a place for this lease yet, save it for
|
||||
later. */
|
||||
if (!comp) {
|
||||
comp = new_lease ("enter_lease");
|
||||
if (!comp) {
|
||||
error ("No memory for lease %s\n",
|
||||
inet_ntoa (lease -> ip_addr));
|
||||
}
|
||||
*comp = *lease;
|
||||
lease -> next = dangling_leases;
|
||||
lease -> prev = (struct lease *)0;
|
||||
dangling_leases = lease;
|
||||
} else {
|
||||
supersede_lease (comp, lease);
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace the data in an existing lease with the data in a new lease;
|
||||
adjust hash tables to suit, and insertion sort the lease into the
|
||||
list of leases by expiry time so that we can always find the oldest
|
||||
lease. */
|
||||
|
||||
void supersede_lease (comp, lease)
|
||||
struct lease *comp, *lease;
|
||||
{
|
||||
int enter_uid = 0;
|
||||
int enter_hwaddr = 0;
|
||||
struct subnet *parent;
|
||||
struct lease *lp;
|
||||
|
||||
/* If the existing lease hasn't expired and has a different
|
||||
unique identifier or, if it doesn't have a unique
|
||||
identifier, a different hardware address, then the two
|
||||
leases are in conflict. */
|
||||
if (comp -> ends > cur_time &&
|
||||
((comp -> uid &&
|
||||
(comp -> uid_len != lease -> uid_len ||
|
||||
memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
|
||||
(!comp -> uid &&
|
||||
((comp -> hardware_addr.htype !=
|
||||
lease -> hardware_addr.htype) ||
|
||||
(comp -> hardware_addr.hlen !=
|
||||
lease -> hardware_addr.hlen) ||
|
||||
memcmp (comp -> hardware_addr.haddr,
|
||||
lease -> hardware_addr.haddr,
|
||||
comp -> hardware_addr.hlen))))) {
|
||||
warn ("Lease conflict at %s",
|
||||
inet_ntoa (comp -> ip_addr));
|
||||
} else {
|
||||
/* If there's a Unique ID, dissociate it from the hash
|
||||
table if necessary, and always free it. */
|
||||
if (comp -> uid) {
|
||||
if (comp -> uid_len != lease -> uid_len ||
|
||||
memcmp (comp -> uid, lease -> uid,
|
||||
comp -> uid_len)) {
|
||||
delete_hash_entry (lease_uid_hash,
|
||||
comp -> uid,
|
||||
comp -> uid_len);
|
||||
enter_uid = 1;
|
||||
}
|
||||
free (comp -> uid);
|
||||
}
|
||||
if (comp -> hardware_addr.htype &&
|
||||
(comp -> hardware_addr.hlen !=
|
||||
lease -> hardware_addr.hlen) ||
|
||||
(comp -> hardware_addr.htype !=
|
||||
lease -> hardware_addr.htype) ||
|
||||
memcmp (comp -> hardware_addr.haddr,
|
||||
lease -> hardware_addr.haddr,
|
||||
comp -> hardware_addr.hlen)) {
|
||||
delete_hash_entry (lease_hw_addr_hash,
|
||||
comp -> hardware_addr.haddr,
|
||||
comp -> hardware_addr.hlen);
|
||||
enter_hwaddr = 1;
|
||||
}
|
||||
|
||||
/* Copy the data files, but not the linkages. */
|
||||
comp -> starts = lease -> starts;
|
||||
comp -> ends = lease -> ends;
|
||||
comp -> timestamp = lease -> timestamp;
|
||||
comp -> uid = lease -> uid;
|
||||
comp -> uid_len = lease -> uid_len;
|
||||
comp -> host = lease -> host;
|
||||
comp -> hardware_addr = lease -> hardware_addr;
|
||||
comp -> state = lease -> state;
|
||||
|
||||
/* Record the lease in the uid hash if necessary. */
|
||||
if (enter_uid && lease -> uid) {
|
||||
add_hash (lease_uid_hash, lease -> uid,
|
||||
lease -> uid_len, (unsigned char *)lease);
|
||||
}
|
||||
|
||||
/* Record it in the hardware address hash if necessary. */
|
||||
if (enter_hwaddr && lease -> hardware_addr.htype) {
|
||||
add_hash (lease_hw_addr_hash,
|
||||
lease -> hardware_addr.haddr,
|
||||
lease -> hardware_addr.hlen,
|
||||
(unsigned char *)lease);
|
||||
}
|
||||
|
||||
/* Remove the lease from its current place in the list. */
|
||||
if (comp -> prev) {
|
||||
comp -> prev -> next = comp -> next;
|
||||
} else {
|
||||
comp -> contain -> leases = comp -> next;
|
||||
}
|
||||
if (comp -> next) {
|
||||
comp -> next -> prev = comp -> prev;
|
||||
}
|
||||
|
||||
/* Find the last insertion point... */
|
||||
if (comp == comp -> contain -> insertion_point ||
|
||||
!comp -> contain -> insertion_point) {
|
||||
lp = comp -> contain -> leases;
|
||||
} else {
|
||||
lp = comp -> contain -> insertion_point;
|
||||
}
|
||||
|
||||
if (!lp) {
|
||||
/* Nothing on the list yet? Just make comp the
|
||||
head of the list. */
|
||||
comp -> contain -> leases = comp;
|
||||
} else if (lp -> ends <= comp -> ends) {
|
||||
/* Skip down the list until we run out of list
|
||||
or find a place for comp. */
|
||||
while (lp -> next && lp -> ends < comp -> ends) {
|
||||
lp = lp -> next;
|
||||
}
|
||||
if (lp -> ends < comp -> ends) {
|
||||
/* If we ran out of list, put comp
|
||||
at the end. */
|
||||
lp -> next = comp;
|
||||
comp -> prev = lp;
|
||||
comp -> next = (struct lease *)0;
|
||||
} else {
|
||||
/* If we didn't, put it between lp and
|
||||
the previous item on the list. */
|
||||
comp -> prev = lp -> prev;
|
||||
comp -> prev -> next = comp;
|
||||
comp -> next = lp;
|
||||
lp -> prev = comp;
|
||||
}
|
||||
} else {
|
||||
/* Skip ip the list until we run out of list
|
||||
or find a place for comp. */
|
||||
while (lp -> prev && lp -> ends > comp -> ends) {
|
||||
lp = lp -> prev;
|
||||
}
|
||||
if (lp -> ends > comp -> ends) {
|
||||
/* If we ran out of list, put comp
|
||||
at the beginning. */
|
||||
lp -> prev = comp;
|
||||
comp -> next = lp;
|
||||
comp -> prev = (struct lease *)0;
|
||||
comp -> contain -> leases = comp;
|
||||
} else {
|
||||
/* If we didn't, put it between lp and
|
||||
the next item on the list. */
|
||||
comp -> next = lp -> next;
|
||||
comp -> next -> prev = comp;
|
||||
comp -> prev = lp;
|
||||
lp -> next = comp;
|
||||
}
|
||||
}
|
||||
comp -> contain -> insertion_point = comp;
|
||||
}
|
||||
}
|
556
common/options.c
Normal file
556
common/options.c
Normal file
@@ -0,0 +1,556 @@
|
||||
/* options.c
|
||||
|
||||
DHCP options parsing and reassembly. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#define DHCP_OPTION_DATA
|
||||
#include "dhcpd.h"
|
||||
|
||||
/* Parse all available options out of the specified packet. */
|
||||
|
||||
void parse_options (packet)
|
||||
struct packet *packet;
|
||||
{
|
||||
/* Initially, zero all option pointers. */
|
||||
memset (packet -> options, 0, sizeof (packet -> options));
|
||||
|
||||
/* If we don't see the magic cookie, there's nothing to parse. */
|
||||
if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
|
||||
packet -> options_valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Go through the options field, up to the end of the packet
|
||||
or the End field. */
|
||||
parse_option_buffer (packet, &packet -> raw -> options [4],
|
||||
packet -> packet_length - DHCP_FIXED_LEN);
|
||||
/* If we parsed a DHCP Option Overload option, parse more
|
||||
options out of the buffer(s) containing them. */
|
||||
if (packet -> options_valid
|
||||
&& packet -> options [DHO_DHCP_OPTION_OVERLOAD].data) {
|
||||
if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)
|
||||
parse_option_buffer (packet,
|
||||
packet -> raw -> file,
|
||||
sizeof packet -> raw -> file);
|
||||
if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)
|
||||
parse_option_buffer (packet,
|
||||
packet -> raw -> sname,
|
||||
sizeof packet -> raw -> sname);
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse options out of the specified buffer, storing addresses of option
|
||||
values in packet -> options and setting packet -> options_valid if no
|
||||
errors are encountered. */
|
||||
|
||||
void parse_option_buffer (packet, buffer, length)
|
||||
struct packet *packet;
|
||||
unsigned char *buffer;
|
||||
int length;
|
||||
{
|
||||
unsigned char *s, *t;
|
||||
unsigned char *end = buffer + length;
|
||||
int len;
|
||||
int code;
|
||||
|
||||
for (s = buffer; *s != DHO_END && s < end; ) {
|
||||
code = s [0];
|
||||
/* Pad options don't have a length - just skip them. */
|
||||
if (code == DHO_PAD) {
|
||||
++s;
|
||||
continue;
|
||||
}
|
||||
/* All other fields (except end, see above) have a
|
||||
one-byte length. */
|
||||
len = s [1];
|
||||
/* If the length is outrageous, the options are bad. */
|
||||
if (s + len + 2 > end) {
|
||||
warn ("Option %s length %d overflows input buffer.",
|
||||
dhcp_options [code].name,
|
||||
len);
|
||||
packet -> options_valid = 0;
|
||||
return;
|
||||
}
|
||||
/* If we haven't seen this option before, just make
|
||||
space for it and copy it there. */
|
||||
if (!packet -> options [code].data) {
|
||||
if (!(t = (unsigned char *)malloc (len + 1)))
|
||||
error ("Can't allocate storage for option %s.",
|
||||
dhcp_options [code].name);
|
||||
/* Copy and NUL-terminate the option (in case it's an
|
||||
ASCII string. */
|
||||
memcpy (t, &s [2], len);
|
||||
t [len] = 0;
|
||||
packet -> options [code].len = len;
|
||||
packet -> options [code].data = t;
|
||||
} else {
|
||||
/* If it's a repeat, concatenate it to whatever
|
||||
we last saw. This is really only required
|
||||
for clients, but what the heck... */
|
||||
t = (unsigned char *)
|
||||
malloc (len + packet -> options [code].len);
|
||||
if (!t)
|
||||
error ("Can't expand storage for option %s.",
|
||||
dhcp_options [code].name);
|
||||
memcpy (t, packet -> options [code].data,
|
||||
packet -> options [code].len);
|
||||
memcpy (t + packet -> options [code].len,
|
||||
&s [2], len);
|
||||
packet -> options [code].len += len;
|
||||
t [packet -> options [code].len] = 0;
|
||||
free (packet -> options [code].data);
|
||||
packet -> options [code].data = t;
|
||||
}
|
||||
s += len + 2;
|
||||
}
|
||||
packet -> options_valid = 1;
|
||||
}
|
||||
|
||||
/* Cons up options based on client-supplied desired option list (if any)
|
||||
and selected server option list. */
|
||||
|
||||
void cons_options (inpacket, outpacket, hp, overload)
|
||||
struct packet *inpacket;
|
||||
struct dhcp_packet *outpacket;
|
||||
struct host_decl *hp;
|
||||
int overload; /* Overload flags that may be set. */
|
||||
{
|
||||
option_mask options_have; /* Options we can send. */
|
||||
option_mask options_want; /* Options client wants. */
|
||||
option_mask options_done; /* Options we've already encoded. */
|
||||
option_mask temp; /* Working option mask. */
|
||||
unsigned char *priority_list;
|
||||
int priority_len;
|
||||
unsigned char *buffer = inpacket -> raw -> options;
|
||||
int buflen, bufix;
|
||||
int reserved = 3; /* Reserved space for overload. */
|
||||
unsigned char *overload_ptr = (unsigned char *)0;
|
||||
int stored_length [256];
|
||||
int missed = 0;
|
||||
int missed_code;
|
||||
int missed_length;
|
||||
int result;
|
||||
int i;
|
||||
|
||||
/* If there's no place to overload with options, don't save space
|
||||
for an overload option. */
|
||||
if (!overload)
|
||||
reserved = 0;
|
||||
|
||||
/* Zero out the stored-lengths array. */
|
||||
memset (stored_length, 0, sizeof stored_length);
|
||||
|
||||
/* If the client has provided a maximum DHCP message size,
|
||||
use that. Otherwise, we use the default MTU size (576 bytes). */
|
||||
/* XXX Maybe it would be safe to assume that we can send a packet
|
||||
to the client that's as big as the one it sent us, even if it
|
||||
didn't specify a large MTU. */
|
||||
if (inpacket -> options [DHO_DHCP_MAX_MESSAGE_SIZE].data)
|
||||
buflen = (getUShort (inpacket -> options
|
||||
[DHO_DHCP_MAX_MESSAGE_SIZE].data)
|
||||
- DHCP_FIXED_LEN);
|
||||
else
|
||||
buflen = 576 - DHCP_FIXED_LEN;
|
||||
|
||||
/* If the client has provided a list of options that it wishes
|
||||
returned, use it to prioritize. */
|
||||
if (inpacket -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
|
||||
priority_list =
|
||||
inpacket -> options
|
||||
[DHO_DHCP_PARAMETER_REQUEST_LIST].data;
|
||||
priority_len =
|
||||
inpacket -> options
|
||||
[DHO_DHCP_PARAMETER_REQUEST_LIST].len;
|
||||
} else {
|
||||
/* Otherwise, prioritize based on the default priority list. */
|
||||
priority_list = dhcp_option_default_priority_list;
|
||||
priority_len = sizeof_dhcp_option_default_priority_list;
|
||||
}
|
||||
|
||||
/* Make a bitmask of all the options the client wants. */
|
||||
OPTION_ZERO (options_want);
|
||||
for (i = 0; i < priority_len; i++)
|
||||
OPTION_SET (options_want, priority_list [i]);
|
||||
|
||||
/* Make a bitmask of all the options we have available. */
|
||||
OPTION_ZERO (options_have);
|
||||
for (i = 0; i < 256; i++)
|
||||
if (hp -> options [i])
|
||||
OPTION_SET (options_have, i);
|
||||
|
||||
again:
|
||||
/* Try copying out options that fit easily. */
|
||||
for (i = 0; i < priority_len; i++) {
|
||||
/* Code for next option to try to store. */
|
||||
int code = priority_list [i];
|
||||
|
||||
/* Number of bytes left to store (some may already
|
||||
have been stored by a previous pass). */
|
||||
int length;
|
||||
|
||||
/* If no data is available for this option, skip it. */
|
||||
if (!hp -> options [code])
|
||||
continue;
|
||||
|
||||
/* Don't look at options that have already been stored. */
|
||||
if (OPTION_ISSET (options_done, code))
|
||||
continue;
|
||||
|
||||
/* Find the value of the option... */
|
||||
if (!tree_evaluate (hp -> options [code]))
|
||||
continue;
|
||||
|
||||
/* We should now have a constant length for the option. */
|
||||
length = (hp -> options [code] -> len - stored_length [code]);
|
||||
|
||||
/* If there's no space for this option, skip it. */
|
||||
if ((bufix + OPTION_SPACE (length) + reserved) > buflen) {
|
||||
/* If this is the first missed option, remember it. */
|
||||
if (++missed == 1) {
|
||||
missed_code = code;
|
||||
missed_length = length;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, store the option. */
|
||||
result = store_option (outpacket, code,
|
||||
buffer + bufix,
|
||||
buflen - bufix - reserved,
|
||||
stored_length);
|
||||
bufix += result;
|
||||
|
||||
/* The following test should always succeed because of
|
||||
preconditioning above. */
|
||||
if (stored_length [code] == hp -> options [code] -> len)
|
||||
OPTION_SET (options_done, code);
|
||||
else {
|
||||
warn ("%s: Only stored %d out of %d bytes.",
|
||||
dhcp_options [code].name,
|
||||
stored_length [code],
|
||||
hp -> options [code] -> len);
|
||||
if (++missed == 1) {
|
||||
missed_code = code;
|
||||
missed_length = hp -> options [code] -> len
|
||||
- stored_length [code];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we didn't miss any options, we're done. */
|
||||
/* XXX Maybe we want to try to encode options the client didn't
|
||||
request but that we have available? */
|
||||
if (!missed)
|
||||
return;
|
||||
|
||||
/* If we did miss one or more options, they must not have fit.
|
||||
It's possible, though, that there's only one option left to
|
||||
store, and that it would fit if we weren't reserving space
|
||||
for the overload option. In that case, we want to avoid
|
||||
overloading. */
|
||||
if (reserved && missed == 1
|
||||
&& (bufix + OPTION_SPACE (missed_length) <= buflen)) {
|
||||
result = store_option (outpacket, missed_code,
|
||||
buffer + bufix, buflen - bufix,
|
||||
stored_length);
|
||||
bufix += result;
|
||||
/* This test should always fail -- we'll send bad
|
||||
data if it doesn't. */
|
||||
if (stored_length [missed_code]
|
||||
== hp -> options [missed_code] -> len) {
|
||||
OPTION_SET (options_done, missed_code);
|
||||
} else {
|
||||
warn ("%s (last): Only stored %d out of %d bytes.",
|
||||
dhcp_options [missed_code].name,
|
||||
stored_length [missed_code],
|
||||
hp -> options [missed_code] -> len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* We've crammed in all the options that completely fit in
|
||||
the current buffer, but maybe we can fit part of the next
|
||||
option into the current buffer and part into the next. */
|
||||
if (bufix + OPTION_SPACE (missed_length) + reserved
|
||||
< buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) {
|
||||
result = store_option (outpacket, missed_code,
|
||||
buffer + bufix,
|
||||
buflen - bufix - reserved,
|
||||
stored_length);
|
||||
bufix += result;
|
||||
|
||||
/* This test should never fail. */
|
||||
if (stored_length [missed_code]
|
||||
== hp -> options [missed_code] -> len) {
|
||||
OPTION_SET (options_done, missed_code);
|
||||
warn ("%s: Unexpected completed store.",
|
||||
dhcp_options [missed_code].name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Okay, nothing else is going to fit in the current buffer
|
||||
except possibly the override option. Store that. */
|
||||
if (reserved) {
|
||||
buffer [bufix++] = DHO_DHCP_OPTION_OVERLOAD;
|
||||
buffer [bufix++] = 1;
|
||||
overload_ptr = buffer + bufix;
|
||||
buffer [bufix++] = 0;
|
||||
/* If there's space, store an End option code. */
|
||||
if (bufix < buflen)
|
||||
buffer [bufix++] = DHO_END;
|
||||
/* If there's still space, pad it. */
|
||||
while (bufix < buflen)
|
||||
buffer [bufix++] = DHO_PAD;
|
||||
}
|
||||
|
||||
/* If we've fallen through to here, we still have options to
|
||||
store, and may be able to overload options into the file
|
||||
and server name fields of the DHCP packet. */
|
||||
|
||||
/* We should have stored an overload option by now if we're
|
||||
going to need it, so if this test fails, there's a programming
|
||||
error somewhere above. */
|
||||
if (overload && !overload_ptr) {
|
||||
warn ("Need to overload, but didn't store overload option!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can we use the file buffer? */
|
||||
if (overload & 1) {
|
||||
buffer = inpacket -> raw -> file;
|
||||
buflen = sizeof inpacket -> raw -> file;
|
||||
bufix = 0;
|
||||
overload &= ~1;
|
||||
goto again;
|
||||
}
|
||||
/* Can we use the sname buffer? */
|
||||
if (overload & 2) {
|
||||
buffer = inpacket -> raw -> sname;
|
||||
buflen = sizeof inpacket -> raw -> sname;
|
||||
bufix = 0;
|
||||
overload &= ~2;
|
||||
goto again;
|
||||
}
|
||||
|
||||
warn ("Insufficient packet space for all options.");
|
||||
}
|
||||
|
||||
/* Copy the option data specified by code from the packet structure's
|
||||
option array into an option buffer specified by buf and buflen,
|
||||
updating stored_length[code] to reflect the amount of code's option
|
||||
data that has been stored so far. Return 1 if all the option data
|
||||
has been stored. */
|
||||
|
||||
int store_option (packet, code, buffer, buflen, stored_length)
|
||||
struct packet *packet;
|
||||
unsigned char code;
|
||||
unsigned char *buffer;
|
||||
int buflen;
|
||||
int *stored_length;
|
||||
{
|
||||
int length = packet -> options [code].len - stored_length [code];
|
||||
int bufix = 0;
|
||||
int rv = 1;
|
||||
if (length > buflen) {
|
||||
rv = 0;
|
||||
length = buflen;
|
||||
}
|
||||
|
||||
/* If the option's length is more than 255, we must store it
|
||||
in multiple hunks. Store 255-byte hunks first. */
|
||||
/* XXX Might a client lose its cookies if options aren't
|
||||
chunked out so that each chunk is aligned to the size
|
||||
of the data being represented? */
|
||||
while (length) {
|
||||
unsigned char incr = length > 255 ? 255 : length;
|
||||
buffer [bufix] = code;
|
||||
buffer [bufix + 1] = incr;
|
||||
memcpy (buffer + bufix + 2, (packet -> options [code].data
|
||||
+ stored_length [code]), incr);
|
||||
length -= incr;
|
||||
stored_length [code] += incr;
|
||||
bufix += 2 + incr;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Format the specified option so that a human can easily read it. */
|
||||
|
||||
char *pretty_print_option (code, data, len)
|
||||
unsigned char code;
|
||||
unsigned char *data;
|
||||
int len;
|
||||
{
|
||||
static char optbuf [32768]; /* XXX */
|
||||
int hunksize = 0;
|
||||
int numhunk = -1;
|
||||
int numelem = 0;
|
||||
char fmtbuf [32];
|
||||
int i, j;
|
||||
char *op = optbuf;
|
||||
unsigned char *dp = data;
|
||||
struct in_addr foo;
|
||||
|
||||
/* Figure out the size of the data. */
|
||||
for (i = 0; dhcp_options [code].format [i]; i++) {
|
||||
if (!numhunk) {
|
||||
warn ("%s: Excess information in format string: %s\n",
|
||||
dhcp_options [code].name,
|
||||
&(dhcp_options [code].format [i]));
|
||||
break;
|
||||
}
|
||||
numelem++;
|
||||
fmtbuf [i] = dhcp_options [code].format [i];
|
||||
switch (dhcp_options [code].format [i]) {
|
||||
case 'A':
|
||||
--numelem;
|
||||
fmtbuf [i] = 0;
|
||||
numhunk = 0;
|
||||
break;
|
||||
case 't':
|
||||
fmtbuf [i] = 't';
|
||||
fmtbuf [i + 1] = 0;
|
||||
numhunk = -2;
|
||||
break;
|
||||
case 'I':
|
||||
case 'l':
|
||||
case 'L':
|
||||
hunksize += 4;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
hunksize += 2;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'f':
|
||||
hunksize++;
|
||||
break;
|
||||
case 'e':
|
||||
break;
|
||||
default:
|
||||
warn ("%s: garbage in format string: %s\n",
|
||||
dhcp_options [code].name,
|
||||
&(dhcp_options [code].format [i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for too few bytes... */
|
||||
if (hunksize > len) {
|
||||
warn ("%s: expecting at least %d bytes; got %d",
|
||||
dhcp_options [code].name,
|
||||
hunksize, len);
|
||||
return "<error>";
|
||||
}
|
||||
/* Check for too many bytes... */
|
||||
if (numhunk == -1 && hunksize < len)
|
||||
warn ("%s: %d extra bytes",
|
||||
dhcp_options [code].name,
|
||||
len - hunksize);
|
||||
|
||||
/* If this is an array, compute its size. */
|
||||
if (!numhunk)
|
||||
numhunk = len / hunksize;
|
||||
/* See if we got an exact number of hunks. */
|
||||
if (numhunk > 0 && numhunk * hunksize < len)
|
||||
warn ("%s: %d extra bytes at end of array\n",
|
||||
dhcp_options [code].name,
|
||||
len - numhunk * hunksize);
|
||||
|
||||
/* A one-hunk array prints the same as a single hunk. */
|
||||
if (numhunk < 0)
|
||||
numhunk = 1;
|
||||
|
||||
printf ("numhunk = %d numelem = %d\n", numhunk, numelem);
|
||||
/* Cycle through the array (or hunk) printing the data. */
|
||||
for (i = 0; i < numhunk; i++) {
|
||||
for (j = 0; j < numelem; j++) {
|
||||
switch (fmtbuf [j]) {
|
||||
case 't':
|
||||
strcpy (op, dp);
|
||||
break;
|
||||
case 'I':
|
||||
foo.s_addr = htonl (getULong (dp));
|
||||
strcpy (op, inet_ntoa (foo));
|
||||
dp += 4;
|
||||
break;
|
||||
case 'l':
|
||||
sprintf (op, "%ld", getLong (dp));
|
||||
dp += 4;
|
||||
break;
|
||||
case 'L':
|
||||
sprintf (op, "%ld", getULong (dp));
|
||||
dp += 4;
|
||||
break;
|
||||
case 's':
|
||||
sprintf (op, "%d", getShort (dp));
|
||||
dp += 2;
|
||||
break;
|
||||
case 'S':
|
||||
sprintf (op, "%d", getUShort (dp));
|
||||
dp += 2;
|
||||
break;
|
||||
case 'b':
|
||||
sprintf (op, "%d", *(char *)dp++);
|
||||
break;
|
||||
case 'B':
|
||||
sprintf (op, "%d", *dp++);
|
||||
break;
|
||||
case 'f':
|
||||
strcpy (op, *dp++ ? "true" : "false");
|
||||
break;
|
||||
default:
|
||||
warn ("Unexpected format code %c", fmtbuf [j]);
|
||||
}
|
||||
op += strlen (op);
|
||||
*op++ = ' ';
|
||||
}
|
||||
}
|
||||
*--op = 0;
|
||||
return optbuf;
|
||||
}
|
||||
|
||||
|
||||
|
65
common/print.c
Normal file
65
common/print.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* print.c
|
||||
|
||||
Turn data structures into printable text. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
char *print_hw_addr (htype, hlen, data)
|
||||
int htype;
|
||||
int hlen;
|
||||
unsigned char *data;
|
||||
{
|
||||
static char habuf [49];
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
s = habuf;
|
||||
for (i = 0; i < hlen; i++) {
|
||||
sprintf (s, "%x", data [i]);
|
||||
s += strlen (s);
|
||||
*s++ = ':';
|
||||
}
|
||||
*--s = 0;
|
||||
return habuf;
|
||||
}
|
||||
|
208
common/socket.c
Normal file
208
common/socket.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/* socket.c
|
||||
|
||||
BSD socket interface code... */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
/* List of sockets we're accepting packets on... */
|
||||
struct socklist {
|
||||
struct socklist *next;
|
||||
struct sockaddr_in addr;
|
||||
int sock;
|
||||
} *sockets;
|
||||
|
||||
/* Return the list of IP addresses associated with each network interface. */
|
||||
|
||||
u_int32_t *get_interface_list (count)
|
||||
int *count;
|
||||
{
|
||||
u_int32_t *intbuf = (u_int32_t *)0;
|
||||
static char buf [8192];
|
||||
struct ifconf ic;
|
||||
int i;
|
||||
int sock;
|
||||
int ifcount = 0;
|
||||
int ifix = 0;
|
||||
|
||||
/* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */
|
||||
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
error ("Can't create addrlist socket");
|
||||
|
||||
/* Get the interface configuration information... */
|
||||
ic.ifc_len = sizeof buf;
|
||||
ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
|
||||
i = ioctl(sock, SIOCGIFCONF, &ic);
|
||||
close (sock);
|
||||
if (i < 0)
|
||||
error ("ioctl: SIOCGIFCONF: %m");
|
||||
|
||||
again:
|
||||
/* Cycle through the list of interfaces looking for IP addresses.
|
||||
Go through twice; once to count the number if addresses, and a
|
||||
second time to copy them into an array of addresses. */
|
||||
for (i = 0; i < ic.ifc_len;) {
|
||||
struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
|
||||
i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len;
|
||||
if (ifp -> ifr_addr.sa_family == AF_INET) {
|
||||
struct sockaddr_in *foo =
|
||||
(struct sockaddr_in *)(&ifp -> ifr_addr);
|
||||
/* We don't want the loopback interface. */
|
||||
if (foo -> sin_addr.s_addr == INADDR_LOOPBACK)
|
||||
continue;
|
||||
if (intbuf)
|
||||
intbuf [ifix++] = foo -> sin_addr.s_addr;
|
||||
else
|
||||
++ifcount;
|
||||
}
|
||||
}
|
||||
/* If we haven't already filled our array, allocate it and go
|
||||
again. */
|
||||
if (!intbuf) {
|
||||
intbuf = (u_int32_t *)dmalloc ((ifcount + 1)
|
||||
* sizeof (u_int32_t),
|
||||
"get_interface_list");
|
||||
if (!intbuf)
|
||||
return intbuf;
|
||||
goto again;
|
||||
}
|
||||
*count = ifcount;
|
||||
return intbuf;
|
||||
}
|
||||
|
||||
void listen_on (port, address)
|
||||
u_int16_t port;
|
||||
u_int32_t address;
|
||||
{
|
||||
struct sockaddr_in name;
|
||||
int sock;
|
||||
struct socklist *tmp;
|
||||
int flag;
|
||||
|
||||
name.sin_family = AF_INET;
|
||||
name.sin_port = port;
|
||||
name.sin_addr.s_addr = address;
|
||||
memset (name.sin_zero, 0, sizeof (name.sin_zero));
|
||||
|
||||
/* List addresses on which we're listening. */
|
||||
note ("Receiving on %s, port %d",
|
||||
inet_ntoa (name.sin_addr), htons (name.sin_port));
|
||||
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
error ("Can't create dhcp socket: %m");
|
||||
|
||||
flag = 1;
|
||||
if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
&flag, sizeof flag) < 0)
|
||||
error ("Can't set SO_REUSEADDR option on dhcp socket: %m");
|
||||
|
||||
if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
|
||||
&flag, sizeof flag) < 0)
|
||||
error ("Can't set SO_BROADCAST option on dhcp socket: %m");
|
||||
|
||||
if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0)
|
||||
error ("Can't bind to dhcp address: %m");
|
||||
|
||||
tmp = (struct socklist *)dmalloc (sizeof (struct socklist),
|
||||
"listen_on");
|
||||
if (!tmp)
|
||||
error ("Can't allocate memory for socket list.");
|
||||
tmp -> addr = name;
|
||||
tmp -> sock = sock;
|
||||
tmp -> next = sockets;
|
||||
sockets = tmp;
|
||||
}
|
||||
|
||||
unsigned char packbuf [65536]; /* Should cover the gnarliest MTU... */
|
||||
|
||||
void dispatch ()
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
int fromlen = sizeof from;
|
||||
fd_set r, w, x;
|
||||
struct socklist *l;
|
||||
int max = 0;
|
||||
int count;
|
||||
int result;
|
||||
|
||||
FD_ZERO (&r);
|
||||
FD_ZERO (&w);
|
||||
FD_ZERO (&x);
|
||||
|
||||
do {
|
||||
/* Set up the read mask. */
|
||||
for (l = sockets; l; l = l -> next) {
|
||||
FD_SET (l -> sock, &r);
|
||||
FD_SET (l -> sock, &x);
|
||||
if (l -> sock > max)
|
||||
max = l -> sock;
|
||||
}
|
||||
|
||||
/* Wait for a packet or a timeout... XXX */
|
||||
count = select (max + 1, &r, &w, &x, (struct timeval *)0);
|
||||
|
||||
/* Not likely to be transitory... */
|
||||
if (count < 0)
|
||||
error ("select: %m");
|
||||
|
||||
for (l = sockets; l; l = l -> next) {
|
||||
if (!FD_ISSET (l -> sock, &r))
|
||||
continue;
|
||||
if ((result =
|
||||
recvfrom (l -> sock, packbuf, sizeof packbuf, 0,
|
||||
(struct sockaddr *)&from, &fromlen))
|
||||
< 0) {
|
||||
warn ("recvfrom failed on %s: %m",
|
||||
inet_ntoa (l -> addr.sin_addr));
|
||||
sleep (5);
|
||||
continue;
|
||||
}
|
||||
note ("request from %s, port %d",
|
||||
inet_ntoa (from.sin_addr),
|
||||
htons (from.sin_port));
|
||||
do_packet (packbuf, result, &from, fromlen, l -> sock);
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
414
common/tables.c
Normal file
414
common/tables.c
Normal file
@@ -0,0 +1,414 @@
|
||||
/* tables.c
|
||||
|
||||
Tables of information... */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
|
||||
/* DHCP Option names, formats and codes, from RFC1533.
|
||||
|
||||
Format codes:
|
||||
|
||||
e - end of data
|
||||
I - IP address
|
||||
l - 32-bit signed integer
|
||||
L - 32-bit unsigned integer
|
||||
s - 16-bit signed integer
|
||||
S - 16-bit unsigned integer
|
||||
b - 8-bit signed integer
|
||||
B - 8-bit unsigned integer
|
||||
t - ASCII text
|
||||
f - flag (true or false)
|
||||
A - array of whatever precedes (e.g., IA means array of IP addresses)
|
||||
*/
|
||||
|
||||
struct universe dhcp_universe;
|
||||
struct option dhcp_options [256] = {
|
||||
"pad", "", &dhcp_universe, 0,
|
||||
"subnet-mask", "I", &dhcp_universe, 1,
|
||||
"time-offset", "l", &dhcp_universe, 2,
|
||||
"routers", "IA", &dhcp_universe, 3,
|
||||
"time-servers", "IA", &dhcp_universe, 4,
|
||||
"name-servers", "IA", &dhcp_universe, 5,
|
||||
"domain-name-servers", "IA", &dhcp_universe, 6,
|
||||
"log-servers", "IA", &dhcp_universe, 7,
|
||||
"cookie-servers", "IA", &dhcp_universe, 8,
|
||||
"lpr-servers", "IA", &dhcp_universe, 9,
|
||||
"impress-servers", "IA", &dhcp_universe, 10,
|
||||
"resource-location-servers", "IA", &dhcp_universe, 11,
|
||||
"host-name", "t", &dhcp_universe, 12,
|
||||
"boot-size", "S", &dhcp_universe, 13,
|
||||
"merit-dump", "t", &dhcp_universe, 14,
|
||||
"domain-name", "t", &dhcp_universe, 15,
|
||||
"swap-server", "I", &dhcp_universe, 16,
|
||||
"root-path", "t", &dhcp_universe, 17,
|
||||
"extensions-path", "t", &dhcp_universe, 18,
|
||||
"ip-forwarding", "f", &dhcp_universe, 19,
|
||||
"non-local-source-routing", "f", &dhcp_universe, 20,
|
||||
"policy-filter", "IIA", &dhcp_universe, 21,
|
||||
"max-dgram-reassembly", "S", &dhcp_universe, 22,
|
||||
"default-ip-ttl", "B", &dhcp_universe, 23,
|
||||
"path-mtu-aging-timeout", "L", &dhcp_universe, 24,
|
||||
"path-mtu-plateau-table", "SA", &dhcp_universe, 25,
|
||||
"interface-mtu", "S", &dhcp_universe, 26,
|
||||
"all-subnets-local", "f", &dhcp_universe, 27,
|
||||
"broadcast-address", "I", &dhcp_universe, 28,
|
||||
"perform-mask-discovery", "f", &dhcp_universe, 29,
|
||||
"mask-supplier", "f", &dhcp_universe, 30,
|
||||
"router-discovery", "f", &dhcp_universe, 31,
|
||||
"router-solicitation-address", "I", &dhcp_universe, 32,
|
||||
"static-routes", "IIA", &dhcp_universe, 33,
|
||||
"trailer-encapsulation", "f", &dhcp_universe, 34,
|
||||
"arp-cache-timeout", "L", &dhcp_universe, 35,
|
||||
"ieee802.3-encapsulation", "f", &dhcp_universe, 36,
|
||||
"default-tcp-ttl", "B", &dhcp_universe, 37,
|
||||
"tcp-keepalive-interval", "L", &dhcp_universe, 38,
|
||||
"tcp-keepalive-garbage", "f", &dhcp_universe, 39,
|
||||
"nis-domain", "t", &dhcp_universe, 40,
|
||||
"nis-servers", "IA", &dhcp_universe, 41,
|
||||
"ntp-servers", "IA", &dhcp_universe, 42,
|
||||
"vendor-encapsulated-options", "t", &dhcp_universe, 43,
|
||||
"netbios-name-servers", "IA", &dhcp_universe, 44,
|
||||
"netbios-dd-server", "IA", &dhcp_universe, 45,
|
||||
"netbios-node-type", "B", &dhcp_universe, 46,
|
||||
"netbios-scope", "t", &dhcp_universe, 47,
|
||||
"font-servers", "IA", &dhcp_universe, 48,
|
||||
"x-display-manager", "IA", &dhcp_universe, 49,
|
||||
"dhcp-requested-address", "I", &dhcp_universe, 50,
|
||||
"dhcp-lease-time", "L", &dhcp_universe, 51,
|
||||
"dhcp-option-overload", "B", &dhcp_universe, 52,
|
||||
"dhcp-message-type", "B", &dhcp_universe, 53,
|
||||
"dhcp-server-identifier", "I", &dhcp_universe, 54,
|
||||
"dhcp-parameter-request-list", "BA", &dhcp_universe, 55,
|
||||
"dhcp-message", "t", &dhcp_universe, 56,
|
||||
"dhcp-max-message-size", "S", &dhcp_universe, 57,
|
||||
"dhcp-renewal-time", "L", &dhcp_universe, 58,
|
||||
"dhcp-rebinding-time", "L", &dhcp_universe, 59,
|
||||
"dhcp-class-identifier", "t", &dhcp_universe, 60,
|
||||
"dhcp-client-identifier", "t", &dhcp_universe, 61,
|
||||
"option-62", "", &dhcp_universe, 62,
|
||||
"option-63", "", &dhcp_universe, 63,
|
||||
"option-64", "", &dhcp_universe, 64,
|
||||
"option-65", "", &dhcp_universe, 65,
|
||||
"option-66", "", &dhcp_universe, 66,
|
||||
"option-67", "", &dhcp_universe, 67,
|
||||
"option-68", "", &dhcp_universe, 68,
|
||||
"option-69", "", &dhcp_universe, 69,
|
||||
"option-70", "", &dhcp_universe, 70,
|
||||
"option-71", "", &dhcp_universe, 71,
|
||||
"option-72", "", &dhcp_universe, 72,
|
||||
"option-73", "", &dhcp_universe, 73,
|
||||
"option-74", "", &dhcp_universe, 74,
|
||||
"option-75", "", &dhcp_universe, 75,
|
||||
"option-76", "", &dhcp_universe, 76,
|
||||
"option-77", "", &dhcp_universe, 77,
|
||||
"option-78", "", &dhcp_universe, 78,
|
||||
"option-79", "", &dhcp_universe, 79,
|
||||
"option-80", "", &dhcp_universe, 80,
|
||||
"option-81", "", &dhcp_universe, 81,
|
||||
"option-82", "", &dhcp_universe, 82,
|
||||
"option-83", "", &dhcp_universe, 83,
|
||||
"option-84", "", &dhcp_universe, 84,
|
||||
"option-85", "", &dhcp_universe, 85,
|
||||
"option-86", "", &dhcp_universe, 86,
|
||||
"option-87", "", &dhcp_universe, 87,
|
||||
"option-88", "", &dhcp_universe, 88,
|
||||
"option-89", "", &dhcp_universe, 89,
|
||||
"option-90", "", &dhcp_universe, 90,
|
||||
"option-91", "", &dhcp_universe, 91,
|
||||
"option-92", "", &dhcp_universe, 92,
|
||||
"option-93", "", &dhcp_universe, 93,
|
||||
"option-94", "", &dhcp_universe, 94,
|
||||
"option-95", "", &dhcp_universe, 95,
|
||||
"option-96", "", &dhcp_universe, 96,
|
||||
"option-97", "", &dhcp_universe, 97,
|
||||
"option-98", "", &dhcp_universe, 98,
|
||||
"option-99", "", &dhcp_universe, 99,
|
||||
"option-100", "", &dhcp_universe, 100,
|
||||
"option-101", "", &dhcp_universe, 101,
|
||||
"option-102", "", &dhcp_universe, 102,
|
||||
"option-103", "", &dhcp_universe, 103,
|
||||
"option-104", "", &dhcp_universe, 104,
|
||||
"option-105", "", &dhcp_universe, 105,
|
||||
"option-106", "", &dhcp_universe, 106,
|
||||
"option-107", "", &dhcp_universe, 107,
|
||||
"option-108", "", &dhcp_universe, 108,
|
||||
"option-109", "", &dhcp_universe, 109,
|
||||
"option-110", "", &dhcp_universe, 110,
|
||||
"option-111", "", &dhcp_universe, 111,
|
||||
"option-112", "", &dhcp_universe, 112,
|
||||
"option-113", "", &dhcp_universe, 113,
|
||||
"option-114", "", &dhcp_universe, 114,
|
||||
"option-115", "", &dhcp_universe, 115,
|
||||
"option-116", "", &dhcp_universe, 116,
|
||||
"option-117", "", &dhcp_universe, 117,
|
||||
"option-118", "", &dhcp_universe, 118,
|
||||
"option-119", "", &dhcp_universe, 119,
|
||||
"option-120", "", &dhcp_universe, 120,
|
||||
"option-121", "", &dhcp_universe, 121,
|
||||
"option-122", "", &dhcp_universe, 122,
|
||||
"option-123", "", &dhcp_universe, 123,
|
||||
"option-124", "", &dhcp_universe, 124,
|
||||
"option-125", "", &dhcp_universe, 125,
|
||||
"option-126", "", &dhcp_universe, 126,
|
||||
"option-127", "", &dhcp_universe, 127,
|
||||
"option-128", "", &dhcp_universe, 128,
|
||||
"option-129", "", &dhcp_universe, 129,
|
||||
"option-130", "", &dhcp_universe, 130,
|
||||
"option-131", "", &dhcp_universe, 131,
|
||||
"option-132", "", &dhcp_universe, 132,
|
||||
"option-133", "", &dhcp_universe, 133,
|
||||
"option-134", "", &dhcp_universe, 134,
|
||||
"option-135", "", &dhcp_universe, 135,
|
||||
"option-136", "", &dhcp_universe, 136,
|
||||
"option-137", "", &dhcp_universe, 137,
|
||||
"option-138", "", &dhcp_universe, 138,
|
||||
"option-139", "", &dhcp_universe, 139,
|
||||
"option-140", "", &dhcp_universe, 140,
|
||||
"option-141", "", &dhcp_universe, 141,
|
||||
"option-142", "", &dhcp_universe, 142,
|
||||
"option-143", "", &dhcp_universe, 143,
|
||||
"option-144", "", &dhcp_universe, 144,
|
||||
"option-145", "", &dhcp_universe, 145,
|
||||
"option-146", "", &dhcp_universe, 146,
|
||||
"option-147", "", &dhcp_universe, 147,
|
||||
"option-148", "", &dhcp_universe, 148,
|
||||
"option-149", "", &dhcp_universe, 149,
|
||||
"option-150", "", &dhcp_universe, 150,
|
||||
"option-151", "", &dhcp_universe, 151,
|
||||
"option-152", "", &dhcp_universe, 152,
|
||||
"option-153", "", &dhcp_universe, 153,
|
||||
"option-154", "", &dhcp_universe, 154,
|
||||
"option-155", "", &dhcp_universe, 155,
|
||||
"option-156", "", &dhcp_universe, 156,
|
||||
"option-157", "", &dhcp_universe, 157,
|
||||
"option-158", "", &dhcp_universe, 158,
|
||||
"option-159", "", &dhcp_universe, 159,
|
||||
"option-160", "", &dhcp_universe, 160,
|
||||
"option-161", "", &dhcp_universe, 161,
|
||||
"option-162", "", &dhcp_universe, 162,
|
||||
"option-163", "", &dhcp_universe, 163,
|
||||
"option-164", "", &dhcp_universe, 164,
|
||||
"option-165", "", &dhcp_universe, 165,
|
||||
"option-166", "", &dhcp_universe, 166,
|
||||
"option-167", "", &dhcp_universe, 167,
|
||||
"option-168", "", &dhcp_universe, 168,
|
||||
"option-169", "", &dhcp_universe, 169,
|
||||
"option-170", "", &dhcp_universe, 170,
|
||||
"option-171", "", &dhcp_universe, 171,
|
||||
"option-172", "", &dhcp_universe, 172,
|
||||
"option-173", "", &dhcp_universe, 173,
|
||||
"option-174", "", &dhcp_universe, 174,
|
||||
"option-175", "", &dhcp_universe, 175,
|
||||
"option-176", "", &dhcp_universe, 176,
|
||||
"option-177", "", &dhcp_universe, 177,
|
||||
"option-178", "", &dhcp_universe, 178,
|
||||
"option-179", "", &dhcp_universe, 179,
|
||||
"option-180", "", &dhcp_universe, 180,
|
||||
"option-181", "", &dhcp_universe, 181,
|
||||
"option-182", "", &dhcp_universe, 182,
|
||||
"option-183", "", &dhcp_universe, 183,
|
||||
"option-184", "", &dhcp_universe, 184,
|
||||
"option-185", "", &dhcp_universe, 185,
|
||||
"option-186", "", &dhcp_universe, 186,
|
||||
"option-187", "", &dhcp_universe, 187,
|
||||
"option-188", "", &dhcp_universe, 188,
|
||||
"option-189", "", &dhcp_universe, 189,
|
||||
"option-190", "", &dhcp_universe, 190,
|
||||
"option-191", "", &dhcp_universe, 191,
|
||||
"option-192", "", &dhcp_universe, 192,
|
||||
"option-193", "", &dhcp_universe, 193,
|
||||
"option-194", "", &dhcp_universe, 194,
|
||||
"option-195", "", &dhcp_universe, 195,
|
||||
"option-196", "", &dhcp_universe, 196,
|
||||
"option-197", "", &dhcp_universe, 197,
|
||||
"option-198", "", &dhcp_universe, 198,
|
||||
"option-199", "", &dhcp_universe, 199,
|
||||
"option-200", "", &dhcp_universe, 200,
|
||||
"option-201", "", &dhcp_universe, 201,
|
||||
"option-202", "", &dhcp_universe, 202,
|
||||
"option-203", "", &dhcp_universe, 203,
|
||||
"option-204", "", &dhcp_universe, 204,
|
||||
"option-205", "", &dhcp_universe, 205,
|
||||
"option-206", "", &dhcp_universe, 206,
|
||||
"option-207", "", &dhcp_universe, 207,
|
||||
"option-208", "", &dhcp_universe, 208,
|
||||
"option-209", "", &dhcp_universe, 209,
|
||||
"option-210", "", &dhcp_universe, 210,
|
||||
"option-211", "", &dhcp_universe, 211,
|
||||
"option-212", "", &dhcp_universe, 212,
|
||||
"option-213", "", &dhcp_universe, 213,
|
||||
"option-214", "", &dhcp_universe, 214,
|
||||
"option-215", "", &dhcp_universe, 215,
|
||||
"option-216", "", &dhcp_universe, 216,
|
||||
"option-217", "", &dhcp_universe, 217,
|
||||
"option-218", "", &dhcp_universe, 218,
|
||||
"option-219", "", &dhcp_universe, 219,
|
||||
"option-220", "", &dhcp_universe, 220,
|
||||
"option-221", "", &dhcp_universe, 221,
|
||||
"option-222", "", &dhcp_universe, 222,
|
||||
"option-223", "", &dhcp_universe, 223,
|
||||
"option-224", "", &dhcp_universe, 224,
|
||||
"option-225", "", &dhcp_universe, 225,
|
||||
"option-226", "", &dhcp_universe, 226,
|
||||
"option-227", "", &dhcp_universe, 227,
|
||||
"option-228", "", &dhcp_universe, 228,
|
||||
"option-229", "", &dhcp_universe, 229,
|
||||
"option-230", "", &dhcp_universe, 230,
|
||||
"option-231", "", &dhcp_universe, 231,
|
||||
"option-232", "", &dhcp_universe, 232,
|
||||
"option-233", "", &dhcp_universe, 233,
|
||||
"option-234", "", &dhcp_universe, 234,
|
||||
"option-235", "", &dhcp_universe, 235,
|
||||
"option-236", "", &dhcp_universe, 236,
|
||||
"option-237", "", &dhcp_universe, 237,
|
||||
"option-238", "", &dhcp_universe, 238,
|
||||
"option-239", "", &dhcp_universe, 239,
|
||||
"option-240", "", &dhcp_universe, 240,
|
||||
"option-241", "", &dhcp_universe, 241,
|
||||
"option-242", "", &dhcp_universe, 242,
|
||||
"option-243", "", &dhcp_universe, 243,
|
||||
"option-244", "", &dhcp_universe, 244,
|
||||
"option-245", "", &dhcp_universe, 245,
|
||||
"option-246", "", &dhcp_universe, 246,
|
||||
"option-247", "", &dhcp_universe, 247,
|
||||
"option-248", "", &dhcp_universe, 248,
|
||||
"option-249", "", &dhcp_universe, 249,
|
||||
"option-250", "", &dhcp_universe, 250,
|
||||
"option-251", "", &dhcp_universe, 251,
|
||||
"option-252", "", &dhcp_universe, 252,
|
||||
"option-253", "", &dhcp_universe, 253,
|
||||
"option-254", "", &dhcp_universe, 254,
|
||||
"option-end", "e", &dhcp_universe, 255,
|
||||
};
|
||||
|
||||
/* Default dhcp option priority list (this is ad hoc and should not be
|
||||
mistaken for a carefully crafted and optimized list). */
|
||||
unsigned char dhcp_option_default_priority_list [] = {
|
||||
DHO_SUBNET_MASK,
|
||||
DHO_TIME_OFFSET,
|
||||
DHO_ROUTERS,
|
||||
DHO_TIME_SERVERS,
|
||||
DHO_NAME_SERVERS,
|
||||
DHO_DOMAIN_NAME_SERVERS,
|
||||
DHO_LOG_SERVERS,
|
||||
DHO_COOKIE_SERVERS,
|
||||
DHO_LPR_SERVERS,
|
||||
DHO_IMPRESS_SERVERS,
|
||||
DHO_RESOURCE_LOCATION_SERVERS,
|
||||
DHO_HOST_NAME,
|
||||
DHO_BOOT_SIZE,
|
||||
DHO_MERIT_DUMP,
|
||||
DHO_DOMAIN_NAME,
|
||||
DHO_SWAP_SERVER,
|
||||
DHO_ROOT_PATH,
|
||||
DHO_EXTENSIONS_PATH,
|
||||
DHO_IP_FORWARDING,
|
||||
DHO_NON_LOCAL_SOURCE_ROUTING,
|
||||
DHO_POLICY_FILTER,
|
||||
DHO_MAX_DGRAM_REASSEMBLY,
|
||||
DHO_DEFAULT_IP_TTL,
|
||||
DHO_PATH_MTU_AGING_TIMEOUT,
|
||||
DHO_PATH_MTU_PLATEAU_TABLE,
|
||||
DHO_INTERFACE_MTU,
|
||||
DHO_ALL_SUBNETS_LOCAL,
|
||||
DHO_BROADCAST_ADDRESS,
|
||||
DHO_PERFORM_MASK_DISCOVERY,
|
||||
DHO_MASK_SUPPLIER,
|
||||
DHO_ROUTER_DISCOVERY,
|
||||
DHO_ROUTER_SOLICITATION_ADDRESS,
|
||||
DHO_STATIC_ROUTES,
|
||||
DHO_TRAILER_ENCAPSULATION,
|
||||
DHO_ARP_CACHE_TIMEOUT,
|
||||
DHO_IEEE802_3_ENCAPSULATION,
|
||||
DHO_DEFAULT_TCP_TTL,
|
||||
DHO_TCP_KEEPALIVE_INTERVAL,
|
||||
DHO_TCP_KEEPALIVE_GARBAGE,
|
||||
DHO_NIS_DOMAIN,
|
||||
DHO_NIS_SERVERS,
|
||||
DHO_NTP_SERVERS,
|
||||
DHO_VENDOR_ENCAPSULATED_OPTIONS,
|
||||
DHO_NETBIOS_NAME_SERVERS,
|
||||
DHO_NETBIOS_DD_SERVER,
|
||||
DHO_NETBIOS_NODE_TYPE,
|
||||
DHO_NETBIOS_SCOPE,
|
||||
DHO_FONT_SERVERS,
|
||||
DHO_X_DISPLAY_MANAGER,
|
||||
DHO_DHCP_REQUESTED_ADDRESS,
|
||||
DHO_DHCP_LEASE_TIME,
|
||||
DHO_DHCP_OPTION_OVERLOAD,
|
||||
DHO_DHCP_MESSAGE_TYPE,
|
||||
DHO_DHCP_SERVER_IDENTIFIER,
|
||||
DHO_DHCP_PARAMETER_REQUEST_LIST,
|
||||
DHO_DHCP_MESSAGE,
|
||||
DHO_DHCP_MAX_MESSAGE_SIZE,
|
||||
DHO_DHCP_RENEWAL_TIME,
|
||||
DHO_DHCP_REBINDING_TIME,
|
||||
DHO_DHCP_CLASS_IDENTIFIER,
|
||||
DHO_DHCP_CLIENT_IDENTIFIER,
|
||||
};
|
||||
|
||||
int sizeof_dhcp_option_default_priority_list =
|
||||
sizeof dhcp_option_default_priority_list;
|
||||
|
||||
|
||||
struct hash_table universe_hash;
|
||||
|
||||
void initialize_universes()
|
||||
{
|
||||
int i;
|
||||
|
||||
dhcp_universe.name = "dhcp";
|
||||
dhcp_universe.hash = new_hash ();
|
||||
if (!dhcp_universe.hash)
|
||||
error ("Can't allocate dhcp option hash table.");
|
||||
for (i = 0; i < 256; i++) {
|
||||
dhcp_universe.options [i] = &dhcp_options [i];
|
||||
add_hash (dhcp_universe.hash, dhcp_options [i].name, 0,
|
||||
(unsigned char *)&dhcp_options [i]);
|
||||
}
|
||||
universe_hash.hash_count = DEFAULT_HASH_SIZE;
|
||||
add_hash (&universe_hash, dhcp_universe.name, 0,
|
||||
(unsigned char *)&dhcp_universe);
|
||||
}
|
391
common/tree.c
Normal file
391
common/tree.c
Normal file
@@ -0,0 +1,391 @@
|
||||
/* tree.c
|
||||
|
||||
Routines for manipulating parse trees... */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of The Internet Software Consortium nor the names
|
||||
* of its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This software has been written for the Internet Software Consortium
|
||||
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
||||
* Enterprises. To learn more about the Internet Software Consortium,
|
||||
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
||||
* Enterprises, see ``http://www.vix.com''.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
|
||||
static TIME tree_evaluate_recurse PROTO ((int *, unsigned char **, int *,
|
||||
struct tree *));
|
||||
static TIME do_host_lookup PROTO ((int *, unsigned char **, int *,
|
||||
struct dns_host_entry *));
|
||||
static void do_data_copy PROTO ((int *, unsigned char **, int *,
|
||||
unsigned char *, int));
|
||||
|
||||
pair cons (car, cdr)
|
||||
caddr_t car;
|
||||
pair cdr;
|
||||
{
|
||||
pair foo = (pair)dmalloc (sizeof *foo, "cons");
|
||||
if (!foo)
|
||||
error ("no memory for cons.");
|
||||
foo -> car = car;
|
||||
foo -> cdr = cdr;
|
||||
return foo;
|
||||
}
|
||||
|
||||
struct tree_cache *tree_cache (tree)
|
||||
struct tree *tree;
|
||||
{
|
||||
struct tree_cache *tc;
|
||||
|
||||
tc = new_tree_cache ("tree_cache");
|
||||
if (!tc)
|
||||
return 0;
|
||||
tc -> value = (char *)0;
|
||||
tc -> len = tc -> buf_size = 0;
|
||||
tc -> timeout = 0;
|
||||
tc -> tree = tree;
|
||||
return tc;
|
||||
}
|
||||
|
||||
struct tree *tree_host_lookup (name)
|
||||
char *name;
|
||||
{
|
||||
struct tree *nt;
|
||||
nt = new_tree ("tree_host_lookup");
|
||||
if (!nt)
|
||||
error ("No memory for host lookup tree node.");
|
||||
nt -> op = TREE_HOST_LOOKUP;
|
||||
nt -> data.host_lookup.host = enter_dns_host (name);
|
||||
return nt;
|
||||
}
|
||||
|
||||
struct dns_host_entry *enter_dns_host (name)
|
||||
char *name;
|
||||
{
|
||||
struct dns_host_entry *dh;
|
||||
|
||||
if (!(dh = (struct dns_host_entry *)dmalloc
|
||||
(sizeof (struct dns_host_entry), "enter_dns_host"))
|
||||
|| !(dh -> hostname = dmalloc (strlen (name) + 1,
|
||||
"enter_dns_host")))
|
||||
error ("Can't allocate space for new host.");
|
||||
strcpy (dh -> hostname, name);
|
||||
dh -> data = (unsigned char *)0;
|
||||
dh -> data_len = 0;
|
||||
dh -> timeout = 0;
|
||||
return dh;
|
||||
}
|
||||
|
||||
struct tree *tree_const (data, len)
|
||||
unsigned char *data;
|
||||
int len;
|
||||
{
|
||||
struct tree *nt;
|
||||
if (!(nt = new_tree ("tree_const"))
|
||||
|| !(nt -> data.const_val.data =
|
||||
(unsigned char *)dmalloc (len, "tree_const")))
|
||||
error ("No memory for constant data tree node.");
|
||||
nt -> op = TREE_CONST;
|
||||
memcpy (nt -> data.const_val.data, data, len);
|
||||
nt -> data.const_val.len = len;
|
||||
return nt;
|
||||
}
|
||||
|
||||
struct tree *tree_concat (left, right)
|
||||
struct tree *left, *right;
|
||||
{
|
||||
struct tree *nt;
|
||||
|
||||
/* If we're concatenating a null tree to a non-null tree, just
|
||||
return the non-null tree; if both trees are null, return
|
||||
a null tree. */
|
||||
if (!left)
|
||||
return right;
|
||||
if (!right)
|
||||
return left;
|
||||
|
||||
/* If both trees are constant, combine them. */
|
||||
if (left -> op = TREE_CONST && right -> op == TREE_CONST) {
|
||||
unsigned char *buf = dmalloc (left -> data.const_val.len
|
||||
+ right -> data.const_val.len,
|
||||
"tree_concat");
|
||||
if (!buf)
|
||||
error ("No memory to concatenate constants.");
|
||||
memcpy (buf, left -> data.const_val.data,
|
||||
left -> data.const_val.len);
|
||||
memcpy (buf + left -> data.const_val.len,
|
||||
right -> data.const_val.data,
|
||||
right -> data.const_val.len);
|
||||
dfree (left -> data.const_val.data, "tree_concat");
|
||||
dfree (right -> data.const_val.data, "tree_concat");
|
||||
left -> data.const_val.data = buf;
|
||||
left -> data.const_val.len += right -> data.const_val.len;
|
||||
free_tree (right, "tree_concat");
|
||||
return left;
|
||||
}
|
||||
|
||||
/* Otherwise, allocate a new node to concatenate the two. */
|
||||
if (!(nt = new_tree ("tree_concat")))
|
||||
error ("No memory for data tree concatenation node.");
|
||||
nt -> op = TREE_CONCAT;
|
||||
nt -> data.concat.left = left;
|
||||
nt -> data.concat.right = right;
|
||||
return nt;
|
||||
}
|
||||
|
||||
struct tree *tree_limit (tree, limit)
|
||||
struct tree *tree;
|
||||
int limit;
|
||||
{
|
||||
struct tree *rv;
|
||||
|
||||
/* If the tree we're limiting is constant, limit it now. */
|
||||
if (tree -> op == TREE_CONST) {
|
||||
if (tree -> data.const_val.len > limit)
|
||||
tree -> data.const_val.len = limit;
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* Otherwise, put in a node which enforces the limit on evaluation. */
|
||||
rv = new_tree ("tree_limit");
|
||||
if (!rv)
|
||||
return (struct tree *)0;
|
||||
rv -> op = TREE_LIMIT;
|
||||
rv -> data.limit.tree = tree;
|
||||
rv -> data.limit.limit = limit;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int tree_evaluate (tree_cache)
|
||||
struct tree_cache *tree_cache;
|
||||
{
|
||||
unsigned char *bp = tree_cache -> value;
|
||||
int bc = tree_cache -> buf_size;
|
||||
int bufix = 0;
|
||||
|
||||
/* If there's no tree associated with this cache, it evaluates
|
||||
to a constant and that was detected at startup. */
|
||||
if (!tree_cache -> tree)
|
||||
return 1;
|
||||
|
||||
/* Try to evaluate the tree without allocating more memory... */
|
||||
tree_cache -> timeout = tree_evaluate_recurse (&bufix, &bp, &bc,
|
||||
tree_cache -> tree);
|
||||
|
||||
/* No additional allocation needed? */
|
||||
if (bufix <= bc) {
|
||||
tree_cache -> len = bufix;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If we can't allocate more memory, return with what we
|
||||
have (maybe nothing). */
|
||||
if (!(bp = (unsigned char *)dmalloc (bufix, "tree_evaluate")))
|
||||
return 0;
|
||||
|
||||
/* Record the change in conditions... */
|
||||
bc = bufix;
|
||||
bufix = 0;
|
||||
|
||||
/* Note that the size of the result shouldn't change on the
|
||||
second call to tree_evaluate_recurse, since we haven't
|
||||
changed the ``current'' time. */
|
||||
tree_evaluate_recurse (&bufix, &bp, &bc, tree_cache -> tree);
|
||||
|
||||
/* Free the old buffer if needed, then store the new buffer
|
||||
location and size and return. */
|
||||
if (tree_cache -> value)
|
||||
dfree (tree_cache -> value, "tree_evaluate");
|
||||
tree_cache -> value = bp;
|
||||
tree_cache -> len = bufix;
|
||||
tree_cache -> buf_size = bc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static TIME tree_evaluate_recurse (bufix, bufp, bufcount, tree)
|
||||
int *bufix;
|
||||
unsigned char **bufp;
|
||||
int *bufcount;
|
||||
struct tree *tree;
|
||||
{
|
||||
int limit;
|
||||
TIME t1, t2;
|
||||
|
||||
switch (tree -> op) {
|
||||
case TREE_CONCAT:
|
||||
t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
|
||||
tree -> data.concat.left);
|
||||
t2 = tree_evaluate_recurse (bufix, bufp, bufcount,
|
||||
tree -> data.concat.right);
|
||||
if (t1 > t2)
|
||||
return t2;
|
||||
return t1;
|
||||
|
||||
case TREE_HOST_LOOKUP:
|
||||
return do_host_lookup (bufix, bufp, bufcount,
|
||||
tree -> data.host_lookup.host);
|
||||
|
||||
case TREE_CONST:
|
||||
do_data_copy (bufix, bufp, bufcount,
|
||||
tree -> data.const_val.data,
|
||||
tree -> data.const_val.len);
|
||||
t1 = MAX_TIME;
|
||||
return t1;
|
||||
|
||||
case TREE_LIMIT:
|
||||
limit = *bufix + tree -> data.limit.limit;
|
||||
t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
|
||||
tree -> data.limit.tree);
|
||||
*bufix = limit;
|
||||
return t1;
|
||||
|
||||
default:
|
||||
warn ("Bad node id in tree: %d.");
|
||||
t1 = MAX_TIME;
|
||||
return t1;
|
||||
}
|
||||
}
|
||||
|
||||
static TIME do_host_lookup (bufix, bufp, bufcount, dns)
|
||||
int *bufix;
|
||||
unsigned char **bufp;
|
||||
int *bufcount;
|
||||
struct dns_host_entry *dns;
|
||||
{
|
||||
struct hostent *h;
|
||||
int i;
|
||||
int new_len;
|
||||
|
||||
debug ("time: now = %d dns = %d %d diff = %d",
|
||||
cur_time, dns -> timeout, cur_time - dns -> timeout);
|
||||
|
||||
/* If the record hasn't timed out, just copy the data and return. */
|
||||
if (cur_time <= dns -> timeout) {
|
||||
debug ("easy copy: %x %d %x",
|
||||
dns -> data, dns -> data_len, *(int *)(dns -> data));
|
||||
do_data_copy (bufix, bufp, bufcount,
|
||||
dns -> data, dns -> data_len);
|
||||
return dns -> timeout;
|
||||
}
|
||||
debug ("Looking up %s", dns -> hostname);
|
||||
|
||||
/* Otherwise, look it up... */
|
||||
h = gethostbyname (dns -> hostname);
|
||||
if (!h) {
|
||||
switch (h_errno) {
|
||||
case HOST_NOT_FOUND:
|
||||
warn ("%s: host unknown.", dns -> hostname);
|
||||
break;
|
||||
case TRY_AGAIN:
|
||||
warn ("%s: temporary name server failure",
|
||||
dns -> hostname);
|
||||
break;
|
||||
case NO_RECOVERY:
|
||||
warn ("%s: name server failed", dns -> hostname);
|
||||
break;
|
||||
case NO_DATA:
|
||||
warn ("%s: no A record associated with address",
|
||||
dns -> hostname);
|
||||
}
|
||||
|
||||
/* Okay to try again after a minute. */
|
||||
return cur_time + 60;
|
||||
}
|
||||
|
||||
debug ("Lookup succeeded; first address is %x",
|
||||
h -> h_addr_list [0]);
|
||||
|
||||
/* Count the number of addresses we got... */
|
||||
for (i = 0; h -> h_addr_list [i]; i++)
|
||||
;
|
||||
|
||||
/* Do we need to allocate more memory? */
|
||||
new_len = i * h -> h_length;
|
||||
if (dns -> buf_len < i) {
|
||||
unsigned char *buf =
|
||||
(unsigned char *)dmalloc (new_len, "do_host_lookup");
|
||||
/* If we didn't get more memory, use what we have. */
|
||||
if (!buf) {
|
||||
new_len = dns -> buf_len;
|
||||
if (!dns -> buf_len) {
|
||||
dns -> timeout = cur_time + 60;
|
||||
return dns -> timeout;
|
||||
}
|
||||
} else {
|
||||
dfree (dns -> data, "do_host_lookup");
|
||||
dns -> data = buf;
|
||||
dns -> buf_len = new_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Addresses are conveniently stored one to the buffer, so we
|
||||
have to copy them out one at a time... :'( */
|
||||
for (i = 0; i < new_len / h -> h_length; i++)
|
||||
memcpy (dns -> data + h -> h_length * i,
|
||||
h -> h_addr_list [i], h -> h_length);
|
||||
debug ("dns -> data: %x h -> h_addr_list [0]: %x",
|
||||
*(int *)(dns -> data), h -> h_addr_list [0]);
|
||||
dns -> data_len = new_len;
|
||||
|
||||
/* Set the timeout for an hour from now.
|
||||
XXX This should really use the time on the DNS reply. */
|
||||
dns -> timeout = cur_time + 3600;
|
||||
|
||||
debug ("hard copy: %x %d %x",
|
||||
dns -> data, dns -> data_len, *(int *)(dns -> data));
|
||||
do_data_copy (bufix, bufp, bufcount, dns -> data, dns -> data_len);
|
||||
return dns -> timeout;
|
||||
}
|
||||
|
||||
static void do_data_copy (bufix, bufp, bufcount, data, len)
|
||||
int *bufix;
|
||||
unsigned char **bufp;
|
||||
int *bufcount;
|
||||
unsigned char *data;
|
||||
int len;
|
||||
{
|
||||
int space = *bufcount - *bufix;
|
||||
|
||||
/* If there's more space than we need, use only what we need. */
|
||||
if (space > len)
|
||||
space = len;
|
||||
|
||||
/* Copy as much data as will fit, then increment the buffer index
|
||||
by the amount we actually had to copy, which could be more. */
|
||||
if (space > 0)
|
||||
memcpy (*bufp + *bufix, data, space);
|
||||
*bufix += len;
|
||||
}
|
Reference in New Issue
Block a user