2
0
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:
Ted Lemon
1995-11-29 07:40:04 +00:00
commit d7837182d3
64 changed files with 18448 additions and 0 deletions

197
common/alloc.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}