Import the OpenBSD dhclient as shipped with OpenBSD-3.7 (the tag

OPENBSD_3_7).
This commit is contained in:
Brooks Davis 2005-06-07 04:05:09 +00:00
parent a9c7144e7a
commit 47c0859616
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/OpenBSD/dist/; revision=147072
29 changed files with 10434 additions and 20 deletions

View File

@ -1,30 +1,48 @@
# ex:ts=8
# $OpenBSD: Makefile,v 1.9 2004/05/04 12:52:05 henning Exp $
#
# @(#)Makefile 1.0 (obrien) 2/6/99
# $Id$
# Copyright (c) 1996, 1997 The Internet Software Consortium.
# All rights reserved.
#
# Copyright (c) 1999 by David O'Brien
# This file is under a "FreeBSD" copyright. See /usr/src/sys/sys/copyright.h
# for the terms of the copyright.
# 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.
#
.PATH: ${.CURDIR}/../../contrib/isc-dhcp/client ${.CURDIR}/../../contrib/isc-dhcp/common
.include <bsd.own.mk>
PROG= dhclient
MAN5= dhclient.conf.5 dhclient.leases.5 dhcp-options.5
MAN8= dhclient.8 dhclient-script.8
SRCS= dhclient.c clparse.c alloc.c dispatch.c hash.c bpf.c options.c \
tree.c conflex.c errwarn.c inet.c packet.c convert.c tables.c \
parse.c privsep.c
SRCS= dhclient.c clparse.c
SRCS+= raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c \
socket.c packet.c memory.c print.c options.c inet.c convert.c \
tree.c tables.c hash.c alloc.c errwarn.c inet_addr.c
PROG= dhclient
MAN= dhclient.8 dhclient.conf.5 dhclient.leases.5 dhclient-script.8
CFLAGS+= -I${.CURDIR}/../../contrib/isc-dhcp/includes \
-I${.CURDIR}/../../contrib/isc-dhcp
CFLAGS+=-Wall
afterinstall:
${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
${.CURDIR}/../../contrib/isc-dhcp/client/scripts/freebsd \
${BINDIR}/dhclient-script
beforeinstall:
${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
${.CURDIR}/dhclient-script ${DESTDIR}/sbin/dhclient-script
.include <bsd.prog.mk>

76
sbin/dhclient/alloc.c Normal file
View File

@ -0,0 +1,76 @@
/* $OpenBSD: alloc.c,v 1.9 2004/05/04 20:28:40 deraadt Exp $ */
/* Memory allocation... */
/*
* Copyright (c) 1995, 1996, 1998 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''.
*/
#include "dhcpd.h"
struct string_list *
new_string_list(size_t size)
{
struct string_list *rval;
rval = calloc(1, sizeof(struct string_list) + size);
if (rval != NULL)
rval->string = ((char *)rval) + sizeof(struct string_list);
return (rval);
}
struct hash_table *
new_hash_table(int count)
{
struct hash_table *rval;
rval = calloc(1, sizeof(struct hash_table) -
(DEFAULT_HASH_SIZE * sizeof(struct hash_bucket *)) +
(count * sizeof(struct hash_bucket *)));
if (rval == NULL)
return (NULL);
rval->hash_count = count;
return (rval);
}
struct hash_bucket *
new_hash_bucket(void)
{
struct hash_bucket *rval = calloc(1, sizeof(struct hash_bucket));
return (rval);
}

374
sbin/dhclient/bpf.c Normal file
View File

@ -0,0 +1,374 @@
/* $OpenBSD: bpf.c,v 1.13 2004/05/05 14:28:58 deraadt Exp $ */
/* BPF socket interface code, originally contributed by Archie Cobbs. */
/*
* Copyright (c) 1995, 1996, 1998, 1999
* 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''.
*/
#include "dhcpd.h"
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <net/bpf.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/if_ether.h>
#define BPF_FORMAT "/dev/bpf%d"
/*
* Called by get_interface_list for each interface that's discovered.
* Opens a packet filter for each interface and adds it to the select
* mask.
*/
int
if_register_bpf(struct interface_info *info)
{
char filename[50];
int sock, b;
/* Open a BPF device */
for (b = 0; 1; b++) {
snprintf(filename, sizeof(filename), BPF_FORMAT, b);
sock = open(filename, O_RDWR, 0);
if (sock < 0) {
if (errno == EBUSY)
continue;
else
error("Can't find free bpf: %m");
} else
break;
}
/* Set the BPF device to point at this interface. */
if (ioctl(sock, BIOCSETIF, info->ifp) < 0)
error("Can't attach interface %s to bpf device %s: %m",
info->name, filename);
return (sock);
}
void
if_register_send(struct interface_info *info)
{
/*
* If we're using the bpf API for sending and receiving, we
* don't need to register this interface twice.
*/
info->wfdesc = info->rfdesc;
}
/*
* Packet filter program...
*
* XXX: Changes to the filter program may require changes to the
* constant offsets used in if_register_send to patch the BPF program!
*/
struct bpf_insn dhcp_bpf_filter[] = {
/* Make sure this is an IP packet... */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
/* Make sure it's a UDP packet... */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
/* Make sure this isn't a fragment... */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
/* Get the IP header length... */
BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),
/* Make sure it's to the right port... */
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */
/* If we passed all the tests, ask for the whole packet. */
BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
/* Otherwise, drop it. */
BPF_STMT(BPF_RET+BPF_K, 0),
};
int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn);
/*
* Packet write filter program:
* 'ip and udp and src port bootps and dst port (bootps or bootpc)'
*/
struct bpf_insn dhcp_bpf_wfilter[] = {
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12),
/* Make sure this is an IP packet... */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10),
/* Make sure it's a UDP packet... */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8),
/* Make sure this isn't a fragment... */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0), /* patched */
/* Get the IP header length... */
BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),
/* Make sure it's from the right port... */
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 68, 0, 3),
/* Make sure it is to the right ports ... */
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
/* If we passed all the tests, ask for the whole packet. */
BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
/* Otherwise, drop it. */
BPF_STMT(BPF_RET+BPF_K, 0),
};
int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn);
void
if_register_receive(struct interface_info *info)
{
struct bpf_version v;
struct bpf_program p;
int flag = 1, sz;
/* Open a BPF device and hang it on this interface... */
info->rfdesc = if_register_bpf(info);
/* Make sure the BPF version is in range... */
if (ioctl(info->rfdesc, BIOCVERSION, &v) < 0)
error("Can't get BPF version: %m");
if (v.bv_major != BPF_MAJOR_VERSION ||
v.bv_minor < BPF_MINOR_VERSION)
error("Kernel BPF version out of range - recompile dhcpd!");
/*
* Set immediate mode so that reads return as soon as a packet
* comes in, rather than waiting for the input buffer to fill
* with packets.
*/
if (ioctl(info->rfdesc, BIOCIMMEDIATE, &flag) < 0)
error("Can't set immediate mode on bpf device: %m");
/* Get the required BPF buffer length from the kernel. */
if (ioctl(info->rfdesc, BIOCGBLEN, &sz) < 0)
error("Can't get bpf buffer length: %m");
info->rbuf_max = sz;
info->rbuf = malloc(info->rbuf_max);
if (!info->rbuf)
error("Can't allocate %lu bytes for bpf input buffer.",
(unsigned long)info->rbuf_max);
info->rbuf_offset = 0;
info->rbuf_len = 0;
/* Set up the bpf filter program structure. */
p.bf_len = dhcp_bpf_filter_len;
p.bf_insns = dhcp_bpf_filter;
/* Patch the server port into the BPF program...
*
* XXX: changes to filter program may require changes to the
* insn number(s) used below!
*/
dhcp_bpf_filter[8].k = LOCAL_PORT;
if (ioctl(info->rfdesc, BIOCSETF, &p) < 0)
error("Can't install packet filter program: %m");
/* Set up the bpf write filter program structure. */
p.bf_len = dhcp_bpf_wfilter_len;
p.bf_insns = dhcp_bpf_wfilter;
if (dhcp_bpf_wfilter[7].k == 0x1fff)
dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK);
if (ioctl(info->rfdesc, BIOCSETWF, &p) < 0)
error("Can't install write filter program: %m");
if (ioctl(info->rfdesc, BIOCLOCK, NULL) < 0)
error("Cannot lock bpf");
}
ssize_t
send_packet(struct interface_info *interface, struct dhcp_packet *raw,
size_t len, struct in_addr from, struct sockaddr_in *to,
struct hardware *hto)
{
unsigned char buf[256];
struct iovec iov[2];
int result, bufp = 0;
/* Assemble the headers... */
assemble_hw_header(interface, buf, &bufp, hto);
assemble_udp_ip_header(buf, &bufp, from.s_addr,
to->sin_addr.s_addr, to->sin_port, (unsigned char *)raw, len);
/* Fire it off */
iov[0].iov_base = (char *)buf;
iov[0].iov_len = bufp;
iov[1].iov_base = (char *)raw;
iov[1].iov_len = len;
result = writev(interface->wfdesc, iov, 2);
if (result < 0)
warning("send_packet: %m");
return (result);
}
ssize_t
receive_packet(struct interface_info *interface, unsigned char *buf,
size_t len, struct sockaddr_in *from, struct hardware *hfrom)
{
int length = 0, offset = 0;
struct bpf_hdr hdr;
/*
* All this complexity is because BPF doesn't guarantee that
* only one packet will be returned at a time. We're getting
* what we deserve, though - this is a terrible abuse of the BPF
* interface. Sigh.
*/
/* Process packets until we get one we can return or until we've
* done a read and gotten nothing we can return...
*/
do {
/* If the buffer is empty, fill it. */
if (interface->rbuf_offset == interface->rbuf_len) {
length = read(interface->rfdesc, interface->rbuf,
interface->rbuf_max);
if (length <= 0)
return (length);
interface->rbuf_offset = 0;
interface->rbuf_len = length;
}
/*
* If there isn't room for a whole bpf header, something
* went wrong, but we'll ignore it and hope it goes
* away... XXX
*/
if (interface->rbuf_len - interface->rbuf_offset <
sizeof(hdr)) {
interface->rbuf_offset = interface->rbuf_len;
continue;
}
/* Copy out a bpf header... */
memcpy(&hdr, &interface->rbuf[interface->rbuf_offset],
sizeof(hdr));
/*
* If the bpf header plus data doesn't fit in what's
* left of the buffer, stick head in sand yet again...
*/
if (interface->rbuf_offset + hdr.bh_hdrlen + hdr.bh_caplen >
interface->rbuf_len) {
interface->rbuf_offset = interface->rbuf_len;
continue;
}
/*
* If the captured data wasn't the whole packet, or if
* the packet won't fit in the input buffer, all we can
* do is drop it.
*/
if (hdr.bh_caplen != hdr.bh_datalen) {
interface->rbuf_offset += hdr.bh_hdrlen = hdr.bh_caplen;
continue;
}
/* Skip over the BPF header... */
interface->rbuf_offset += hdr.bh_hdrlen;
/* Decode the physical header... */
offset = decode_hw_header(interface->rbuf,
interface->rbuf_offset, hfrom);
/*
* If a physical layer checksum failed (dunno of any
* physical layer that supports this, but WTH), skip
* this packet.
*/
if (offset < 0) {
interface->rbuf_offset += hdr.bh_caplen;
continue;
}
interface->rbuf_offset += offset;
hdr.bh_caplen -= offset;
/* Decode the IP and UDP headers... */
offset = decode_udp_ip_header(interface->rbuf,
interface->rbuf_offset, from, NULL, hdr.bh_caplen);
/* If the IP or UDP checksum was bad, skip the packet... */
if (offset < 0) {
interface->rbuf_offset += hdr.bh_caplen;
continue;
}
interface->rbuf_offset += offset;
hdr.bh_caplen -= offset;
/*
* If there's not enough room to stash the packet data,
* we have to skip it (this shouldn't happen in real
* life, though).
*/
if (hdr.bh_caplen > len) {
interface->rbuf_offset += hdr.bh_caplen;
continue;
}
/* Copy out the data in the packet... */
memcpy(buf, interface->rbuf + interface->rbuf_offset,
hdr.bh_caplen);
interface->rbuf_offset += hdr.bh_caplen;
return (hdr.bh_caplen);
} while (!length);
return (0);
}

938
sbin/dhclient/clparse.c Normal file
View File

@ -0,0 +1,938 @@
/* $OpenBSD: clparse.c,v 1.18 2004/09/15 18:15:18 henning Exp $ */
/* Parser for dhclient config and lease files... */
/*
* Copyright (c) 1997 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''.
*/
#include "dhcpd.h"
#include "dhctoken.h"
struct client_config top_level_config;
struct interface_info *dummy_interfaces;
extern struct interface_info *ifi;
char client_script_name[] = "/sbin/dhclient-script";
/*
* client-conf-file :== client-declarations EOF
* client-declarations :== <nil>
* | client-declaration
* | client-declarations client-declaration
*/
int
read_client_conf(void)
{
FILE *cfile;
char *val;
int token;
struct client_config *config;
new_parse(path_dhclient_conf);
/* Set up the initial dhcp option universe. */
initialize_universes();
/* Initialize the top level client configuration. */
memset(&top_level_config, 0, sizeof(top_level_config));
/* Set some defaults... */
top_level_config.timeout = 60;
top_level_config.select_interval = 0;
top_level_config.reboot_timeout = 10;
top_level_config.retry_interval = 300;
top_level_config.backoff_cutoff = 15;
top_level_config.initial_interval = 3;
top_level_config.bootp_policy = ACCEPT;
top_level_config.script_name = client_script_name;
top_level_config.requested_options
[top_level_config.requested_option_count++] = DHO_SUBNET_MASK;
top_level_config.requested_options
[top_level_config.requested_option_count++] = DHO_BROADCAST_ADDRESS;
top_level_config.requested_options
[top_level_config.requested_option_count++] = DHO_TIME_OFFSET;
top_level_config.requested_options
[top_level_config.requested_option_count++] = DHO_ROUTERS;
top_level_config.requested_options
[top_level_config.requested_option_count++] = DHO_DOMAIN_NAME;
top_level_config.requested_options
[top_level_config.requested_option_count++] =
DHO_DOMAIN_NAME_SERVERS;
top_level_config.requested_options
[top_level_config.requested_option_count++] = DHO_HOST_NAME;
if ((cfile = fopen(path_dhclient_conf, "r")) != NULL) {
do {
token = peek_token(&val, cfile);
if (token == EOF)
break;
parse_client_statement(cfile, NULL, &top_level_config);
} while (1);
token = next_token(&val, cfile); /* Clear the peek buffer */
fclose(cfile);
}
/*
* Set up state and config structures for clients that don't
* have per-interface configuration declarations.
*/
config = NULL;
if (!ifi->client) {
ifi->client = malloc(sizeof(struct client_state));
if (!ifi->client)
error("no memory for client state.");
memset(ifi->client, 0, sizeof(*(ifi->client)));
}
if (!ifi->client->config) {
if (!config) {
config = malloc(sizeof(struct client_config));
if (!config)
error("no memory for client config.");
memcpy(config, &top_level_config,
sizeof(top_level_config));
}
ifi->client->config = config;
}
return (!warnings_occurred);
}
/*
* lease-file :== client-lease-statements EOF
* client-lease-statements :== <nil>
* | client-lease-statements LEASE client-lease-statement
*/
void
read_client_leases(void)
{
FILE *cfile;
char *val;
int token;
new_parse(path_dhclient_db);
/* Open the lease file. If we can't open it, just return -
we can safely trust the server to remember our state. */
if ((cfile = fopen(path_dhclient_db, "r")) == NULL)
return;
do {
token = next_token(&val, cfile);
if (token == EOF)
break;
if (token != LEASE) {
warning("Corrupt lease file - possible data loss!");
skip_to_semi(cfile);
break;
} else
parse_client_lease_statement(cfile, 0);
} while (1);
fclose(cfile);
}
/*
* client-declaration :==
* SEND option-decl |
* DEFAULT option-decl |
* SUPERSEDE option-decl |
* PREPEND option-decl |
* APPEND option-decl |
* hardware-declaration |
* REQUEST option-list |
* REQUIRE option-list |
* TIMEOUT number |
* RETRY number |
* REBOOT number |
* SELECT_TIMEOUT number |
* SCRIPT string |
* interface-declaration |
* LEASE client-lease-statement |
* ALIAS client-lease-statement
*/
void
parse_client_statement(FILE *cfile, struct interface_info *ip,
struct client_config *config)
{
int token;
char *val;
struct option *option;
switch (next_token(&val, cfile)) {
case SEND:
parse_option_decl(cfile, &config->send_options[0]);
return;
case DEFAULT:
option = parse_option_decl(cfile, &config->defaults[0]);
if (option)
config->default_actions[option->code] = ACTION_DEFAULT;
return;
case SUPERSEDE:
option = parse_option_decl(cfile, &config->defaults[0]);
if (option)
config->default_actions[option->code] =
ACTION_SUPERSEDE;
return;
case APPEND:
option = parse_option_decl(cfile, &config->defaults[0]);
if (option)
config->default_actions[option->code] = ACTION_APPEND;
return;
case PREPEND:
option = parse_option_decl(cfile, &config->defaults[0]);
if (option)
config->default_actions[option->code] = ACTION_PREPEND;
return;
case MEDIA:
parse_string_list(cfile, &config->media, 1);
return;
case HARDWARE:
if (ip)
parse_hardware_param(cfile, &ip->hw_address);
else {
parse_warn("hardware address parameter %s",
"not allowed here.");
skip_to_semi(cfile);
}
return;
case REQUEST:
config->requested_option_count =
parse_option_list(cfile, config->requested_options);
return;
case REQUIRE:
memset(config->required_options, 0,
sizeof(config->required_options));
parse_option_list(cfile, config->required_options);
return;
case TIMEOUT:
parse_lease_time(cfile, &config->timeout);
return;
case RETRY:
parse_lease_time(cfile, &config->retry_interval);
return;
case SELECT_TIMEOUT:
parse_lease_time(cfile, &config->select_interval);
return;
case REBOOT:
parse_lease_time(cfile, &config->reboot_timeout);
return;
case BACKOFF_CUTOFF:
parse_lease_time(cfile, &config->backoff_cutoff);
return;
case INITIAL_INTERVAL:
parse_lease_time(cfile, &config->initial_interval);
return;
case SCRIPT:
config->script_name = parse_string(cfile);
return;
case INTERFACE:
if (ip)
parse_warn("nested interface declaration.");
parse_interface_declaration(cfile, config);
return;
case LEASE:
parse_client_lease_statement(cfile, 1);
return;
case ALIAS:
parse_client_lease_statement(cfile, 2);
return;
case REJECT:
parse_reject_statement(cfile, config);
return;
default:
parse_warn("expecting a statement.");
skip_to_semi(cfile);
break;
}
token = next_token(&val, cfile);
if (token != SEMI) {
parse_warn("semicolon expected.");
skip_to_semi(cfile);
}
}
int
parse_X(FILE *cfile, u_int8_t *buf, int max)
{
int token;
char *val;
int len;
token = peek_token(&val, cfile);
if (token == NUMBER_OR_NAME || token == NUMBER) {
len = 0;
do {
token = next_token(&val, cfile);
if (token != NUMBER && token != NUMBER_OR_NAME) {
parse_warn("expecting hexadecimal constant.");
skip_to_semi(cfile);
return (0);
}
convert_num(&buf[len], val, 16, 8);
if (len++ > max) {
parse_warn("hexadecimal constant too long.");
skip_to_semi(cfile);
return (0);
}
token = peek_token(&val, cfile);
if (token == COLON)
token = next_token(&val, cfile);
} while (token == COLON);
val = (char *)buf;
} else if (token == STRING) {
token = next_token(&val, cfile);
len = strlen(val);
if (len + 1 > max) {
parse_warn("string constant too long.");
skip_to_semi(cfile);
return (0);
}
memcpy(buf, val, len + 1);
} else {
parse_warn("expecting string or hexadecimal data");
skip_to_semi(cfile);
return (0);
}
return (len);
}
/*
* option-list :== option_name |
* option_list COMMA option_name
*/
int
parse_option_list(FILE *cfile, u_int8_t *list)
{
int ix, i;
int token;
char *val;
ix = 0;
do {
token = next_token(&val, cfile);
if (!is_identifier(token)) {
parse_warn("expected option name.");
skip_to_semi(cfile);
return (0);
}
for (i = 0; i < 256; i++)
if (!strcasecmp(dhcp_options[i].name, val))
break;
if (i == 256) {
parse_warn("%s: unexpected option name.", val);
skip_to_semi(cfile);
return (0);
}
list[ix++] = i;
if (ix == 256) {
parse_warn("%s: too many options.", val);
skip_to_semi(cfile);
return (0);
}
token = next_token(&val, cfile);
} while (token == COMMA);
if (token != SEMI) {
parse_warn("expecting semicolon.");
skip_to_semi(cfile);
return (0);
}
return (ix);
}
/*
* interface-declaration :==
* INTERFACE string LBRACE client-declarations RBRACE
*/
void
parse_interface_declaration(FILE *cfile, struct client_config *outer_config)
{
int token;
char *val;
struct interface_info *ip;
token = next_token(&val, cfile);
if (token != STRING) {
parse_warn("expecting interface name (in quotes).");
skip_to_semi(cfile);
return;
}
ip = interface_or_dummy(val);
if (!ip->client)
make_client_state(ip);
if (!ip->client->config)
make_client_config(ip, outer_config);
token = next_token(&val, cfile);
if (token != LBRACE) {
parse_warn("expecting left brace.");
skip_to_semi(cfile);
return;
}
do {
token = peek_token(&val, cfile);
if (token == EOF) {
parse_warn("unterminated interface declaration.");
return;
}
if (token == RBRACE)
break;
parse_client_statement(cfile, ip, ip->client->config);
} while (1);
token = next_token(&val, cfile);
}
struct interface_info *
interface_or_dummy(char *name)
{
struct interface_info *ip;
/* Find the interface (if any) that matches the name. */
if (!strcmp(ifi->name, name))
return (ifi);
/* If it's not a real interface, see if it's on the dummy list. */
for (ip = dummy_interfaces; ip; ip = ip->next)
if (!strcmp(ip->name, name))
return (ip);
/*
* If we didn't find an interface, make a dummy interface as a
* placeholder.
*/
ip = malloc(sizeof(*ip));
if (!ip)
error("Insufficient memory to record interface %s", name);
memset(ip, 0, sizeof(*ip));
strlcpy(ip->name, name, IFNAMSIZ);
ip->next = dummy_interfaces;
dummy_interfaces = ip;
return (ip);
}
void
make_client_state(struct interface_info *ip)
{
ip->client = malloc(sizeof(*(ip->client)));
if (!ip->client)
error("no memory for state on %s", ip->name);
memset(ip->client, 0, sizeof(*(ip->client)));
}
void
make_client_config(struct interface_info *ip, struct client_config *config)
{
ip->client->config = malloc(sizeof(struct client_config));
if (!ip->client->config)
error("no memory for config for %s", ip->name);
memset(ip->client->config, 0, sizeof(*(ip->client->config)));
memcpy(ip->client->config, config, sizeof(*config));
}
/*
* client-lease-statement :==
* RBRACE client-lease-declarations LBRACE
*
* client-lease-declarations :==
* <nil> |
* client-lease-declaration |
* client-lease-declarations client-lease-declaration
*/
void
parse_client_lease_statement(FILE *cfile, int is_static)
{
struct client_lease *lease, *lp, *pl;
struct interface_info *ip;
int token;
char *val;
token = next_token(&val, cfile);
if (token != LBRACE) {
parse_warn("expecting left brace.");
skip_to_semi(cfile);
return;
}
lease = malloc(sizeof(struct client_lease));
if (!lease)
error("no memory for lease.");
memset(lease, 0, sizeof(*lease));
lease->is_static = is_static;
ip = NULL;
do {
token = peek_token(&val, cfile);
if (token == EOF) {
parse_warn("unterminated lease declaration.");
return;
}
if (token == RBRACE)
break;
parse_client_lease_declaration(cfile, lease, &ip);
} while (1);
token = next_token(&val, cfile);
/* If the lease declaration didn't include an interface
* declaration that we recognized, it's of no use to us.
*/
if (!ip) {
free_client_lease(lease);
return;
}
/* Make sure there's a client state structure... */
if (!ip->client)
make_client_state(ip);
/* If this is an alias lease, it doesn't need to be sorted in. */
if (is_static == 2) {
ip->client->alias = lease;
return;
}
/*
* The new lease may supersede a lease that's not the active
* lease but is still on the lease list, so scan the lease list
* looking for a lease with the same address, and if we find it,
* toss it.
*/
pl = NULL;
for (lp = ip->client->leases; lp; lp = lp->next) {
if (lp->address.len == lease->address.len &&
!memcmp(lp->address.iabuf, lease->address.iabuf,
lease->address.len)) {
if (pl)
pl->next = lp->next;
else
ip->client->leases = lp->next;
free_client_lease(lp);
break;
}
}
/*
* If this is a preloaded lease, just put it on the list of
* recorded leases - don't make it the active lease.
*/
if (is_static) {
lease->next = ip->client->leases;
ip->client->leases = lease;
return;
}
/*
* The last lease in the lease file on a particular interface is
* the active lease for that interface. Of course, we don't
* know what the last lease in the file is until we've parsed
* the whole file, so at this point, we assume that the lease we
* just parsed is the active lease for its interface. If
* there's already an active lease for the interface, and this
* lease is for the same ip address, then we just toss the old
* active lease and replace it with this one. If this lease is
* for a different address, then if the old active lease has
* expired, we dump it; if not, we put it on the list of leases
* for this interface which are still valid but no longer
* active.
*/
if (ip->client->active) {
if (ip->client->active->expiry < cur_time)
free_client_lease(ip->client->active);
else if (ip->client->active->address.len ==
lease->address.len &&
!memcmp(ip->client->active->address.iabuf,
lease->address.iabuf, lease->address.len))
free_client_lease(ip->client->active);
else {
ip->client->active->next = ip->client->leases;
ip->client->leases = ip->client->active;
}
}
ip->client->active = lease;
/* Phew. */
}
/*
* client-lease-declaration :==
* BOOTP |
* INTERFACE string |
* FIXED_ADDR ip_address |
* FILENAME string |
* SERVER_NAME string |
* OPTION option-decl |
* RENEW time-decl |
* REBIND time-decl |
* EXPIRE time-decl
*/
void
parse_client_lease_declaration(FILE *cfile, struct client_lease *lease,
struct interface_info **ipp)
{
int token;
char *val;
struct interface_info *ip;
switch (next_token(&val, cfile)) {
case BOOTP:
lease->is_bootp = 1;
break;
case INTERFACE:
token = next_token(&val, cfile);
if (token != STRING) {
parse_warn("expecting interface name (in quotes).");
skip_to_semi(cfile);
break;
}
ip = interface_or_dummy(val);
*ipp = ip;
break;
case FIXED_ADDR:
if (!parse_ip_addr(cfile, &lease->address))
return;
break;
case MEDIUM:
parse_string_list(cfile, &lease->medium, 0);
return;
case FILENAME:
lease->filename = parse_string(cfile);
return;
case SERVER_NAME:
lease->server_name = parse_string(cfile);
return;
case RENEW:
lease->renewal = parse_date(cfile);
return;
case REBIND:
lease->rebind = parse_date(cfile);
return;
case EXPIRE:
lease->expiry = parse_date(cfile);
return;
case OPTION:
parse_option_decl(cfile, lease->options);
return;
default:
parse_warn("expecting lease declaration.");
skip_to_semi(cfile);
break;
}
token = next_token(&val, cfile);
if (token != SEMI) {
parse_warn("expecting semicolon.");
skip_to_semi(cfile);
}
}
struct option *
parse_option_decl(FILE *cfile, struct option_data *options)
{
char *val;
int token;
u_int8_t buf[4];
u_int8_t hunkbuf[1024];
int hunkix = 0;
char *vendor;
char *fmt;
struct universe *universe;
struct option *option;
struct iaddr ip_addr;
u_int8_t *dp;
int len;
int nul_term = 0;
token = next_token(&val, cfile);
if (!is_identifier(token)) {
parse_warn("expecting identifier after option keyword.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
if ((vendor = strdup(val)) == NULL)
error("no memory for vendor information.");
token = peek_token(&val, cfile);
if (token == DOT) {
/* Go ahead and take the DOT token... */
token = next_token(&val, cfile);
/* The next token should be an identifier... */
token = next_token(&val, cfile);
if (!is_identifier(token)) {
parse_warn("expecting identifier after '.'");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
/* Look up the option name hash table for the specified
vendor. */
universe = ((struct universe *)hash_lookup(&universe_hash,
(unsigned char *)vendor, 0));
/* If it's not there, we can't parse the rest of the
declaration. */
if (!universe) {
parse_warn("no vendor named %s.", vendor);
skip_to_semi(cfile);
return (NULL);
}
} else {
/* Use the default hash table, which contains all the
standard dhcp option names. */
val = vendor;
universe = &dhcp_universe;
}
/* Look up the actual option info... */
option = (struct option *)hash_lookup(universe->hash,
(unsigned char *)val, 0);
/* If we didn't get an option structure, it's an undefined option. */
if (!option) {
if (val == vendor)
parse_warn("no option named %s", val);
else
parse_warn("no option named %s for vendor %s",
val, vendor);
skip_to_semi(cfile);
return (NULL);
}
/* Free the initial identifier token. */
free(vendor);
/* Parse the option data... */
do {
for (fmt = option->format; *fmt; fmt++) {
if (*fmt == 'A')
break;
switch (*fmt) {
case 'X':
len = parse_X(cfile, &hunkbuf[hunkix],
sizeof(hunkbuf) - hunkix);
hunkix += len;
break;
case 't': /* Text string... */
token = next_token(&val, cfile);
if (token != STRING) {
parse_warn("expecting string.");
skip_to_semi(cfile);
return (NULL);
}
len = strlen(val);
if (hunkix + len + 1 > sizeof(hunkbuf)) {
parse_warn("option data buffer %s",
"overflow");
skip_to_semi(cfile);
return (NULL);
}
memcpy(&hunkbuf[hunkix], val, len + 1);
nul_term = 1;
hunkix += len;
break;
case 'I': /* IP address. */
if (!parse_ip_addr(cfile, &ip_addr))
return (NULL);
len = ip_addr.len;
dp = ip_addr.iabuf;
alloc:
if (hunkix + len > sizeof(hunkbuf)) {
parse_warn("option data buffer "
"overflow");
skip_to_semi(cfile);
return (NULL);
}
memcpy(&hunkbuf[hunkix], dp, len);
hunkix += len;
break;
case 'L': /* Unsigned 32-bit integer... */
case 'l': /* Signed 32-bit integer... */
token = next_token(&val, cfile);
if (token != NUMBER) {
need_number:
parse_warn("expecting number.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
convert_num(buf, val, 0, 32);
len = 4;
dp = buf;
goto alloc;
case 's': /* Signed 16-bit integer. */
case 'S': /* Unsigned 16-bit integer. */
token = next_token(&val, cfile);
if (token != NUMBER)
goto need_number;
convert_num(buf, val, 0, 16);
len = 2;
dp = buf;
goto alloc;
case 'b': /* Signed 8-bit integer. */
case 'B': /* Unsigned 8-bit integer. */
token = next_token(&val, cfile);
if (token != NUMBER)
goto need_number;
convert_num(buf, val, 0, 8);
len = 1;
dp = buf;
goto alloc;
case 'f': /* Boolean flag. */
token = next_token(&val, cfile);
if (!is_identifier(token)) {
parse_warn("expecting identifier.");
bad_flag:
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
if (!strcasecmp(val, "true") ||
!strcasecmp(val, "on"))
buf[0] = 1;
else if (!strcasecmp(val, "false") ||
!strcasecmp(val, "off"))
buf[0] = 0;
else {
parse_warn("expecting boolean.");
goto bad_flag;
}
len = 1;
dp = buf;
goto alloc;
default:
warning("Bad format %c in parse_option_param.",
*fmt);
skip_to_semi(cfile);
return (NULL);
}
}
token = next_token(&val, cfile);
} while (*fmt == 'A' && token == COMMA);
if (token != SEMI) {
parse_warn("semicolon expected.");
skip_to_semi(cfile);
return (NULL);
}
options[option->code].data = malloc(hunkix + nul_term);
if (!options[option->code].data)
error("out of memory allocating option data.");
memcpy(options[option->code].data, hunkbuf, hunkix + nul_term);
options[option->code].len = hunkix;
return (option);
}
void
parse_string_list(FILE *cfile, struct string_list **lp, int multiple)
{
int token;
char *val;
struct string_list *cur, *tmp;
/* Find the last medium in the media list. */
if (*lp)
for (cur = *lp; cur->next; cur = cur->next)
; /* nothing */
else
cur = NULL;
do {
token = next_token(&val, cfile);
if (token != STRING) {
parse_warn("Expecting media options.");
skip_to_semi(cfile);
return;
}
tmp = new_string_list(strlen(val) + 1);
if (tmp == NULL)
error("no memory for string list entry.");
strlcpy(tmp->string, val, strlen(val) + 1);
tmp->next = NULL;
/* Store this medium at the end of the media list. */
if (cur)
cur->next = tmp;
else
*lp = tmp;
cur = tmp;
token = next_token(&val, cfile);
} while (multiple && token == COMMA);
if (token != SEMI) {
parse_warn("expecting semicolon.");
skip_to_semi(cfile);
}
}
void
parse_reject_statement(FILE *cfile, struct client_config *config)
{
int token;
char *val;
struct iaddr addr;
struct iaddrlist *list;
do {
if (!parse_ip_addr(cfile, &addr)) {
parse_warn("expecting IP address.");
skip_to_semi(cfile);
return;
}
list = malloc(sizeof(struct iaddrlist));
if (!list)
error("no memory for reject list!");
list->addr = addr;
list->next = config->reject_list;
config->reject_list = list;
token = next_token(&val, cfile);
} while (token == COMMA);
if (token != SEMI) {
parse_warn("expecting semicolon.");
skip_to_semi(cfile);
}
}

525
sbin/dhclient/conflex.c Normal file
View File

@ -0,0 +1,525 @@
/* $OpenBSD: conflex.c,v 1.7 2004/09/15 19:02:38 deraadt Exp $ */
/* Lexical scanner for dhcpd config file... */
/*
* Copyright (c) 1995, 1996, 1997 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''.
*/
#include <ctype.h>
#include "dhcpd.h"
#include "dhctoken.h"
int lexline;
int lexchar;
char *token_line;
char *prev_line;
char *cur_line;
char *tlname;
int eol_token;
static char line1[81];
static char line2[81];
static int lpos;
static int line;
static int tlpos;
static int tline;
static int token;
static int ugflag;
static char *tval;
static char tokbuf[1500];
static int get_char(FILE *);
static int get_token(FILE *);
static void skip_to_eol(FILE *);
static int read_string(FILE *);
static int read_number(int, FILE *);
static int read_num_or_name(int, FILE *);
static int intern(char *, int);
void
new_parse(char *name)
{
tlname = name;
lpos = line = 1;
cur_line = line1;
prev_line = line2;
token_line = cur_line;
cur_line[0] = prev_line[0] = 0;
warnings_occurred = 0;
}
static int
get_char(FILE *cfile)
{
int c = getc(cfile);
if (!ugflag) {
if (c == '\n') {
if (cur_line == line1) {
cur_line = line2;
prev_line = line1;
} else {
cur_line = line2;
prev_line = line1;
}
line++;
lpos = 1;
cur_line[0] = 0;
} else if (c != EOF) {
if (lpos <= 81) {
cur_line[lpos - 1] = c;
cur_line[lpos] = 0;
}
lpos++;
}
} else
ugflag = 0;
return (c);
}
static int
get_token(FILE *cfile)
{
int c, ttok;
static char tb[2];
int l, p;
do {
l = line;
p = lpos;
c = get_char(cfile);
if (!(c == '\n' && eol_token) && isascii(c) && isspace(c))
continue;
if (c == '#') {
skip_to_eol(cfile);
continue;
}
if (c == '"') {
lexline = l;
lexchar = p;
ttok = read_string(cfile);
break;
}
if ((isascii(c) && isdigit(c)) || c == '-') {
lexline = l;
lexchar = p;
ttok = read_number(c, cfile);
break;
} else if (isascii(c) && isalpha(c)) {
lexline = l;
lexchar = p;
ttok = read_num_or_name(c, cfile);
break;
} else {
lexline = l;
lexchar = p;
tb[0] = c;
tb[1] = 0;
tval = tb;
ttok = c;
break;
}
} while (1);
return (ttok);
}
int
next_token(char **rval, FILE *cfile)
{
int rv;
if (token) {
if (lexline != tline)
token_line = cur_line;
lexchar = tlpos;
lexline = tline;
rv = token;
token = 0;
} else {
rv = get_token(cfile);
token_line = cur_line;
}
if (rval)
*rval = tval;
return (rv);
}
int
peek_token(char **rval, FILE *cfile)
{
int x;
if (!token) {
tlpos = lexchar;
tline = lexline;
token = get_token(cfile);
if (lexline != tline)
token_line = prev_line;
x = lexchar;
lexchar = tlpos;
tlpos = x;
x = lexline;
lexline = tline;
tline = x;
}
if (rval)
*rval = tval;
return (token);
}
static void
skip_to_eol(FILE *cfile)
{
int c;
do {
c = get_char(cfile);
if (c == EOF)
return;
if (c == '\n')
return;
} while (1);
}
static int
read_string(FILE *cfile)
{
int i, c, bs = 0;
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(int c, FILE *cfile)
{
int seenx = 0, i = 0, token = NUMBER;
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 (token);
}
static int
read_num_or_name(int c, FILE *cfile)
{
int i = 0;
int rv = NUMBER_OR_NAME;
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 = NAME;
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(char *atom, int dfv)
{
if (!isascii(atom[0]))
return (dfv);
switch (tolower(atom[0])) {
case 'a':
if (!strcasecmp(atom + 1, "lways-reply-rfc1048"))
return (ALWAYS_REPLY_RFC1048);
if (!strcasecmp(atom + 1, "ppend"))
return (APPEND);
if (!strcasecmp(atom + 1, "llow"))
return (ALLOW);
if (!strcasecmp(atom + 1, "lias"))
return (ALIAS);
if (!strcasecmp(atom + 1, "bandoned"))
return (ABANDONED);
if (!strcasecmp(atom + 1, "uthoritative"))
return (AUTHORITATIVE);
break;
case 'b':
if (!strcasecmp(atom + 1, "ackoff-cutoff"))
return (BACKOFF_CUTOFF);
if (!strcasecmp(atom + 1, "ootp"))
return (BOOTP);
if (!strcasecmp(atom + 1, "ooting"))
return (BOOTING);
if (!strcasecmp(atom + 1, "oot-unknown-clients"))
return (BOOT_UNKNOWN_CLIENTS);
case 'c':
if (!strcasecmp(atom + 1, "lass"))
return (CLASS);
if (!strcasecmp(atom + 1, "iaddr"))
return (CIADDR);
if (!strcasecmp(atom + 1, "lient-identifier"))
return (CLIENT_IDENTIFIER);
if (!strcasecmp(atom + 1, "lient-hostname"))
return (CLIENT_HOSTNAME);
break;
case 'd':
if (!strcasecmp(atom + 1, "omain"))
return (DOMAIN);
if (!strcasecmp(atom + 1, "eny"))
return (DENY);
if (!strncasecmp(atom + 1, "efault", 6)) {
if (!atom[7])
return (DEFAULT);
if (!strcasecmp(atom + 7, "-lease-time"))
return (DEFAULT_LEASE_TIME);
break;
}
if (!strncasecmp(atom + 1, "ynamic-bootp", 12)) {
if (!atom[13])
return (DYNAMIC_BOOTP);
if (!strcasecmp(atom + 13, "-lease-cutoff"))
return (DYNAMIC_BOOTP_LEASE_CUTOFF);
if (!strcasecmp(atom + 13, "-lease-length"))
return (DYNAMIC_BOOTP_LEASE_LENGTH);
break;
}
break;
case 'e':
if (!strcasecmp(atom + 1, "thernet"))
return (ETHERNET);
if (!strcasecmp(atom + 1, "nds"))
return (ENDS);
if (!strcasecmp(atom + 1, "xpire"))
return (EXPIRE);
break;
case 'f':
if (!strcasecmp(atom + 1, "ilename"))
return (FILENAME);
if (!strcasecmp(atom + 1, "ixed-address"))
return (FIXED_ADDR);
if (!strcasecmp(atom + 1, "ddi"))
return (FDDI);
break;
case 'g':
if (!strcasecmp(atom + 1, "iaddr"))
return (GIADDR);
if (!strcasecmp(atom + 1, "roup"))
return (GROUP);
if (!strcasecmp(atom + 1, "et-lease-hostnames"))
return (GET_LEASE_HOSTNAMES);
break;
case 'h':
if (!strcasecmp(atom + 1, "ost"))
return (HOST);
if (!strcasecmp(atom + 1, "ardware"))
return (HARDWARE);
if (!strcasecmp(atom + 1, "ostname"))
return (HOSTNAME);
break;
case 'i':
if (!strcasecmp(atom + 1, "nitial-interval"))
return (INITIAL_INTERVAL);
if (!strcasecmp(atom + 1, "nterface"))
return (INTERFACE);
break;
case 'l':
if (!strcasecmp(atom + 1, "ease"))
return (LEASE);
break;
case 'm':
if (!strcasecmp(atom + 1, "ax-lease-time"))
return (MAX_LEASE_TIME);
if (!strncasecmp(atom + 1, "edi", 3)) {
if (!strcasecmp(atom + 4, "a"))
return (MEDIA);
if (!strcasecmp(atom + 4, "um"))
return (MEDIUM);
break;
}
break;
case 'n':
if (!strcasecmp(atom + 1, "ameserver"))
return (NAMESERVER);
if (!strcasecmp(atom + 1, "etmask"))
return (NETMASK);
if (!strcasecmp(atom + 1, "ext-server"))
return (NEXT_SERVER);
if (!strcasecmp(atom + 1, "ot"))
return (TOKEN_NOT);
break;
case 'o':
if (!strcasecmp(atom + 1, "ption"))
return (OPTION);
if (!strcasecmp(atom + 1, "ne-lease-per-client"))
return (ONE_LEASE_PER_CLIENT);
break;
case 'p':
if (!strcasecmp(atom + 1, "repend"))
return (PREPEND);
if (!strcasecmp(atom + 1, "acket"))
return (PACKET);
break;
case 'r':
if (!strcasecmp(atom + 1, "ange"))
return (RANGE);
if (!strcasecmp(atom + 1, "equest"))
return (REQUEST);
if (!strcasecmp(atom + 1, "equire"))
return (REQUIRE);
if (!strcasecmp(atom + 1, "etry"))
return (RETRY);
if (!strcasecmp(atom + 1, "enew"))
return (RENEW);
if (!strcasecmp(atom + 1, "ebind"))
return (REBIND);
if (!strcasecmp(atom + 1, "eboot"))
return (REBOOT);
if (!strcasecmp(atom + 1, "eject"))
return (REJECT);
break;
case 's':
if (!strcasecmp(atom + 1, "earch"))
return (SEARCH);
if (!strcasecmp(atom + 1, "tarts"))
return (STARTS);
if (!strcasecmp(atom + 1, "iaddr"))
return (SIADDR);
if (!strcasecmp(atom + 1, "ubnet"))
return (SUBNET);
if (!strcasecmp(atom + 1, "hared-network"))
return (SHARED_NETWORK);
if (!strcasecmp(atom + 1, "erver-name"))
return (SERVER_NAME);
if (!strcasecmp(atom + 1, "erver-identifier"))
return (SERVER_IDENTIFIER);
if (!strcasecmp(atom + 1, "elect-timeout"))
return (SELECT_TIMEOUT);
if (!strcasecmp(atom + 1, "end"))
return (SEND);
if (!strcasecmp(atom + 1, "cript"))
return (SCRIPT);
if (!strcasecmp(atom + 1, "upersede"))
return (SUPERSEDE);
break;
case 't':
if (!strcasecmp(atom + 1, "imestamp"))
return (TIMESTAMP);
if (!strcasecmp(atom + 1, "imeout"))
return (TIMEOUT);
if (!strcasecmp(atom + 1, "oken-ring"))
return (TOKEN_RING);
break;
case 'u':
if (!strncasecmp(atom + 1, "se", 2)) {
if (!strcasecmp(atom + 3, "r-class"))
return (USER_CLASS);
if (!strcasecmp(atom + 3, "-host-decl-names"))
return (USE_HOST_DECL_NAMES);
if (!strcasecmp(atom + 3,
"-lease-addr-for-default-route"))
return (USE_LEASE_ADDR_FOR_DEFAULT_ROUTE);
break;
}
if (!strcasecmp(atom + 1, "id"))
return (UID);
if (!strcasecmp(atom + 1, "nknown-clients"))
return (UNKNOWN_CLIENTS);
break;
case 'v':
if (!strcasecmp(atom + 1, "endor-class"))
return (VENDOR_CLASS);
break;
case 'y':
if (!strcasecmp(atom + 1, "iaddr"))
return (YIADDR);
break;
}
return (dfv);
}

114
sbin/dhclient/convert.c Normal file
View File

@ -0,0 +1,114 @@
/* $OpenBSD: convert.c,v 1.5 2004/02/07 11:35:59 henning Exp $ */
/*
* Safe copying of option values into and out of the option buffer,
* which can't be assumed to be aligned.
*/
/*
* Copyright (c) 1995, 1996 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''.
*/
#include "dhcpd.h"
u_int32_t
getULong(unsigned char *buf)
{
u_int32_t ibuf;
memcpy(&ibuf, buf, sizeof(ibuf));
return (ntohl(ibuf));
}
int32_t
getLong(unsigned char *(buf))
{
int32_t ibuf;
memcpy(&ibuf, buf, sizeof(ibuf));
return (ntohl(ibuf));
}
u_int16_t
getUShort(unsigned char *buf)
{
u_int16_t ibuf;
memcpy(&ibuf, buf, sizeof(ibuf));
return (ntohs(ibuf));
}
int16_t
getShort(unsigned char *buf)
{
int16_t ibuf;
memcpy(&ibuf, buf, sizeof(ibuf));
return (ntohs(ibuf));
}
void
putULong(unsigned char *obuf, u_int32_t val)
{
u_int32_t tmp = htonl(val);
memcpy(obuf, &tmp, sizeof(tmp));
}
void
putLong(unsigned char *obuf, int32_t val)
{
int32_t tmp = htonl(val);
memcpy(obuf, &tmp, sizeof(tmp));
}
void
putUShort(unsigned char *obuf, unsigned int val)
{
u_int16_t tmp = htons(val);
memcpy(obuf, &tmp, sizeof(tmp));
}
void
putShort(unsigned char *obuf, int val)
{
int16_t tmp = htons(val);
memcpy(obuf, &tmp, sizeof(tmp));
}

View File

@ -0,0 +1,227 @@
#!/bin/sh
#
# $OpenBSD: dhclient-script,v 1.6 2004/05/06 18:22:41 claudio Exp $
#
# Copyright (c) 2003 Kenneth R Westerback <krw@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#
#
# Helper functions that implement common actions.
#
delete_old_address() {
if [ -n "$old_ip_address" ]; then
ifconfig $interface inet -alias $old_ip_address $medium
route delete "$old_ip_address" 127.0.0.1 >/dev/null 2>&1
fi
}
add_new_address() {
ifconfig $interface \
inet $new_ip_address \
netmask $new_subnet_mask \
broadcast $new_broadcast_address \
$medium
# XXX Original TIMEOUT code did not do this unless $new_routers was set?
route add $new_ip_address 127.0.0.1 >/dev/null 2>&1
}
delete_old_alias() {
if [ -n "$alias_ip_address" ]; then
ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
fi
}
add_new_alias() {
if [ -n "$alias_ip_address" ]; then
ifconfig $interface inet alias $alias_ip_address netmask \
$alias_subnet_mask
route add $alias_ip_address 127.0.0.1
fi
}
delete_old_routes() {
# Delete existing default route. We only allow one, so no need to
# process $old_routers list.
route delete default >/dev/null 2>&1
if [ -n "$old_static_routes" ]; then
set $old_static_routes
while [ $# -gt 1 ]; do
route delete "$1" "$2"
shift; shift
done
fi
arp -dan
}
add_new_routes() {
route delete default >/dev/null 2>&1
for router in $new_routers; do
if [ "$new_ip_address" = "$router" ]; then
route add default -iface $router >/dev/null 2>&1
else
route add default $router >/dev/null 2>&1
fi
# 2nd and subsequent default routers error out, so explicitly
# stop processing the list after the first one.
break
done
if [ -n "$new_static_routes" ]; then
set $new_static_routes
while [ $# -gt 1 ]; do
route add $1 $2
shift; shift
done
fi
}
add_new_resolv_conf() {
# XXX Old code did not create/update resolv.conf unless both
# $new_domain_name and $new_domain_name_servers were provided. PR
# #3135 reported some ISP's only provide $new_domain_name_servers and
# thus broke the script. This code creates the resolv.conf if either
# are provided.
rm -f /etc/resolv.conf.std
if [ -n "$new_domain_name" ]; then
echo "search $new_domain_name" >>/etc/resolv.conf.std
fi
if [ -n "$new_domain_name_servers" ]; then
for nameserver in $new_domain_name_servers; do
echo "nameserver $nameserver" >>/etc/resolv.conf.std
done
fi
if [ -f /etc/resolv.conf.std ]; then
if [ -f /etc/resolv.conf.tail ]; then
cat /etc/resolv.conf.tail >>/etc/resolv.conf.std
fi
# In case (e.g. during OpenBSD installs) /etc/resolv.conf
# is a symbolic link, take care to preserve the link and write
# the new data in the correct location.
if [ -f /etc/resolv.conf ]; then
cat /etc/resolv.conf > /etc/resolv.conf.save
fi
cat /etc/resolv.conf.std > /etc/resolv.conf
rm -f /etc/resolv.conf.std
# Try to ensure correct ownership and permissions.
chown -RL root:wheel /etc/resolv.conf
chmod -RL 644 /etc/resolv.conf
return 0
fi
return 1
}
#
# Start of active code.
#
if [ -n "$new_network_number" ]; then
echo "New Network Number: $new_network_number"
fi
if [ -n "$new_broadcast_address" ]; then
echo "New Broadcast Address: $new_broadcast_address"
fi
case $reason in
MEDIUM)
ifconfig $interface $medium
ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1
sleep 1
;;
PREINIT)
delete_old_alias
ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 broadcast 255.255.255.255 up
;;
ARPCHECK|ARPSEND)
;;
BOUND|RENEW|REBIND|REBOOT)
if [ -n "$old_ip_address" ]; then
if [ "$old_ip_address" != "$alias_ip_address" ]; then
delete_old_alias
fi
if [ "$old_ip_address" != "$new_ip_address" ]; then
delete_old_address
delete_old_routes
fi
fi
if [ "$reason" = BOUND ] || \
[ "$reason" = REBOOT ] || \
[ -z "$old_ip_address" ] || \
[ "$old_ip_address" != "$new_ip_address" ]; then
add_new_address
add_new_routes
fi
if [ "$new_ip_address" != "$alias_ip_address" ]; then
add_new_alias
fi
add_new_resolv_conf
;;
EXPIRE|FAIL)
delete_old_alias
if [ -n "$old_ip_address" ]; then
delete_old_address
delete_old_routes
fi
# XXX Why add alias we just deleted above?
add_new_alias
if [ -f /etc/resolv.conf.save ]; then
cat /etc/resolv.conf.save > /etc/resolv.conf
fi
;;
TIMEOUT)
delete_old_alias
add_new_address
sleep 1
if [ -n "$new_routers" ]; then
set "$new_routers"
if ping -q -c 1 -w 1 "$1"; then
if [ "$new_ip_address" != "$alias_ip_address" ]; then
add_new_alias
fi
add_new_routes
if add_new_resolv_conf; then
exit 0
fi
fi
fi
ifconfig $interface inet -alias $new_ip_address $medium
# XXX Why not a delete_old_address as before all other invocations of
# delete_old_routes?
delete_old_routes
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,246 @@
.\" $OpenBSD: dhclient-script.8,v 1.2 2004/04/09 18:30:15 jmc Exp $
.\"
.\" Copyright (c) 1997 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.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
.Dd January 1, 1997
.Dt DHCLIENT-SCRIPT 8
.Os
.Sh NAME
.Nm dhclient-script
.Nd DHCP client network configuration script
.Sh DESCRIPTION
The DHCP client network configuration script is invoked from time to
time by
.Xr dhclient 8 .
This script is used by the DHCP client to set each interface's initial
configuration prior to requesting an address, to test the address once it
has been offered, and to set the interface's final configuration once a
lease has been acquired.
If no lease is acquired, the script is used to test predefined leases, if
any, and also called once if no valid lease can be identified.
.Pp
.\" No standard client script exists for some operating systems, even though
.\" the actual client may work, so a pioneering user may well need to create
.\" a new script or modify an existing one.
In general, customizations specific to a particular computer should be done
in the
.Pa /etc/dhclient.conf
file.
.Sh OPERATION
When
.Xr dhclient 8
needs to invoke the client configuration script, it sets up a number of
environment variables and runs
.Nm dhclient-script .
In all cases,
.Va $reason
is set to the name of the reason why the script has been invoked.
The following reasons are currently defined:
MEDIUM, PREINIT, ARPCHECK, ARPSEND, BOUND, RENEW, REBIND, REBOOT,
EXPIRE, FAIL and TIMEOUT.
.Bl -tag -width "ARPCHECK"
.It MEDIUM
The DHCP client is requesting that an interface's media type be set.
The interface name is passed in
.Va $interface ,
and the media type is passed in
.Va $medium .
.It PREINIT
The DHCP client is requesting that an interface be configured as
required in order to send packets prior to receiving an actual address.
.\" For clients which use the BSD socket library,
This means configuring the interface with an IP address of 0.0.0.0
and a broadcast address of 255.255.255.255.
.\" For other clients, it may be possible to simply configure the interface up
.\" without actually giving it an IP address at all.
The interface name is passed in
.Va $interface ,
and the media type in
.Va $medium .
.Pp
If an IP alias has been declared in
.Xr dhclient.conf 5 ,
its address will be passed in
.Va $alias_ip_address ,
and that IP alias should be deleted from the interface,
along with any routes to it.
.It ARPSEND
The DHCP client is requesting that an address that has been offered to
it be checked to see if somebody else is using it, by sending an ARP
request for that address.
It's not clear how to implement this, so no examples exist yet.
The IP address to check is passed in
.Va $new_ip_address ,
and the interface name is passed in
.Va $interface .
.It ARPCHECK
The DHCP client wants to know if a response to the ARP request sent
using ARPSEND has been received.
If one has, the script should exit with a nonzero status, indicating that
the offered address has already been requested and should be declined.
.Va $new_ip_address
and
.Va $interface
are set as with ARPSEND.
.It BOUND
The DHCP client has done an initial binding to a new address.
The new IP address is passed in
.Va $new_ip_address ,
and the interface name is passed in
.Va $interface .
The media type is passed in
.Va $medium .
Any options acquired from the server are passed using the option name
described in
.Xr dhcp-options 5 ,
except that dashes
.Pq Sq -
are replaced by underscores
.Pq Sq _
in order to make valid shell variables, and the variable names start with new_.
So for example, the new subnet mask would be passed in
.Va $new_subnet_mask .
.Pp
When a binding has been completed, a lot of network parameters are
likely to need to be set up.
A new
.Pa /etc/resolv.conf
needs to be created, using the values of
.Va $new_domain_name
and
.Va $new_domain_name_servers
(which may list more than one server, separated by spaces).
A default route should be set using
.Va $new_routers ,
and static routes may need to be set up using
.Va $new_static_routes .
.Pp
If an IP alias has been declared, it must be set up here.
The alias IP address will be written as
.Va $alias_ip_address ,
and other DHCP options that are set for the alias (e.g., subnet mask)
will be passed in variables named as described previously except starting with
$alias_ instead of $new_.
Care should be taken that the alias IP address not be used if it is identical
to the bound IP address
.Pq Va $new_ip_address ,
since the other alias parameters may be incorrect in this case.
.It RENEW
When a binding has been renewed, the script is called as in BOUND,
except that in addition to all the variables starting with $new_,
there is another set of variables starting with $old_.
Persistent settings that may have changed need to be deleted \- for example,
if a local route to the bound address is being configured, the old local
route should be deleted.
If the default route has changed, the old default route should be deleted.
If the static routes have changed, the old ones should be deleted.
Otherwise, processing can be done as with BOUND.
.It REBIND
The DHCP client has rebound to a new DHCP server.
This can be handled as with RENEW, except that if the IP address has changed,
the ARP table should be cleared.
.It REBOOT
The DHCP client has successfully reacquired its old address after a reboot.
This can be processed as with BOUND.
.It EXPIRE
The DHCP client has failed to renew its lease or acquire a new one,
and the lease has expired.
The IP address must be relinquished, and all related parameters should be
deleted, as in RENEW and REBIND.
.It FAIL
The DHCP client has been unable to contact any DHCP servers, and any
leases that have been tested have not proved to be valid.
The parameters from the last lease tested should be deconfigured.
This can be handled in the same way as EXPIRE.
.It TIMEOUT
The DHCP client has been unable to contact any DHCP servers.
However, an old lease has been identified, and its parameters have
been passed in as with BOUND.
The client configuration script should test these parameters and,
if it has reason to believe they are valid, should exit with a value of zero.
If not, it should exit with a nonzero value.
.El
.Pp
The usual way to test a lease is to set up the network as with REBIND
(since this may be called to test more than one lease) and then ping
the first router defined in
.Va $routers .
If a response is received, the lease must be valid for the network to
which the interface is currently connected.
It would be more complete to try to ping all of the routers listed in
.Va $new_routers ,
as well as those listed in
.Va $new_static_routes ,
but current scripts do not do this.
.\" .Sh FILES
.\" Each operating system should generally have its own script file,
.\" although the script files for similar operating systems may be similar
.\" or even identical.
.\" The script files included in the Internet Software Consortium DHCP
.\" distribution appear in the distribution tree under client/scripts,
.\" and bear the names of the operating systems on which they are intended
.\" to work.
.Sh SEE ALSO
.Xr dhclient.conf 5 ,
.Xr dhclient.leases 5 ,
.Xr dhclient 8 ,
.Xr dhcpd 8 ,
.Xr dhcrelay 8
.Sh AUTHORS
The original version of
.Nm
was written for the Internet Software Consortium by
.An Ted Lemon Aq mellon@fugue.com
in cooperation with Vixie Enterprises.
.Pp
The
.Ox
implementation of
.Nm
was written by
.An Kenneth R. Westerback Aq krw@openbsd.org .
.Sh BUGS
If more than one interface is being used, there's no obvious way to
avoid clashes between server-supplied configuration parameters \- for
example, the stock dhclient-script rewrites
.Pa /etc/resolv.conf .
If more than one interface is being configured,
.Pa /etc/resolv.conf
will be repeatedly initialized to the values provided by one server, and then
the other.
Assuming the information provided by both servers is valid, this shouldn't
cause any real problems, but it could be confusing.

181
sbin/dhclient/dhclient.8 Normal file
View File

@ -0,0 +1,181 @@
.\" $OpenBSD: dhclient.8,v 1.3 2004/04/09 18:30:15 jmc Exp $
.\"
.\" Copyright (c) 1997 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.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.Dd April 7, 2004
.Dt DHCLIENT 8
.Os
.Sh NAME
.Nm dhclient
.Nd Dynamic Host Configuration Protocol (DHCP) Client
.Sh SYNOPSIS
.Nm
.Op Fl dqu
.Op Fl c Ar file
.Op Fl l Ar file
.Ar interface
.Sh DESCRIPTION
The
.Nm
utility provides a means for configuring network interfaces using DHCP, BOOTP,
or if these protocols fail, by statically assigning an address.
.Pp
The name of the network interface that
.Nm
should attempt to
configure must be specified on the command line.
.Pp
The options are as follows:
.Bl -tag -width "-p port"
.It Fl c Ar file
Specify an alternate location,
.Ar file ,
for the configuration file.
.It Fl d
Forces
.Nm
to always run as a foreground process.
By default,
.Nm
runs in the foreground until it has configured the interface, and then
will revert to running in the background.
.It Fl l Ar file
Specify an alternate location,
.Ar file ,
for the leases file.
.It Fl q
Forces
.Nm
to be less verbose on startup.
.It Fl u
Forces
.Nm
to reject leases with unknown options in them.
The default behaviour is to accept such lease offers.
.El
.Pp
The DHCP protocol allows a host to contact a central server which
maintains a list of IP addresses which may be assigned on one or more
subnets.
A DHCP client may request an address from this pool, and
then use it on a temporary basis for communication on the network.
The DHCP protocol also provides a mechanism whereby a client can learn
important details about the network to which it is attached, such as
the location of a default router, the location of a name server, and
so on.
.Pp
On startup,
.Nm
reads
.Pa /etc/dhclient.conf
for configuration instructions.
It then gets a list of all the
network interfaces that are configured in the current system.
It then attempts to configure each interface with DHCP.
.Pp
In order to keep track of leases across system reboots and server
restarts,
.Nm
keeps a list of leases it has been assigned in the
.Pa /var/db/dhclient.leases.IFNAME
file.
.Qq IFNAME
represents the network interface of the DHCP client
.Pq e.g. em0 ,
one for each interface.
On startup, after reading the
.Xr dhclient.conf 5
file,
.Nm
reads the leases file to refresh its memory about what leases it has been
assigned.
.Pp
Old leases are kept around in case the DHCP server is unavailable when
.Nm
is first invoked (generally during the initial system boot
process).
In that event, old leases from the
.Pa dhclient.leases.IFNAME
file which have not yet expired are tested, and if they are determined to
be valid, they are used until either they expire or the DHCP server
becomes available.
.Pp
A mobile host which may sometimes need to access a network on which no
DHCP server exists may be preloaded with a lease for a fixed
address on that network.
When all attempts to contact a DHCP server have failed,
.Nm
will try to validate the static lease, and if it
succeeds, it will use that lease until it is restarted.
.Pp
A mobile host may also travel to some networks on which DHCP is not
available but BOOTP is.
In that case, it may be advantageous to
arrange with the network administrator for an entry on the BOOTP
database, so that the host can boot quickly on that network rather
than cycling through the list of old leases.
.Sh NOTES
You must have the Berkeley Packet Filter (BPF) configured in your kernel.
.Nm
requires at least one
.Pa /dev/bpf*
file for each broadcast network interface that is attached to your system.
See
.Xr bpf 4
for more information.
.Sh FILES
.Bl -tag -width /var/db/dhclient.leases.IFNAME~ -compact
.It Pa /etc/dhclient.conf
DHCP client configuration file
.It Pa /var/db/dhclient.leases.IFNAME
database of acquired leases
.El
.Sh SEE ALSO
.Xr dhclient.conf 5 ,
.Xr dhclient.leases 5 ,
.Xr dhclient-script 8 ,
.Xr dhcp 8 ,
.Xr dhcpd 8 ,
.Xr dhcrelay 8
.Sh AUTHORS
.Nm
was written by
.An Ted Lemon Aq mellon@fugue.com
and
.An Elliot Poger Aq elliot@poger.com .
.Pp
The current implementation was reworked by
.An Henning Brauer Aq henning@openbsd.org .

2373
sbin/dhclient/dhclient.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
send host-name "andare.fugue.com";
send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
send dhcp-lease-time 3600;
supersede domain-name "fugue.com home.vix.com";
prepend domain-name-servers 127.0.0.1;
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, host-name;
require subnet-mask, domain-name-servers;
timeout 60;
retry 60;
reboot 10;
select-timeout 5;
initial-interval 2;
script "/etc/dhclient-script";
media "-link0 -link1 -link2", "link0 link1";
reject 192.33.137.209;
alias {
interface "ep0";
fixed-address 192.5.5.213;
option subnet-mask 255.255.255.255;
}
lease {
interface "ep0";
fixed-address 192.33.137.200;
medium "link0 link1";
option host-name "andare.swiftmedia.com";
option subnet-mask 255.255.255.0;
option broadcast-address 192.33.137.255;
option routers 192.33.137.250;
option domain-name-servers 127.0.0.1;
renew 2 2000/1/12 00:00:01;
rebind 2 2000/1/12 00:00:01;
expire 2 2000/1/12 00:00:01;
}

View File

@ -0,0 +1,541 @@
.\" $OpenBSD: dhclient.conf.5,v 1.5 2004/11/01 23:10:18 henning Exp $
.\"
.\" Copyright (c) 1997 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.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
.Dd January 1, 1997
.Dt DHCLIENT.CONF 5
.Os
.Sh NAME
.Nm dhclient.conf
.Nd DHCP client configuration file
.Sh DESCRIPTION
The
.Nm
file contains configuration information for
.Xr dhclient 8 ,
the Internet Software Consortium DHCP Client.
.Pp
The
.Nm
file is a free-form ASCII text file.
It is parsed by the recursive-descent parser built into
.Xr dhclient 8 .
The file may contain extra tabs and newlines for formatting purposes.
Keywords in the file are case-insensitive.
Comments may be placed anywhere within the file (except within quotes).
Comments begin with the
.Sq #
character and end at the end of the line.
.Pp
The
.Nm
file can be used to configure the behaviour of the client in a wide variety
of ways: protocol timing, information requested from the server, information
required of the server, defaults to use if the server does not provide
certain information, values with which to override information provided by
the server, or values to prepend or append to information provided by the
server.
The configuration file can also be preinitialized with addresses to
use on networks that don't have DHCP servers.
.Sh PROTOCOL TIMING
The timing behaviour of the client need not be configured by the user.
If no timing configuration is provided by the user, a fairly
reasonable timing behaviour will be used by default \- one which
results in fairly timely updates without placing an inordinate load on
the server.
.Pp
The following statements can be used to adjust the timing behaviour of
the DHCP client if required, however:
.Bl -tag -width Ds
.It Ic timeout Ar time ;
The
.Ic timeout
statement determines the amount of time that must pass between the
time that the client begins to try to determine its address and the
time that it decides that it's not going to be able to contact a server.
By default, this timeout is sixty seconds.
After the timeout has passed, if there are any static leases defined in the
configuration file, or any leases remaining in the lease database that
have not yet expired, the client will loop through these leases
attempting to validate them, and if it finds one that appears to be
valid, it will use that lease's address.
If there are no valid static leases or unexpired leases in the lease database,
the client will restart the protocol after the defined retry interval.
.It Ic retry Ar time ;
The
.Ic retry
statement determines the time that must pass after the client has
determined that there is no DHCP server present before it tries again
to contact a DHCP server.
By default, this is five minutes.
.It Ic select-timeout Ar time ;
It is possible (some might say desirable) for there to be more than
one DHCP server serving any given network.
In this case, it is possible that a client may be sent more than one offer
in response to its initial lease discovery message.
It may be that one of these offers is preferable to the other
(e.g., one offer may have the address the client previously used,
and the other may not).
.Pp
The
.Ic select-timeout
is the time after the client sends its first lease discovery request
at which it stops waiting for offers from servers, assuming that it
has received at least one such offer.
If no offers have been received by the time the
.Ic select-timeout
has expired, the client will accept the first offer that arrives.
.Pp
By default, the
.Ic select-timeout
is zero seconds \- that is, the client will take the first offer it sees.
.It Ic reboot Ar time ;
When the client is restarted, it first tries to reacquire the last
address it had.
This is called the INIT-REBOOT state.
If it is still attached to the same network it was attached to when it last
ran, this is the quickest way to get started.
The
.Ic reboot
statement sets the time that must elapse after the client first tries
to reacquire its old address before it gives up and tries to discover
a new address.
By default, the reboot timeout is ten seconds.
.It Ic backoff-cutoff Ar time ;
The client uses an exponential backoff algorithm with some randomness,
so that if many clients try to configure themselves at the same time,
they will not make their requests in lockstep.
The
.Ic backoff-cutoff
statement determines the maximum amount of time that the client is
allowed to back off.
It defaults to two minutes.
.It Ic initial-interval Ar time ;
The
.Ic initial-interval
statement sets the amount of time between the first attempt to reach a
server and the second attempt to reach a server.
Each time a message is sent, the interval between messages is incremented by
twice the current interval multiplied by a random number between zero and one.
If it is greater than the backoff-cutoff amount, it is set to that
amount.
It defaults to ten seconds.
.El
.Sh LEASE REQUIREMENTS AND REQUESTS
The DHCP protocol allows the client to request that the server send it
specific information, and not send it other information that it is not
prepared to accept.
The protocol also allows the client to reject offers from servers if they
don't contain information the client needs, or if the information provided
is not satisfactory.
.Pp
There is a variety of data contained in offers that DHCP servers send
to DHCP clients.
The data that can be specifically requested is what are called
.Em DHCP Options .
DHCP Options are defined in
.Xr dhcp-options 5 .
.Bl -tag -width Ds
.It Xo
.Ic request Op Ar option
.Oo , Ar ... option Oc ;
.Xc
The
.Ic request
statement causes the client to request that any server responding to the
client send the client its values for the specified options.
Only the option names should be specified in the request statement \- not
option parameters.
.It Xo
.Ic require Op Ar option
.Oo , Ar ... option Oc ;
.Xc
The
.Ic require
statement lists options that must be sent in order for an offer to be accepted.
Offers that do not contain all the listed options will be ignored.
.It Xo
.Ic send No { Op Ar option declaration
.Oo , Ar ... option declaration Oc }
.Xc
The
.Ic send
statement causes the client to send the specified options to the server with
the specified values.
These are full option declarations as described in
.Xr dhcp-options 5 .
Options that are always sent in the DHCP protocol should not be specified
here, except that the client can specify a
.Ar dhcp-lease-time
option other than the default requested lease time, which is two hours.
The other obvious use for this statement is to send information to the server
that will allow it to differentiate between this client and other
clients or kinds of clients.
.El
.Sh OPTION MODIFIERS
In some cases, a client may receive option data from the server which
is not really appropriate for that client, or may not receive
information that it needs, and for which a useful default value exists.
It may also receive information which is useful, but which needs to be
supplemented with local information.
To handle these needs, several option modifiers are available.
.Bl -tag -width Ds
.It Xo
.Ic default No { Op Ar option declaration
.Oo , Ar ... option declaration Oc }
.Xc
If for some set of options the client should use the value supplied by
the server, but needs to use some default value if no value was supplied
by the server, these values can be defined in the
.Ic default
statement.
.It Xo
.Ic supersede No { Op Ar option declaration
.Oo , Ar ... option declaration Oc }
.Xc
If for some set of options the client should always use its own value
rather than any value supplied by the server, these values can be defined
in the
.Ic supersede
statement.
.It Xo
.Ic prepend No { Op Ar option declaration
.Oo , Ar ... option declaration Oc }
.Xc
If for some set of options the client should use a value you supply,
and then use the values supplied by the server, if any,
these values can be defined in the
.Ic prepend
statement.
The
.Ic prepend
statement can only be used for options which allow more than one value to
be given.
This restriction is not enforced \- if violated, the results are unpredictable.
.It Xo
.Ic append No { Op Ar option declaration
.Oo , Ar ... option declaration Oc }
.Xc
If for some set of options the client should first use the values
supplied by the server, if any, and then use values you supply, these
values can be defined in the
.Ic append
statement.
The
.Ic append
statement can only be used for options which allow more than one value to
be given.
This restriction is not enforced \- if you ignore it,
the behaviour will be unpredictable.
.El
.Sh LEASE DECLARATIONS
The lease declaration:
.Pp
.Xo
.Ic \ \& lease No { Ar lease-declaration
.Oo Ar ... lease-declaration Oc }
.Xc
.Pp
The DHCP client may decide after some period of time (see
.Sx PROTOCOL TIMING )
that it is not going to succeed in contacting a server.
At that time, it consults its own database of old leases and tests each one
that has not yet timed out by pinging the listed router for that lease to
see if that lease could work.
It is possible to define one or more
.Em fixed
leases in the client configuration file for networks where there is no DHCP
or BOOTP service, so that the client can still automatically configure its
address.
This is done with the
.Ic lease
statement.
.Pp
NOTE: the lease statement is also used in the
.Pa dhclient.leases
file in order to record leases that have been received from DHCP servers.
Some of the syntax for leases as described below is only needed in the
.Pa dhclient.leases
file.
Such syntax is documented here for completeness.
.Pp
A lease statement consists of the lease keyword, followed by a left
curly brace, followed by one or more lease declaration statements,
followed by a right curly brace.
The following lease declarations are possible:
.Bl -tag -width Ds
.It Ic bootp ;
The
.Ic bootp
statement is used to indicate that the lease was acquired using the
BOOTP protocol rather than the DHCP protocol.
It is never necessary to specify this in the client configuration file.
The client uses this syntax in its lease database file.
.It Ic interface Ar \&"string\&" ;
The
.Ic interface
lease statement is used to indicate the interface on which the lease is valid.
If set, this lease will only be tried on a particular interface.
When the client receives a lease from a server, it always records the
interface number on which it received that lease.
If predefined leases are specified in the
.Nm
file, the interface should also be specified, although this is not required.
.It Ic fixed-address Ar ip-address ;
The
.Ic fixed-address
statement is used to set the IP address of a particular lease.
This is required for all lease statements.
The IP address must be specified as a dotted quad (e.g., 12.34.56.78).
.It Ic filename Ar \&"string\&" ;
The
.Ic filename
statement specifies the name of the boot filename to use.
This is not used by the standard client configuration script, but is
included for completeness.
.It Ic server-name Ar \&"string\&" ;
The
.Ic server-name
statement specifies the name of the boot server name to use.
This is also not used by the standard client configuration script.
.It Ic option Ar option-declaration ;
The
.Ic option
statement is used to specify the value of an option supplied by the server,
or, in the case of predefined leases declared in
.Nm dhclient.conf ,
the value that the user wishes the client configuration script to use if the
predefined lease is used.
.It Ic script Ar \&"script-name\&" ;
The
.Ic script
statement is used to specify the pathname of the DHCP client configuration
script.
This script is used by the DHCP client to set each interface's initial
configuration prior to requesting an address, to test the address once it
has been offered, and to set the interface's final configuration once a
lease has been acquired.
If no lease is acquired, the script is used to test predefined leases, if
any, and also called once if no valid lease can be identified.
For more information, see
.Xr dhclient.leases 5 .
.It Ic medium Ar \&"media setup\&" ;
The
.Ic medium
statement can be used on systems where network interfaces cannot
automatically determine the type of network to which they are connected.
The media setup string is a system-dependent parameter which is passed
to the DHCP client configuration script when initializing the interface.
On
.Ux
and UNIX-like systems, the argument is passed on the ifconfig command line
when configuring the interface.
.Pp
The DHCP client automatically declares this parameter if it used a
media type (see the
.Ic media
statement) when configuring the interface in order to obtain a lease.
This statement should be used in predefined leases only if the network
interface requires media type configuration.
.It Ic renew Ar date ;
.It Ic rebind Ar date ;
.It Ic expire Ar date ;
The
.Ic renew
statement defines the time at which the DHCP client should begin trying to
contact its server to renew a lease that it is using.
The
.Ic rebind
statement defines the time at which the DHCP client should begin to try to
contact
.Em any
DHCP server in order to renew its lease.
The
.Ic expire
statement defines the time at which the DHCP client must stop using a lease
if it has not been able to contact a server in order to renew it.
.El
.Pp
These declarations are automatically set in leases acquired by the
DHCP client, but must also be configured in predefined leases \- a
predefined lease whose expiry time has passed will not be used by the
DHCP client.
.Pp
Dates are specified as follows:
.Pp
.Ar \ \&<weekday>
.Sm off
.Ar <year> No / Ar <month> No / Ar <day>
.Ar <hour> : <minute> : <second>
.Sm on
.Pp
The weekday is present to make it easy for a human to tell when a
lease expires \- it's specified as a number from zero to six, with zero
being Sunday.
When declaring a predefined lease, it can always be specified as zero.
The year is specified with the century, so it should generally be four
digits except for really long leases.
The month is specified as a number starting with 1 for January.
The day of the month is likewise specified starting with 1.
The hour is a number between 0 and 23,
the minute a number between 0 and 59,
and the second also a number between 0 and 59.
.Sh ALIAS DECLARATIONS
.Ic alias No { Ar declarations ... No }
.Pp
Some DHCP clients running TCP/IP roaming protocols may require that in
addition to the lease they may acquire via DHCP, their interface also
be configured with a predefined IP alias so that they can have a
permanent IP address even while roaming.
The Internet Software Consortium DHCP client doesn't support roaming with
fixed addresses directly, but in order to facilitate such experimentation,
the DHCP client can be set up to configure an IP alias using the
.Ic alias
declaration.
.Pp
The
.Ic alias
declaration resembles a lease declaration, except that options other than
the subnet-mask option are ignored by the standard client configuration
script, and expiry times are ignored.
A typical alias declaration includes an interface declaration, a fixed-address
declaration for the IP alias address, and a subnet-mask option declaration.
A medium statement should never be included in an alias declaration.
.Sh OTHER DECLARATIONS
.Bl -tag -width Ds
.It Ic reject Ar ip-address ;
The
.Ic reject
statement causes the DHCP client to reject offers from servers who use
the specified address as a server identifier.
This can be used to avoid being configured by rogue or misconfigured DHCP
servers, although it should be a last resort \- better to track down
the bad DHCP server and fix it.
.It Xo
.Ic interface Ar \&"name\&" No { Ar declarations
.Ar ... No }
.Xc
A client with more than one network interface may require different
behaviour depending on which interface is being configured.
All timing parameters and declarations other than lease and alias
declarations can be enclosed in an interface declaration, and those
parameters will then be used only for the interface that matches the
specified name.
Interfaces for which there is no interface declaration will use the
parameters declared outside of any interface declaration,
or the default settings.
.It Xo
.Ic media Ar \&"media setup\&"
.Oo , Ar \&"media setup\&" , ... Oc ;
.Xc
The
.Ic media
statement defines one or more media configuration parameters which may
be tried while attempting to acquire an IP address.
The DHCP client will cycle through each media setup string on the list,
configuring the interface using that setup and attempting to boot,
and then trying the next one.
This can be used for network interfaces which aren't capable of sensing
the media type unaided \- whichever media type succeeds in getting a request
to the server and hearing the reply is probably right (no guarantees).
.Pp
The media setup is only used for the initial phase of address
acquisition (the DHCPDISCOVER and DHCPOFFER packets).
Once an address has been acquired, the DHCP client will record it in its
lease database and will record the media type used to acquire the address.
Whenever the client tries to renew the lease, it will use that same media type.
The lease must expire before the client will go back to cycling through media
types.
.El
.Sh EXAMPLES
The following configuration file is used on a laptop
which has an IP alias of 192.5.5.213, and has one interface,
ep0 (a 3Com 3C589C).
Booting intervals have been shortened somewhat from the default, because
the client is known to spend most of its time on networks with little DHCP
activity.
The laptop does roam to multiple networks.
.Bd -literal -offset indent
timeout 60;
retry 60;
reboot 10;
select-timeout 5;
initial-interval 2;
reject 192.33.137.209;
interface "ep0" {
send host-name "andare.fugue.com";
send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
send dhcp-lease-time 3600;
supersede domain-name "fugue.com rc.vix.com home.vix.com";
prepend domain-name-servers 127.0.0.1;
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, host-name;
require subnet-mask, domain-name-servers;
script "/etc/dhclient-script";
media "media 10baseT/UTP", "media 10base2/BNC";
}
alias {
interface "ep0";
fixed-address 192.5.5.213;
option subnet-mask 255.255.255.255;
}
.Ed
.Pp
This is a very complicated
.Nm
file \- in general, yours should be much simpler.
In many cases, it's sufficient to just create an empty
.Nm
file \- the defaults are usually fine.
.Sh SEE ALSO
.Xr dhclient.leases 5 ,
.Xr dhcp-options 5 ,
.Xr dhcpd.conf 5 ,
.Xr dhclient 8 ,
.Xr dhcpd 8
.Pp
RFC 2132, RFC 2131.
.Sh AUTHORS
.Xr dhclient 8
was written by
.An Ted Lemon Aq mellon@vix.com
under a contract with Vixie Labs.
.Pp
The current implementation was reworked by
.An Henning Brauer Aq henning@openbsd.org .

View File

@ -0,0 +1,87 @@
.\" $OpenBSD: dhclient.leases.5,v 1.4 2004/04/15 08:59:47 jmc Exp $
.\"
.\" Copyright (c) 1997 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.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
.Dd January 1, 1997
.Dt DHCLIENT.LEASES 5
.Os
.Sh NAME
.Nm dhclient.leases
.Nd DHCP client lease database
.Sh DESCRIPTION
The Internet Software Consortium DHCP client keeps a persistent
database of leases that it has acquired that are still valid.
The database is a free-form ASCII file containing one valid declaration
per lease.
If more than one declaration appears for a given lease,
the last one in the file is used.
The file is written as a log, so this is not an unusual occurrence.
.Pp
The lease file is named
.Qq dhclient.leases.IFNAME ,
where
.Qq IFNAME
represents the network interface the DHCP client acquired the lease on.
For example, if
.Xr dhclient 8
is configured for the em0 network device,
the lease file will be named
.Qq dhclient.leases.em0 .
.Pp
The format of the lease declarations is described in
.Xr dhclient.conf 5 .
.Sh FILES
.Bl -tag -width "/var/db/dhclient.leases.IFNAME "
.It /var/db/dhclient.leases.IFNAME
Current lease file.
.El
.Sh SEE ALSO
.Xr dhclient.conf 5 ,
.Xr dhcp-options 5 ,
.Xr dhcpd.conf 5 ,
.Xr dhclient 8 ,
.Xr dhcpd 8
.Pp
RFC 2132, RFC 2131.
.Sh AUTHORS
.Xr dhclient 8
was written by
.An Ted Lemon Aq mellon@vix.com
under a contract with Vixie Labs.
.Pp
The current implementation was reworked by
.An Henning Brauer Aq henning@openbsd.org .

View File

@ -0,0 +1,590 @@
.\" $OpenBSD: dhcp-options.5,v 1.5 2005/03/02 15:30:42 jmc Exp $
.\"
.\" Copyright (c) 1995, 1996, 1997, 1998 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.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
.Dd January 1, 1995
.Dt DHCP-OPTIONS 5
.Os
.Sh NAME
.Nm dhcp-options
.Nd Dynamic Host Configuration Protocol options
.Sh DESCRIPTION
The Dynamic Host Configuration protocol allows the client to receive
.Ic options
from the DHCP server describing the network configuration and various
services that are available on the network.
When configuring
.Xr dhcpd 8
or
.Xr dhclient 8 ,
options must often be declared.
The syntax for declaring options, and the names and formats of the options
that can be declared, are documented here.
.Sh REFERENCE: OPTION STATEMENTS
DHCP
.Ic option
statements always start with the
.Ic option
keyword, followed by an option name, followed by option data.
The option names and data formats are described below.
It is not necessary to exhaustively specify all DHCP options \-
only those options which are needed by clients must be specified.
.Pp
Option data comes in a variety of formats, as defined below:
.Pp
The
.Ar ip-address
data type can be entered either as an explicit IP address
(e.g., 239.254.197.10) or as a domain name (e.g., haagen.isc.org).
A domain name must resolve to a single IP address.
.Pp
The
.Ar int32
data type specifies a signed 32-bit integer.
The
.Ar uint32
data type specifies an unsigned 32-bit integer.
The
.Ar int16
and
.Ar uint16
data types specify signed and unsigned 16-bit integers.
The
.Ar int8
and
.Ar uint8
data types specify signed and unsigned 8-bit integers.
Unsigned 8-bit integers are also sometimes referred to as octets.
.Pp
The
.Ar string
data type specifies an
.Tn NVT
.Pq Network Virtual Terminal
.Tn ASCII
string, which must be enclosed in double quotes \- for example,
to specify a domain-name option, the syntax would be
.Pp
.Dl option domain-name \&"isc.org\&";
.Pp
The
.Ar flag
data type specifies a boolean value.
Booleans can be either true or false
(or on or off, if that makes more sense to you).
.Pp
The
.Ar data-string
data type specifies either an
.Tn NVT ASCII
string enclosed in double quotes, or a series of octets specified in
hexadecimal, separated by colons.
For example:
.Pp
.Dl option dhcp-client-identifier \&"CLIENT-FOO\&";
or
.Dl option dhcp-client-identifier 43:4c:49:45:54:2d:46:4f:4f;
.Pp
The documentation for the various options mentioned below is taken
from the IETF draft document on DHCP options, RFC 2132.
Options which are not listed by name may be defined by the name
.Pf option\- Ns Ar nnn ,
where
.Ar nnn
is the decimal number of the option code.
These options may be followed either by a string, enclosed in quotes, or by
a series of octets, expressed as two-digit hexadecimal numbers separated
by colons.
For example:
.Bd -literal -offset indent
option option-133 "my-option-133-text";
option option-129 1:54:c9:2b:47;
.Ed
.Pp
Because
.Xr dhcpd 8
does not know the format of these undefined option codes,
no checking is done to ensure the correctness of the entered data.
.Pp
The standard options are:
.Ss RFC 1497 Vendor Extensions
.Bl -tag -width Ds
.It Ic option subnet-mask Ar ip-address ;
The
.Ic subnet-mask
option specifies the client's subnet mask as per RFC 950.
If no subnet-mask option is provided anywhere in scope, as a last resort
.Xr dhcpd 8
will use the subnet mask from the subnet declaration for the network on
which an address is being assigned.
However,
.Em any
subnet-mask option declaration that is in scope for the address being
assigned will override the subnet mask specified in the subnet declaration.
.It Ic option time-offset Ar int32 ;
The
.Ic time-offset
option specifies the offset of the client's subnet in seconds from
Coordinated Universal Time (UTC).
.It Xo
.Ic option routers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic routers
option specifies a list of IP addresses for routers on the client's subnet.
Routers should be listed in order of preference.
.It Xo
.Ic option time-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic time-server
option specifies a list of RFC 868 time servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option ien116-name-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic ien116-name-servers
option specifies a list of IEN 116 name servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option domain-name-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic domain-name-servers
option specifies a list of Domain Name System (STD 13, RFC 1035) name servers
available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option log-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic log-servers
option specifies a list of MIT-LCS UDP log servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option cookie-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic cookie-servers
option specifies a list of RFC 865 cookie servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option lpr-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic lpr-servers
option specifies a list of RFC 1179 line printer servers available to the
client.
Servers should be listed in order of preference.
.It Xo
.Ic option impress-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic impress-servers
option specifies a list of Imagen Impress servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option resource-location-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
This option specifies a list of RFC 887 Resource Location servers available
to the client.
Servers should be listed in order of preference.
.It Ic option host-name Ar string ;
This option specifies the name of the client.
The name may or may not be qualified with the local domain name
(it is preferable to use the
.Ic domain-name
option to specify the domain name).
See RFC 1035 for character set restrictions.
.It Ic option boot-size Ar uint16 ;
This option specifies the length in 512-octet blocks of the default
boot image for the client.
.It Ic option merit-dump Ar string ;
This option specifies the pathname of a file to which the client's
core image should be dumped in the event the client crashes.
The path is formatted as a character string consisting of characters from
the
.Tn NVT ASCII
character set.
.It Ic option domain-name Ar string ;
This option specifies the domain name that the client should use when
resolving hostnames via the Domain Name System.
.It Ic option swap-server Ar ip-address ;
This specifies the IP address of the client's swap server.
.It Ic option root-path Ar string ;
This option specifies the pathname that contains the client's root disk.
The path is formatted as a character string consisting of characters from
the
.Tn NVT ASCII
character set.
.El
.Ss IP Layer Parameters per Host
.Bl -tag -width Ds
.It Ic option ip-forwarding Ar flag ;
This option specifies whether the client should configure its IP layer
for packet forwarding.
A value of 0 means disable IP forwarding, and a value of 1 means enable
IP forwarding.
.It Ic option non-local-source-routing Ar flag ;
This option specifies whether the client should configure its IP
layer to allow forwarding of datagrams with non-local source routes
(see Section 3.3.5 of [4] for a discussion of this topic).
A value of 0 means disallow forwarding of such datagrams, and a value of 1
means allow forwarding.
.It Xo
.Ic option policy-filter Ar ip-address ip-address
.Oo , Ar ip-address ip-address ... Oc ;
.Xc
This option specifies policy filters for non-local source routing.
The filters consist of a list of IP addresses and masks which specify
destination/mask pairs with which to filter incoming source routes.
.Pp
Any source-routed datagram whose next-hop address does not match one
of the filters should be discarded by the client.
.Pp
See STD 3 (RFC 1122) for further information.
.It Ic option max-dgram-reassembly Ar uint16 ;
This option specifies the maximum size datagram that the client should be
prepared to reassemble.
The minimum legal value is 576.
.It Ic option default-ip-ttl Ar uint8 ;
This option specifies the default time-to-live that the client should
use on outgoing datagrams.
.It Ic option path-mtu-aging-timeout Ar uint32 ;
This option specifies the timeout (in seconds) to use when aging Path
MTU values discovered by the mechanism defined in RFC 1191.
.It Xo
.Ic option path-mtu-plateau-table Ar uint16
.Oo , Ar uint16 ... Oc ;
.Xc
This option specifies a table of MTU sizes to use when performing
Path MTU Discovery as defined in RFC 1191.
The table is formatted as a list of 16-bit unsigned integers,
ordered from smallest to largest.
The minimum MTU value cannot be smaller than 68.
.El
.Ss IP Layer Parameters per Interface
.Bl -tag -width Ds
.It Ic option interface-mtu Ar uint16 ;
This option specifies the MTU to use on this interface.
The minimum legal value for the MTU is 68.
.It Ic option all-subnets-local Ar flag ;
This option specifies whether or not the client may assume that all subnets
of the IP network to which the client is connected use the same MTU as the
subnet of that network to which the client is directly connected.
A value of 1 indicates that all subnets share the same MTU.
A value of 0 means that the client should assume that some subnets of the
directly connected network may have smaller MTUs.
.It Ic option broadcast-address Ar ip-address ;
This option specifies the broadcast address in use on the client's subnet.
Legal values for broadcast addresses are specified in section 3.2.1.3 of
STD 3 (RFC 1122).
.It Ic option perform-mask-discovery Ar flag ;
This option specifies whether or not the client should perform subnet mask
discovery using ICMP.
A value of 0 indicates that the client should not perform mask discovery.
A value of 1 means that the client should perform mask discovery.
.It Ic option mask-supplier Ar flag ;
This option specifies whether or not the client should respond to subnet mask
requests using ICMP.
A value of 0 indicates that the client should not respond.
A value of 1 means that the client should respond.
.It Ic option router-discovery Ar flag ;
This option specifies whether or not the client should solicit routers using
the Router Discovery mechanism defined in RFC 1256.
A value of 0 indicates that the client should not perform router discovery.
A value of 1 means that the client should perform router discovery.
.It Ic option router-solicitation-address Ar ip-address ;
This option specifies the address to which the client should transmit
router solicitation requests.
.It Xo
.Ic option static-routes Ar ip-address ip-address
.Oo , Ar ip-address ip-address ... Oc ;
.Xc
This option specifies a list of static routes that the client should
install in its routing cache.
If multiple routes to the same destination are specified, they are listed
in descending order of priority.
.Pp
The routes consist of a list of IP address pairs.
The first address is the destination address,
and the second address is the router for the destination.
.Pp
The default route (0.0.0.0) is an illegal destination for a static route.
To specify the default route, use the
.Ic routers
option.
.El
.Ss Link Layer Parameters per Interface
.Bl -tag -width Ds
.It Ic option trailer-encapsulation Ar flag ;
This option specifies whether or not the client should negotiate the
use of trailers (RFC 893 [14]) when using the ARP protocol.
A value of 0 indicates that the client should not attempt to use trailers.
A value of 1 means that the client should attempt to use trailers.
.It Ic option arp-cache-timeout Ar uint32 ;
This option specifies the timeout in seconds for ARP cache entries.
.It Ic option ieee802-3-encapsulation Ar flag ;
This option specifies whether or not the client should use Ethernet
Version 2 (RFC 894) or IEEE 802.3 (RFC 1042) encapsulation if the
interface is an Ethernet.
A value of 0 indicates that the client should use RFC 894 encapsulation.
A value of 1 means that the client should use RFC 1042 encapsulation.
.El
.Ss TCP Parameters
.Bl -tag -width Ds
.It Ic option default-tcp-ttl Ar uint8 ;
This option specifies the default TTL that the client should use when
sending TCP segments.
The minimum value is 1.
.It Ic option tcp-keepalive-interval Ar uint32 ;
This option specifies the interval (in seconds) that the client TCP
should wait before sending a keepalive message on a TCP connection.
The time is specified as a 32-bit unsigned integer.
A value of zero indicates that the client should not generate keepalive
messages on connections unless specifically requested by an application.
.It Ic option tcp-keepalive-garbage Ar flag ;
This option specifies whether or not the client should send TCP keepalive
messages with an octet of garbage for compatibility with older implementations.
A value of 0 indicates that a garbage octet should not be sent.
A value of 1 indicates that a garbage octet should be sent.
.El
.Ss Application and Service Parameters
.Bl -tag -width Ds
.It Ic option nis-domain Ar string ;
This option specifies the name of the client's NIS (Sun Network Information
Services) domain.
The domain is formatted as a character string consisting of characters
from the
.Tn NVT ASCII
character set.
.It Xo
.Ic option nis-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
This option specifies a list of IP addresses indicating NIS servers
available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option ntp-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
This option specifies a list of IP addresses indicating NTP (RFC 1035)
servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option netbios-name-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The NetBIOS name server (NBNS) option specifies a list of RFC 1001/1002
NBNS name servers listed in order of preference.
NetBIOS Name Service is currently more commonly referred to as WINS.
WINS servers can be specified using the
.Ic netbios-name-servers
option.
.It Xo
.Ic option netbios-dd-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The NetBIOS datagram distribution server (NBDD) option specifies a
list of RFC 1001/1002 NBDD servers listed in order of preference.
.It Ic option netbios-node-type Ar uint8 ;
The NetBIOS node type option allows NetBIOS over TCP/IP clients which
are configurable to be configured as described in RFC 1001/1002.
The value is specified as a single octet which identifies the client type.
.Pp
Possible node types are:
.Bl -tag -width Ds
.It 1
B-node: Broadcast - no WINS
.It 2
P-node: Peer - WINS only
.It 4
M-node: Mixed - broadcast, then WINS
.It 8
H-node: Hybrid - WINS, then broadcast
.El
.It Ic option netbios-scope Ar string ;
The NetBIOS scope option specifies the NetBIOS over TCP/IP scope
parameter for the client as specified in RFC 1001/1002.
See RFC 1001, RFC 1002, and RFC 1035 for character-set restrictions.
.It Xo
.Ic option font-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
This option specifies a list of X Window System Font servers available
to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option x-display-manager Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
This option specifies a list of systems that are running the X Window
System Display Manager and are available to the client.
Addresses should be listed in order of preference.
.It Ic option dhcp-client-identifier Ar data-string ;
This option can be used to specify a DHCP client identifier in a
host declaration, so that
.Xr dhcpd 8
can find the host record by matching against the client identifier.
.It Ic option nisplus-domain Ar string ;
This option specifies the name of the client's NIS+ domain.
The domain is formatted as a character string consisting of characters
from the
.Tn NVT ASCII
character set.
.It Xo
.Ic option nisplus-servers Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
This option specifies a list of IP addresses indicating NIS+ servers
available to the client.
Servers should be listed in order of preference.
.It Ic option tftp-server-name Ar string ;
This option is used to identify a TFTP server and, if supported by the
client, should have the same effect as the
.Ic server-name
declaration.
BOOTP clients are unlikely to support this option.
Some DHCP clients will support it, and others actually require it.
.It Ic option bootfile-name Ar string ;
This option is used to identify a bootstrap file.
If supported by the client, it should have the same effect as the
.Ic filename
declaration.
BOOTP clients are unlikely to support this option.
Some DHCP clients will support it, and others actually require it.
.It Xo
.Ic option mobile-ip-home-agent Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
This option specifies a list of IP addresses indicating mobile IP
home agents available to the client.
Agents should be listed in order of preference, although normally there
will be only one such agent.
.It Xo
.Ic option smtp-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic smtp-server
option specifies a list of SMTP servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option pop-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic pop-server
option specifies a list of POP3 servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option nntp-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic nntp-server
option specifies a list of NNTP servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option www-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic www-server
option specifies a list of WWW servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option finger-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic finger-server
option specifies a list of
.Xr finger 1
servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option irc-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic irc-server
option specifies a list of IRC servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option streettalk-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The
.Ic streettalk-server
option specifies a list of StreetTalk servers available to the client.
Servers should be listed in order of preference.
.It Xo
.Ic option streettalk-directory-assistance-server Ar ip-address
.Oo , Ar ip-address ... Oc ;
.Xc
The StreetTalk Directory Assistance (STDA) server option specifies a
list of STDA servers available to the client.
Servers should be listed in order of preference.
.El
.Sh SEE ALSO
.Xr dhclient.conf 5 ,
.Xr dhcpd.conf 5 ,
.Xr dhcpd.leases 5 ,
.Xr dhclient 8 ,
.Xr dhcpd 8
.Pp
RFC 2131, RFC 2132.
.Sh AUTHORS
.Xr dhcpd 8
was written by
.An Ted Lemon Aq mellon@vix.com
under a contract with Vixie Labs.
.Pp
The current implementation was reworked by
.An Henning Brauer Aq henning@openbsd.org .

168
sbin/dhclient/dhcp.h Normal file
View File

@ -0,0 +1,168 @@
/* $OpenBSD: dhcp.h,v 1.5 2004/05/04 15:49:49 deraadt Exp $ */
/* Protocol structures... */
/*
* Copyright (c) 1995, 1996 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''.
*/
#define DHCP_UDP_OVERHEAD (14 + /* Ethernet header */ \
20 + /* IP header */ \
8) /* UDP header */
#define DHCP_SNAME_LEN 64
#define DHCP_FILE_LEN 128
#define DHCP_FIXED_NON_UDP 236
#define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD)
/* Everything but options. */
#define DHCP_MTU_MAX 1500
#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
#define BOOTP_MIN_LEN 300
#define DHCP_MIN_LEN 548
struct dhcp_packet {
u_int8_t op; /* Message opcode/type */
u_int8_t htype; /* Hardware addr type (see net/if_types.h) */
u_int8_t hlen; /* Hardware addr length */
u_int8_t hops; /* Number of relay agent hops from client */
u_int32_t xid; /* Transaction ID */
u_int16_t secs; /* Seconds since client started looking */
u_int16_t flags; /* Flag bits */
struct in_addr ciaddr; /* Client IP address (if already in use) */
struct in_addr yiaddr; /* Client IP address */
struct in_addr siaddr; /* IP address of next server to talk to */
struct in_addr giaddr; /* DHCP relay agent IP address */
unsigned char chaddr[16]; /* Client hardware address */
char sname[DHCP_SNAME_LEN]; /* Server name */
char file[DHCP_FILE_LEN]; /* Boot filename */
unsigned char options[DHCP_OPTION_LEN];
/* Optional parameters
(actual length dependent on MTU). */
};
/* BOOTP (rfc951) message types */
#define BOOTREQUEST 1
#define BOOTREPLY 2
/* Possible values for flags field... */
#define BOOTP_BROADCAST 32768L
/* Possible values for hardware type (htype) field... */
#define HTYPE_ETHER 1 /* Ethernet */
#define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */
#define HTYPE_FDDI 8 /* FDDI... */
/* Magic cookie validating dhcp options field (and bootp vendor
extensions field). */
#define DHCP_OPTIONS_COOKIE "\143\202\123\143"
/* DHCP Option codes: */
#define DHO_PAD 0
#define DHO_SUBNET_MASK 1
#define DHO_TIME_OFFSET 2
#define DHO_ROUTERS 3
#define DHO_TIME_SERVERS 4
#define DHO_NAME_SERVERS 5
#define DHO_DOMAIN_NAME_SERVERS 6
#define DHO_LOG_SERVERS 7
#define DHO_COOKIE_SERVERS 8
#define DHO_LPR_SERVERS 9
#define DHO_IMPRESS_SERVERS 10
#define DHO_RESOURCE_LOCATION_SERVERS 11
#define DHO_HOST_NAME 12
#define DHO_BOOT_SIZE 13
#define DHO_MERIT_DUMP 14
#define DHO_DOMAIN_NAME 15
#define DHO_SWAP_SERVER 16
#define DHO_ROOT_PATH 17
#define DHO_EXTENSIONS_PATH 18
#define DHO_IP_FORWARDING 19
#define DHO_NON_LOCAL_SOURCE_ROUTING 20
#define DHO_POLICY_FILTER 21
#define DHO_MAX_DGRAM_REASSEMBLY 22
#define DHO_DEFAULT_IP_TTL 23
#define DHO_PATH_MTU_AGING_TIMEOUT 24
#define DHO_PATH_MTU_PLATEAU_TABLE 25
#define DHO_INTERFACE_MTU 26
#define DHO_ALL_SUBNETS_LOCAL 27
#define DHO_BROADCAST_ADDRESS 28
#define DHO_PERFORM_MASK_DISCOVERY 29
#define DHO_MASK_SUPPLIER 30
#define DHO_ROUTER_DISCOVERY 31
#define DHO_ROUTER_SOLICITATION_ADDRESS 32
#define DHO_STATIC_ROUTES 33
#define DHO_TRAILER_ENCAPSULATION 34
#define DHO_ARP_CACHE_TIMEOUT 35
#define DHO_IEEE802_3_ENCAPSULATION 36
#define DHO_DEFAULT_TCP_TTL 37
#define DHO_TCP_KEEPALIVE_INTERVAL 38
#define DHO_TCP_KEEPALIVE_GARBAGE 39
#define DHO_NIS_DOMAIN 40
#define DHO_NIS_SERVERS 41
#define DHO_NTP_SERVERS 42
#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43
#define DHO_NETBIOS_NAME_SERVERS 44
#define DHO_NETBIOS_DD_SERVER 45
#define DHO_NETBIOS_NODE_TYPE 46
#define DHO_NETBIOS_SCOPE 47
#define DHO_FONT_SERVERS 48
#define DHO_X_DISPLAY_MANAGER 49
#define DHO_DHCP_REQUESTED_ADDRESS 50
#define DHO_DHCP_LEASE_TIME 51
#define DHO_DHCP_OPTION_OVERLOAD 52
#define DHO_DHCP_MESSAGE_TYPE 53
#define DHO_DHCP_SERVER_IDENTIFIER 54
#define DHO_DHCP_PARAMETER_REQUEST_LIST 55
#define DHO_DHCP_MESSAGE 56
#define DHO_DHCP_MAX_MESSAGE_SIZE 57
#define DHO_DHCP_RENEWAL_TIME 58
#define DHO_DHCP_REBINDING_TIME 59
#define DHO_DHCP_CLASS_IDENTIFIER 60
#define DHO_DHCP_CLIENT_IDENTIFIER 61
#define DHO_DHCP_USER_CLASS_ID 77
#define DHO_END 255
/* DHCP message types. */
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCPINFORM 8

437
sbin/dhclient/dhcpd.h Normal file
View File

@ -0,0 +1,437 @@
/* $OpenBSD: dhcpd.h,v 1.33 2004/05/06 22:29:15 deraadt Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
* Copyright (c) 1995, 1996, 1997, 1998, 1999
* 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''.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
#include <paths.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#include "dhcp.h"
#include "tree.h"
#define LOCAL_PORT 68
#define REMOTE_PORT 67
struct option_data {
int len;
u_int8_t *data;
};
struct string_list {
struct string_list *next;
char *string;
};
struct iaddr {
int len;
unsigned char iabuf[16];
};
struct iaddrlist {
struct iaddrlist *next;
struct iaddr addr;
};
struct packet {
struct dhcp_packet *raw;
int packet_length;
int packet_type;
int options_valid;
int client_port;
struct iaddr client_addr;
struct interface_info *interface;
struct hardware *haddr;
struct option_data options[256];
};
struct hardware {
u_int8_t htype;
u_int8_t hlen;
u_int8_t haddr[16];
};
struct client_lease {
struct client_lease *next;
time_t expiry, renewal, rebind;
struct iaddr address;
char *server_name;
char *filename;
struct string_list *medium;
unsigned int is_static : 1;
unsigned int is_bootp : 1;
struct option_data options[256];
};
/* Possible states in which the client can be. */
enum dhcp_state {
S_REBOOTING,
S_INIT,
S_SELECTING,
S_REQUESTING,
S_BOUND,
S_RENEWING,
S_REBINDING
};
struct client_config {
struct option_data defaults[256];
enum {
ACTION_DEFAULT,
ACTION_SUPERSEDE,
ACTION_PREPEND,
ACTION_APPEND
} default_actions[256];
struct option_data send_options[256];
u_int8_t required_options[256];
u_int8_t requested_options[256];
int requested_option_count;
time_t timeout;
time_t initial_interval;
time_t retry_interval;
time_t select_interval;
time_t reboot_timeout;
time_t backoff_cutoff;
struct string_list *media;
char *script_name;
enum { IGNORE, ACCEPT, PREFER }
bootp_policy;
struct string_list *medium;
struct iaddrlist *reject_list;
};
struct client_state {
struct client_lease *active;
struct client_lease *new;
struct client_lease *offered_leases;
struct client_lease *leases;
struct client_lease *alias;
enum dhcp_state state;
struct iaddr destination;
u_int32_t xid;
u_int16_t secs;
time_t first_sending;
time_t interval;
struct string_list *medium;
struct dhcp_packet packet;
int packet_length;
struct iaddr requested_address;
struct client_config *config;
char **scriptEnv;
int scriptEnvsize;
struct string_list *env;
int envc;
};
struct interface_info {
struct interface_info *next;
struct hardware hw_address;
struct in_addr primary_address;
char name[IFNAMSIZ];
int rfdesc;
int wfdesc;
unsigned char *rbuf;
size_t rbuf_max;
size_t rbuf_offset;
size_t rbuf_len;
struct ifreq *ifp;
struct client_state *client;
int noifmedia;
int errors;
int dead;
u_int16_t index;
};
struct timeout {
struct timeout *next;
time_t when;
void (*func)(void *);
void *what;
};
struct protocol {
struct protocol *next;
int fd;
void (*handler)(struct protocol *);
void *local;
};
#define DEFAULT_HASH_SIZE 97
struct hash_bucket {
struct hash_bucket *next;
unsigned char *name;
int len;
unsigned char *value;
};
struct hash_table {
int hash_count;
struct hash_bucket *buckets[DEFAULT_HASH_SIZE];
};
/* Default path to dhcpd config file. */
#define _PATH_DHCLIENT_CONF "/etc/dhclient.conf"
#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases"
#define DHCPD_LOG_FACILITY LOG_DAEMON
#define MAX_TIME 0x7fffffff
#define MIN_TIME 0
/* External definitions... */
/* options.c */
int cons_options(struct packet *, struct dhcp_packet *, int,
struct tree_cache **, int, int, int, u_int8_t *, int);
char *pretty_print_option(unsigned int,
unsigned char *, int, int, int);
void do_packet(struct interface_info *, struct dhcp_packet *,
int, unsigned int, struct iaddr, struct hardware *);
/* errwarn.c */
extern int warnings_occurred;
void error(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
int warning(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
int note(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
int debug(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
int parse_warn(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
/* conflex.c */
extern int lexline, lexchar;
extern char *token_line, *tlname;
extern char comments[4096];
extern int comment_index;
extern int eol_token;
void new_parse(char *);
int next_token(char **, FILE *);
int peek_token(char **, FILE *);
/* parse.c */
void skip_to_semi(FILE *);
int parse_semi(FILE *);
char *parse_string(FILE *);
int parse_ip_addr(FILE *, struct iaddr *);
void parse_hardware_param(FILE *, struct hardware *);
void parse_lease_time(FILE *, time_t *);
unsigned char *parse_numeric_aggregate(FILE *, unsigned char *, int *,
int, int, int);
void convert_num(unsigned char *, char *, int, int);
time_t parse_date(FILE *);
/* tree.c */
pair cons(caddr_t, pair);
/* alloc.c */
struct string_list *new_string_list(size_t size);
struct hash_table *new_hash_table(int);
struct hash_bucket *new_hash_bucket(void);
/* bpf.c */
int if_register_bpf(struct interface_info *);
void if_register_send(struct interface_info *);
void if_register_receive(struct interface_info *);
ssize_t send_packet(struct interface_info *, struct dhcp_packet *, size_t,
struct in_addr, struct sockaddr_in *, struct hardware *);
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t,
struct sockaddr_in *, struct hardware *);
/* dispatch.c */
extern void (*bootp_packet_handler)(struct interface_info *,
struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *);
void discover_interfaces(struct interface_info *);
void reinitialize_interfaces(void);
void dispatch(void);
void got_one(struct protocol *);
void add_timeout(time_t, void (*)(void *), void *);
void cancel_timeout(void (*)(void *), void *);
void add_protocol(char *, int, void (*)(struct protocol *), void *);
void remove_protocol(struct protocol *);
int interface_link_status(char *);
/* hash.c */
struct hash_table *new_hash(void);
void add_hash(struct hash_table *, unsigned char *, int, unsigned char *);
unsigned char *hash_lookup(struct hash_table *, unsigned char *, int);
/* tables.c */
extern struct option dhcp_options[256];
extern unsigned char dhcp_option_default_priority_list[];
extern int sizeof_dhcp_option_default_priority_list;
extern struct hash_table universe_hash;
extern struct universe dhcp_universe;
void initialize_universes(void);
/* convert.c */
u_int32_t getULong(unsigned char *);
int32_t getLong(unsigned char *);
u_int16_t getUShort(unsigned char *);
int16_t getShort(unsigned char *);
void putULong(unsigned char *, u_int32_t);
void putLong(unsigned char *, int32_t);
void putUShort(unsigned char *, unsigned int);
void putShort(unsigned char *, int);
/* inet.c */
struct iaddr subnet_number(struct iaddr, struct iaddr);
struct iaddr broadcast_addr(struct iaddr, struct iaddr);
int addr_eq(struct iaddr, struct iaddr);
char *piaddr(struct iaddr);
/* dhclient.c */
extern char *path_dhclient_conf;
extern char *path_dhclient_db;
extern time_t cur_time;
extern int log_priority;
extern int log_perror;
extern struct client_config top_level_config;
void dhcpoffer(struct packet *);
void dhcpack(struct packet *);
void dhcpnak(struct packet *);
void send_discover(void *);
void send_request(void *);
void send_decline(void *);
void state_reboot(void *);
void state_init(void *);
void state_selecting(void *);
void state_requesting(void *);
void state_bound(void *);
void state_panic(void *);
void bind_lease(struct interface_info *);
void make_discover(struct interface_info *, struct client_lease *);
void make_request(struct interface_info *, struct client_lease *);
void make_decline(struct interface_info *, struct client_lease *);
void free_client_lease(struct client_lease *);
void rewrite_client_leases(void);
void write_client_lease(struct interface_info *, struct client_lease *, int);
void priv_script_init(char *, char *);
void priv_script_write_params(char *, struct client_lease *);
int priv_script_go(void);
void script_init(char *, struct string_list *);
void script_write_params(char *, struct client_lease *);
int script_go(void);
void client_envadd(struct client_state *,
const char *, const char *, const char *, ...);
void script_set_env(struct client_state *, const char *, const char *,
const char *);
void script_flush_env(struct client_state *);
int dhcp_option_ev_name(char *, size_t, struct option *);
struct client_lease *packet_to_lease(struct packet *);
void go_daemon(void);
void client_location_changed(void);
void bootp(struct packet *);
void dhcp(struct packet *);
/* packet.c */
void assemble_hw_header(struct interface_info *, unsigned char *,
int *, struct hardware *);
void assemble_udp_ip_header(unsigned char *, int *, u_int32_t, u_int32_t,
unsigned int, unsigned char *, int);
ssize_t decode_hw_header(unsigned char *, int, struct hardware *);
ssize_t decode_udp_ip_header(unsigned char *, int, struct sockaddr_in *,
unsigned char *, int);
/* ethernet.c */
void assemble_ethernet_header(struct interface_info *, unsigned char *,
int *, struct hardware *);
ssize_t decode_ethernet_header(struct interface_info *, unsigned char *,
int, struct hardware *);
/* clparse.c */
int read_client_conf(void);
void read_client_leases(void);
void parse_client_statement(FILE *, struct interface_info *,
struct client_config *);
int parse_X(FILE *, u_int8_t *, int);
int parse_option_list(FILE *, u_int8_t *);
void parse_interface_declaration(FILE *, struct client_config *);
struct interface_info *interface_or_dummy(char *);
void make_client_state(struct interface_info *);
void make_client_config(struct interface_info *, struct client_config *);
void parse_client_lease_statement(FILE *, int);
void parse_client_lease_declaration(FILE *, struct client_lease *,
struct interface_info **);
struct option *parse_option_decl(FILE *, struct option_data *);
void parse_string_list(FILE *, struct string_list **, int);
void parse_reject_statement(FILE *, struct client_config *);
/* privsep.c */
struct buf *buf_open(size_t);
int buf_add(struct buf *, void *, size_t);
int buf_close(int, struct buf *);
ssize_t buf_read(int, void *, size_t);
void dispatch_imsg(int);

136
sbin/dhclient/dhctoken.h Normal file
View File

@ -0,0 +1,136 @@
/* $OpenBSD: dhctoken.h,v 1.2 2004/02/04 12:16:56 henning Exp $ */
/* Tokens for config file lexer and parser. */
/*
* Copyright (c) 1995, 1996, 1997, 1998, 1999
* 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''.
*/
#define SEMI ';'
#define DOT '.'
#define COLON ':'
#define COMMA ','
#define SLASH '/'
#define LBRACE '{'
#define RBRACE '}'
#define FIRST_TOKEN HOST
#define HOST 256
#define HARDWARE 257
#define FILENAME 258
#define FIXED_ADDR 259
#define OPTION 260
#define ETHERNET 261
#define STRING 262
#define NUMBER 263
#define NUMBER_OR_NAME 264
#define NAME 265
#define TIMESTAMP 266
#define STARTS 267
#define ENDS 268
#define UID 269
#define CLASS 270
#define LEASE 271
#define RANGE 272
#define PACKET 273
#define CIADDR 274
#define YIADDR 275
#define SIADDR 276
#define GIADDR 277
#define SUBNET 278
#define NETMASK 279
#define DEFAULT_LEASE_TIME 280
#define MAX_LEASE_TIME 281
#define VENDOR_CLASS 282
#define USER_CLASS 283
#define SHARED_NETWORK 284
#define SERVER_NAME 285
#define DYNAMIC_BOOTP 286
#define SERVER_IDENTIFIER 287
#define DYNAMIC_BOOTP_LEASE_CUTOFF 288
#define DYNAMIC_BOOTP_LEASE_LENGTH 289
#define BOOT_UNKNOWN_CLIENTS 290
#define NEXT_SERVER 291
#define TOKEN_RING 292
#define GROUP 293
#define ONE_LEASE_PER_CLIENT 294
#define GET_LEASE_HOSTNAMES 295
#define USE_HOST_DECL_NAMES 296
#define SEND 297
#define CLIENT_IDENTIFIER 298
#define REQUEST 299
#define REQUIRE 300
#define TIMEOUT 301
#define RETRY 302
#define SELECT_TIMEOUT 303
#define SCRIPT 304
#define INTERFACE 305
#define RENEW 306
#define REBIND 307
#define EXPIRE 308
#define UNKNOWN_CLIENTS 309
#define ALLOW 310
#define BOOTP 311
#define DENY 312
#define BOOTING 313
#define DEFAULT 314
#define MEDIA 315
#define MEDIUM 316
#define ALIAS 317
#define REBOOT 318
#define ABANDONED 319
#define BACKOFF_CUTOFF 320
#define INITIAL_INTERVAL 321
#define NAMESERVER 322
#define DOMAIN 323
#define SEARCH 324
#define SUPERSEDE 325
#define APPEND 326
#define PREPEND 327
#define HOSTNAME 328
#define CLIENT_HOSTNAME 329
#define REJECT 330
#define FDDI 331
#define USE_LEASE_ADDR_FOR_DEFAULT_ROUTE 332
#define AUTHORITATIVE 333
#define TOKEN_NOT 334
#define ALWAYS_REPLY_RFC1048 335
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
(x) != STRING && \
(x) != NUMBER && \
(x) != EOF)

495
sbin/dhclient/dispatch.c Normal file
View File

@ -0,0 +1,495 @@
/* $OpenBSD: dispatch.c,v 1.31 2004/09/21 04:07:03 david Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
* Copyright (c) 1995, 1996, 1997, 1998, 1999
* 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''.
*/
#include "dhcpd.h"
#include <sys/ioctl.h>
#include <net/if_media.h>
#include <ifaddrs.h>
#include <poll.h>
struct protocol *protocols;
struct timeout *timeouts;
static struct timeout *free_timeouts;
static int interfaces_invalidated;
void (*bootp_packet_handler)(struct interface_info *,
struct dhcp_packet *, int, unsigned int,
struct iaddr, struct hardware *);
static int interface_status(struct interface_info *ifinfo);
/*
* Use getifaddrs() to get a list of all the attached interfaces. For
* each interface that's of type INET and not the loopback interface,
* register that interface with the network I/O software, figure out
* what subnet it's on, and add it to the list of interfaces.
*/
void
discover_interfaces(struct interface_info *iface)
{
struct ifaddrs *ifap, *ifa;
struct sockaddr_in foo;
struct ifreq *tif;
if (getifaddrs(&ifap) != 0)
error("getifaddrs failed");
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
if ((ifa->ifa_flags & IFF_LOOPBACK) ||
(ifa->ifa_flags & IFF_POINTOPOINT) ||
(!(ifa->ifa_flags & IFF_UP)))
continue;
if (strcmp(iface->name, ifa->ifa_name))
continue;
/*
* If we have the capability, extract link information
* and record it in a linked list.
*/
if (ifa->ifa_addr->sa_family == AF_LINK) {
struct sockaddr_dl *foo =
(struct sockaddr_dl *)ifa->ifa_addr;
iface->index = foo->sdl_index;
iface->hw_address.hlen = foo->sdl_alen;
iface->hw_address.htype = HTYPE_ETHER; /* XXX */
memcpy(iface->hw_address.haddr,
LLADDR(foo), foo->sdl_alen);
} else if (ifa->ifa_addr->sa_family == AF_INET) {
struct iaddr addr;
memcpy(&foo, ifa->ifa_addr, sizeof(foo));
if (foo.sin_addr.s_addr == htonl(INADDR_LOOPBACK))
continue;
if (!iface->ifp) {
int len = IFNAMSIZ + ifa->ifa_addr->sa_len;
if ((tif = malloc(len)) == NULL)
error("no space to remember ifp");
strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ);
memcpy(&tif->ifr_addr, ifa->ifa_addr,
ifa->ifa_addr->sa_len);
iface->ifp = tif;
iface->primary_address = foo.sin_addr;
}
addr.len = 4;
memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len);
}
}
if (!iface->ifp)
error("%s: not found", iface->name);
/* Register the interface... */
if_register_receive(iface);
if_register_send(iface);
add_protocol(iface->name, iface->rfdesc, got_one, iface);
freeifaddrs(ifap);
}
void
reinitialize_interfaces(void)
{
interfaces_invalidated = 1;
}
/*
* Wait for packets to come in using poll(). When a packet comes in,
* call receive_packet to receive the packet and possibly strip hardware
* addressing information from it, and then call through the
* bootp_packet_handler hook to try to do something with it.
*/
void
dispatch(void)
{
int count, i, to_msec, nfds = 0;
struct protocol *l;
struct pollfd *fds;
time_t howlong;
for (l = protocols; l; l = l->next)
nfds++;
fds = malloc(nfds * sizeof(struct pollfd));
if (fds == NULL)
error("Can't allocate poll structures.");
do {
/*
* Call any expired timeouts, and then if there's still
* a timeout registered, time out the select call then.
*/
another:
if (timeouts) {
struct timeout *t;
if (timeouts->when <= cur_time) {
t = timeouts;
timeouts = timeouts->next;
(*(t->func))(t->what);
t->next = free_timeouts;
free_timeouts = t;
goto another;
}
/*
* Figure timeout in milliseconds, and check for
* potential overflow, so we can cram into an
* int for poll, while not polling with a
* negative timeout and blocking indefinitely.
*/
howlong = timeouts->when - cur_time;
if (howlong > INT_MAX / 1000)
howlong = INT_MAX / 1000;
to_msec = howlong * 1000;
} else
to_msec = -1;
/* Set up the descriptors to be polled. */
for (i = 0, l = protocols; l; l = l->next) {
struct interface_info *ip = l->local;
if (ip && (l->handler != got_one || !ip->dead)) {
fds[i].fd = l->fd;
fds[i].events = POLLIN;
fds[i].revents = 0;
i++;
}
}
if (i == 0)
error("No live interfaces to poll on - exiting.");
/* Wait for a packet or a timeout... XXX */
count = poll(fds, nfds, to_msec);
/* Not likely to be transitory... */
if (count == -1) {
if (errno == EAGAIN || errno == EINTR) {
time(&cur_time);
continue;
} else
error("poll: %m");
}
/* Get the current time... */
time(&cur_time);
i = 0;
for (l = protocols; l; l = l->next) {
struct interface_info *ip;
ip = l->local;
if ((fds[i].revents & (POLLIN | POLLHUP))) {
fds[i].revents = 0;
if (ip && (l->handler != got_one ||
!ip->dead))
(*(l->handler))(l);
if (interfaces_invalidated)
break;
}
i++;
}
interfaces_invalidated = 0;
} while (1);
}
void
got_one(struct protocol *l)
{
struct sockaddr_in from;
struct hardware hfrom;
struct iaddr ifrom;
ssize_t result;
union {
/*
* Packet input buffer. Must be as large as largest
* possible MTU.
*/
unsigned char packbuf[4095];
struct dhcp_packet packet;
} u;
struct interface_info *ip = l->local;
if ((result = receive_packet(ip, u.packbuf, sizeof(u), &from,
&hfrom)) == -1) {
warning("receive_packet failed on %s: %s", ip->name,
strerror(errno));
ip->errors++;
if ((!interface_status(ip)) ||
(ip->noifmedia && ip->errors > 20)) {
/* our interface has gone away. */
warning("Interface %s no longer appears valid.",
ip->name);
ip->dead = 1;
interfaces_invalidated = 1;
close(l->fd);
remove_protocol(l);
free(ip);
}
return;
}
if (result == 0)
return;
if (bootp_packet_handler) {
ifrom.len = 4;
memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);
(*bootp_packet_handler)(ip, &u.packet, result,
from.sin_port, ifrom, &hfrom);
}
}
int
interface_status(struct interface_info *ifinfo)
{
char *ifname = ifinfo->name;
int ifsock = ifinfo->rfdesc;
struct ifreq ifr;
struct ifmediareq ifmr;
/* get interface flags */
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", ifname);
goto inactive;
}
/*
* if one of UP and RUNNING flags is dropped,
* the interface is not active.
*/
if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
goto inactive;
/* Next, check carrier on the interface, if possible */
if (ifinfo->noifmedia)
goto active;
memset(&ifmr, 0, sizeof(ifmr));
strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
if (errno != EINVAL) {
syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m",
ifname);
ifinfo->noifmedia = 1;
goto active;
}
/*
* EINVAL (or ENOTTY) simply means that the interface
* does not support the SIOCGIFMEDIA ioctl. We regard it alive.
*/
ifinfo->noifmedia = 1;
goto active;
}
if (ifmr.ifm_status & IFM_AVALID) {
switch (ifmr.ifm_active & IFM_NMASK) {
case IFM_ETHER:
if (ifmr.ifm_status & IFM_ACTIVE)
goto active;
else
goto inactive;
break;
default:
goto inactive;
}
}
inactive:
return (0);
active:
return (1);
}
void
add_timeout(time_t when, void (*where)(void *), void *what)
{
struct timeout *t, *q;
/* See if this timeout supersedes an existing timeout. */
t = NULL;
for (q = timeouts; q; q = q->next) {
if (q->func == where && q->what == what) {
if (t)
t->next = q->next;
else
timeouts = q->next;
break;
}
t = q;
}
/* If we didn't supersede a timeout, allocate a timeout
structure now. */
if (!q) {
if (free_timeouts) {
q = free_timeouts;
free_timeouts = q->next;
q->func = where;
q->what = what;
} else {
q = malloc(sizeof(struct timeout));
if (!q)
error("Can't allocate timeout structure!");
q->func = where;
q->what = what;
}
}
q->when = when;
/* Now sort this timeout into the timeout list. */
/* Beginning of list? */
if (!timeouts || timeouts->when > q->when) {
q->next = timeouts;
timeouts = q;
return;
}
/* Middle of list? */
for (t = timeouts; t->next; t = t->next) {
if (t->next->when > q->when) {
q->next = t->next;
t->next = q;
return;
}
}
/* End of list. */
t->next = q;
q->next = NULL;
}
void
cancel_timeout(void (*where)(void *), void *what)
{
struct timeout *t, *q;
/* Look for this timeout on the list, and unlink it if we find it. */
t = NULL;
for (q = timeouts; q; q = q->next) {
if (q->func == where && q->what == what) {
if (t)
t->next = q->next;
else
timeouts = q->next;
break;
}
t = q;
}
/* If we found the timeout, put it on the free list. */
if (q) {
q->next = free_timeouts;
free_timeouts = q;
}
}
/* Add a protocol to the list of protocols... */
void
add_protocol(char *name, int fd, void (*handler)(struct protocol *),
void *local)
{
struct protocol *p;
p = malloc(sizeof(*p));
if (!p)
error("can't allocate protocol struct for %s", name);
p->fd = fd;
p->handler = handler;
p->local = local;
p->next = protocols;
protocols = p;
}
void
remove_protocol(struct protocol *proto)
{
struct protocol *p, *next, *prev;
prev = NULL;
for (p = protocols; p; p = next) {
next = p->next;
if (p == proto) {
if (prev)
prev->next = p->next;
else
protocols = p->next;
free(p);
}
}
}
int
interface_link_status(char *ifname)
{
struct ifmediareq ifmr;
int sock;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
error("Can't create socket");
memset(&ifmr, 0, sizeof(ifmr));
strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) {
/* EINVAL -> link state unknown. treat as active */
if (errno != EINVAL)
syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m",
ifname);
close(sock);
return (1);
}
close(sock);
if (ifmr.ifm_status & IFM_AVALID) {
if ((ifmr.ifm_active & IFM_NMASK) == IFM_ETHER) {
if (ifmr.ifm_status & IFM_ACTIVE)
return (1);
else
return (0);
}
}
return (1);
}

234
sbin/dhclient/errwarn.c Normal file
View File

@ -0,0 +1,234 @@
/* $OpenBSD: errwarn.c,v 1.7 2004/05/04 22:23:01 mickey Exp $ */
/* Errors and warnings... */
/*
* Copyright (c) 1996 The Internet Software Consortium.
* All Rights Reserved.
* 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, 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 RADIOMAIL CORPORATION, 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 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. Further modifications have
* been made for the Internet Software Consortium under a contract
* with Vixie Laboratories.
*/
#include <errno.h>
#include "dhcpd.h"
static void do_percentm(char *obuf, size_t size, char *ibuf);
static char mbuf[1024];
static char fbuf[1024];
int warnings_occurred;
/*
* Log an error message, then exit.
*/
void
error(char *fmt, ...)
{
va_list list;
do_percentm(fbuf, sizeof(fbuf), fmt);
va_start(list, fmt);
vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
va_end(list);
#ifndef DEBUG
syslog(log_priority | LOG_ERR, "%s", mbuf);
#endif
/* Also log it to stderr? */
if (log_perror) {
write(2, mbuf, strlen(mbuf));
write(2, "\n", 1);
}
syslog(LOG_CRIT, "exiting.");
if (log_perror) {
fprintf(stderr, "exiting.\n");
fflush(stderr);
}
exit(1);
}
/*
* Log a warning message...
*/
int
warning(char *fmt, ...)
{
va_list list;
do_percentm(fbuf, sizeof(fbuf), fmt);
va_start(list, fmt);
vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
va_end(list);
#ifndef DEBUG
syslog(log_priority | LOG_ERR, "%s", mbuf);
#endif
if (log_perror) {
write(2, mbuf, strlen(mbuf));
write(2, "\n", 1);
}
return (0);
}
/*
* Log a note...
*/
int
note(char *fmt, ...)
{
va_list list;
do_percentm(fbuf, sizeof(fbuf), fmt);
va_start(list, fmt);
vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
va_end(list);
#ifndef DEBUG
syslog(log_priority | LOG_INFO, "%s", mbuf);
#endif
if (log_perror) {
write(2, mbuf, strlen(mbuf));
write(2, "\n", 1);
}
return (0);
}
/*
* Log a debug message...
*/
int
debug(char *fmt, ...)
{
va_list list;
do_percentm(fbuf, sizeof(fbuf), fmt);
va_start(list, fmt);
vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
va_end(list);
#ifndef DEBUG
syslog(log_priority | LOG_DEBUG, "%s", mbuf);
#endif
if (log_perror) {
write(2, mbuf, strlen(mbuf));
write(2, "\n", 1);
}
return (0);
}
/*
* Find %m in the input string and substitute an error message string.
*/
static void
do_percentm(char *obuf, size_t size, char *ibuf)
{
char ch;
char *s = ibuf;
char *t = obuf;
size_t prlen;
size_t fmt_left;
int saved_errno = errno;
/*
* We wouldn't need this mess if printf handled %m, or if
* strerror() had been invented before syslog().
*/
for (fmt_left = size; (ch = *s); ++s) {
if (ch == '%' && s[1] == 'm') {
++s;
prlen = snprintf(t, fmt_left, "%s",
strerror(saved_errno));
if (prlen >= fmt_left)
prlen = fmt_left - 1;
t += prlen;
fmt_left -= prlen;
} else {
if (fmt_left > 1) {
*t++ = ch;
fmt_left--;
}
}
}
*t = '\0';
}
int
parse_warn(char *fmt, ...)
{
va_list list;
static char spaces[] =
" "
" "; /* 80 spaces */
do_percentm(mbuf, sizeof(mbuf), fmt);
snprintf(fbuf, sizeof(fbuf), "%s line %d: %s", tlname, lexline, mbuf);
va_start(list, fmt);
vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
va_end(list);
#ifndef DEBUG
syslog(log_priority | LOG_ERR, "%s", mbuf);
syslog(log_priority | LOG_ERR, "%s", token_line);
if (lexline < 81)
syslog(log_priority | LOG_ERR,
"%s^", &spaces[sizeof(spaces) - lexchar]);
#endif
if (log_perror) {
write(2, mbuf, strlen(mbuf));
write(2, "\n", 1);
write(2, token_line, strlen(token_line));
write(2, "\n", 1);
write(2, spaces, lexchar - 1);
write(2, "^\n", 2);
}
warnings_occurred = 1;
return (0);
}

119
sbin/dhclient/hash.c Normal file
View File

@ -0,0 +1,119 @@
/* $OpenBSD: hash.c,v 1.9 2004/05/10 15:30:47 deraadt Exp $ */
/* Routines for manipulating hash tables... */
/*
* Copyright (c) 1995, 1996, 1997, 1998 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''.
*/
#include "dhcpd.h"
static int do_hash(unsigned char *, int, int);
struct hash_table *
new_hash(void)
{
struct hash_table *rv = new_hash_table(DEFAULT_HASH_SIZE);
if (!rv)
return (rv);
memset(&rv->buckets[0], 0,
DEFAULT_HASH_SIZE * sizeof(struct hash_bucket *));
return (rv);
}
static int
do_hash(unsigned char *name, int len, int size)
{
unsigned char *s = name;
int accum = 0, i = len;
while (i--) {
/* Add the character in... */
accum += *s++;
/* Add carry back in... */
while (accum > 255)
accum = (accum & 255) + (accum >> 8);
}
return (accum % size);
}
void add_hash(struct hash_table *table, unsigned char *name, int len,
unsigned char *pointer)
{
struct hash_bucket *bp;
int hashno;
if (!table)
return;
if (!len)
len = strlen((char *)name);
hashno = do_hash(name, len, table->hash_count);
bp = new_hash_bucket();
if (!bp) {
warning("Can't add %s to hash table.", name);
return;
}
bp->name = name;
bp->value = pointer;
bp->next = table->buckets[hashno];
bp->len = len;
table->buckets[hashno] = bp;
}
unsigned char *
hash_lookup(struct hash_table *table, unsigned char *name, int len)
{
struct hash_bucket *bp;
int hashno;
if (!table)
return (NULL);
if (!len)
len = strlen((char *)name);
hashno = do_hash(name, len, table->hash_count);
for (bp = table->buckets[hashno]; bp; bp = bp->next)
if (len == bp->len && !memcmp(bp->name, name, len))
return (bp->value);
return (NULL);
}

118
sbin/dhclient/inet.c Normal file
View File

@ -0,0 +1,118 @@
/* $OpenBSD: inet.c,v 1.7 2004/05/04 21:48:16 deraadt Exp $ */
/*
* Subroutines to manipulate internet addresses in a safely portable
* way...
*/
/*
* Copyright (c) 1996 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''.
*/
#include "dhcpd.h"
/*
* Return just the network number of an internet address...
*/
struct iaddr
subnet_number(struct iaddr addr, struct iaddr mask)
{
struct iaddr rv;
int i;
rv.len = 0;
/* Both addresses must have the same length... */
if (addr.len != mask.len)
return (rv);
rv.len = addr.len;
for (i = 0; i < rv.len; i++)
rv.iabuf[i] = addr.iabuf[i] & mask.iabuf[i];
return (rv);
}
/*
* Given a subnet number and netmask, return the address on that subnet
* for which the host portion of the address is all ones (the standard
* broadcast address).
*/
struct iaddr
broadcast_addr(struct iaddr subnet, struct iaddr mask)
{
struct iaddr rv;
int i;
if (subnet.len != mask.len) {
rv.len = 0;
return (rv);
}
for (i = 0; i < subnet.len; i++)
rv.iabuf[i] = subnet.iabuf[i] | (~mask.iabuf[i] & 255);
rv.len = subnet.len;
return (rv);
}
int
addr_eq(struct iaddr addr1, struct iaddr addr2)
{
if (addr1.len != addr2.len)
return (0);
return (memcmp(addr1.iabuf, addr2.iabuf, addr1.len) == 0);
}
char *
piaddr(struct iaddr addr)
{
static char pbuf[32];
struct in_addr a;
char *s;
memcpy(&a, &(addr.iabuf), sizeof(struct in_addr));
if (addr.len == 0)
strlcpy(pbuf, "<null address>", sizeof(pbuf));
else {
s = inet_ntoa(a);
if (s != NULL)
strlcpy(pbuf, s, sizeof(pbuf));
else
strlcpy(pbuf, "<invalid address>", sizeof(pbuf));
}
return (pbuf);
}

717
sbin/dhclient/options.c Normal file
View File

@ -0,0 +1,717 @@
/* $OpenBSD: options.c,v 1.15 2004/12/26 03:17:07 deraadt Exp $ */
/* DHCP options parsing and reassembly. */
/*
* Copyright (c) 1995, 1996, 1997, 1998 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''.
*/
#include <ctype.h>
#define DHCP_OPTION_DATA
#include "dhcpd.h"
int bad_options = 0;
int bad_options_max = 5;
void parse_options(struct packet *);
void parse_option_buffer(struct packet *, unsigned char *, int);
int store_options(unsigned char *, int, struct tree_cache **,
unsigned char *, int, int, int, int);
/*
* Parse all available options out of the specified packet.
*/
void
parse_options(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_NON_UDP - 4);
/*
* 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,
(unsigned char *)packet->raw->file,
sizeof(packet->raw->file));
if (packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)
parse_option_buffer(packet,
(unsigned char *)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(struct packet *packet,
unsigned char *buffer, int length)
{
unsigned char *s, *t, *end = buffer + length;
int len, 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;
}
if (s + 2 > end) {
len = 65536;
goto bogus;
}
/*
* All other fields (except end, see above) have a
* one-byte length.
*/
len = s[1];
/*
* If the length is outrageous, silently skip the rest,
* and mark the packet bad. Unfortunately some crappy
* dhcp servers always seem to give us garbage on the
* end of a packet. so rather than keep refusing, give
* up and try to take one after seeing a few without
* anything good.
*/
if (s + len + 2 > end) {
bogus:
bad_options++;
warning("option %s (%d) %s.",
dhcp_options[code].name, len,
"larger than buffer");
if (bad_options == bad_options_max) {
packet->options_valid = 1;
bad_options = 0;
warning("Many bogus options seen in offers. "
"Taking this offer in spite of bogus "
"options - hope for the best!");
} else {
warning("rejecting bogus offer.");
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 = calloc(1, 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 = calloc(1, len + packet->options[code].len + 1);
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 options into a big buffer, and then split them out into the
* three separate buffers if needed. This allows us to cons up a set of
* vendor options using the same routine.
*/
int
cons_options(struct packet *inpacket, struct dhcp_packet *outpacket,
int mms, struct tree_cache **options,
int overload, /* Overload flags that may be set. */
int terminate, int bootpp, u_int8_t *prl, int prl_len)
{
unsigned char priority_list[300], buffer[4096];
int priority_len, main_buffer_size, mainbufix, bufix;
int option_size, length;
/*
* If the client has provided a maximum DHCP message size, use
* that; otherwise, if it's BOOTP, only 64 bytes; otherwise use
* up to the minimum IP MTU size (576 bytes).
*
* XXX if a BOOTP client specifies a max message size, we will
* honor it.
*/
if (!mms &&
inpacket &&
inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data &&
(inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].len >=
sizeof(u_int16_t)))
mms = getUShort(
inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data);
if (mms)
main_buffer_size = mms - DHCP_FIXED_LEN;
else if (bootpp)
main_buffer_size = 64;
else
main_buffer_size = 576 - DHCP_FIXED_LEN;
if (main_buffer_size > sizeof(buffer))
main_buffer_size = sizeof(buffer);
/* Preload the option priority list with mandatory options. */
priority_len = 0;
priority_list[priority_len++] = DHO_DHCP_MESSAGE_TYPE;
priority_list[priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
priority_list[priority_len++] = DHO_DHCP_LEASE_TIME;
priority_list[priority_len++] = DHO_DHCP_MESSAGE;
/*
* If the client has provided a list of options that it wishes
* returned, use it to prioritize. Otherwise, prioritize based
* on the default priority list.
*/
if (inpacket &&
inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
int prlen =
inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].len;
if (prlen + priority_len > sizeof(priority_list))
prlen = sizeof(priority_list) - priority_len;
memcpy(&priority_list[priority_len],
inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data,
prlen);
priority_len += prlen;
prl = priority_list;
} else if (prl) {
if (prl_len + priority_len > sizeof(priority_list))
prl_len = sizeof(priority_list) - priority_len;
memcpy(&priority_list[priority_len], prl, prl_len);
priority_len += prl_len;
prl = priority_list;
} else {
memcpy(&priority_list[priority_len],
dhcp_option_default_priority_list,
sizeof_dhcp_option_default_priority_list);
priority_len += sizeof_dhcp_option_default_priority_list;
}
/* Copy the options into the big buffer... */
option_size = store_options(
buffer,
(main_buffer_size - 7 + ((overload & 1) ? DHCP_FILE_LEN : 0) +
((overload & 2) ? DHCP_SNAME_LEN : 0)),
options, priority_list, priority_len, main_buffer_size,
(main_buffer_size + ((overload & 1) ? DHCP_FILE_LEN : 0)),
terminate);
/* Put the cookie up front... */
memcpy(outpacket->options, DHCP_OPTIONS_COOKIE, 4);
mainbufix = 4;
/*
* If we're going to have to overload, store the overload option
* at the beginning. If we can, though, just store the whole
* thing in the packet's option buffer and leave it at that.
*/
if (option_size <= main_buffer_size - mainbufix) {
memcpy(&outpacket->options[mainbufix],
buffer, option_size);
mainbufix += option_size;
if (mainbufix < main_buffer_size)
outpacket->options[mainbufix++] = DHO_END;
length = DHCP_FIXED_NON_UDP + mainbufix;
} else {
outpacket->options[mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
outpacket->options[mainbufix++] = 1;
if (option_size >
main_buffer_size - mainbufix + DHCP_FILE_LEN)
outpacket->options[mainbufix++] = 3;
else
outpacket->options[mainbufix++] = 1;
memcpy(&outpacket->options[mainbufix],
buffer, main_buffer_size - mainbufix);
bufix = main_buffer_size - mainbufix;
length = DHCP_FIXED_NON_UDP + mainbufix;
if (overload & 1) {
if (option_size - bufix <= DHCP_FILE_LEN) {
memcpy(outpacket->file,
&buffer[bufix], option_size - bufix);
mainbufix = option_size - bufix;
if (mainbufix < DHCP_FILE_LEN)
outpacket->file[mainbufix++] = (char)DHO_END;
while (mainbufix < DHCP_FILE_LEN)
outpacket->file[mainbufix++] = (char)DHO_PAD;
} else {
memcpy(outpacket->file,
&buffer[bufix], DHCP_FILE_LEN);
bufix += DHCP_FILE_LEN;
}
}
if ((overload & 2) && option_size < bufix) {
memcpy(outpacket->sname,
&buffer[bufix], option_size - bufix);
mainbufix = option_size - bufix;
if (mainbufix < DHCP_SNAME_LEN)
outpacket->file[mainbufix++] = (char)DHO_END;
while (mainbufix < DHCP_SNAME_LEN)
outpacket->file[mainbufix++] = (char)DHO_PAD;
}
}
return (length);
}
/*
* Store all the requested options into the requested buffer.
*/
int
store_options(unsigned char *buffer, int buflen, struct tree_cache **options,
unsigned char *priority_list, int priority_len, int first_cutoff,
int second_cutoff, int terminate)
{
int bufix = 0, option_stored[256], i, ix, tto;
/* Zero out the stored-lengths array. */
memset(option_stored, 0, sizeof(option_stored));
/*
* Copy out the options in the order that they appear in the
* priority list...
*/
for (i = 0; i < priority_len; i++) {
/* Code for next option to try to store. */
int code = priority_list[i];
int optstart;
/*
* 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 (!options[code]) {
continue;
}
/*
* The client could ask for things that are mandatory,
* in which case we should avoid storing them twice...
*/
if (option_stored[code])
continue;
option_stored[code] = 1;
/* We should now have a constant length for the option. */
length = options[code]->len;
/* Do we add a NUL? */
if (terminate && dhcp_options[code].format[0] == 't') {
length++;
tto = 1;
} else
tto = 0;
/* Try to store the option. */
/*
* If the option's length is more than 255, we must
* store it in multiple hunks. Store 255-byte hunks
* first. However, in any case, if the option data will
* cross a buffer boundary, split it across that
* boundary.
*/
ix = 0;
optstart = bufix;
while (length) {
unsigned char incr = length > 255 ? 255 : length;
/*
* If this hunk of the buffer will cross a
* boundary, only go up to the boundary in this
* pass.
*/
if (bufix < first_cutoff &&
bufix + incr > first_cutoff)
incr = first_cutoff - bufix;
else if (bufix < second_cutoff &&
bufix + incr > second_cutoff)
incr = second_cutoff - bufix;
/*
* If this option is going to overflow the
* buffer, skip it.
*/
if (bufix + 2 + incr > buflen) {
bufix = optstart;
break;
}
/* Everything looks good - copy it in! */
buffer[bufix] = code;
buffer[bufix + 1] = incr;
if (tto && incr == length) {
memcpy(buffer + bufix + 2,
options[code]->value + ix, incr - 1);
buffer[bufix + 2 + incr - 1] = 0;
} else
memcpy(buffer + bufix + 2,
options[code]->value + ix, incr);
length -= incr;
ix += incr;
bufix += 2 + incr;
}
}
return (bufix);
}
/*
* Format the specified option so that a human can easily read it.
*/
char *
pretty_print_option(unsigned int code, unsigned char *data, int len,
int emit_commas, int emit_quotes)
{
static char optbuf[32768]; /* XXX */
int hunksize = 0, numhunk = -1, numelem = 0;
char fmtbuf[32], *op = optbuf;
int i, j, k, opleft = sizeof(optbuf);
unsigned char *dp = data;
struct in_addr foo;
char comma;
/* Code should be between 0 and 255. */
if (code > 255)
error("pretty_print_option: bad code %d", code);
if (emit_commas)
comma = ',';
else
comma = ' ';
/* Figure out the size of the data. */
for (i = 0; dhcp_options[code].format[i]; i++) {
if (!numhunk) {
warning("%s: Excess information in format string: %s",
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 'X':
for (k = 0; k < len; k++)
if (!isascii(data[k]) ||
!isprint(data[k]))
break;
if (k == len) {
fmtbuf[i] = 't';
numhunk = -2;
} else {
fmtbuf[i] = 'x';
hunksize++;
comma = ':';
numhunk = 0;
}
fmtbuf[i + 1] = 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:
warning("%s: garbage in format string: %s",
dhcp_options[code].name,
&(dhcp_options[code].format[i]));
break;
}
}
/* Check for too few bytes... */
if (hunksize > len) {
warning("%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)
warning("%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)
warning("%s: %d extra bytes at end of array",
dhcp_options[code].name, len - numhunk * hunksize);
/* A one-hunk array prints the same as a single hunk. */
if (numhunk < 0)
numhunk = 1;
/* Cycle through the array (or hunk) printing the data. */
for (i = 0; i < numhunk; i++) {
for (j = 0; j < numelem; j++) {
int opcount;
switch (fmtbuf[j]) {
case 't':
if (emit_quotes) {
*op++ = '"';
opleft--;
}
for (; dp < data + len; dp++) {
if (!isascii(*dp) ||
!isprint(*dp)) {
if (dp + 1 != data + len ||
*dp != 0) {
snprintf(op, opleft,
"\\%03o", *dp);
op += 4;
opleft -= 4;
}
} else if (*dp == '"' ||
*dp == '\'' ||
*dp == '$' ||
*dp == '`' ||
*dp == '\\') {
*op++ = '\\';
*op++ = *dp;
opleft -= 2;
} else {
*op++ = *dp;
opleft--;
}
}
if (emit_quotes) {
*op++ = '"';
opleft--;
}
*op = 0;
break;
case 'I':
foo.s_addr = htonl(getULong(dp));
opcount = strlcpy(op, inet_ntoa(foo), opleft);
if (opcount >= opleft)
goto toobig;
opleft -= opcount;
dp += 4;
break;
case 'l':
opcount = snprintf(op, opleft, "%ld",
(long)getLong(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
dp += 4;
break;
case 'L':
opcount = snprintf(op, opleft, "%ld",
(unsigned long)getULong(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
dp += 4;
break;
case 's':
opcount = snprintf(op, opleft, "%d",
getShort(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
dp += 2;
break;
case 'S':
opcount = snprintf(op, opleft, "%d",
getUShort(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
dp += 2;
break;
case 'b':
opcount = snprintf(op, opleft, "%d",
*(char *)dp++);
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
break;
case 'B':
opcount = snprintf(op, opleft, "%d", *dp++);
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
break;
case 'x':
opcount = snprintf(op, opleft, "%x", *dp++);
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
break;
case 'f':
opcount = strlcpy(op,
*dp++ ? "true" : "false", opleft);
if (opcount >= opleft)
goto toobig;
opleft -= opcount;
break;
default:
warning("Unexpected format code %c", fmtbuf[j]);
}
op += strlen(op);
opleft -= strlen(op);
if (opleft < 1)
goto toobig;
if (j + 1 < numelem && comma != ':') {
*op++ = ' ';
opleft--;
}
}
if (i + 1 < numhunk) {
*op++ = comma;
opleft--;
}
if (opleft < 1)
goto toobig;
}
return (optbuf);
toobig:
warning("dhcp option too large");
return ("<error>");
}
void
do_packet(struct interface_info *interface, struct dhcp_packet *packet,
int len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
{
struct packet tp;
int i;
if (packet->hlen > sizeof(packet->chaddr)) {
note("Discarding packet with invalid hlen.");
return;
}
memset(&tp, 0, sizeof(tp));
tp.raw = packet;
tp.packet_length = len;
tp.client_port = from_port;
tp.client_addr = from;
tp.interface = interface;
tp.haddr = hfrom;
parse_options(&tp);
if (tp.options_valid &&
tp.options[DHO_DHCP_MESSAGE_TYPE].data)
tp.packet_type = tp.options[DHO_DHCP_MESSAGE_TYPE].data[0];
if (tp.packet_type)
dhcp(&tp);
else
bootp(&tp);
/* Free the data associated with the options. */
for (i = 0; i < 256; i++)
if (tp.options[i].len && tp.options[i].data)
free(tp.options[i].data);
}

253
sbin/dhclient/packet.c Normal file
View File

@ -0,0 +1,253 @@
/* $OpenBSD: packet.c,v 1.9 2004/05/04 18:58:50 deraadt Exp $ */
/* Packet assembly code, originally contributed by Archie Cobbs. */
/*
* Copyright (c) 1995, 1996, 1999 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''.
*/
#include "dhcpd.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/if_ether.h>
#define ETHER_HEADER_SIZE (ETHER_ADDR_LEN * 2 + sizeof(u_int16_t))
u_int32_t checksum(unsigned char *, unsigned, u_int32_t);
u_int32_t wrapsum(u_int32_t);
void assemble_ethernet_header(struct interface_info *, unsigned char *,
int *, struct hardware *);
ssize_t decode_ethernet_header(struct interface_info *, unsigned char *,
int bufix, struct hardware *);
u_int32_t
checksum(unsigned char *buf, unsigned nbytes, u_int32_t sum)
{
int i;
/* Checksum all the pairs of bytes first... */
for (i = 0; i < (nbytes & ~1U); i += 2) {
sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i)));
if (sum > 0xFFFF)
sum -= 0xFFFF;
}
/*
* If there's a single byte left over, checksum it, too.
* Network byte order is big-endian, so the remaining byte is
* the high byte.
*/
if (i < nbytes) {
sum += buf[i] << 8;
if (sum > 0xFFFF)
sum -= 0xFFFF;
}
return (sum);
}
u_int32_t
wrapsum(u_int32_t sum)
{
sum = ~sum & 0xFFFF;
return (htons(sum));
}
void
assemble_hw_header(struct interface_info *interface, unsigned char *buf,
int *bufix, struct hardware *to)
{
struct ether_header eh;
if (to != NULL && to->hlen == 6) /* XXX */
memcpy(eh.ether_dhost, to->haddr, sizeof(eh.ether_dhost));
else
memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost));
if (interface->hw_address.hlen == sizeof(eh.ether_shost))
memcpy(eh.ether_shost, interface->hw_address.haddr,
sizeof(eh.ether_shost));
else
memset(eh.ether_shost, 0x00, sizeof(eh.ether_shost));
eh.ether_type = htons(ETHERTYPE_IP);
memcpy(&buf[*bufix], &eh, ETHER_HEADER_SIZE);
*bufix += ETHER_HEADER_SIZE;
}
void
assemble_udp_ip_header(unsigned char *buf, int *bufix, u_int32_t from,
u_int32_t to, unsigned int port, unsigned char *data, int len)
{
struct ip ip;
struct udphdr udp;
ip.ip_v = 4;
ip.ip_hl = 5;
ip.ip_tos = IPTOS_LOWDELAY;
ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len);
ip.ip_id = 0;
ip.ip_off = 0;
ip.ip_ttl = 16;
ip.ip_p = IPPROTO_UDP;
ip.ip_sum = 0;
ip.ip_src.s_addr = from;
ip.ip_dst.s_addr = to;
ip.ip_sum = wrapsum(checksum((unsigned char *)&ip, sizeof(ip), 0));
memcpy(&buf[*bufix], &ip, sizeof(ip));
*bufix += sizeof(ip);
udp.uh_sport = htons(LOCAL_PORT); /* XXX */
udp.uh_dport = port; /* XXX */
udp.uh_ulen = htons(sizeof(udp) + len);
memset(&udp.uh_sum, 0, sizeof(udp.uh_sum));
udp.uh_sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp),
checksum(data, len, checksum((unsigned char *)&ip.ip_src,
2 * sizeof(ip.ip_src),
IPPROTO_UDP + (u_int32_t)ntohs(udp.uh_ulen)))));
memcpy(&buf[*bufix], &udp, sizeof(udp));
*bufix += sizeof(udp);
}
ssize_t
decode_hw_header(unsigned char *buf, int bufix, struct hardware *from)
{
struct ether_header eh;
memcpy(&eh, buf + bufix, ETHER_HEADER_SIZE);
memcpy(from->haddr, eh.ether_shost, sizeof(eh.ether_shost));
from->htype = ARPHRD_ETHER;
from->hlen = sizeof(eh.ether_shost);
return (sizeof(eh));
}
ssize_t
decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
unsigned char *data, int buflen)
{
struct ip *ip;
struct udphdr *udp;
u_int32_t ip_len = (buf[bufix] & 0xf) << 2;
u_int32_t sum, usum;
static int ip_packets_seen;
static int ip_packets_bad_checksum;
static int udp_packets_seen;
static int udp_packets_bad_checksum;
static int udp_packets_length_checked;
static int udp_packets_length_overflow;
int len = 0;
ip = (struct ip *)(buf + bufix);
udp = (struct udphdr *)(buf + bufix + ip_len);
/* Check the IP header checksum - it should be zero. */
ip_packets_seen++;
if (wrapsum(checksum(buf + bufix, ip_len, 0)) != 0) {
ip_packets_bad_checksum++;
if (ip_packets_seen > 4 &&
(ip_packets_seen / ip_packets_bad_checksum) < 2) {
note("%d bad IP checksums seen in %d packets",
ip_packets_bad_checksum, ip_packets_seen);
ip_packets_seen = ip_packets_bad_checksum = 0;
}
return (-1);
}
if (ntohs(ip->ip_len) != buflen)
debug("ip length %d disagrees with bytes received %d.",
ntohs(ip->ip_len), buflen);
memcpy(&from->sin_addr, &ip->ip_src, 4);
/*
* Compute UDP checksums, including the ``pseudo-header'', the
* UDP header and the data. If the UDP checksum field is zero,
* we're not supposed to do a checksum.
*/
if (!data) {
data = buf + bufix + ip_len + sizeof(*udp);
len = ntohs(udp->uh_ulen) - sizeof(*udp);
udp_packets_length_checked++;
if (len + data > buf + bufix + buflen) {
udp_packets_length_overflow++;
if (udp_packets_length_checked > 4 &&
(udp_packets_length_checked /
udp_packets_length_overflow) < 2) {
note("%d udp packets in %d too long - dropped",
udp_packets_length_overflow,
udp_packets_length_checked);
udp_packets_length_overflow =
udp_packets_length_checked = 0;
}
return (-1);
}
if (len + data != buf + bufix + buflen)
debug("accepting packet with data after udp payload.");
}
usum = udp->uh_sum;
udp->uh_sum = 0;
sum = wrapsum(checksum((unsigned char *)udp, sizeof(*udp),
checksum(data, len, checksum((unsigned char *)&ip->ip_src,
2 * sizeof(ip->ip_src),
IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen)))));
udp_packets_seen++;
if (usum && usum != sum) {
udp_packets_bad_checksum++;
if (udp_packets_seen > 4 &&
(udp_packets_seen / udp_packets_bad_checksum) < 2) {
note("%d bad udp checksums in %d packets",
udp_packets_bad_checksum, udp_packets_seen);
udp_packets_seen = udp_packets_bad_checksum = 0;
}
return (-1);
}
memcpy(&from->sin_port, &udp->uh_sport, sizeof(udp->uh_sport));
return (ip_len + sizeof(*udp));
}

577
sbin/dhclient/parse.c Normal file
View File

@ -0,0 +1,577 @@
/* $OpenBSD: parse.c,v 1.11 2004/05/05 23:07:47 deraadt Exp $ */
/* Common parser code for dhcpd and dhclient. */
/*
* Copyright (c) 1995, 1996, 1997, 1998 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''.
*/
#include "dhcpd.h"
#include "dhctoken.h"
/* Skip to the semicolon ending the current statement. If we encounter
* braces, the matching closing brace terminates the statement. If we
* encounter a right brace but haven't encountered a left brace, return
* leaving the brace in the token buffer for the caller. If we see a
* semicolon and haven't seen a left brace, return. This lets us skip
* over:
*
* statement;
* statement foo bar { }
* statement foo bar { statement { } }
* statement}
*
* ...et cetera.
*/
void
skip_to_semi(FILE *cfile)
{
int brace_count = 0, token;
char *val;
do {
token = peek_token(&val, cfile);
if (token == RBRACE) {
if (brace_count) {
token = next_token(&val, cfile);
if (!--brace_count)
return;
} else
return;
} else if (token == LBRACE) {
brace_count++;
} else if (token == SEMI && !brace_count) {
token = next_token(&val, cfile);
return;
} else if (token == '\n') {
/*
* EOL only happens when parsing
* /etc/resolv.conf, and we treat it like a
* semicolon because the resolv.conf file is
* line-oriented.
*/
token = next_token(&val, cfile);
return;
}
token = next_token(&val, cfile);
} while (token != EOF);
}
int
parse_semi(FILE *cfile)
{
int token;
char *val;
token = next_token(&val, cfile);
if (token != SEMI) {
parse_warn("semicolon expected.");
skip_to_semi(cfile);
return (0);
}
return (1);
}
/*
* string-parameter :== STRING SEMI
*/
char *
parse_string(FILE *cfile)
{
char *val, *s;
int token;
token = next_token(&val, cfile);
if (token != STRING) {
parse_warn("filename must be a string");
skip_to_semi(cfile);
return (NULL);
}
s = malloc(strlen(val) + 1);
if (!s)
error("no memory for string %s.", val);
strlcpy(s, val, strlen(val) + 1);
if (!parse_semi(cfile))
return (NULL);
return (s);
}
int
parse_ip_addr(FILE *cfile, struct iaddr *addr)
{
addr->len = 4;
if (parse_numeric_aggregate(cfile, addr->iabuf,
&addr->len, DOT, 10, 8))
return (1);
return (0);
}
/*
* hardware-parameter :== HARDWARE ETHERNET csns SEMI
* csns :== NUMBER | csns COLON NUMBER
*/
void
parse_hardware_param(FILE *cfile, struct hardware *hardware)
{
unsigned char *t;
int token, hlen;
char *val;
token = next_token(&val, cfile);
switch (token) {
case ETHERNET:
hardware->htype = HTYPE_ETHER;
break;
case TOKEN_RING:
hardware->htype = HTYPE_IEEE802;
break;
case FDDI:
hardware->htype = HTYPE_FDDI;
break;
default:
parse_warn("expecting a network hardware type");
skip_to_semi(cfile);
return;
}
/*
* Parse the hardware address information. Technically, it
* would make a lot of sense to restrict the length of the data
* we'll accept here to the length of a particular hardware
* address type. Unfortunately, there are some broken clients
* out there that put bogus data in the chaddr buffer, and we
* accept that data in the lease file rather than simply failing
* on such clients. Yuck.
*/
hlen = 0;
t = parse_numeric_aggregate(cfile, NULL, &hlen, COLON, 16, 8);
if (!t)
return;
if (hlen > sizeof(hardware->haddr)) {
free(t);
parse_warn("hardware address too long");
} else {
hardware->hlen = hlen;
memcpy((unsigned char *)&hardware->haddr[0], t,
hardware->hlen);
if (hlen < sizeof(hardware->haddr))
memset(&hardware->haddr[hlen], 0,
sizeof(hardware->haddr) - hlen);
free(t);
}
token = next_token(&val, cfile);
if (token != SEMI) {
parse_warn("expecting semicolon.");
skip_to_semi(cfile);
}
}
/*
* lease-time :== NUMBER SEMI
*/
void
parse_lease_time(FILE *cfile, time_t *timep)
{
char *val;
int token;
token = next_token(&val, cfile);
if (token != NUMBER) {
parse_warn("Expecting numeric lease time");
skip_to_semi(cfile);
return;
}
convert_num((unsigned char *)timep, val, 10, 32);
/* Unswap the number - convert_num returns stuff in NBO. */
*timep = ntohl(*timep); /* XXX */
parse_semi(cfile);
}
/*
* No BNF for numeric aggregates - that's defined by the caller. What
* this function does is to parse a sequence of numbers separated by the
* token specified in separator. If max is zero, any number of numbers
* will be parsed; otherwise, exactly max numbers are expected. Base
* and size tell us how to internalize the numbers once they've been
* tokenized.
*/
unsigned char *
parse_numeric_aggregate(FILE *cfile, unsigned char *buf, int *max,
int separator, int base, int size)
{
unsigned char *bufp = buf, *s = NULL;
int token, count = 0;
char *val, *t;
pair c = NULL;
if (!bufp && *max) {
bufp = malloc(*max * size / 8);
if (!bufp)
error("can't allocate space for numeric aggregate");
} else
s = bufp;
do {
if (count) {
token = peek_token(&val, cfile);
if (token != separator) {
if (!*max)
break;
if (token != RBRACE && token != LBRACE)
token = next_token(&val, cfile);
parse_warn("too few numbers.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
token = next_token(&val, cfile);
}
token = next_token(&val, cfile);
if (token == EOF) {
parse_warn("unexpected end of file");
break;
}
/* Allow NUMBER_OR_NAME if base is 16. */
if (token != NUMBER &&
(base != 16 || token != NUMBER_OR_NAME)) {
parse_warn("expecting numeric value.");
skip_to_semi(cfile);
return (NULL);
}
/*
* If we can, convert the number now; otherwise, build a
* linked list of all the numbers.
*/
if (s) {
convert_num(s, val, base, size);
s += size / 8;
} else {
t = malloc(strlen(val) + 1);
if (!t)
error("no temp space for number.");
strlcpy(t, val, strlen(val) + 1);
c = cons(t, c);
}
} while (++count != *max);
/* If we had to cons up a list, convert it now. */
if (c) {
bufp = malloc(count * size / 8);
if (!bufp)
error("can't allocate space for numeric aggregate.");
s = bufp + count - size / 8;
*max = count;
}
while (c) {
pair cdr = c->cdr;
convert_num(s, (char *)c->car, base, size);
s -= size / 8;
/* Free up temp space. */
free(c->car);
free(c);
c = cdr;
}
return (bufp);
}
void
convert_num(unsigned char *buf, char *str, int base, int size)
{
int negative = 0, tval, max;
u_int32_t val = 0;
char *ptr = str;
if (*ptr == '-') {
negative = 1;
ptr++;
}
/* If base wasn't specified, figure it out from the data. */
if (!base) {
if (ptr[0] == '0') {
if (ptr[1] == 'x') {
base = 16;
ptr += 2;
} else if (isascii(ptr[1]) && isdigit(ptr[1])) {
base = 8;
ptr += 1;
} else
base = 10;
} else
base = 10;
}
do {
tval = *ptr++;
/* XXX assumes ASCII... */
if (tval >= 'a')
tval = tval - 'a' + 10;
else if (tval >= 'A')
tval = tval - 'A' + 10;
else if (tval >= '0')
tval -= '0';
else {
warning("Bogus number: %s.", str);
break;
}
if (tval >= base) {
warning("Bogus number: %s: digit %d not in base %d",
str, tval, base);
break;
}
val = val * base + tval;
} while (*ptr);
if (negative)
max = (1 << (size - 1));
else
max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
if (val > max) {
switch (base) {
case 8:
warning("value %s%o exceeds max (%d) for precision.",
negative ? "-" : "", val, max);
break;
case 16:
warning("value %s%x exceeds max (%d) for precision.",
negative ? "-" : "", val, max);
break;
default:
warning("value %s%u exceeds max (%d) for precision.",
negative ? "-" : "", val, max);
break;
}
}
if (negative)
switch (size) {
case 8:
*buf = -(unsigned long)val;
break;
case 16:
putShort(buf, -(unsigned long)val);
break;
case 32:
putLong(buf, -(unsigned long)val);
break;
default:
warning("Unexpected integer size: %d", size);
break;
}
else
switch (size) {
case 8:
*buf = (u_int8_t)val;
break;
case 16:
putUShort(buf, (u_int16_t)val);
break;
case 32:
putULong(buf, val);
break;
default:
warning("Unexpected integer size: %d", size);
break;
}
}
/*
* date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
* NUMBER COLON NUMBER COLON NUMBER SEMI
*
* Dates are always in GMT; first number is day of week; next is
* year/month/day; next is hours:minutes:seconds on a 24-hour
* clock.
*/
time_t
parse_date(FILE *cfile)
{
static int months[11] = { 31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334 };
int guess, token;
struct tm tm;
char *val;
/* Day of week... */
token = next_token(&val, cfile);
if (token != NUMBER) {
parse_warn("numeric day of week expected.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
tm.tm_wday = atoi(val);
/* Year... */
token = next_token(&val, cfile);
if (token != NUMBER) {
parse_warn("numeric year expected.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
tm.tm_year = atoi(val);
if (tm.tm_year > 1900)
tm.tm_year -= 1900;
/* Slash separating year from month... */
token = next_token(&val, cfile);
if (token != SLASH) {
parse_warn("expected slash separating year from month.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
/* Month... */
token = next_token(&val, cfile);
if (token != NUMBER) {
parse_warn("numeric month expected.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
tm.tm_mon = atoi(val) - 1;
/* Slash separating month from day... */
token = next_token(&val, cfile);
if (token != SLASH) {
parse_warn("expected slash separating month from day.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
/* Month... */
token = next_token(&val, cfile);
if (token != NUMBER) {
parse_warn("numeric day of month expected.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
tm.tm_mday = atoi(val);
/* Hour... */
token = next_token(&val, cfile);
if (token != NUMBER) {
parse_warn("numeric hour expected.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
tm.tm_hour = atoi(val);
/* Colon separating hour from minute... */
token = next_token(&val, cfile);
if (token != COLON) {
parse_warn("expected colon separating hour from minute.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
/* Minute... */
token = next_token(&val, cfile);
if (token != NUMBER) {
parse_warn("numeric minute expected.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
tm.tm_min = atoi(val);
/* Colon separating minute from second... */
token = next_token(&val, cfile);
if (token != COLON) {
parse_warn("expected colon separating hour from minute.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
/* Minute... */
token = next_token(&val, cfile);
if (token != NUMBER) {
parse_warn("numeric minute expected.");
if (token != SEMI)
skip_to_semi(cfile);
return (NULL);
}
tm.tm_sec = atoi(val);
tm.tm_isdst = 0;
/* XXX: We assume that mktime does not use tm_yday. */
tm.tm_yday = 0;
/* Make sure the date ends in a semicolon... */
token = next_token(&val, cfile);
if (token != SEMI) {
parse_warn("semicolon expected.");
skip_to_semi(cfile);
return (NULL);
}
/* Guess the time value... */
guess = ((((((365 * (tm.tm_year - 70) + /* Days in years since '70 */
(tm.tm_year - 69) / 4 + /* Leap days since '70 */
(tm.tm_mon /* Days in months this year */
? months[tm.tm_mon - 1]
: 0) +
(tm.tm_mon > 1 && /* Leap day this year */
!((tm.tm_year - 72) & 3)) +
tm.tm_mday - 1) * 24) + /* Day of month */
tm.tm_hour) * 60) +
tm.tm_min) * 60) + tm.tm_sec;
/*
* This guess could be wrong because of leap seconds or other
* weirdness we don't know about that the system does. For
* now, we're just going to accept the guess, but at some point
* it might be nice to do a successive approximation here to get
* an exact value. Even if the error is small, if the server
* is restarted frequently (and thus the lease database is
* reread), the error could accumulate into something
* significant.
*/
return (guess);
}

235
sbin/dhclient/privsep.c Normal file
View File

@ -0,0 +1,235 @@
/* $OpenBSD: privsep.c,v 1.7 2004/05/10 18:34:42 deraadt Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "dhcpd.h"
#include "privsep.h"
struct buf *
buf_open(size_t len)
{
struct buf *buf;
if ((buf = calloc(1, sizeof(struct buf))) == NULL)
return (NULL);
if ((buf->buf = malloc(len)) == NULL) {
free(buf);
return (NULL);
}
buf->size = len;
return (buf);
}
int
buf_add(struct buf *buf, void *data, size_t len)
{
if (buf->wpos + len > buf->size)
return (-1);
memcpy(buf->buf + buf->wpos, data, len);
buf->wpos += len;
return (0);
}
int
buf_close(int sock, struct buf *buf)
{
ssize_t n;
do {
n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos);
if (n != -1)
buf->rpos += n;
if (n == 0) { /* connection closed */
errno = 0;
return (-1);
}
} while (n == -1 && (errno == EAGAIN || errno == EINTR));
if (buf->rpos < buf->size)
error("short write: wanted %lu got %ld bytes",
(unsigned long)buf->size, (long)buf->rpos);
free(buf->buf);
free(buf);
return (n);
}
ssize_t
buf_read(int sock, void *buf, size_t nbytes)
{
ssize_t n, r = 0;
char *p = buf;
do {
n = read(sock, p, nbytes);
if (n == 0)
error("connection closed");
if (n != -1) {
r += n;
p += n;
nbytes -= n;
}
} while (n == -1 && (errno == EINTR || errno == EAGAIN));
if (n == -1)
error("buf_read: %m");
if (r < nbytes)
error("short read: wanted %lu got %ld bytes",
(unsigned long)nbytes, (long)r);
return (r);
}
void
dispatch_imsg(int fd)
{
struct imsg_hdr hdr;
char *medium, *reason, *filename,
*servername, *prefix;
size_t medium_len, reason_len, filename_len,
servername_len, prefix_len, totlen;
struct client_lease lease;
int ret, i, optlen;
struct buf *buf;
buf_read(fd, &hdr, sizeof(hdr));
switch (hdr.code) {
case IMSG_SCRIPT_INIT:
if (hdr.len < sizeof(hdr) + sizeof(size_t))
error("corrupted message received");
buf_read(fd, &medium_len, sizeof(medium_len));
if (hdr.len < medium_len + sizeof(size_t) + sizeof(hdr)
+ sizeof(size_t) || medium_len == SIZE_T_MAX)
error("corrupted message received");
if (medium_len > 0) {
if ((medium = calloc(1, medium_len + 1)) == NULL)
error("%m");
buf_read(fd, medium, medium_len);
} else
medium = NULL;
buf_read(fd, &reason_len, sizeof(reason_len));
if (hdr.len < medium_len + reason_len + sizeof(hdr) ||
reason_len == SIZE_T_MAX)
error("corrupted message received");
if (reason_len > 0) {
if ((reason = calloc(1, reason_len + 1)) == NULL)
error("%m");
buf_read(fd, reason, reason_len);
} else
reason = NULL;
priv_script_init(reason, medium);
free(reason);
free(medium);
break;
case IMSG_SCRIPT_WRITE_PARAMS:
bzero(&lease, sizeof lease);
totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t);
if (hdr.len < totlen)
error("corrupted message received");
buf_read(fd, &lease, sizeof(lease));
buf_read(fd, &filename_len, sizeof(filename_len));
totlen += filename_len + sizeof(size_t);
if (hdr.len < totlen || filename_len == SIZE_T_MAX)
error("corrupted message received");
if (filename_len > 0) {
if ((filename = calloc(1, filename_len + 1)) == NULL)
error("%m");
buf_read(fd, filename, filename_len);
} else
filename = NULL;
buf_read(fd, &servername_len, sizeof(servername_len));
totlen += servername_len + sizeof(size_t);
if (hdr.len < totlen || servername_len == SIZE_T_MAX)
error("corrupted message received");
if (servername_len > 0) {
if ((servername =
calloc(1, servername_len + 1)) == NULL)
error("%m");
buf_read(fd, servername, servername_len);
} else
servername = NULL;
buf_read(fd, &prefix_len, sizeof(prefix_len));
totlen += prefix_len;
if (hdr.len < totlen || prefix_len == SIZE_T_MAX)
error("corrupted message received");
if (prefix_len > 0) {
if ((prefix = calloc(1, prefix_len + 1)) == NULL)
error("%m");
buf_read(fd, prefix, prefix_len);
} else
prefix = NULL;
for (i = 0; i < 256; i++) {
totlen += sizeof(optlen);
if (hdr.len < totlen)
error("corrupted message received");
buf_read(fd, &optlen, sizeof(optlen));
lease.options[i].data = NULL;
lease.options[i].len = optlen;
if (optlen > 0) {
totlen += optlen;
if (hdr.len < totlen || optlen == SIZE_T_MAX)
error("corrupted message received");
lease.options[i].data =
calloc(1, optlen + 1);
if (lease.options[i].data == NULL)
error("%m");
buf_read(fd, lease.options[i].data, optlen);
}
}
lease.server_name = servername;
lease.filename = filename;
priv_script_write_params(prefix, &lease);
free(servername);
free(filename);
free(prefix);
for (i = 0; i < 256; i++)
if (lease.options[i].len > 0)
free(lease.options[i].data);
break;
case IMSG_SCRIPT_GO:
if (hdr.len != sizeof(hdr))
error("corrupted message received");
ret = priv_script_go();
hdr.code = IMSG_SCRIPT_GO_RET;
hdr.len = sizeof(struct imsg_hdr) + sizeof(int);
if ((buf = buf_open(hdr.len)) == NULL)
error("buf_open: %m");
if (buf_add(buf, &hdr, sizeof(hdr)))
error("buf_add: %m");
if (buf_add(buf, &ret, sizeof(ret)))
error("buf_add: %m");
if (buf_close(fd, buf) == -1)
error("buf_close: %m");
break;
default:
error("received unknown message, code %d", hdr.code);
}
}

47
sbin/dhclient/privsep.h Normal file
View File

@ -0,0 +1,47 @@
/* $OpenBSD: privsep.h,v 1.2 2004/05/04 18:51:18 henning Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <poll.h>
#include <pwd.h>
struct buf {
u_char *buf;
size_t size;
size_t wpos;
size_t rpos;
};
enum imsg_code {
IMSG_NONE,
IMSG_SCRIPT_INIT,
IMSG_SCRIPT_WRITE_PARAMS,
IMSG_SCRIPT_GO,
IMSG_SCRIPT_GO_RET
};
struct imsg_hdr {
enum imsg_code code;
size_t len;
};
struct buf *buf_open(size_t);
int buf_add(struct buf *, void *, size_t);
int buf_close(int, struct buf *);
ssize_t buf_read(int sock, void *, size_t);

430
sbin/dhclient/tables.c Normal file
View File

@ -0,0 +1,430 @@
/* $OpenBSD: tables.c,v 1.4 2004/05/04 20:28:40 deraadt Exp $ */
/* Tables of information... */
/*
* Copyright (c) 1995, 1996 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''.
*/
#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 },
{ "ien116-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", "X", &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", "X", &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", "X", &dhcp_universe, 61 },
{ "option-62", "X", &dhcp_universe, 62 },
{ "option-63", "X", &dhcp_universe, 63 },
{ "nisplus-domain", "t", &dhcp_universe, 64 },
{ "nisplus-servers", "IA", &dhcp_universe, 65 },
{ "tftp-server-name", "t", &dhcp_universe, 66 },
{ "bootfile-name", "t", &dhcp_universe, 67 },
{ "mobile-ip-home-agent", "IA", &dhcp_universe, 68 },
{ "smtp-server", "IA", &dhcp_universe, 69 },
{ "pop-server", "IA", &dhcp_universe, 70 },
{ "nntp-server", "IA", &dhcp_universe, 71 },
{ "www-server", "IA", &dhcp_universe, 72 },
{ "finger-server", "IA", &dhcp_universe, 73 },
{ "irc-server", "IA", &dhcp_universe, 74 },
{ "streettalk-server", "IA", &dhcp_universe, 75 },
{ "streettalk-directory-assistance-server", "IA", &dhcp_universe, 76 },
{ "user-class", "t", &dhcp_universe, 77 },
{ "option-78", "X", &dhcp_universe, 78 },
{ "option-79", "X", &dhcp_universe, 79 },
{ "option-80", "X", &dhcp_universe, 80 },
{ "option-81", "X", &dhcp_universe, 81 },
{ "option-82", "X", &dhcp_universe, 82 },
{ "option-83", "X", &dhcp_universe, 83 },
{ "option-84", "X", &dhcp_universe, 84 },
{ "nds-servers", "IA", &dhcp_universe, 85 },
{ "nds-tree-name", "X", &dhcp_universe, 86 },
{ "nds-context", "X", &dhcp_universe, 87 },
{ "option-88", "X", &dhcp_universe, 88 },
{ "option-89", "X", &dhcp_universe, 89 },
{ "option-90", "X", &dhcp_universe, 90 },
{ "option-91", "X", &dhcp_universe, 91 },
{ "option-92", "X", &dhcp_universe, 92 },
{ "option-93", "X", &dhcp_universe, 93 },
{ "option-94", "X", &dhcp_universe, 94 },
{ "option-95", "X", &dhcp_universe, 95 },
{ "option-96", "X", &dhcp_universe, 96 },
{ "option-97", "X", &dhcp_universe, 97 },
{ "option-98", "X", &dhcp_universe, 98 },
{ "option-99", "X", &dhcp_universe, 99 },
{ "option-100", "X", &dhcp_universe, 100 },
{ "option-101", "X", &dhcp_universe, 101 },
{ "option-102", "X", &dhcp_universe, 102 },
{ "option-103", "X", &dhcp_universe, 103 },
{ "option-104", "X", &dhcp_universe, 104 },
{ "option-105", "X", &dhcp_universe, 105 },
{ "option-106", "X", &dhcp_universe, 106 },
{ "option-107", "X", &dhcp_universe, 107 },
{ "option-108", "X", &dhcp_universe, 108 },
{ "option-109", "X", &dhcp_universe, 109 },
{ "option-110", "X", &dhcp_universe, 110 },
{ "option-111", "X", &dhcp_universe, 111 },
{ "option-112", "X", &dhcp_universe, 112 },
{ "option-113", "X", &dhcp_universe, 113 },
{ "option-114", "X", &dhcp_universe, 114 },
{ "option-115", "X", &dhcp_universe, 115 },
{ "option-116", "X", &dhcp_universe, 116 },
{ "option-117", "X", &dhcp_universe, 117 },
{ "option-118", "X", &dhcp_universe, 118 },
{ "option-119", "X", &dhcp_universe, 119 },
{ "option-120", "X", &dhcp_universe, 120 },
{ "option-121", "X", &dhcp_universe, 121 },
{ "option-122", "X", &dhcp_universe, 122 },
{ "option-123", "X", &dhcp_universe, 123 },
{ "option-124", "X", &dhcp_universe, 124 },
{ "option-125", "X", &dhcp_universe, 125 },
{ "option-126", "X", &dhcp_universe, 126 },
{ "option-127", "X", &dhcp_universe, 127 },
{ "option-128", "X", &dhcp_universe, 128 },
{ "option-129", "X", &dhcp_universe, 129 },
{ "option-130", "X", &dhcp_universe, 130 },
{ "option-131", "X", &dhcp_universe, 131 },
{ "option-132", "X", &dhcp_universe, 132 },
{ "option-133", "X", &dhcp_universe, 133 },
{ "option-134", "X", &dhcp_universe, 134 },
{ "option-135", "X", &dhcp_universe, 135 },
{ "option-136", "X", &dhcp_universe, 136 },
{ "option-137", "X", &dhcp_universe, 137 },
{ "option-138", "X", &dhcp_universe, 138 },
{ "option-139", "X", &dhcp_universe, 139 },
{ "option-140", "X", &dhcp_universe, 140 },
{ "option-141", "X", &dhcp_universe, 141 },
{ "option-142", "X", &dhcp_universe, 142 },
{ "option-143", "X", &dhcp_universe, 143 },
{ "option-144", "X", &dhcp_universe, 144 },
{ "option-145", "X", &dhcp_universe, 145 },
{ "option-146", "X", &dhcp_universe, 146 },
{ "option-147", "X", &dhcp_universe, 147 },
{ "option-148", "X", &dhcp_universe, 148 },
{ "option-149", "X", &dhcp_universe, 149 },
{ "option-150", "X", &dhcp_universe, 150 },
{ "option-151", "X", &dhcp_universe, 151 },
{ "option-152", "X", &dhcp_universe, 152 },
{ "option-153", "X", &dhcp_universe, 153 },
{ "option-154", "X", &dhcp_universe, 154 },
{ "option-155", "X", &dhcp_universe, 155 },
{ "option-156", "X", &dhcp_universe, 156 },
{ "option-157", "X", &dhcp_universe, 157 },
{ "option-158", "X", &dhcp_universe, 158 },
{ "option-159", "X", &dhcp_universe, 159 },
{ "option-160", "X", &dhcp_universe, 160 },
{ "option-161", "X", &dhcp_universe, 161 },
{ "option-162", "X", &dhcp_universe, 162 },
{ "option-163", "X", &dhcp_universe, 163 },
{ "option-164", "X", &dhcp_universe, 164 },
{ "option-165", "X", &dhcp_universe, 165 },
{ "option-166", "X", &dhcp_universe, 166 },
{ "option-167", "X", &dhcp_universe, 167 },
{ "option-168", "X", &dhcp_universe, 168 },
{ "option-169", "X", &dhcp_universe, 169 },
{ "option-170", "X", &dhcp_universe, 170 },
{ "option-171", "X", &dhcp_universe, 171 },
{ "option-172", "X", &dhcp_universe, 172 },
{ "option-173", "X", &dhcp_universe, 173 },
{ "option-174", "X", &dhcp_universe, 174 },
{ "option-175", "X", &dhcp_universe, 175 },
{ "option-176", "X", &dhcp_universe, 176 },
{ "option-177", "X", &dhcp_universe, 177 },
{ "option-178", "X", &dhcp_universe, 178 },
{ "option-179", "X", &dhcp_universe, 179 },
{ "option-180", "X", &dhcp_universe, 180 },
{ "option-181", "X", &dhcp_universe, 181 },
{ "option-182", "X", &dhcp_universe, 182 },
{ "option-183", "X", &dhcp_universe, 183 },
{ "option-184", "X", &dhcp_universe, 184 },
{ "option-185", "X", &dhcp_universe, 185 },
{ "option-186", "X", &dhcp_universe, 186 },
{ "option-187", "X", &dhcp_universe, 187 },
{ "option-188", "X", &dhcp_universe, 188 },
{ "option-189", "X", &dhcp_universe, 189 },
{ "option-190", "X", &dhcp_universe, 190 },
{ "option-191", "X", &dhcp_universe, 191 },
{ "option-192", "X", &dhcp_universe, 192 },
{ "option-193", "X", &dhcp_universe, 193 },
{ "option-194", "X", &dhcp_universe, 194 },
{ "option-195", "X", &dhcp_universe, 195 },
{ "option-196", "X", &dhcp_universe, 196 },
{ "option-197", "X", &dhcp_universe, 197 },
{ "option-198", "X", &dhcp_universe, 198 },
{ "option-199", "X", &dhcp_universe, 199 },
{ "option-200", "X", &dhcp_universe, 200 },
{ "option-201", "X", &dhcp_universe, 201 },
{ "option-202", "X", &dhcp_universe, 202 },
{ "option-203", "X", &dhcp_universe, 203 },
{ "option-204", "X", &dhcp_universe, 204 },
{ "option-205", "X", &dhcp_universe, 205 },
{ "option-206", "X", &dhcp_universe, 206 },
{ "option-207", "X", &dhcp_universe, 207 },
{ "option-208", "X", &dhcp_universe, 208 },
{ "option-209", "X", &dhcp_universe, 209 },
{ "option-210", "X", &dhcp_universe, 210 },
{ "option-211", "X", &dhcp_universe, 211 },
{ "option-212", "X", &dhcp_universe, 212 },
{ "option-213", "X", &dhcp_universe, 213 },
{ "option-214", "X", &dhcp_universe, 214 },
{ "option-215", "X", &dhcp_universe, 215 },
{ "option-216", "X", &dhcp_universe, 216 },
{ "option-217", "X", &dhcp_universe, 217 },
{ "option-218", "X", &dhcp_universe, 218 },
{ "option-219", "X", &dhcp_universe, 219 },
{ "option-220", "X", &dhcp_universe, 220 },
{ "option-221", "X", &dhcp_universe, 221 },
{ "option-222", "X", &dhcp_universe, 222 },
{ "option-223", "X", &dhcp_universe, 223 },
{ "option-224", "X", &dhcp_universe, 224 },
{ "option-225", "X", &dhcp_universe, 225 },
{ "option-226", "X", &dhcp_universe, 226 },
{ "option-227", "X", &dhcp_universe, 227 },
{ "option-228", "X", &dhcp_universe, 228 },
{ "option-229", "X", &dhcp_universe, 229 },
{ "option-230", "X", &dhcp_universe, 230 },
{ "option-231", "X", &dhcp_universe, 231 },
{ "option-232", "X", &dhcp_universe, 232 },
{ "option-233", "X", &dhcp_universe, 233 },
{ "option-234", "X", &dhcp_universe, 234 },
{ "option-235", "X", &dhcp_universe, 235 },
{ "option-236", "X", &dhcp_universe, 236 },
{ "option-237", "X", &dhcp_universe, 237 },
{ "option-238", "X", &dhcp_universe, 238 },
{ "option-239", "X", &dhcp_universe, 239 },
{ "option-240", "X", &dhcp_universe, 240 },
{ "option-241", "X", &dhcp_universe, 241 },
{ "option-242", "X", &dhcp_universe, 242 },
{ "option-243", "X", &dhcp_universe, 243 },
{ "option-244", "X", &dhcp_universe, 244 },
{ "option-245", "X", &dhcp_universe, 245 },
{ "option-246", "X", &dhcp_universe, 246 },
{ "option-247", "X", &dhcp_universe, 247 },
{ "option-248", "X", &dhcp_universe, 248 },
{ "option-249", "X", &dhcp_universe, 249 },
{ "option-250", "X", &dhcp_universe, 250 },
{ "option-251", "X", &dhcp_universe, 251 },
{ "option-252", "X", &dhcp_universe, 252 },
{ "option-253", "X", &dhcp_universe, 253 },
{ "option-254", "X", &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_DHCP_REQUESTED_ADDRESS,
DHO_DHCP_OPTION_OVERLOAD,
DHO_DHCP_MAX_MESSAGE_SIZE,
DHO_DHCP_RENEWAL_TIME,
DHO_DHCP_REBINDING_TIME,
DHO_DHCP_CLASS_IDENTIFIER,
DHO_DHCP_CLIENT_IDENTIFIER,
DHO_SUBNET_MASK,
DHO_TIME_OFFSET,
DHO_ROUTERS,
DHO_TIME_SERVERS,
DHO_NAME_SERVERS,
DHO_DOMAIN_NAME_SERVERS,
DHO_HOST_NAME,
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_PARAMETER_REQUEST_LIST,
/* Presently-undefined options... */
62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
251, 252, 253, 254,
};
int sizeof_dhcp_option_default_priority_list =
sizeof(dhcp_option_default_priority_list);
struct hash_table universe_hash;
void
initialize_universes(void)
{
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,
(unsigned char *)dhcp_options[i].name, 0,
(unsigned char *)&dhcp_options[i]);
}
universe_hash.hash_count = DEFAULT_HASH_SIZE;
add_hash(&universe_hash,
(unsigned char *)dhcp_universe.name, 0,
(unsigned char *)&dhcp_universe);
}

56
sbin/dhclient/tree.c Normal file
View File

@ -0,0 +1,56 @@
/* $OpenBSD: tree.c,v 1.13 2004/05/06 22:29:15 deraadt Exp $ */
/* Routines for manipulating parse trees... */
/*
* Copyright (c) 1995, 1996, 1997 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''.
*/
#include "dhcpd.h"
extern int h_errno;
pair
cons(caddr_t car, pair cdr)
{
pair foo = calloc(1, sizeof(*foo));
if (!foo)
error("no memory for cons.");
foo->car = car;
foo->cdr = cdr;
return (foo);
}

66
sbin/dhclient/tree.h Normal file
View File

@ -0,0 +1,66 @@
/* $OpenBSD: tree.h,v 1.5 2004/05/06 22:29:15 deraadt Exp $ */
/* Definitions for address 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''.
*/
/* A pair of pointers, suitable for making a linked list. */
typedef struct _pair {
caddr_t car;
struct _pair *cdr;
} *pair;
struct tree_cache {
unsigned char *value;
int len;
int buf_size;
time_t timeout;
};
struct universe {
char *name;
struct hash_table *hash;
struct option *options[256];
};
struct option {
char *name;
char *format;
struct universe *universe;
unsigned char code;
};