From: David van Moolenbroek Date: Tue, 14 Feb 2017 17:50:02 +0000 (+0000) Subject: Retire MINIX dhcpd(8) X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=refs%2Fchanges%2F39%2F3439%2F1;p=minix.git Retire MINIX dhcpd(8) Change-Id: I4b8c738b6176ce390a7a7817b0dcaf9caffe636c --- diff --git a/distrib/sets/lists/minix-base/mi b/distrib/sets/lists/minix-base/mi index 7a2e75228..65f5a8555 100644 --- a/distrib/sets/lists/minix-base/mi +++ b/distrib/sets/lists/minix-base/mi @@ -326,7 +326,7 @@ ./usr/bin/deroff minix-base ./usr/bin/devmand minix-base ./usr/bin/devsize minix-base -./usr/bin/dhcpd minix-base +./usr/bin/dhcpd minix-base obsolete ./usr/bin/dhrystone minix-base ./usr/bin/diff minix-base ./usr/bin/dirname minix-base @@ -609,7 +609,7 @@ ./usr/bin/znew minix-base ./usr/etc minix-base ./usr/etc/daily minix-base -./usr/etc/dhcptags.conf minix-base +./usr/etc/dhcptags.conf minix-base obsolete ./usr/etc/rc minix-base ./usr/include/c++ minix-base gcc=5 ./usr/include/c++/experimental minix-base gcc=5 diff --git a/distrib/sets/lists/minix-debug/mi b/distrib/sets/lists/minix-debug/mi index 0a3fdd674..ddaf06aa9 100644 --- a/distrib/sets/lists/minix-debug/mi +++ b/distrib/sets/lists/minix-debug/mi @@ -254,7 +254,7 @@ ./usr/libdata/debug/usr/bin/deroff.debug minix-debug debug ./usr/libdata/debug/usr/bin/devmand.debug minix-debug debug ./usr/libdata/debug/usr/bin/devsize.debug minix-debug debug -./usr/libdata/debug/usr/bin/dhcpd.debug minix-debug debug +./usr/libdata/debug/usr/bin/dhcpd.debug minix-debug debug,obsolete ./usr/libdata/debug/usr/bin/dhrystone.debug minix-debug debug ./usr/libdata/debug/usr/bin/diff.debug minix-debug debug ./usr/libdata/debug/usr/bin/dirname.debug minix-debug debug diff --git a/distrib/sets/lists/minix-man/mi b/distrib/sets/lists/minix-man/mi index 651b925f4..22892fd3d 100644 --- a/distrib/sets/lists/minix-man/mi +++ b/distrib/sets/lists/minix-man/mi @@ -3274,7 +3274,7 @@ ./usr/man/man5/configfile.5 minix-man ./usr/man/man5/cpio.5 minix-man ./usr/man/man5/crontab.5 minix-man -./usr/man/man5/dhcp.conf.5 minix-man +./usr/man/man5/dhcp.conf.5 minix-man obsolete ./usr/man/man5/dir.5 minix-man obsolete ./usr/man/man5/editrc.5 minix-man ./usr/man/man5/ethers.5 minix-man @@ -3382,7 +3382,7 @@ ./usr/man/man8/cron.8 minix-man ./usr/man/man8/dev_mkdb.8 minix-man ./usr/man/man8/devsize.8 minix-man -./usr/man/man8/dhcpd.8 minix-man +./usr/man/man8/dhcpd.8 minix-man obsolete ./usr/man/man8/diskctl.8 minix-man ./usr/man/man8/fbdctl.8 minix-man ./usr/man/man8/fdisk.8 minix-man diff --git a/etc/Makefile b/etc/Makefile index e25a70dae..d1fcd0199 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -458,7 +458,6 @@ install-etc-files-safe: .PHONY .MAKE check_DESTDIR MAKEDEV .else # LSC Minix Specific .for owner group mode sdir tdir files in \ ${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/usr/ ${DESTDIR}/usr/etc/ daily \ - ${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/usr/ ${DESTDIR}/usr/etc/ dhcptags.conf \ ${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/usr/ ${DESTDIR}/usr/etc/ rc \ ${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/ ${DESTDIR}/usr/lib/ crontab \ ${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/ ${DESTDIR}/etc/ system.conf \ diff --git a/etc/usr/dhcptags.conf b/etc/usr/dhcptags.conf deleted file mode 100644 index e649b46b0..000000000 --- a/etc/usr/dhcptags.conf +++ /dev/null @@ -1,63 +0,0 @@ -# A list of all tags mentioned in RFC-1533. - -tag 1 netmask ip 1 1; -tag 2 zoneoffset number 4 1; -tag 3 gateway ip 1 0; -tag 4 timeserver ip 1 0; -tag 5 nameserver ip 1 0; -tag 6 DNSserver ip 1 0; -tag 7 logserver ip 1 0; -tag 8 cookieserver ip 1 0; -tag 9 LPR ip 1 0; -tag 10 impress ip 1 0; -tag 11 resource ip 1 0; -tag 12 hostname ascii 1 0; -tag 13 bootfilesize number 2 1; -tag 14 coredump ip 1 0; -tag 15 domain ascii 1 0; -tag 16 swapserver ip 1 1; -tag 17 rootpath ascii 1 0; -tag 18 extensions ascii 1 0; -tag 19 IPforwarding boolean 1 1; -tag 20 IPnonlocalsource boolean 1 1; -tag 21 IPpolicyfilter ip 2 0; -tag 22 IPmaxreassembly number 2 1; -tag 23 IPTTL number 1 1; -tag 24 IPMTUaging number 4 1; -tag 25 IPMTUplateau number 2 0; -tag 26 IPMTU number 2 1; -tag 27 IPsublocal boolean 1 1; -tag 28 IPbroadcast ip 1 1; -tag 29 IPmaskdiscovery boolean 1 1; -tag 30 IPmasksupplier boolean 1 1; -tag 31 IPdiscovery boolean 1 1; -tag 32 IPsolicitation ip 1 1; -tag 33 IPstaticroute ip 2 0; -tag 34 ARPtrailer boolean 1 1; -tag 35 ARPtimeout number 4 1; -tag 36 ETHencapsulation boolean 1 1; -tag 37 TCPTTL number 1 1; -tag 38 TCPkeepaliveinterval number 4 1; -tag 39 TCPkeepalivegarbage boolean 1 1; -tag 40 NISdomain ascii 1 0; -tag 41 NISserver ip 1 0; -tag 42 NTPserver ip 1 0; -tag 43 VENDOR octet 1 0; -tag 44 NetBIOSNS ip 1 0; -tag 45 NetBIOSdgram ip 1 0; -tag 46 NetBIOSnodetype number 1 1; -tag 47 NetBIOSscope octet 1 0; -tag 48 Xfontserver ip 1 0; -tag 49 XDM ip 1 0; -tag 50 DHCPreqip ip 1 1; -tag 51 DHCPlease number 4 1; -tag 52 DHCPoverload number 1 1; -tag 53 DHCPtype number 1 1; -tag 54 DHCPserverID ip 1 1; -tag 55 DHCPreqpar number 1 0; -tag 56 DHCPmessage ascii 1 0; -tag 57 DHCPsize number 2 1; -tag 58 DHCPrenewal number 4 1; -tag 59 DHCPrebinding number 4 1; -tag 60 DHCPclassID ascii 1 0; -tag 61 DHCPclientID octet 1 0; diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index c2853c996..62167dde1 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -8,7 +8,7 @@ CPPFLAGS.fslib.c+= -I${NETBSDSRCDIR}/minix/fs CPPFLAGS.fsversion.c+= -I${NETBSDSRCDIR}/minix/fs -SRCS+= dhcp_gettag.c dhcp_settag.c fsversion.c gcov.c itoa.c \ +SRCS+= fsversion.c gcov.c itoa.c \ oneC_sum.c read_tsc_64.c servxcheck.c fslib.c .endif # defined(__MINIX) diff --git a/minix/commands/Makefile b/minix/commands/Makefile index 1f2b24035..00dd3b8ba 100644 --- a/minix/commands/Makefile +++ b/minix/commands/Makefile @@ -6,7 +6,7 @@ SUBDIR= arp at backup \ cawf cdprobe \ cleantmp \ compress crc cron crontab \ - DESCRIBE devmand devsize dhcpd \ + DESCRIBE devmand devsize \ dhrystone \ eject \ fix format fsck.mfs \ diff --git a/minix/commands/dhcpd/Makefile b/minix/commands/dhcpd/Makefile deleted file mode 100644 index ec9267b41..000000000 --- a/minix/commands/dhcpd/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# Makefile for dhcpd. - -PROG= dhcpd -SRCS= dhcpd.c tags.c devices.c ether.c -MAN= dhcpd.8 dhcp.conf.5 - -.include diff --git a/minix/commands/dhcpd/arp.h b/minix/commands/dhcpd/arp.h deleted file mode 100644 index 0d0b131fd..000000000 --- a/minix/commands/dhcpd/arp.h +++ /dev/null @@ -1,26 +0,0 @@ -/* arp.h - Address Resolution Protocol packet format. - * Author: Kees J. Bot - * 16 Dec 2000 - */ -#ifndef ARP_H -#define ARP_H - -typedef struct arp46 { - ether_addr_t dstaddr; - ether_addr_t srcaddr; - ether_type_t ethtype; /* ARP_PROTO. */ - u16_t hdr, pro; /* ARP_ETHERNET & ETH_IP_PROTO. */ - u8_t hln, pln; /* 6 & 4. */ - u16_t op; /* ARP_REQUEST or ARP_REPLY. */ - ether_addr_t sha; /* Source hardware address. */ - u8_t spa[4]; /* Source protocol address. */ - ether_addr_t tha; /* Likewise for the target. */ - u8_t tpa[4]; - char padding[60 - (4*6 + 2*4 + 4*2 + 2*1)]; -} arp46_t; - -#define ARP_ETHERNET 1 /* ARP on Ethernet. */ -#define ARP_REQUEST 1 /* A request for an IP address. */ -#define ARP_REPLY 2 /* A reply to a request. */ - -#endif /* ARP_H */ diff --git a/minix/commands/dhcpd/devices.c b/minix/commands/dhcpd/devices.c deleted file mode 100644 index 183d31e98..000000000 --- a/minix/commands/dhcpd/devices.c +++ /dev/null @@ -1,347 +0,0 @@ -/* devices.c - Handle network devices. - * Author: Kees J. Bot - * 11 Jun 1999 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dhcpd.h" - -void get_buf(buf_t **bp) -{ - /* Allocate and return a buffer pointer iff *bp == nil. */ - if (*bp != nil) { - /* Already has one. */ - } else { - /* Get one from the heap. */ - buf_t *new= allocate(sizeof(*new)); - new->dhcp= (dhcp_t *) (new->buf + sizeof(eth_hdr_t) - + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)); - new->udpio= ((udp_io_hdr_t *) new->dhcp) - 1; - new->udp= ((udp_hdr_t *) new->dhcp) - 1; - new->ip= ((ip_hdr_t *) new->udp) - 1; - new->eth= ((eth_hdr_t *) new->ip) - 1; - *bp= new; - } -} - -void put_buf(buf_t **bp) -{ - /* Return a buffer to the heap. */ - if (*bp != nil) { - free(*bp); - *bp= nil; - } -} - -void give_buf(buf_t **dbp, buf_t **sbp) -{ - /* Hand over a buffer to another variable. */ - put_buf(dbp); - *dbp= *sbp; - *sbp= nil; -} - -#define N_FDS 16 /* Minix can go async on many fds. */ - -static fd_t fds[N_FDS]; /* List of open descriptors. */ -static struct network *fdwaitq; /* Queue of nets waiting for fds. */ - -network_t *newnetwork(void) -{ - /* Create and initialize a network structure. */ - network_t *new; - - new= allocate(sizeof(*new)); - memset(new, 0, sizeof(*new)); - new->hostname= nil; - new->solicit= NEVER; - new->sol_ct= -1; - return new; -} - -void closefd(fd_t *fdp) -{ - /* Close a descriptor. */ - if (fdp->fdtype != FT_CLOSED) { - asyn_close(&asyn, fdp->fd); - close(fdp->fd); - fdp->fdtype= FT_CLOSED; - fdp->since= 0; - put_buf(&fdp->bp); - if (debug >= 3) printf("%s: Closed\n", fdp->device); - } -} - -static void timeout(int signum) -{ - /* nothing to do, ioctl will be aborted automatically */ - if (alarm(1) == (unsigned int)-1) fatal("alarm(1)"); -} - -int opendev(network_t *np, fdtype_t fdtype, int compete) -{ - /* Make sure that a network has the proper device open and configured. - * Return true if this is made so, or false if the device doesn't exist. - * If compete is true then the caller competes for old descriptors. - * The errno value is EAGAIN if we're out of descriptors. - */ - fd_t *fdp, *fdold; - time_t oldest; - nwio_ethstat_t ethstat; - nwio_ethopt_t ethopt; - nwio_ipopt_t ipopt; - nwio_udpopt_t udpopt; - network_t **pqp; - static char devbytype[][4] = { "", "eth", "ip", "udp", "udp" }; - - /* Don't attempt to open higher level devices if not bound. */ - if (!(np->flags & NF_BOUND) && fdtype > FT_ETHERNET) { - errno= EAGAIN; - return 0; - } - - /* Check if already open / Find the oldest descriptor. */ - fdold= nil; - oldest= NEVER; - for (fdp= fds; fdp < arraylimit(fds); fdp++) { - if (fdp->n == np->n && fdp->fdtype == fdtype) { - /* Already open. */ - np->fdp= fdp; - return 1; - } - if (fdp->since <= oldest) { fdold= fdp; oldest= fdp->since; } - } - - /* None free? Then wait for one to get old if so desired. */ - if (fdold->fdtype != FT_CLOSED && !compete) { - errno= EAGAIN; - return 0; - } - - if (!(np->flags & NF_WAIT)) { - for (pqp= &fdwaitq; *pqp != nil; pqp= &(*pqp)->wait) {} - *pqp= np; - np->wait= nil; - np->flags |= NF_WAIT; - } - - /* We allow a net to keep a descriptor for half of the fast period. */ - oldest += DELTA_FAST/2; - - if (fdwaitq != np || (fdold->fdtype != FT_CLOSED && oldest > now)) { - /* This net is not the first in the queue, or the oldest isn't - * old enough. Forget it for now. - */ - if (oldest < event) event= oldest; - errno= EAGAIN; - return 0; - } - - /* The oldest is mine. */ - np->flags &= ~NF_WAIT; - fdwaitq= np->wait; - closefd(fdold); - - /* Open the proper device in the proper mode. */ - fdp= fdold; - fdp->n= np->n; - if (lwip && (fdtype == FT_ETHERNET || fdtype == FT_ICMP)) - sprintf(fdp->device, "/dev/ip"); - else - sprintf(fdp->device, "/dev/%s%d", devbytype[fdtype], np->n); - np->fdp= fdp; - - if ((fdp->fd= open(fdp->device, O_RDWR)) < 0) { - if (errno == ENOENT || errno == ENODEV || errno == ENXIO) return 0; - fatal(fdp->device); - } - - switch (fdtype) { - case FT_ETHERNET: - if (lwip) { - nwio_ipopt_t ipopt; - int result; - char ethdev[64]; - int efd; - - sprintf(ethdev, "/dev/eth%d", np->n); - - if ((efd = open(fdp->device, O_RDWR)) < 0) { - if (errno == ENOENT || errno == ENODEV || - errno == ENXIO) - return 0; - fatal(ethdev); - } - - if (ioctl(efd, NWIOGETHSTAT, ðstat) < 0) { - /* Not an Ethernet. */ - close(efd); - return 0; - } - close(efd); - - np->eth= ethstat.nwes_addr; - - ipopt.nwio_flags= NWIO_COPY | NWIO_PROTOSPEC; - ipopt.nwio_proto= 17; /* UDP */ - result= ioctl (fdp->fd, NWIOSIPOPT, &ipopt); - if (result<0) - perror("ioctl (NWIOSIPOPT)"), exit(1); - - break; - } - /* Cannot use NWIOGETHSTAT in non-blocking mode due to a race between - * the reply from the ethernet driver and the cancel message from VFS - * for reaching inet. Hence, a signal is used to interrupt NWIOGETHSTAT - * in case the driver isn't ready yet. - */ - if (signal(SIGALRM, timeout) == SIG_ERR) fatal("signal(SIGALRM)"); - if (alarm(1) == (unsigned int)-1) fatal("alarm(1)"); - if (ioctl(np->fdp->fd, NWIOGETHSTAT, ðstat) < 0) { - /* Not an Ethernet. */ - close(fdp->fd); - return 0; - } - if (alarm(0) == (unsigned int)-1) fatal("alarm(0)"); - np->eth= ethstat.nwes_addr; - ethopt.nweo_flags= NWEO_COPY | NWEO_EN_LOC | NWEO_EN_BROAD - | NWEO_REMANY | NWEO_TYPEANY | NWEO_RWDATALL; - - if (ioctl(fdp->fd, NWIOSETHOPT, ðopt) < 0) { - fprintf(stderr, "%s: %s: Unable to set eth options: %s\n", - program, fdp->device, strerror(errno)); - exit(1); - } - break; - - case FT_ICMP: - ipopt.nwio_flags= NWIO_COPY | NWIO_EN_LOC | NWIO_EN_BROAD - | NWIO_REMANY | NWIO_PROTOSPEC - | NWIO_HDR_O_SPEC | NWIO_RWDATALL; - ipopt.nwio_tos= 0; - ipopt.nwio_ttl= 1; - ipopt.nwio_df= 0; - ipopt.nwio_hdropt.iho_opt_siz= 0; - ipopt.nwio_proto= IPPROTO_ICMP; - - if (ioctl(fdp->fd, NWIOSIPOPT, &ipopt) < 0) { - fprintf(stderr, "%s: %s: Unable to set IP options: %s\n", - program, fdp->device, strerror(errno)); - exit(1); - } - break; - - case FT_BOOTPC: - if (lwip) { - struct sockaddr_in si_me; - - close(fdp->fd); - fdp->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fdp->fd < 0) - return 0; - memset((char *) &si_me, 0, sizeof(si_me)); - si_me.sin_family = AF_INET; - si_me.sin_addr.s_addr = htonl(INADDR_ANY); - si_me.sin_port = htons(port_client); - if (bind(fdp->fd, (struct sockaddr *) &si_me, - sizeof(si_me)) == -1) { - close(fdp->fd); - printf("DHCP : cannot bind client socket to port %d\n", - port_client); - return 0; - } - break; - } - udpopt.nwuo_flags= NWUO_COPY | NWUO_EN_LOC | NWUO_EN_BROAD - | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL - | NWUO_DI_IPOPT | NWUO_LP_SET; - udpopt.nwuo_locport= port_client; - goto udp; - - case FT_BOOTPS: - udpopt.nwuo_flags= NWUO_EXCL | NWUO_EN_LOC | NWUO_EN_BROAD - | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL - | NWUO_DI_IPOPT | NWUO_LP_SET; - udpopt.nwuo_locport= port_server; - udp: - if (ioctl(fdp->fd, NWIOSUDPOPT, &udpopt) == -1) { - fprintf(stderr, "%s: %s: Unable to set UDP options: %s\n", - program, fdp->device, strerror(errno)); - exit(1); - } - break; - - default:; - } - - fdp->fdtype= fdtype; - fdp->since= now; - if (debug >= 3) printf("%s: Opened\n", fdp->device); - return 1; -} - -void closedev(network_t *np, fdtype_t fdtype) -{ - /* We no longer need a given type of device to be open. */ - fd_t *fdp; - - for (fdp= fds; fdp < arraylimit(fds); fdp++) { - if (fdp->n == np->n && (fdp->fdtype == fdtype || fdtype == FT_ALL)) { - closefd(fdp); - } - } -} - -char *ipdev(int n) -{ - /* IP device for network #n. */ - static char device[sizeof("/dev/ipNNN")]; - - sprintf(device, "/dev/ip%d", n); - return device; -} - -void set_ipconf(char *device, ipaddr_t ip, ipaddr_t mask, unsigned mtu) -{ - /* Set IP address and netmask of an IP device. */ - int fd; - nwio_ipconf_t ipconf; - - if (test > 0) return; - - if ((fd= open(device, O_RDWR)) < 0) fatal(device); - ipconf.nwic_flags= NWIC_IPADDR_SET | NWIC_NETMASK_SET; - ipconf.nwic_ipaddr= ip; - ipconf.nwic_netmask= mask; -#ifdef NWIC_MTU_SET - if (mtu != 0) { - ipconf.nwic_flags |= NWIC_MTU_SET; - ipconf.nwic_mtu= mtu; - } -#endif - if (ioctl(fd, NWIOSIPCONF, &ipconf) < 0) fatal(device); - close(fd); -} diff --git a/minix/commands/dhcpd/dhcp.conf.5 b/minix/commands/dhcpd/dhcp.conf.5 deleted file mode 100644 index da9e5ebe3..000000000 --- a/minix/commands/dhcpd/dhcp.conf.5 +++ /dev/null @@ -1,498 +0,0 @@ -.TH DHCP.CONF 5 -.SH NAME -dhcp.conf \- dynamic host configuration protocol configuration -.SH SYNOPSIS -.B /etc/dhcp.conf -.SH DESCRIPTION -.de SP -.if t .sp 0.4 -.if n .sp -.. -The file -.B /etc/dhcp.conf -contains the configuration for the DHCP client/server program -.BR dhcpd . -This text is a long summation of all the elements that can be found in this -configuration file. For a more "just tell me what to do" approach see -.BR boot (8). -.PP -The syntax used is that of the common configuration file described in -.BR configfile (5). -.PP -To find information for a client we first need its IP address. Occasionally -this IP address is already known (the special "INFORM" query), but normally -we have to make a first pass through the configuration file for a -.B client -entry. If that fails then we use an IP address from the pool file. If we -now have an IP address then the real information gathering can begin. -.PP -The DHCP daemon reads the configuration file from beginning to end and -gathers all information that matches, and information from all macros that -are mentioned within the elements that match. If we end up with DHCP -information that includes at least a netmask definition, and is good for the -network the request came in from, then it is returned to the client. If a -DHCP tag is specified twice then the last one wins. -.PP -In the description below we use [ and ] to denote optional things, and | to -show a choice between two things. -.PP -Client IDs can be either ordinary Ethernet addresses, that are treated as a -seven octet string (01 followed by the Ethernet address), or any random -octet string in hexadecimal. -.PP -IP addresses can be simply that, or host names. These host names are -searched in -.B /etc/hosts -by -.B dhcpd -itself using a domain based prefix match, i.e. you can use "flotsam" for -"flotsam.example.com", but not "alpha" for "alphabeta". Once the program -decides to be a server it will also look up names normally in the DNS. -If a host has more than one IP address then the address on the network the -query was seen on is used. -.PP -Case isn't important in the configuration file, "client", "CLIENT" and -"ClIeNt" are all treated the same. -.PP -Some elements may optionally name a macro or a curly braces enclosed -parameter list of more elements. If the element matches then the data -in the macro body or parameter list is gathered. -.PP -The following elements can be used: -.PP -.B client -.I client-ID -.RB [ ip #] -.I host -.RI [ macro |{ params }]; -.PP -.RS -Defines a client with a given client ID that is to have the IP address -denoted by -.I host . -On the first pass only the client ID is matched looking for an IP address -that lies on the network the request came in on. On the -information gathering pass both client ID and IP address must match. If -a machine has the same Ethernet address on two or more interfaces then the -IP address given out is the one on the same network as the request came in -on. The optional interface name -.RB ( ip #) -must be used if the DHCP daemon is gathering data for itself at boot time -to differentiate interfaces with the same ethernet addresses. This is -only necessary under Minix-vmd when ethernets on different VLANs share -the same physical ethernet. The interface name is only used for a machine's -own networks, it ignored on entries for other hosts. -.RE -.PP -.B class -.IR class-name " ..." -.IR macro |{ params }; -.PP -.RS -Includes the macro or parameters if one of the class names is matched. A -host normally includes a class ID in its request. MINIX 3 and Minix-vmd -use "Minix" as the class name. For Windows the class ID starts with -"MSFT", and Solaris' starts with "SUNW". -(Use -.B dhcpd \-d3 -to find out what the full IDs are exactly.) The class names are matched if a -.I class-name -is a prefix of the class ID sent by the client. -.RE -.PP -.B host -.I host-spec -.IR macro |{ params }; -.PP -.RS -Includes the macro or parameters if the IP address of the client matches the -host specification. This can either be an ordinary hostname, or a netblock -in CIDR notation, e.g. 172.35.0.0/16. The example includes all IP addresses -whose top 16 bits are the same as the top 16 bits of 172.35.0.0. Such a -netblock automatically defines a netmask (255.255.0.0 in the example) if no -netmask has been specified yet. -.RE -.PP -.B interface -.BR ip # -.I host -.RI [ macro |{ params }]; -.PP -.RS -Makes -.B dhcpd -set the IP address of interface -.BR ip # -(where # is a number) to the IP address denoted by -.IR host . -This element should only be used for interfaces that are not true Ethernets, -and so do not have a unique Ethernet address that can be used for a client -element. If the machine has at least one true Ethernet then all interface -elements should be added to the parameter list of a host or client element -for that Ethernet interface. This binds them to that machine and allows a -single configuration file to be shared among machines. Especially a server -should never have "free" interface elements. The macro or parameters are -only evaluated if data is gathered for the given interface. (Note that they -will be hidden by a client element for another interface.) -.RE -.PP -.B macro -.IR macro-name ; -.PP -.RS -Include the parameter list of the macro named -.I macro-name -defined elsewhere. (This means that "host flotsam stuff" is just short -for "host flotsam { macro stuff; }".) -.RE -.PP -.B macro -.I macro-name -.RI { params }; -.PP -.RS -Defines a macro with the given parameter list. Whenever the macro is used -the parameter list is substituted instead. A macro can not be defined -within another parameter list. -.RE -.PP -.B option -.RB [ ip #] -.B server -.RB [ inform ]; -.br -.B option -.RB [ ip #] -.B relay -.IR host ; -.br -.B option -.RB [ ip #] -.BR possessive ; -.br -.B option -.RB [ ip #] -.B hostname -.IR name ; -.PP -.RS -Makes -.B dhcpd -set special options for the interface that it is gathering data for, or the -interface denoted by the optional -.BR ip # -argument. The options are: -.SP -.B server -.RB [ inform ] -.RS -Be a DHCP server on the network connected to the interface. Add the word -.B inform -if DHCPINFORM requests must be answered for hosts we don't have an address -for. -.RE -.SP -.B relay -.I host -.RS -Be a DHCP relay to the indicated host. -.RE -.SP -.B possessive -.RS -Do not disable the interface if the DHCP lease expires. Useful if the -DHCP server of the provider is unreliable, crashing a lot and causing the -lease to expire. (Think twice before turning this option on. You have to -be absolutely sure that it's the DHCP server that's the culprit and not -a flaky network. You don't want an IP address conflict to be your fault.) -.RE -.SP -.B hostname -.I name -.RS -Use the given name as our hostname in the DHCP queries. Some sites key on -that bit of information instead of a client ID. -.RE -.RE -.PP -.B tag -.I number name type granularity -.IR max ; -.PP -.RS -Defines a DHCP tag for the given tag number and gives it a name. The name can -be used in the configuration file to set tag values when gathering data. -The -.I type -field can be one of -.BR ascii , -.BR boolean , -.BR ip , -.BR number -or -.BR octet -to specify the type of the tag as a simple string, a boolean, an IP address, -a number, or a string of octet values. -The -.I granularity -field specifies that that number of items must be given or a multiple -thereof, unless the type is a number, then it is the size of the number (1, -2 or 4). -The -.I max -field tells the maximum number of items that may be used with the tag, with -0 meaning "unlimited". -.SP -Three tags, the ones that MINIX 3 really cares about, have been predefined, -and there are also a few pseudotags predefined for the static fields in a -DHCP packet that one may want to set: -.SP -.RS -.nf -tag ? siaddr ip 1 1; -tag ? sname ascii 1 64; -tag ? file ascii 1 128; -tag 1 netmask ip 1 1; -tag 3 gateway ip 1 0; -tag 6 DNSserver ip 1 0; -.fi -.RE -.SP -The file -.B /usr/etc/dhcptags.conf -contains tag definitions for all standard DHCP tags. It is wise to include -this file at the top of any DHCP configuration file. -.RE -.PP -.B no -.IR tag-name ; -.PP -.RS -Removes a tag with the given name from the data gathered at this point. -Useful if one host is different from all others, for instance if it doesn't -need a gateway definition, because it happens to be the gateway. -.RE -.PP -.IR "ascii-tag string" ; -.PP -.RS -Adds an ASCII tag to the gathered data. The string can be a simple word, or -a quoted string. -.RE -.PP -.I boolean-tag -.BR false | true ; -.PP -.RS -Set a boolean tag to be false or true. (Encoded as a octet of value 0 or 1. -Note that if you prefer to use 0 or 1 instead of false or true then you can -define a boolean tag as a size 1 number instead.) -.RE -.PP -.IR "ip-tag host" " ...;" -.PP -.RS -Sets a tag that needs one or more IP addresses. The host names are -translated as usual. To make it easier to specify netmasks one can use a -slash followed by a number, e.g. -.BR "netmask /27" , -which is a handy alternative for -.BR "netmask 255.255.255.224" . -.RE -.PP -.IR "number-tag number" " ...;" -.PP -.RS -Set a number tag. -.RE -.PP -.IR "octet-tag hexdigits" ; -.PP -.RS -Set an octet string tag. -.I Hexdigits -is a series of hexadecimal digits that are two by two used to set the -octets. -.RE -.PP -.SH EXAMPLE -As an example the DHCP configuration used by the author of this document is -included. His network at home consists of a number of PCs, an ISDN router -named rhone and a PC named saone serving as router/tunnel to/via a cable -ISP. Both the rhone and the saone connect the home net to the network of -the Vrije Universiteit, but the rhone is only active if the cable doesn't -work. -.PP -The saone is a DHCP server, and one of the ordinary PCs is a backup DHCP -server. Both use the same configuration file, which is added below, with -extra commentary introduced by -.B ## -at a deeper indent level: -.RS -.de xS \" Example start -.sp -.nf -.ft C -.. -.de xE \" Example end -.fi -.ft R -.. -.de cS \" Commentary start -.sp -.in +12m -.ti -\w'## 'u -##\ \c -.. -.de cE \" Commentary end -.in -12m -.. -.xS -.ta +8m +16m -include /usr/etc/dhcptags.conf; -.xE -.cS -With the help of the tag definitions we can use tags like "DHCPlease". -.cE -.xS -host 130.37.102.64/27 { - DNSserver saone darask; - host 130.37.102.88/29 { DHCPlease 259200; } -}; -.xE -.cS -This defines the network 130.37.102.64/27, with netmask 255.255.255.224 -(implicit from the network definition). The DNS servers for this net are -saone and darask. A smaller subrange of addresses is used as an address -pool on the saone, so a lease of 259200 seconds (3 days) is defined. The -netmask is still /27, as set by the outer network definition. -.cE -.xS -host 130.37.102.248/30 {}; -.xE -.cS -A network of two addresses for routing tests. -.cE -.xS -host saone { - option server; - option ip1 possessive; - interface ip2 saone-net2; - DNSserver 130.37.24.3 130.37.24.6; -}; -.xE -.cS -With the network definitions done we turn our attention to the hosts. Saone -is a DHCP server on its main interface. The second interface -.RB ( ip1 ) -is connected to the cable modem. It gets its address from the cableco's -DHCP server, and if that server decides to go deaf then the saone keeps -the interface up ("possessive") even if the lease expires. The pseudo IP -interface -.B ip2 -is set to the IP address of -.BR saone-net2 , -one side of the encrypted tunnel over the cable to a Minix-vmd box at the VU. -The DNS servers specified override the default setting for the network, naming -two external servers at the VU that know the world. -.cE -.xS -host darask { - option server; - DNSserver saone; - class MINIX 3 { DNSserver saone 130.37.24.3 130.37.24.6; }; -}; -.xE -.cS -The darask is also a server, the backup for saone on the odd chance that it -is unavailable. It uses saone and the external name servers, but only -when it is running MINIX 3. When running Windows it only uses saone. -.cE -.xS -.ta +32m +16m -client 0:1:1b:a:68:ce darask; # NE2000 -client 0:1:1b:a:77:23 burask; # NE2000 -#lient 0:0:c0:b0:da:64 burask; # WD8013EWC -client 8:0:5a:38:b2:f finiah; # PCMCIA NE2000 -client 0:0:c0:3a:12:10 bardelask; # WD8003 -#lient 2:60:8c:ab:8a:6d bardelask; # 3C503 -client 0:a0:c5:20:9:6d rhone; -client 0:1:1b:a:4c:3b saone; # NE2000 -#lient 0:0:c0:fb:2:6a saone-net1; # WD8013EWC -.xE -.cS -Lastly the ethernet addresses of all the hosts are listed, so that they can -be translated to IP addresses. The lines that are commented out are for -extra network cards that are currently unused. The last is used to connect -to the cable modem, so it's only here because it's nice to have the ethernet -address written down somewhere. -.cE -.RE -.PP -The host names shown above are translated by DHCP using this -.BR /etc/hosts : -.RS -.xS -.ta +\w'130.37.102.249mm'u -604800 %ttl -2419200 %stale - -130.37.102.65 darask.kjb.upwind.org -130.37.102.66 burask.kjb.upwind.org -130.37.102.67 finiah.kjb.upwind.org -130.37.102.68 bardelask.kjb.upwind.org -130.37.102.69 roniah.kjb.upwind.org - -130.37.102.70 saone.kjb.upwind.org -130.37.102.2 saone-net2.kjb.upwind.org - -130.37.102.88 rhone.kjb.upwind.org -130.37.102.89 dyn89.kjb.upwind.org -130.37.102.90 dyn90.kjb.upwind.org -130.37.102.91 dyn91.kjb.upwind.org -130.37.102.92 dyn92.kjb.upwind.org -130.37.102.93 dyn93.kjb.upwind.org -130.37.102.94 dyn94.kjb.upwind.org - -130.37.102.249 tst1.kjb.upwind.org -130.37.102.250 tst2.kjb.upwind.org -.xE -.RE -.SH FILES -.TP -.B /usr/etc/dhcptags.conf -A supplied list of standard tag definitions as per RFC-1533. (Well, the -tag numbers and their meaning are standard, the names are made up.) -.SH "SEE ALSO" -.BR RFC-2131 , -.BR RFC-1533 , -.BR configfile (5), -.BR hosts (5), -.BR boot (8), -.BR dhcpd (8). -.SH NOTES -The amount of memory -.B dhcpd -needs increases with the size of configuration file. MINIX 3 can -handle -.B dhcptags.conf -and a modest sized -.BR dhcp.conf . -You have to increase the stack size to accommodate more. (No problem under -Minix-vmd, of course.) -.SH NOTES -Items that are only necessary for a certain host should only be specified -for that host. Items for a whole network are best added to a netblock -specification. Use class elements for a certain type of host, and macros -for exceptions. Try to limit information as much as possibly to those hosts -that need it. (Don't go overboard. A MINIX 3 machine won't be bothered by a -few NetBIOS tags.) -.PP -DHCPINFORM requests should always be answered when being a server, but -J. Random Sysadmin trying to diagnose problems doesn't like it when little -MINIX 3 machines show up in a packet trace unexpectedly. It's best to be -inconspicuous on a network you don't own. -.SH BUGS -There are a few too many subtle mistakes one can make. -.SH AUTHOR -Kees J. Bot diff --git a/minix/commands/dhcpd/dhcpd.8 b/minix/commands/dhcpd/dhcpd.8 deleted file mode 100644 index 0598d9dd0..000000000 --- a/minix/commands/dhcpd/dhcpd.8 +++ /dev/null @@ -1,208 +0,0 @@ -.TH DHCPD 8 -.SH NAME -dhcpd \- dynamic host configuration protocol daemon -.SH SYNOPSIS -.in +.5i -.ti -.5i -.B dhdpd -.RB [ \-qar ] -.RB [ \-t [\fIlevel\fP]] -.RB [ \-d [\fIlevel\fP]] -.RB [ \-f -.IR configfile ] -.RB [ \-c -.IR cachefile ] -.RB [ \-p -.IR poolfile ] -.RI [ host " ...]" -.in -.5i -.SH DESCRIPTION -.de SP -.if t .sp 0.4 -.if n .sp -.. -.B Dhcpd -is a client and a server for the Dynamic Host Configuration Protocol. As a -client it collects DHCP data to configure the Ethernet networks with, and as -a server it answers DHCP queries from other machines. -.PP -This manual page describes the operation of -.BR dhcpd , -the associated configuration file is described in -.BR dhcp.conf (5). -(The latter, together with -.BR boot (8), -is of more practical value when it comes to getting a machine's networks -interfaces up and running. See the options section below for debugging DCHP -problems.) -.SS Initialization -On a normal startup, i.e. none of the -.BR \-q , -.BR \-a -or -.BR \-r -options are given, -.B dhcpd -determines what IP devices are present, and which of those are Ethernets. -For each network it looks for information in the configuration file as if -it were a server answering a query for that network. If any information is -found then the IP address is configured and the information stored in the -cache file. -.SS "Client Operation" -For each still unconfigured network a DHCP DISCOVER request is broadcast on -that network. If a DHCP OFFER reply is received then a DHCP REQUEST is -broadcast for the IP address offered, and if a DHCP ACK is received then the -network is configured and the information stored in the cache file. -.PP -If no reply is received then another query is sent after 4 seconds, and then -again after 8 seconds, doubling each time until 64 seconds. Every 64 -seconds thereafter a request is broadcast until a reply is received. -.PP -Once configured the DHCP lease, rebind and renew times are computed. At the -renew time a DHCP REQUEST is sent to the DHCP server to extend the lease. -Normally we get an answer and refresh our information, but if no reply is -received we wait for half the remaining time until the rebind time and keep -retrying and halving the remaining time. When the rebind time is reached -the DHCP REQUEST is broadcast to try and reach some other DHCP server. -Halving the remaining time again and again until the lease expires. At that -point we go back to square one and broadcast a DHCP DISCOVER. -.PP -If at any point a DHCP NAK is received we start over completely. After a -DHCP OFFER an ARP request is transmitted just before the DHCP REQUEST to -check if the address offered is already in use. If an ARP reply is received -before the DHCP ACK then after the ACK we send a DHCP DECLINE to the server -to tell that the address isn't what we want and again we start over. -.SS "Router Discovery" -The gateway offered by the DHCP server is made known to the TCP/IP server by -sending an ICMP router advertisement to the local interface with a short -lifetime and a low priority. Then up to three router solicitations are -broadcast three seconds apart to look for a router. If a router answers -with a router advertisement then we no longer worry about routing for that -interface. Otherwise the router information is refreshed before it expires -and another solicitation is sent out. This happens about twice an hour. -.SS "Server Operation" -Once all networks so marked are configured the daemon starts answering -requests by other machines or relaying requests to other DHCP servers. -DHCP requests are answered if information for a client -can be found in the configuration file, or if a free address can be found in -the pool file, or if a client rerequests an address it already owns. -.PP -If the daemon is both a server and a relay for a network then it will try -to answer a request and only relay if it has no answer. -.SS "Nothing more to do?" -If the daemon finds out that all networks have an infinite lease (configured -with a fixed address), there is no router information to keep warm, and -it isn't a server then it simply exits. -.SS "Asynchronous I/O?" -MINIX 3 doesn't have the asynchronous I/O that Minix-vmd has, so under MINIX 3 -the daemon only works with one network at a time. If it's stuck on the same -network for 32 seconds then that network is closed and another network is -tried for 32 seconds. This usually works ok as a client, but as a server it -can only handle one network. -.SH OPTIONS -.TP -.B \-q -Read and print the cache and pool file contents, showing DHCP information -for each network, and the IP addresses in the pool with lease times and -current/last owners of those addresses. -.TP -.B \-a -Add the named hosts (or IP addresses) to the pool file. -.TP -.B \-r -Remove hosts from the pool file. -.TP -.RB [ \-t [\fIlevel\fP]] -Set the test level (by default 1). At test level 1 all networks are seen as -unconfigured, will not be configured and no data will be put in the cache. -The program will just act as-if. At test level 2 the interfaces will not be -configured from the configuration file, the data must come from a remote -server. At level 3 the renewal, rebind and lease time will be 60, 120 -and 180 seconds. At level 4 these times will be 60, 60, and 120. At -level 5 these times will be 60, 60, and 60. These test levels are meant -to debug the DHCP client code, and are best used with a high debug level. -.TP -.RB [ \-d [\fIlevel\fP]] -Set the debug level (by default 1). At debug level 1 the program shows -Ethernet and IP addresses as they are determined or configured, DHCP -messages sent and received with little detail (one line per message), and -memory use. At debug level 2 each DHCP packet is decoded and shown in -detail. At debug level 3 device opens and closes are shown. The debugging -level may also be increased by 1 at runtime by sending signal -.BR SIGUSR1 -or turned off (set to 0) with -.BR SIGUSR2 . -.TP -.BI \-f " configfile" -Names the configuration file, by default -.BR /etc/dhcp.conf . -.TP -.BI \-c " cachefile" -Names the cache file, by default -.BR /usr/adm/dhcp.cache . -.TP -.BI \-p " poolfile" -Names the IP address pool, by default -.BR /usr/adm/dhcp.pool . -.SH "SEE ALSO" -.BR RFC-2131 , -.BR RFC-1533 , -.BR dhcp.conf (5), -.BR hosts (5), -.BR ifconfig (8), -.BR inet (8), -.BR boot (8), -.BR inetd (8), -.BR nonamed (8). -.SH DIAGNOSTICS -.TP -"'/etc/dhcp.conf', line ..." -The program exits on any configuration file error. You have to correct the -error and restart the program. -.TP -"No lease set for address ..." -There must be a lease time defined for addresses in the pool. Correct and -restart the program. -.TP -"###### declines #.#.#.# saying '...'" -A client with the given client identifier (usually 01 followed by the client's -Ethernet address) declines an IP address, hopefully with a message telling -why. This usually means that the IP address is already in use by another -host. This program, acting as a client, will tell what other host in its -message, but Windows has no additional info alas. -.TP -"Got a NAK from #.#.#.# [through #.#.#.#] saying '...'" -The server with the given IP address doesn't want us to have or keep the IP -address we were offered or are rerequesting. This could mean that the server -has forgotten about us and has given our address to another machine. This -is bad if our lease hasn't yet expired. There may be a relay involved, and -there may even be a text message with precise information. -.TP -"#.#.#.# offered by #.#.#.# is already in use by #:#:#:#:#:#" -We got an ARP reply for an offered address. We won't accept it, and send -out a DECLINE when we get an ACK. -.TP -"DHCP packet too big, ..." -You've got way to much information in the configuration file, more than fits -in a minimum size DHCP packet. (Notify the author if you really need to send -more information. He doesn't think anyone needs to.) -.TP -"Pool table is corrupt" -You will have to remove and refill the pool file. Chaos may ensue if -there are active clients and they don't use ARP to detect each other. -(Most do.) -.SH BUGS -There is no randomization of timers. Modern systems don't blink under the -load of several clients broadcasting a few packets in sync. -.PP -There is no extra time spent waiting for an ARP reply. It is assumed that -any IP stack will immediately respond, so that the DHCP server can't -possibly beat it at sending out an ACK. (The DHCP server has to commit the -lease to stable storage first anyway.) -.PP -Way more nonsense can be sent in a DHCP packet that MINIX 3 could do -something with, but nobody does so we don't bother. -.PP -DHCP was invented by a rabid gerbil on speed. -.SH AUTHOR -Kees J. Bot diff --git a/minix/commands/dhcpd/dhcpd.c b/minix/commands/dhcpd/dhcpd.c deleted file mode 100644 index d4c1bfda0..000000000 --- a/minix/commands/dhcpd/dhcpd.c +++ /dev/null @@ -1,1434 +0,0 @@ -/* dhcpd 1.15 - Dynamic Host Configuration Protocol daemon. - * Author: Kees J. Bot - * 11 Jun 1999 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "arp.h" -#define EXTERN -#include "dhcpd.h" - -char *configfile= PATH_DHCPCONF; -char *poolfile= PATH_DHCPPOOL; -static char *cachefile= PATH_DHCPCACHE; -static int qflag; /* True if printing cached DHCP data. */ -static int aflag, rflag; /* True if adding or deleting pool addresses. */ - -#define BCAST_IP htonl(0xFFFFFFFFUL) - -/* We try to play with up to this many networks. */ -#define N_NETS 32 -static unsigned n_nets; /* Actual number of networks. */ - -int lwip; - -void report(const char *label) -{ - static FILE *logfp; - if(!logfp) - logfp = fopen("/usr/log/dhcp.log", "w"); - if(logfp) - fprintf(logfp, "%s: %s: %s\n", program, label, strerror(errno)); -} - -void fatal(const char *label) -{ - report(label); - exit(1); -} - -void *allocate(size_t size) -{ - void *mem; - - if ((mem= malloc(size)) == nil) fatal("Can't allocate memory"); - return mem; -} - -/* Choose a DHCP xid based on the start time and network number. Not really - * random, but we don't have anything more random than the clock anyway. - */ -#define XID(np) htonl(((u32_t) (np)->start << 8) | (np)->n) - -static network_t *network[N_NETS]; - -int ifname2if(const char *name) -{ - /* Translate an interface name to a number, -1 if bad. */ - char *end; - unsigned long n; - - if (*name++ != 'i' || *name++ != 'p') return -1; - n= strtoul(name, &end, 10); - if (end == name || *end != 0) return -1; - if (n >= N_NETS) return -1; - return n; -} - -network_t *if2net(int n) -{ - /* Translate an interface number to a network struct. */ - int i; - - for (i= 0; i < n_nets; i++) { - if (network[i]->n == n) return network[i]; - } - return nil; -} - -static ipaddr_t defaultmask(ipaddr_t ip) -{ - /* Compute netmask by the oldfashioned Class rules. */ - if (B(&ip)[0] < 0x80) return htonl(0xFF000000UL); /* Class A. */ - if (B(&ip)[0] < 0xC0) return htonl(0xFFFF0000UL); /* Class B. */ - if (B(&ip)[0] < 0xE0) return htonl(0xFFFFFF00UL); /* Class C. */ - return htonl(0xFFFFFFFFUL); /* Multicast? Shouldn't happen... */ -} - -#define POOL_MAGIC htonl(0x81F85D00UL) - -typedef struct pool { /* Dynamic pool entry. */ - u32_t magic; /* Pool file magic number. */ - ipaddr_t ip; /* IP address. */ - u32_t expire; /* When does/did the lease expire? */ - u8_t len; /* Client ID length. */ - u8_t unused[19]; /* Space for extensions. */ - u8_t clid[CLID_MAX]; /* Client ID of current/last user. */ -} pool_t; - -static int openpool(int mode) -{ - /* Open the dynamic pool and lock it, return fd on success or -1. */ - int fd; - struct flock lck; - - if ((fd= open(poolfile, mode, 0644)) < 0) { - if (errno != ENOENT) fatal(poolfile); - return -1; - } - if (mode != O_RDONLY) { - lck.l_type= F_WRLCK; - lck.l_whence= SEEK_SET; - lck.l_start= 0; - lck.l_len= 0; - if (fcntl(fd, F_SETLKW, &lck) < 0) fatal(poolfile); - } - return fd; -} - -static int readpool(int fd, pool_t *entry) -{ - /* Read one pool table entry, return true unless EOF. */ - ssize_t r; - - if ((r= read(fd, entry, sizeof(*entry))) < 0) fatal(poolfile); - if (r == 0) return 0; - - if (r != sizeof(*entry) || entry->magic != POOL_MAGIC) { - fprintf(stderr, "%s: %s: Pool table is corrupt\n", - program, poolfile); - close(fd); - return 0; - } - return 1; -} - -static void writepool(int fd, pool_t *entry) -{ - /* (Over)write a pool table entry. */ - if (write(fd, entry, sizeof(*entry)) < 0 - || (entry->expire > now && fsync(fd) < 0) - ) { - fatal(poolfile); - } -} - -static ipaddr_t findpool(u8_t *client, size_t len, ipaddr_t ifip) -{ - /* Look for a client ID in the dynamic address pool within the same network - * as 'ifip'. Select an unused one for a new client if necessary. Return - * 0 if nothing is available, otherwise the IP address we can offer. - */ - int fd, found; - pool_t entry, oldest; - dhcp_t dhcp; - u8_t *pmask; - ipaddr_t mask; - - /* Any information available on the network the client is at? */ - if (!makedhcp(&dhcp, nil, 0, nil, 0, ifip, ifip, nil)) return 0; - - if ((fd= openpool(O_RDWR)) < 0) return 0; - - (void) gettag(&dhcp, DHCP_TAG_NETMASK, &pmask, nil); - memcpy(&mask, pmask, sizeof(mask)); - - oldest.expire= NEVER; - while ((found= readpool(fd, &entry))) { - /* Deleted entry? */ - if (entry.ip == 0) continue; - - /* Correct network? */ - if (((entry.ip ^ ifip) & mask) != 0) continue; - - /* Client present? */ - if (entry.len == len && memcmp(entry.clid, client, len) == 0) break; - - /* Oldest candidate for a new lease? */ - entry.expire= ntohl(entry.expire); - if (entry.expire < oldest.expire) oldest= entry; - } - close(fd); - - if (found) return entry.ip; - if (oldest.expire <= now) return oldest.ip; - return 0; -} - -static int commitpool(ipaddr_t ip, u8_t *client, size_t len, time_t expire) -{ - /* Commit a new binding to stable storage, return true on success. */ - int fd; - pool_t entry; - - if ((fd= openpool(O_RDWR)) < 0) return 0; - - do { - if (!readpool(fd, &entry)) { - close(fd); - return 0; - } - } while (entry.ip != ip); - - entry.expire= htonl(expire); - entry.len= len; - memcpy(entry.clid, client, len); - if (lseek(fd, -(off_t)sizeof(entry), SEEK_CUR) == -1) fatal(poolfile); - writepool(fd, &entry); - close(fd); - return 1; -} - -static void updatepool(int add, const char *name) -{ - /* Add a new IP address to the dynamic pool. */ - ipaddr_t ip; - int fd, i; - pool_t entry; - struct hostent *he; - off_t off, off0; - - if ((he= gethostbyname(name)) == nil || he->h_addrtype != AF_INET) { - fprintf(stderr, "%s: %s: Unknown host\n", program, name); - exit(1); - } - for (i= 0; he->h_addr_list[i] != nil; i++) {} - if (i != 1) { - fprintf(stderr, "%s: %s has %d addresses\n", program, name, i); - exit(1); - } - memcpy(&ip, he->h_addr_list[0], sizeof(ip)); - - if ((fd= openpool(O_RDWR|O_CREAT)) < 0) fatal(poolfile); - - off= 0; - off0= -1; - while (readpool(fd, &entry)) { - if (add) { - if (entry.ip == ip) { - fprintf(stderr, "%s: %s: %s is already present\n", - program, poolfile, name); - exit(1); - } - if (entry.ip == 0 && off0 == -1) off0= off; - } else { - if (entry.ip == ip) { - memset(&entry, 0, sizeof(entry)); - entry.magic= POOL_MAGIC; - entry.ip= 0; - if (lseek(fd, off, SEEK_SET) == -1) fatal(poolfile); - writepool(fd, &entry); - } - } - off+= sizeof(entry); - } - - if (add) { - if (off0 != -1 && lseek(fd, off0, SEEK_SET) == -1) fatal(poolfile); - memset(&entry, 0, sizeof(entry)); - entry.magic= POOL_MAGIC; - entry.ip= ip; - writepool(fd, &entry); - } - close(fd); -} - -static void cachedhcp(int n, dhcp_t *dp) -{ - /* Store a DHCP packet in a cache where those who care can find it. */ - static int inited; - FILE *fp; - int fd; - int mode; - - if (test > 0) return; - - if (!inited) { - /* First time, clear store and also save my pid. */ - if ((fp= fopen(PATH_DHCPPID, "w")) != nil) { - if (fprintf(fp, "%d\n", getpid()) == EOF || fclose(fp) == EOF) { - fatal(PATH_DHCPPID); - } - } - inited= 1; - mode= O_WRONLY | O_CREAT | O_TRUNC; - } else { - mode= O_WRONLY; - } - - dp->xid= htonl(now); /* To tell how old this data is. */ - - if ((fd= open(cachefile, mode, 0666)) < 0 - || lseek(fd, (off_t) n * sizeof(*dp), SEEK_SET) == -1 - || write(fd, dp, sizeof(*dp)) < 0 - || close(fd) < 0 - ) { - if (errno != ENOENT) fatal(cachefile); - } -} - -static void printdata(void) -{ - /* Show the contents of the cache and the dynamic pool. */ - int fd; - dhcp_t d; - ssize_t r; - int i; - pool_t entry; - unsigned long expire; - char delta[3*sizeof(u32_t)]; - - initdhcpconf(); - - if ((fd= open(cachefile, O_RDONLY)) < 0) fatal(cachefile); - i= 0; - while ((r= read(fd, &d, sizeof(d))) == sizeof(d)) { - if (d.yiaddr != 0) { - printf("DHCP data for network %d:\n", i); - printdhcp(&d); - } - i++; - } - if (r < 0) fatal(cachefile); - close(fd); - - if ((fd= openpool(O_RDONLY)) >= 0) { - printf("Dynamic address pool since %ld:\n", (long) now); - while (readpool(fd, &entry)) { - if (entry.ip == 0) continue; - expire= ntohl(entry.expire); - if (expire == 0) { - strcpy(delta, "unused"); - } else - if (expire == 0xFFFFFFFFUL) { - strcpy(delta, "infinite"); - } else - if (expire < now) { - sprintf(delta, "-%llu", now - expire); - } else { - sprintf(delta, "+%llu", expire - now); - } - printf("\t%-15s %8s ", inet_ntoa(*(struct in_addr *)&entry.ip), - delta); - for (i= 0; i < entry.len; i++) { - printf("%02X", entry.clid[i]); - } - fputc('\n', stdout); - } - close(fd); - } -} - -static udpport_t portbyname(const char *name) -{ - struct servent *se; - - if ((se= getservbyname(name, "udp")) == nil) { - fprintf(stderr, "%s: Unknown port \"%s\"\n", program, name); - exit(1); - } - return se->s_port; -} - -static int sendpacket(network_t *np, void *data, size_t len) -{ - /* Send out a packet using a filedescriptor that is probably in async mode, - * so first dup() a sync version, then write. Return true on success. - */ - int fd; - ssize_t r; - - if ((fd= dup(np->fdp->fd)) < 0) fatal("Can't dup()"); - if ((r= write(fd, data, len)) < 0) { - report(np->fdp->device); - sleep(10); - } - close(fd); - return r >= 0; -} - -static size_t servdhcp(network_t *np, buf_t *bp, size_t dlen) -{ - buf_t *abp= nil; - ipaddr_t cip, ifip; - u8_t defclid[1+sizeof(bp->dhcp->chaddr)]; - u8_t *pdata, *client, *class, *server, *reqip, *lease; - u32_t expire; - size_t len, cilen, calen; - int type, dyn; - u8_t atype; - static char NAKMESS[] = "IP address requested isn't yours"; - - if (test > 0) return 0; - - /* The IP address of the interface close to the client. */ - ifip= bp->dhcp->giaddr != 0 ? bp->dhcp->giaddr : np->ip; - - /* All kinds of DHCP tags. */ - if (gettag(bp->dhcp, DHCP_TAG_TYPE, &pdata, nil)) { - type= *pdata; - } else { - type= -1; /* BOOTP? */ - } - - if (!gettag(bp->dhcp, DHCP_TAG_CLIENTID, &client, &cilen)) { - defclid[0]= bp->dhcp->htype; - memcpy(defclid+1, bp->dhcp->chaddr, bp->dhcp->hlen); - client= defclid; - cilen= 1+bp->dhcp->hlen; - } - - if (!gettag(bp->dhcp, DHCP_TAG_CLASSID, &class, &calen)) { - calen= 0; - } - - if (!gettag(bp->dhcp, DHCP_TAG_SERVERID, &server, nil)) { - server= B(&np->ip); - } - - if (!gettag(bp->dhcp, DHCP_TAG_REQIP, &reqip, nil)) { - reqip= nil; - } - - /* I'm a server? Then see if I know this client. */ - if ((np->flags & NF_SERVING) - && bp->dhcp->op == DHCP_BOOTREQUEST - && between(1, bp->dhcp->hlen, sizeof(bp->dhcp->chaddr)) - && (server == nil || memcmp(server, &np->ip, sizeof(np->ip)) == 0) - ) { - get_buf(&abp); - - /* Is the client in my tables? */ - (void) makedhcp(abp->dhcp, class, calen, client, cilen, 0, ifip, nil); - cip= abp->dhcp->yiaddr; - - dyn= 0; - /* If not, do we have a dynamic address? */ - if (cip == 0 && (cip= findpool(client, cilen, ifip)) != 0) dyn= 1; - - if (type == DHCP_INFORM) { - /* The client already has an address, it just wants information. - * We only answer if we could answer a normal request (cip != 0), - * unless configured to answer anyone. - */ - if (cip != 0 || (np->flags & NF_INFORM)) cip= bp->dhcp->ciaddr; - } - - if (cip == 0 || !makedhcp(abp->dhcp, class, calen, - client, cilen, cip, ifip, nil)) { - put_buf(&abp); - } - - if (abp != nil) { - if (gettag(abp->dhcp, DHCP_TAG_LEASE, &lease, nil)) { - memcpy(&expire, lease, sizeof(expire)); - expire= now + ntohl(expire); - if (expire < now) expire= 0xFFFFFFFFUL; - } else { - if (dyn) { - /* A dynamic address must have a lease. */ - fprintf(stderr, "%s: No lease set for address %s\n", - program, inet_ntoa(*(struct in_addr *)&cip)); - exit(1); - } - lease= nil; - expire= 0xFFFFFFFFUL; - } - - /* What does our client want, and what do we say? */ - switch (type) { - case DHCP_DISCOVER: - atype= DHCP_OFFER; - - /* Assign this address for a short moment. */ - if (dyn && !commitpool(cip, client, cilen, now + DELTA_FAST)) { - put_buf(&abp); - } - break; - - case -1:/* BOOTP */ - case DHCP_REQUEST: - case DHCP_INFORM: - atype= DHCP_ACK; - /* The address wanted must be the address we offer. */ - if ((reqip != nil && memcmp(reqip, &cip, sizeof(cip)) != 0) - || (bp->dhcp->ciaddr != 0 && bp->dhcp->ciaddr != cip) - ) { - atype= DHCP_NAK; - } else - if (dyn && type == DHCP_REQUEST) { - /* Assign this address for the duration of the lease. */ - if (!commitpool(cip, client, cilen, expire)) put_buf(&abp); - } - break; - - case DHCP_DECLINE: - /* Our client doesn't want the offered address! */ - if (dyn - && reqip != nil - && memcmp(reqip, &cip, sizeof(cip)) == 0 - ) { - int i; - - fprintf(stderr, "%s: ", program); - for (i= 0; i < cilen; i++) { - fprintf(stderr, "%02X", client[i]); - } - fprintf(stderr, " declines %s", - inet_ntoa(*(struct in_addr *)&cip)); - if (gettag(bp->dhcp, DHCP_TAG_MESSAGE, &pdata, &len)) { - fprintf(stderr, " saying: \"%.*s\"", (int)len, pdata); - } - fputc('\n', stderr); - - /* Disable address for the duration of the lease. */ - (void) commitpool(cip, nil, 0, expire); - } - put_buf(&abp); - break; - - case DHCP_RELEASE: - /* Our client is nice enough to return its address. */ - if (dyn) (void) commitpool(cip, client, cilen, now); - put_buf(&abp); - break; - - default: /* Anything else is ignored. */ - put_buf(&abp); - } - } - - if (abp != nil) { - /* Finish the return packet. */ - abp->dhcp->htype= bp->dhcp->htype; - abp->dhcp->hlen= bp->dhcp->hlen; - abp->dhcp->hops= 0; - abp->dhcp->xid= bp->dhcp->xid; - abp->dhcp->secs= 0; - abp->dhcp->flags= bp->dhcp->flags; - abp->dhcp->ciaddr= 0; - abp->dhcp->yiaddr= atype == DHCP_NAK ? 0 : cip; - if (atype == DHCP_NAK) abp->dhcp->siaddr= 0; - abp->dhcp->giaddr= bp->dhcp->giaddr; - memcpy(abp->dhcp->chaddr,bp->dhcp->chaddr,sizeof(bp->dhcp->chaddr)); - - settag(abp->dhcp, DHCP_TAG_SERVERID, &np->ip, sizeof(np->ip)); - - if (lease == nil) { - /* No lease specified? Then give an infinite lease. */ - settag(abp->dhcp, DHCP_TAG_LEASE, &expire, sizeof(expire)); - } - - if (type == DHCP_INFORM) { - /* Oops, this one has a fixed address, so no lease business. */ - abp->dhcp->yiaddr= 0; - settag(abp->dhcp, DHCP_TAG_LEASE, nil, 0); - settag(abp->dhcp, DHCP_TAG_RENEWAL, nil, 0); - settag(abp->dhcp, DHCP_TAG_REBINDING, nil, 0); - } - - if (atype == DHCP_NAK) { - /* A NAK doesn't need much. */ - memset(abp->dhcp->sname, 0, sizeof(abp->dhcp->sname)); - memset(abp->dhcp->file, 0, sizeof(abp->dhcp->file)); - memset(abp->dhcp->options, 255, sizeof(abp->dhcp->options)); - settag(abp->dhcp, DHCP_TAG_MESSAGE, NAKMESS, sizeof(NAKMESS)); - } - - settag(abp->dhcp, DHCP_TAG_TYPE, &atype, sizeof(atype)); - - /* Figure out where to send this to. */ - abp->udpio->uih_src_addr= np->ip; - abp->udpio->uih_src_port= port_server; - if (bp->dhcp->giaddr != 0) { - abp->udpio->uih_dst_addr= bp->dhcp->giaddr; - abp->udpio->uih_dst_port= port_server; - } else - if (bp->dhcp->flags & DHCP_FLAGS_BCAST) { - abp->udpio->uih_dst_addr= BCAST_IP; - abp->udpio->uih_dst_port= port_client; - } else - if (bp->udpio->uih_src_addr != 0 - && bp->udpio->uih_dst_addr == np->ip - ) { - abp->udpio->uih_dst_addr= bp->udpio->uih_src_addr; - abp->udpio->uih_dst_port= port_client; - } else { - abp->udpio->uih_dst_addr= BCAST_IP; - abp->udpio->uih_dst_port= port_client; - } - abp->udpio->uih_ip_opt_len= 0; - abp->udpio->uih_data_len= sizeof(dhcp_t); - - /* Copy the packet to the input buffer, and return the new size. */ - memcpy(bp->buf, abp->buf, sizeof(bp->buf)); - put_buf(&abp); - return sizeof(udp_io_hdr_t) + sizeof(dhcp_t); - } - } - - /* I'm a relay? If it is a not already a relayed request then relay. */ - if ((np->flags & NF_RELAYING) - && bp->dhcp->op == DHCP_BOOTREQUEST - && bp->dhcp->giaddr == 0 - ) { - bp->dhcp->giaddr= np->ip; - bp->udpio->uih_src_addr= np->ip; - bp->udpio->uih_src_port= port_server; - bp->udpio->uih_dst_addr= np->server; - bp->udpio->uih_dst_port= port_server; - return dlen; - } - - /* I'm a relay? If the server sends a reply to me then relay back. */ - if ((np->flags & NF_RELAYING) - && bp->dhcp->op == DHCP_BOOTREPLY - && bp->dhcp->giaddr == np->ip - ) { - bp->dhcp->giaddr= 0; - bp->udpio->uih_src_addr= np->ip; - bp->udpio->uih_src_port= port_server; - bp->udpio->uih_dst_addr= BCAST_IP; - bp->udpio->uih_dst_port= port_client; - return dlen; - } - - /* Don't know what to do otherwise, so doing nothing seems wise. */ - return 0; -} - -static void onsig(int sig) -{ - switch (sig) { - case SIGUSR1: debug++; break; - case SIGUSR2: debug= 0; break; - } -} - -static void usage(void) -{ - fprintf(stderr, -"Usage: %s [-qar] [-t[L]] [-d[L]] [-f config] [-c cache] [-p pool] [host ...]\n", - program); - exit(1); -} - -int main(int argc, char **argv) -{ - int i; - network_t *np; - struct sigaction sa; - ssize_t r; - buf_t *bp; - static struct timeval eventtv; - -main: - n_nets = 0; - r = -1; - bp = nil; - program= argv[0]; - start= now= time(nil); - - debug= 0; - i= 1; - while (i < argc && argv[i][0] == '-') { - char *opt= argv[i++]+1; - - if (opt[0] == '-' && opt[1] == 0) break; /* -- */ - - if (strcmp(opt, "-lwip") == 0) { - lwip = 1; - continue; - } - - while (*opt != 0) switch (*opt++) { - case 'f': - if (*opt == 0) { - if (i == argc) usage(); - opt= argv[i++]; - } - configfile= opt; - opt= ""; - break; - case 'c': - if (*opt == 0) { - if (i == argc) usage(); - opt= argv[i++]; - } - cachefile= opt; - opt= ""; - break; - case 'p': - if (*opt == 0) { - if (i == argc) usage(); - opt= argv[i++]; - } - poolfile= opt; - opt= ""; - break; - case 't': - test= 1; - if (between('0', *opt, '9')) test= strtoul(opt, &opt, 10); - break; - case 'd': - debug= 1; - if (between('0', *opt, '9')) debug= strtoul(opt, &opt, 10); - break; - case 'q': - qflag= 1; - break; - case 'a': - aflag= 1; - break; - case 'r': - rflag= 1; - break; - default: - usage(); - } - } - if (aflag + rflag + qflag > 1) usage(); - - if (aflag || rflag) { - /* Add or remove addresses from the dynamic pool. */ - while (i < argc) updatepool(aflag, argv[i++]); - exit(0); - } - - if (i != argc) usage(); - - if (qflag) { - /* Only show the contents of the cache and dynamic pool to the user. */ - printdata(); - exit(0); - } - - /* BOOTP ports. */ - port_server= portbyname("bootps"); - port_client= portbyname("bootpc"); - - sa.sa_handler= onsig; - sigemptyset(&sa.sa_mask); - sa.sa_flags= 0; - sigaction(SIGUSR1, &sa, nil); - sigaction(SIGUSR2, &sa, nil); - - /* Initial configuration. */ - for (i= 0; i < N_NETS; i++) { - int fd; - ipaddr_t ip, mask; - - /* Is there something there? */ - if ((fd= open(ipdev(i), O_RDWR|O_NONBLOCK)) < 0) { - if (errno != ENOENT && errno != ENODEV && errno != ENXIO) { - fatal(ipdev(i)); - } - continue; - } - close(fd); - - network[n_nets++]= np= newnetwork(); - np->n= i; - - /* Ethernet? */ - if (lwip) { - np->type = NT_ETHERNET; - } else if (opendev(np, FT_ETHERNET, 1)) { - np->type= B(&np->eth)[0] != 'Z' ? NT_ETHERNET : NT_SINK; - if (debug >= 1) { - printf("%s: Ethernet address is %s%s\n", - np->fdp->device, ether_ntoa(&np->eth), - np->type == NT_SINK ? " (sink)" : ""); - } - closedev(np, FT_ETHERNET); - } - - /* Only true Ethernets worry about DHCP. */ - if (np->type != NT_ETHERNET) np->renew= np->rebind= np->lease= NEVER; - } - - /* Try to find my interfaces in the DHCP table. */ - for (i= 0; i < n_nets; i++) { - ipaddr_t cip; - u8_t clid[1+DHCP_HLEN_ETH]; - size_t cilen; - - np= network[i]; - if (np->flags & NF_BOUND) continue; - - if (np->type == NT_IP) { - cilen= 0; - } else { - ether2clid(clid, &np->eth); - cilen= 1+DHCP_HLEN_ETH; - } - - /* Try to find an Ethernet address, or the IP address of an already - * configured network. If we have data we get an IP address back. - */ - get_buf(&bp); - (void) makedhcp(bp->dhcp, (u8_t *) "Minix", 5, - clid, cilen, np->ip, 0, np); - cip= bp->dhcp->yiaddr; - - /* Gather information on the interface. */ - if (cip != 0 - && makedhcp(bp->dhcp, (u8_t *) "Minix", 5, - clid, cilen, cip, cip, np) - && test < 2 - ) { - u8_t *pdata; - u16_t mtu; - - cachedhcp(np->n, bp->dhcp); - np->ip= cip; - (void) gettag(bp->dhcp, DHCP_TAG_NETMASK, &pdata, nil); - memcpy(&np->mask, pdata, sizeof(np->mask)); - if (gettag(bp->dhcp, DHCP_TAG_GATEWAY, &pdata, nil)) { - memcpy(&np->gateway, pdata, sizeof(np->gateway)); - } else { - np->gateway= 0; - } - if (gettag(bp->dhcp, DHCP_TAG_IPMTU, &pdata, nil)) { - memcpy(&mtu, pdata, sizeof(mtu)); - mtu= ntohs(mtu); - } else { - mtu= 0; - } - set_ipconf(ipdev(np->n), np->ip, np->mask, mtu); - if (debug >= 1) { - printf("%s: IP address is %s\n", - ipdev(np->n), cidr_ntoa(np->ip, np->mask)); - } - np->flags |= NF_BOUND; - np->renew= np->rebind= np->lease= NEVER; - np->sol_ct= N_SOLICITS; - np->solicit= 0; - - /* Other (previous) interfaces may have been defined. */ - i= 0; - } - put_buf(&bp); - } - - for (;;) { - now= time(nil); - event= NEVER; - - /* Is it time to request/renew a lease? */ - for (i= 0; i < n_nets; i++) { - np= network[i]; - - if (np->renew <= now) { - u8_t type; - static u8_t taglist[] = { - DHCP_TAG_NETMASK, DHCP_TAG_GATEWAY, DHCP_TAG_DNS, - DHCP_TAG_HOSTNAME - }; - u8_t ethclid[1+DHCP_HLEN_ETH]; - - /* We may have lost our binding or even our lease. */ - if (np->rebind <= now) np->server= BCAST_IP; - - if (np->lease <= now) { - if (np->flags & NF_BOUND) closedev(np, FT_ALL); - - if ((np->flags & (NF_BOUND | NF_POSSESSIVE)) == NF_BOUND) { - set_ipconf(ipdev(np->n), np->ip= 0, np->mask= 0, 0); - if (debug >= 1) { - printf("%s: Interface disabled (lease expired)\n", - ipdev(np->n)); - } - } - np->flags &= ~NF_BOUND; - } - - /* See if we can open the network we need to send on. */ - if (!(np->flags & NF_BOUND)) { - if (!opendev(np, FT_ETHERNET, 1)) continue; - } else { - if (!opendev(np, FT_BOOTPC, 1)) continue; - } - - if (!(np->flags & NF_NEGOTIATING)) { - /* We need to start querying a DHCP server. */ - np->start= now; - np->delta= DELTA_FIRST; - np->flags |= NF_NEGOTIATING; - } - - /* Fill in a DHCP query packet. */ - get_buf(&bp); - dhcp_init(bp->dhcp); - bp->dhcp->op= DHCP_BOOTREQUEST; - bp->dhcp->htype= DHCP_HTYPE_ETH; - bp->dhcp->hlen= DHCP_HLEN_ETH; - bp->dhcp->xid= XID(np); - bp->dhcp->secs= htons(now - np->start > 0xFFFF - ? 0xFFFF : now - np->start); - memcpy(bp->dhcp->chaddr, &np->eth, sizeof(np->eth)); - - if (np->lease <= now) { - /* First time, or my old server is unresponsive. */ - type= DHCP_DISCOVER; - } else { - /* Request an offered address or renew an address. */ - type= DHCP_REQUEST; - if (np->flags & NF_BOUND) { - /* A renewal, I claim my current address. */ - bp->dhcp->ciaddr= np->ip; - } else { - /* Nicely ask for the address just offered. */ - settag(bp->dhcp, DHCP_TAG_REQIP, &np->ip, - sizeof(np->ip)); - settag(bp->dhcp, DHCP_TAG_SERVERID, &np->server, - sizeof(np->server)); - } - } - settag(bp->dhcp, DHCP_TAG_TYPE, &type, 1); - - /* My client ID. Simply use the default. */ - ether2clid(ethclid, &np->eth); - settag(bp->dhcp, DHCP_TAG_CLIENTID, ethclid, sizeof(ethclid)); - - /* The Class ID may serve to recognize Minix hosts. */ - settag(bp->dhcp, DHCP_TAG_CLASSID, "Minix", 5); - - /* The few tags that Minix can make good use of. */ - settag(bp->dhcp, DHCP_TAG_REQPAR, taglist, sizeof(taglist)); - - /* Some weird sites use a hostname, not a client ID. */ - if (np->hostname != nil) { - settag(bp->dhcp, DHCP_TAG_HOSTNAME, - (void *)np->hostname, strlen(np->hostname)); - } - - bp->udpio->uih_src_addr= np->ip; - bp->udpio->uih_dst_addr= np->server; - bp->udpio->uih_src_port= port_client; - bp->udpio->uih_dst_port= port_server; - bp->udpio->uih_ip_opt_len= 0; - bp->udpio->uih_data_len= sizeof(dhcp_t); - - if (!(np->flags & NF_BOUND)) { - /* Rebind over Ethernet. */ - udp2ether(bp, np); - if (sendpacket(np, (lwip ? bp->ip : (void *) bp->eth), - (lwip ? 0 : sizeof(eth_hdr_t)) + sizeof(ip_hdr_t) - + sizeof(udp_hdr_t) + sizeof(dhcp_t))) { - if (debug >= 1) { - printf("%s: Broadcast DHCP %s\n", - np->fdp->device, dhcptypename(type)); - if (debug >= 2) printdhcp(bp->dhcp); - } - } - } else { - /* Renew over UDP. */ - if (sendpacket(np, bp->udpio, sizeof(udp_io_hdr_t) - + sizeof(dhcp_t))) { - if (debug >= 1) { - printf("%s: Sent DHCP %s to %s\n", - np->fdp->device, - dhcptypename(type), - inet_ntoa(*(struct in_addr *)&np->server)); - if (debug >= 2) printdhcp(bp->dhcp); - } - } - } - put_buf(&bp); - - /* When to continue querying a DHCP server? */ - if (np->flags & NF_BOUND) { - /* Still bound, keep halving time till next event. */ - time_t e, d; - - e= now < np->rebind ? np->rebind : np->lease; - d= (e - now) / 2; - if (d < DELTA_SLOW) d= DELTA_SLOW; - np->renew= now + d; - if (np->renew > e) np->renew= e; - } else { - /* Not bound, be desparate. */ - np->renew= now + np->delta; - if ((np->delta *= 2) > DELTA_FAST) np->delta= DELTA_FAST; - } - } - if (np->renew < event) event= np->renew; - } - - /* Read DHCP responses. */ - for (i= 0; i < n_nets; i++) { - np= network[i]; - if (!(np->flags & NF_NEGOTIATING)) continue; - - if (!(np->flags & NF_BOUND)) { - if (!opendev(np, FT_ETHERNET, 0)) continue; - get_buf(&np->fdp->bp); - r= asyn_read(&asyn, np->fdp->fd, - lwip ? np->fdp->bp->ip : (void *) np->fdp->bp->eth, - lwip ? BUF_IP_SIZE : BUF_ETH_SIZE); - } else { - if (!opendev(np, FT_BOOTPC, 0)) continue; - get_buf(&np->fdp->bp); - r= asyn_read(&asyn, np->fdp->fd, np->fdp->bp->udpio, - BUF_UDP_SIZE); - } - if (r != -1) break; - if (errno != ASYN_INPROGRESS && errno != EPACKSIZE) { - report(np->fdp->device); - sleep(10); - } - } - - /* Is there a response? */ - if (i < n_nets) { - give_buf(&bp, &np->fdp->bp); - if (((!(np->flags & NF_BOUND) - && r >= (lwip ? 0 : (sizeof(eth_hdr_t)) + sizeof(ip_hdr_t) - + sizeof(udp_hdr_t) + offsetof(dhcp_t, options)) - && ether2udp(bp) - && bp->udpio->uih_dst_port == port_client) - || - ((np->flags & NF_BOUND) - && r >= sizeof(udp_io_hdr_t) + offsetof(dhcp_t, options))) - && bp->dhcp->op == DHCP_BOOTREPLY - && bp->dhcp->htype == DHCP_HTYPE_ETH - && bp->dhcp->hlen == DHCP_HLEN_ETH - && bp->dhcp->xid == XID(np) - && memcmp(bp->dhcp->chaddr, &np->eth, sizeof(np->eth)) == 0 - ) { - /* Pfew! We got a DHCP reply! */ - u8_t *pdata; - size_t len; - int type; - ipaddr_t mask, gateway, relay, server; - u16_t mtu; - u32_t lease, renew, rebind, t; - - relay= bp->udpio->uih_src_addr; - if (gettag(bp->dhcp, DHCP_TAG_SERVERID, &pdata, nil)) { - memcpy(&server, pdata, sizeof(server)); - } else { - server= relay; - } - - if (gettag(bp->dhcp, DHCP_TAG_TYPE, &pdata, nil)) { - type= pdata[0]; - } else { - type= DHCP_ACK; /* BOOTP? */ - } - - if (debug >= 1) { - printf("%s: Got a DHCP %s from %s", - np->fdp->device, dhcptypename(type), - inet_ntoa(*(struct in_addr *)&server)); - if (relay != server) - printf(" through %s\n", - inet_ntoa(*(struct in_addr *)&relay)); - else printf("\n"); - if (debug >= 2) printdhcp(bp->dhcp); - } - - if (gettag(bp->dhcp, DHCP_TAG_NETMASK, &pdata, nil)) { - memcpy(&mask, pdata, sizeof(mask)); - } else { - mask= defaultmask(bp->dhcp->ciaddr); - } - - if (gettag(bp->dhcp, DHCP_TAG_IPMTU, &pdata, nil)) { - memcpy(&mtu, pdata, sizeof(mtu)); - mtu= ntohs(mtu); - } else { - mtu= 0; - } - - if (gettag(bp->dhcp, DHCP_TAG_GATEWAY, &pdata, nil)) { - memcpy(&gateway, pdata, sizeof(gateway)); - } else { - gateway= 0; - } - - lease= NEVER; - if (gettag(bp->dhcp, DHCP_TAG_LEASE, &pdata, nil)) { - memcpy(&lease, pdata, sizeof(lease)); - lease= ntohl(lease); - } - - rebind= lease - lease / 8; - if (gettag(bp->dhcp, DHCP_TAG_REBINDING, &pdata, nil)) { - memcpy(&t, pdata, sizeof(t)); - t= ntohl(t); - if (t < rebind) rebind= t; - } - - renew= lease / 2; - if (gettag(bp->dhcp, DHCP_TAG_RENEWAL, &pdata, nil)) { - memcpy(&t, pdata, sizeof(t)); - t= ntohl(t); - if (t < renew) renew= t; - } - - if (type == DHCP_OFFER && np->rebind <= np->renew) { - /* It's an offer for an address and we haven't taken one - * yet. It's all the same to us, so take this one. - */ - np->ip= bp->dhcp->yiaddr; - np->mask= mask; - np->server= server; - np->gateway= gateway; - np->delta= DELTA_FIRST; - np->renew= now; - np->rebind= np->lease= now + DELTA_FAST; - - /* Send out an ARP request to see if the offered address - * is in use already. - */ - make_arp(bp, np); - if (sendpacket(np, bp->eth, sizeof(arp46_t))) { - if (debug >= 2) { - printf("Sent ARP for %s\n", - inet_ntoa(*(struct in_addr *)&np->ip)); - } - } - np->flags &= ~NF_CONFLICT; - } - - if (type == DHCP_ACK && !(np->flags & NF_CONFLICT)) { - /* An acknowledgment. The address is all mine. */ - cachedhcp(np->n, bp->dhcp); - np->ip= bp->dhcp->yiaddr; - np->mask= mask; - np->server= server; - set_ipconf(ipdev(np->n), np->ip, np->mask, mtu); - if (debug >= 1) { - printf("%s: Address set to %s\n", - ipdev(np->n), cidr_ntoa(np->ip, np->mask)); - } - if (lease >= NEVER - now) { - /* The lease is infinite! */ - np->renew= np->rebind= np->lease= NEVER; - } else { - np->lease= now + lease; - np->renew= now + renew; - np->rebind= now + rebind; - } - if (test >= 3) { - np->renew= now + 60; - np->rebind= test >= 4 ? np->renew : np->renew + 60; - np->lease= test >= 5 ? np->rebind : np->rebind + 60; - } - if (!(np->flags & NF_IRDP)) { - np->sol_ct= (np->flags & NF_BOUND) ? 1 : N_SOLICITS; - np->solicit= 0; - } - np->flags &= ~NF_NEGOTIATING; - np->flags |= NF_BOUND; - closedev(np, FT_ETHERNET); - closedev(np, FT_BOOTPC); - } - - if (type == DHCP_ACK && (np->flags & NF_CONFLICT)) { - /* Alas there is a conflict. Decline to use the address. */ - u8_t ethclid[1+DHCP_HLEN_ETH]; - static char USED[]= "Address in use by 00:00:00:00:00:00"; - - type= DHCP_DECLINE; - dhcp_init(bp->dhcp); - bp->dhcp->op= DHCP_BOOTREQUEST; - bp->dhcp->htype= DHCP_HTYPE_ETH; - bp->dhcp->hlen= DHCP_HLEN_ETH; - bp->dhcp->xid= XID(np); - bp->dhcp->secs= 0; - memcpy(bp->dhcp->chaddr, &np->eth, sizeof(np->eth)); - settag(bp->dhcp, DHCP_TAG_REQIP, &np->ip, sizeof(np->ip)); - settag(bp->dhcp, DHCP_TAG_TYPE, &type, 1); - ether2clid(ethclid, &np->eth); - settag(bp->dhcp, DHCP_TAG_CLIENTID,ethclid,sizeof(ethclid)); - strcpy(USED+18, ether_ntoa(&np->conflict)); - settag(bp->dhcp, DHCP_TAG_MESSAGE, USED, strlen(USED)); - - bp->udpio->uih_src_port= port_client; - bp->udpio->uih_dst_port= port_server; - bp->udpio->uih_ip_opt_len= 0; - bp->udpio->uih_data_len= sizeof(dhcp_t); - udp2ether(bp, np); - - if (sendpacket(np, bp->eth, - sizeof(eth_hdr_t) + sizeof(ip_hdr_t) - + sizeof(udp_hdr_t) + sizeof(dhcp_t))) { - if (debug >= 1) { - printf("%s: Broadcast DHCP %s\n", - np->fdp->device, dhcptypename(type)); - if (debug >= 2) printdhcp(bp->dhcp); - } - } - - np->renew= np->rebind= np->lease= now + DELTA_FAST; - np->delta= DELTA_FIRST; - } - - if (type == DHCP_NAK) { - /* Oops, a DHCP server doesn't like me, start over! */ - np->renew= np->rebind= np->lease= now + DELTA_FAST; - np->delta= DELTA_FIRST; - - fprintf(stderr, "%s: Got a NAK from %s", - program, inet_ntoa(*(struct in_addr *)&server)); - if (relay != server) { - fprintf(stderr, " through %s", - inet_ntoa(*(struct in_addr *)&relay)); - } - if (gettag(bp->dhcp, DHCP_TAG_MESSAGE, &pdata, &len)) { - fprintf(stderr, " saying: \"%.*s\"", (int)len, pdata); - } - fputc('\n', stderr); - } - } else - if (!(np->flags & NF_BOUND) - && np->rebind > now - && r >= sizeof(arp46_t) - && is_arp_me(bp, np) - ) { - /* Oh no, someone else is using the address offered to me! */ - np->flags |= NF_CONFLICT; - - fprintf(stderr, "%s: %s: %s offered by ", - program, - np->fdp->device, - inet_ntoa(*(struct in_addr *)&np->ip)); - fprintf(stderr, "%s is already in use by %s\n", - inet_ntoa(*(struct in_addr *)&np->server), - ether_ntoa(&np->conflict)); - } - put_buf(&bp); - if (np->renew < event) event= np->renew; - } - - /* Perform router solicitations. */ - for (i= 0; i < n_nets; i++) { - np= network[i]; - if (!(np->flags & NF_BOUND)) continue; - - if (np->solicit <= now) { - if (!opendev(np, FT_ICMP, 1)) continue; - np->solicit= NEVER; - - get_buf(&bp); - if (np->gateway != 0) { - /* No IRDP response seen yet, advertise the router given - * by DHCP to my own interface. - */ - icmp_advert(bp, np); - if (sendpacket(np, bp->ip, sizeof(ip_hdr_t) + 16)) { - if (debug >= 2) { - printf("%s: Sent advert for %s to self\n", - np->fdp->device, - inet_ntoa(*(struct in_addr *)&np->gateway)); - } - } - np->solicit= now + DELTA_ADV/2; - } - - if (np->sol_ct >= 0 && --np->sol_ct >= 0) { - /* Send a router solicitation. */ - icmp_solicit(bp); - if (sendpacket(np, bp->ip, sizeof(*bp->ip) + 8)) { - if (debug >= 2) { - printf("%s: Broadcast router solicitation\n", - np->fdp->device); - } - } - np->solicit= now + DELTA_SOL; - } else { - /* No response, or not soliciting right now. */ - closedev(np, FT_ICMP); - } - - put_buf(&bp); - } - if (np->solicit < event) event= np->solicit; - } - - /* Read router adverts. */ - for (i= 0; i < n_nets; i++) { - np= network[i]; - if (!(np->flags & NF_BOUND)) continue; - if (np->sol_ct < 0) continue; - - if (!opendev(np, FT_ICMP, 0)) continue; - get_buf(&np->fdp->bp); - r= asyn_read(&asyn, np->fdp->fd, np->fdp->bp->ip, BUF_IP_SIZE); - if (r != -1) break; - if (errno != ASYN_INPROGRESS && errno != EPACKSIZE) { - report(np->fdp->device); - sleep(10); - } - } - - /* Is there an advert? */ - if (i < n_nets && r >= sizeof(ip_hdr_t) + 8) { - ipaddr_t router; - - give_buf(&bp, &np->fdp->bp); - if ((router= icmp_is_advert(bp)) != 0) { - if (debug >= 2) { - printf("%s: Router advert received from %s\n", - np->fdp->device, - inet_ntoa(*(struct in_addr *)&router)); - } - np->solicit= NEVER; - np->sol_ct= -1; - np->flags |= NF_IRDP; - closedev(np, FT_ICMP); - } - put_buf(&bp); - } - - /* We start serving if all the interfaces so marked are configured. */ - for (i= 0; i < n_nets; i++) { - np= network[i]; - if ((np->flags & NF_RELAYING) && (np->flags & NF_BOUND)) { - if (((np->ip ^ np->server) & np->mask) == 0) { - /* Don't relay to a server that is on this same net. */ - np->flags &= ~NF_RELAYING; - } - } - if (!(np->flags & (NF_SERVING|NF_RELAYING))) continue; - if (!(np->flags & NF_BOUND)) { serving= 0; break; } - serving= 1; - } - - /* Read DHCP requests. */ - for (i= 0; i < n_nets; i++) { - np= network[i]; - if (!(np->flags & NF_BOUND)) continue; - if (!(np->flags & (NF_SERVING|NF_RELAYING)) || !serving) continue; - - if (!opendev(np, FT_BOOTPS, 0)) continue; - get_buf(&np->fdp->bp); - r= asyn_read(&asyn, np->fdp->fd, np->fdp->bp->udpio, BUF_UDP_SIZE); - - if (r != -1) break; - if (errno != ASYN_INPROGRESS && errno != EPACKSIZE) { - report(np->fdp->device); - sleep(10); - } - } - - /* Is there a request? */ - if (i < n_nets - && r >= sizeof(udp_io_hdr_t) + offsetof(dhcp_t, options) - ) { - give_buf(&bp, &np->fdp->bp); - - if (debug >= 1) { - printf("%s: Got DHCP packet from %s to ", - np->fdp->device, - inet_ntoa(*(struct in_addr *)&bp->udpio->uih_src_addr)); - printf("%s\n", - inet_ntoa(*(struct in_addr *)&bp->udpio->uih_dst_addr)); - if (debug >= 2) printdhcp(bp->dhcp); - } - - /* Can we do something with this DHCP packet? */ - if ((r= servdhcp(np, bp, r)) > 0) { - /* Yes, we have something to send somewhere. */ - if (sendpacket(np, bp->udpio, r)) { - if (debug >= 1) { - printf("%s: Sent DHCP packet to %s\n", - np->fdp->device, - inet_ntoa(*(struct in_addr *) - &bp->udpio->uih_dst_addr)); - if (debug >= 2) printdhcp(bp->dhcp); - } - } - } - put_buf(&bp); - } - - if (debug >= 1) { - static char *lastbrk; - extern char _end; - - if (sbrk(0) != lastbrk) { - lastbrk= sbrk(0); - printf("Memory use = %lu\n", - (unsigned long) (lastbrk - &_end)); - } - fflush(stdout); - } - - /* Bail out if not a server, and there is nothing else to do ever. */ - if (!serving && event == NEVER) break; - - /* Wait for something to do. */ - eventtv.tv_sec= event; - if (asyn_wait(&asyn, 0, event == NEVER ? nil : &eventtv) < 0) { - if (errno != EINTR) { - report("asyn_wait()"); - sleep(10); - } - } - } - if (debug >= 1) printf("Nothing more to do! Starting over...\n"); - sleep(2); - goto main; - - return 0; -} diff --git a/minix/commands/dhcpd/dhcpd.h b/minix/commands/dhcpd/dhcpd.h deleted file mode 100644 index 35d729d3e..000000000 --- a/minix/commands/dhcpd/dhcpd.h +++ /dev/null @@ -1,162 +0,0 @@ -/* dhcpd.h - Dynamic Host Configuration Protocol daemon. - * Author: Kees J. Bot - * 16 Dec 2000 - */ - -#define nil ((void*)0) - -#include -#include - -/* Paths to files. */ -#define PATH_DHCPCONF _PATH_DHCPCONF -#define PATH_DHCPPID _PATH_DHCPPID -#define PATH_DHCPCACHE _PATH_DHCPCACHE -#define PATH_DHCPPOOL _PATH_DHCPPOOL - -#define CLID_MAX 32 /* Maximum client ID length. */ - -#ifndef EXTERN -#define EXTERN extern -#endif - -extern int lwip; - -EXTERN char *program; /* This program's name. */ -extern char *configfile; /* Configuration file. */ -extern char *poolfile; /* Dynamic address pool. */ -EXTERN int serving; /* True if being a DHCP server. */ -EXTERN unsigned test; /* Test level. */ -EXTERN unsigned debug; /* Debug level. */ -EXTERN asynchio_t asyn; /* Bookkeeping for all async I/O. */ - -/* BOOTP UDP ports: (That they are different is quite stupid.) */ -EXTERN u16_t port_server; /* Port server listens on. */ -EXTERN u16_t port_client; /* Port client listens on. */ - -#define arraysize(a) (sizeof(a) / sizeof((a)[0])) -#define arraylimit(a) ((a) + arraysize(a)) -#define between(a,c,z) (sizeof(c) <= sizeof(unsigned) ? \ - (unsigned) (c) - (a) <= (unsigned) (z) - (a) : \ - (unsigned long) (c) - (a) <= (unsigned long) (z) - (a)) - -/* To treat objects as octet arrays: */ -#define B(a) ((u8_t *) (a)) - -/* Times. */ -EXTERN time_t start, now; /* Start and current time. */ -EXTERN time_t event; /* Time of the next timed event. */ - -/* Special times and periods: */ -#define NEVER (sizeof(time_t) <= sizeof(int) ? INT_MAX : LONG_MAX) -#define DELTA_FIRST 4 /* Between first and second query. */ -#define DELTA_FAST 64 /* Unbound queries this often. */ -#define DELTA_SLOW 512 /* Bound queries are more relaxed. */ -#define N_SOLICITS 3 /* Number of solicitations. */ -#define DELTA_SOL 3 /* Time between solicitations. */ -#define DELTA_ADV 2048 /* Router adverts to self lifetime. */ - -/* Buffers for packets. */ -typedef struct buf { - eth_hdr_t *eth; /* Ethernet header in payload. */ - ip_hdr_t *ip; /* IP header in payload. */ - udp_hdr_t *udp; /* UDP header in payload. */ - udp_io_hdr_t *udpio; /* UDP I/O header in payload. */ - dhcp_t *dhcp; /* DHCP data in payload. */ - u8_t pad[2]; /* buf[] must start at 2 mod 4. */ - /* Payload: */ - u8_t buf[ETH_MAX_PACK_SIZE]; -} buf_t; - -#define BUF_ETH_SIZE (ETH_MAX_PACK_SIZE) -#define BUF_IP_SIZE (BUF_ETH_SIZE - sizeof(eth_hdr_t)) -#define BUF_UDP_SIZE (BUF_IP_SIZE - sizeof(ip_hdr_t) - sizeof(udp_hdr_t) \ - + sizeof(udp_io_hdr_t)) - -/* Type of network device open: Ethernet, ICMP, BOOTP client, BOOTP server. */ -typedef enum { FT_CLOSED, FT_ETHERNET, FT_ICMP, FT_BOOTPC, FT_BOOTPS } fdtype_t; - -#define FT_ALL FT_CLOSED /* To close all open descriptors at once. */ - -typedef struct fd { /* An open descriptor. */ - i8_t fd; /* Open descriptor. */ - u8_t fdtype; /* Type of network open. */ - char device[sizeof("/dev/eth###")]; /* Device name. */ - u8_t n; /* Network that owns it. */ - buf_t *bp; /* Associated packet buffer. */ - time_t since; /* Open since when? */ -} fd_t; - -/* Network state: Any IP device, Ethernet in sink mode, True Ethernet. */ -typedef enum { NT_IP, NT_SINK, NT_ETHERNET } nettype_t; - -typedef struct network { /* Information on a network. */ - u8_t n; /* Network number. */ - ether_addr_t eth; /* Ethernet address of this net. */ - u8_t type; /* What kind of net is this? */ - i8_t sol_ct; /* Router solicitation count. */ - ether_addr_t conflict; /* Address conflict with this one. */ - unsigned flags; /* Various flags. */ - fd_t *fdp; /* Current open device. */ - struct network *wait; /* Wait for a resource list. */ - ipaddr_t ip; /* IP address of this net. */ - ipaddr_t mask; /* Associated netmask. */ - ipaddr_t gateway; /* My router. */ - ipaddr_t server; /* My DHCP server. */ - const char *hostname; /* Optional hostname to query for. */ - time_t start; /* Query or lease start time. */ - time_t delta; /* Query again after delta seconds. */ - time_t renew; /* Next query or go into renewal. */ - time_t rebind; /* When to go into rebind. */ - time_t lease; /* When our lease expires. */ - time_t solicit; /* Time to do a router solicitation. */ -} network_t; - -/* Flags. */ -#define NF_NEGOTIATING 0x001 /* Negotiating with a DHCP server. */ -#define NF_BOUND 0x002 /* Address configured through DHCP. */ -#define NF_SERVING 0x004 /* I'm a server on this network. */ -#define NF_RELAYING 0x008 /* I'm relaying for this network. */ -#define NF_WAIT 0x010 /* Wait for a resource to free up. */ -#define NF_IRDP 0x020 /* IRDP is used on this net. */ -#define NF_CONFLICT 0x040 /* There is an address conflict. */ -#define NF_POSSESSIVE 0x080 /* Keep address if lease expires. */ -#define NF_INFORM 0x100 /* It's ok to answer DHCPINFORM. */ - -/* Functions defined in dhcpd.c. */ -void report(const char *label); -void fatal(const char *label); -void *allocate(size_t size); -int ifname2if(const char *name); -network_t *if2net(int n); - -/* Devices.c */ -void get_buf(buf_t **bp); -void put_buf(buf_t **bp); -void give_buf(buf_t **dbp, buf_t **sbp); -network_t *newnetwork(void); -void closefd(fd_t *fdp); -int opendev(network_t *np, fdtype_t fdtype, int compete); -void closedev(network_t *np, fdtype_t fdtype); -char *ipdev(int n); -void set_ipconf(char *device, ipaddr_t ip, ipaddr_t mask, unsigned mtu); - -/* Ether.c */ -void udp2ether(buf_t *bp, network_t *np); -int ether2udp(buf_t *bp); -void make_arp(buf_t *bp, network_t *np); -int is_arp_me(buf_t *bp, network_t *np); -void icmp_solicit(buf_t *bp); -void icmp_advert(buf_t *bp, network_t *np); -ipaddr_t icmp_is_advert(buf_t *bp); - -/* Tags.c */ -#define gettag(dp, st, pd, pl) dhcp_gettag((dp), (st), (pd), (pl)) -void settag(dhcp_t *dp, int tag, void *data, size_t len); -char *cidr_ntoa(ipaddr_t addr, ipaddr_t mask); -void ether2clid(u8_t *clid, ether_addr_t *eth); -void initdhcpconf(void); -int makedhcp(dhcp_t *dp, u8_t *class, size_t calen, u8_t *client, size_t cilen, - ipaddr_t ip, ipaddr_t ifip, network_t *np); -char *dhcptypename(int type); -void printdhcp(dhcp_t *dp); diff --git a/minix/commands/dhcpd/ether.c b/minix/commands/dhcpd/ether.c deleted file mode 100644 index b9edadf1a..000000000 --- a/minix/commands/dhcpd/ether.c +++ /dev/null @@ -1,206 +0,0 @@ -/* ether.c - Raw Ethernet stuff - * Author: Kees J. Bot - * 16 Dec 2000 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "arp.h" -#include "dhcpd.h" - -static ether_addr_t BCAST_ETH = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; -#define BCAST_IP htonl(0xFFFFFFFFUL) -#define LOCALHOST htonl(0x7F000001UL) - -static u16_t udp_cksum(ipaddr_t src, ipaddr_t dst, udp_hdr_t *udp) -{ - /* Compute the checksum of an UDP packet plus data. */ - struct udp_pseudo { - ipaddr_t src, dst; - u8_t zero, proto; - u16_t length; - } pseudo; - size_t len; - - /* Fill in the UDP pseudo header that must be prefixed to the UDP - * packet to compute the checksum of the whole thing. - */ - pseudo.src= src; - pseudo.dst= dst; - pseudo.zero= 0; - pseudo.proto= IPPROTO_UDP; - pseudo.length= udp->uh_length; - - len= ntohs(udp->uh_length); - if (len & 1) { - /* Length is odd? Pad with a zero. */ - B(udp)[len++]= 0; - } - return oneC_sum(oneC_sum(0, &pseudo, sizeof(pseudo)), udp, len); -} - -void udp2ether(buf_t *bp, network_t *np) -{ - /* Transform a packet in UDP format to raw Ethernet. Ignore the UDP - * addresses, always broadcast from 0.0.0.0. - */ - udp_io_hdr_t udpio; - - /* Save the UDP I/O header. */ - udpio= *bp->udpio; - - /* Fill in the Ethernet, IP and UDP headers. */ - bp->eth->eh_dst= BCAST_ETH; - bp->eth->eh_src= np->eth; - bp->eth->eh_proto= htons(ETH_IP_PROTO); - bp->ip->ih_vers_ihl= 0x45; - bp->ip->ih_tos= 0; - bp->ip->ih_length= htons(sizeof(ip_hdr_t) - + sizeof(udp_hdr_t) + udpio.uih_data_len); - bp->ip->ih_id= 0; - bp->ip->ih_flags_fragoff= ntohs(0x4000); - bp->ip->ih_ttl= IP_MAX_TTL; - bp->ip->ih_proto= IPPROTO_UDP; - bp->ip->ih_hdr_chk= 0; - bp->ip->ih_src= 0; - bp->ip->ih_dst= BCAST_IP; - bp->ip->ih_hdr_chk= ~oneC_sum(0, bp->ip, sizeof(*bp->ip)); - bp->udp->uh_src_port= udpio.uih_src_port; - bp->udp->uh_dst_port= udpio.uih_dst_port; - bp->udp->uh_length= htons(sizeof(udp_hdr_t) + udpio.uih_data_len); - bp->udp->uh_chksum= 0; - bp->udp->uh_chksum= ~udp_cksum(bp->ip->ih_src, bp->ip->ih_dst, bp->udp); -} - -int ether2udp(buf_t *bp) -{ - /* Transform an UDP packet read from raw Ethernet to normal UDP. - * Return true iff the packet is indeed UDP and has no errors. - */ - udp_io_hdr_t udpio; - - if (bp->eth->eh_proto != htons(ETH_IP_PROTO) - || bp->ip->ih_vers_ihl != 0x45 - || bp->ip->ih_proto != IPPROTO_UDP - || oneC_sum(0, bp->ip, 20) != (u16_t) ~0 - || udp_cksum(bp->ip->ih_src, bp->ip->ih_dst, bp->udp) != (u16_t) ~0 - ) { - /* Not UDP/IP or checksums bad. */ - return 0; - } - udpio.uih_src_addr= bp->ip->ih_src; - udpio.uih_dst_addr= bp->ip->ih_dst; - udpio.uih_src_port= bp->udp->uh_src_port; - udpio.uih_dst_port= bp->udp->uh_dst_port; - udpio.uih_ip_opt_len= 0; - udpio.uih_data_len= ntohs(bp->udp->uh_length) - sizeof(udp_hdr_t); - *bp->udpio= udpio; - return 1; -} - -void make_arp(buf_t *bp, network_t *np) -{ - /* Create an ARP packet to query for my IP address. */ - arp46_t *arp= (arp46_t *) bp->eth; - - memset(arp, 0, sizeof(*arp)); - arp->dstaddr= BCAST_ETH; - arp->srcaddr= np->eth; - arp->ethtype= htons(ETH_ARP_PROTO); - arp->hdr= htons(ARP_ETHERNET); - arp->pro= htons(ETH_IP_PROTO); - arp->op= htons(ARP_REQUEST); - arp->hln= 6; - arp->pln= 4; - - arp->sha= np->eth; - memcpy(arp->spa, &np->ip, sizeof(np->ip)); - memcpy(arp->tpa, &np->ip, sizeof(np->ip)); -} - -int is_arp_me(buf_t *bp, network_t *np) -{ - /* True iff an ARP packet is a reply from someone else with an address I - * thought was mine. (That's like, bad.) - */ - arp46_t *arp= (arp46_t *) bp->eth; - - if (arp->ethtype == htons(ETH_ARP_PROTO) - && arp->hdr == htons(ARP_ETHERNET) - && arp->pro == htons(ETH_IP_PROTO) - && arp->op == htons(ARP_REPLY) - && memcmp(&arp->spa, &np->ip, sizeof(np->ip)) == 0 - && memcmp(&arp->sha, &np->eth, sizeof(np->eth)) != 0 - ) { - np->conflict= arp->sha; - return 1; - } - return 0; -} - -void icmp_solicit(buf_t *bp) -{ - /* Fill in a router solicitation ICMP packet. */ - icmp_hdr_t *icmp= (icmp_hdr_t *) (bp->ip + 1); - - bp->ip->ih_vers_ihl= 0x45; - bp->ip->ih_dst= BCAST_IP; - - icmp->ih_type= ICMP_TYPE_ROUTE_SOL; - icmp->ih_code= 0; - icmp->ih_hun.ihh_unused= 0; - icmp->ih_chksum= 0; - icmp->ih_chksum= ~oneC_sum(0, icmp, 8); -} - -void icmp_advert(buf_t *bp, network_t *np) -{ - /* Fill in a router advert to be sent to my own interface. */ - u32_t *data; - icmp_hdr_t *icmp= (icmp_hdr_t *) (bp->ip + 1); - - bp->ip->ih_vers_ihl= 0x45; - bp->ip->ih_dst= LOCALHOST; - - icmp->ih_type= ICMP_TYPE_ROUTER_ADVER; - icmp->ih_code= 0; - icmp->ih_hun.ihh_ram.iram_na= 1; - icmp->ih_hun.ihh_ram.iram_aes= 2; - icmp->ih_hun.ihh_ram.iram_lt= htons(DELTA_ADV); - data = (u32_t *) icmp->ih_dun.uhd_data; - data[0] = np->gateway; - data[1] = htonl((u32_t) -9999); - icmp->ih_chksum= 0; - icmp->ih_chksum= ~oneC_sum(0, icmp, 16); -} - -ipaddr_t icmp_is_advert(buf_t *bp) -{ - /* Check if an IP packet is a router advertisement, and if it's genuine, - * i.e. the sender is mentioned in the packet. - */ - icmp_hdr_t *icmp= (icmp_hdr_t *) (bp->ip + 1); - int i; - - if (icmp->ih_type == ICMP_TYPE_ROUTER_ADVER) { - for (i= 0; i < icmp->ih_hun.ihh_ram.iram_na; i++) { - if (((u32_t *) icmp->ih_dun.uhd_data)[2*i] == bp->ip->ih_src) { - /* It's a router! */ - return bp->ip->ih_src; - } - } - } - return 0; -} diff --git a/minix/commands/dhcpd/tags.c b/minix/commands/dhcpd/tags.c deleted file mode 100644 index 6ab015c90..000000000 --- a/minix/commands/dhcpd/tags.c +++ /dev/null @@ -1,926 +0,0 @@ -/* tags.c - Obtain DHCP tags from the config file - * Author: Kees J. Bot - * 16 Dec 2000 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dhcpd.h" - -#define doff(field) offsetof(dhcp_t, field) - -void settag(dhcp_t *dp, int tag, void *data, size_t len) -{ - if (!dhcp_settag(dp, tag, data, len)) { - /* Oops, it didn't fit? Is this really Minix??? */ - fprintf(stderr, - "%s: DHCP packet too big, please trim the configuration\n", - program); - exit(1); - } -} - -static int name2ip(ipaddr_t *pip, const char *name, ipaddr_t ifip) -{ - /* Translate a name to an IP address, preferably from the hosts file, - * but also from the DNS if being a server. Prefer the address closest - * to the interface with IP address 'ifip' if there are choices.. - */ - extern struct hostent *_gethostent(void); /* File reading versions. */ - extern void _endhostent(void); - struct hostent *he; - size_t len= strlen(name); - u32_t d, distance= -1; - ipaddr_t ip; - int i; - char *hn; - - /* Already an IP address? */ - if (inet_aton(name, (struct in_addr *)pip)) return 1; - - /* In the hosts file? */ - while ((he= _gethostent()) != nil) { - hn= he->h_name; - i= -1; - do { - if (strncasecmp(name, hn, len) == 0 - && (hn[len] == 0 || hn[len] == '.') - ) { - memcpy(&ip, he->h_addr, sizeof(ip)); - d= ntohl(ip) ^ ntohl(ifip); - if (d < distance) { - *pip= ip; - distance= d; - } - break; - } - } while ((hn= he->h_aliases[++i]) != nil); - } - _endhostent(); - if (distance < -1) return 1; - - /* Nothing? Try the real DNS if being a server. */ - if (serving) { - if ((he= gethostbyname(name)) != nil && he->h_addrtype == AF_INET) { - /* Select the address closest to 'ifip'. */ - for (i= 0; he->h_addr_list[i] != nil; i++) { - memcpy(&ip, he->h_addr_list[i], sizeof(ip)); - d= ntohl(ip) ^ ntohl(ifip); - if (d < distance) { - *pip= ip; - distance= d; - } - } - return 1; - } - } - return 0; -} - -static char *ip2name(ipaddr_t ip) -{ - /* Translate an IP address to a name, etc, etc. */ - extern struct hostent *_gethostent(void); /* File reading versions. */ - extern void _endhostent(void); - struct hostent *he; - - /* In the hosts file? */ - while ((he= _gethostent()) != nil) { - if (memcmp(he->h_addr, &ip, sizeof(ip)) == 0) break; - } - _endhostent(); - - /* Nothing? Try the real DNS if being a server. */ - if (he == nil && serving) { - he= gethostbyaddr((char *) &ip, sizeof(ip), AF_INET); - } - return he != nil ? he->h_name : nil; -} - -static int cidr_aton(const char *cidr, ipaddr_t *addr, ipaddr_t *mask) -{ - char *slash, *check; - ipaddr_t a; - int ok; - unsigned long len; - - if ((slash= strchr(cidr, '/')) == nil) return 0; - - *slash++= 0; - ok= inet_aton(cidr, (struct in_addr *)&a); - - len= strtoul(slash, &check, 10); - if (check == slash || *check != 0 || len > 32) ok= 0; - - *--slash= '/'; - if (!ok) return 0; - *addr= a; - *mask= htonl(len == 0 ? 0 : (0xFFFFFFFFUL << (32-len)) & 0xFFFFFFFFUL); - return 1; -} - -char *cidr_ntoa(ipaddr_t addr, ipaddr_t mask) -{ - ipaddr_t testmask= 0xFFFFFFFFUL; - int n; - static char result[sizeof("255.255.255.255/255.255.255.255")]; - - for (n= 32; n >= 0; n--) { - if (mask == htonl(testmask)) break; - testmask= (testmask << 1) & 0xFFFFFFFFUL; - } - - sprintf(result, "%s/%-2d", inet_ntoa(*(struct in_addr *)&addr), n); - if (n == -1) strcpy(strchr(result, '/')+1, - inet_ntoa(*(struct in_addr *)&mask)); - return result; -} - -static size_t ascii2octet(u8_t *b, size_t size, const char *a) -{ - /* Convert a series of hex digit pairs to an octet (binary) array at - * 'b' with length 'size'. Return the number of octets in 'a' or - * -1 on error. - */ - size_t len; - int n, c; - - len= 0; - n= 0; - while ((c= *a++) != 0) { - if (between('0', c, '9')) c= (c - '0') + 0x0; - else - if (between('a', c, 'f')) c= (c - 'a') + 0xa; - else - if (between('A', c, 'F')) c= (c - 'A') + 0xA; - else { - return -1; - } - - if (n == 0) { - if (len < size) b[len] = c << 4; - } else { - if (len < size) b[len] |= c; - len++; - } - n ^= 1; - } - return n == 0 ? len : -1; -} - -void ether2clid(u8_t *clid, ether_addr_t *eth) -{ - /* Convert an Ethernet address to the default client ID form. */ - clid[0]= DHCP_HTYPE_ETH; - memcpy(clid+1, eth, DHCP_HLEN_ETH); -} - -static size_t ascii2clid(u8_t *clid, const char *a) -{ - /* Convert an ethernet address, or a series of hex digits to a client ID. - * Return its length if ok, otherwise -1. - */ - size_t len; - ether_addr_t *eth; - - if ((eth= ether_aton(a)) != nil) { - ether2clid(clid, eth); - len= 1+DHCP_HLEN_ETH; - } else { - len= ascii2octet(clid, CLID_MAX, a); - } - return len; -} - -static config_t *dhcpconf; /* In-core DHCP configuration. */ - -/* DHCP tag types. */ -typedef enum { TT_ASCII, TT_BOOLEAN, TT_IP, TT_NUMBER, TT_OCTET } tagtype_t; - -/* DHCP/BOOTP tag definitions. */ -typedef struct tagdef { - u8_t tag; /* Tag number. */ - u8_t type; /* Type and flags. */ - u8_t gran; /* Granularity. */ - u8_t max; /* Maximum number of arguments. */ - const char *name; /* Defined name. */ -} tagdef_t; - -#define TF_TYPE 0x07 /* To mask out the type. */ -#define TF_STATIC 0x08 /* "Static", i.e. a struct field. */ -#define TF_RO 0x10 /* Read-only, user can't set. */ - -/* List of static DHCP fields. The tag field is misused here as an offset - * into the DHCP structure. - */ -static tagdef_t statictag[] = { - { doff(op), TT_NUMBER|TF_STATIC|TF_RO, 1, 1, "op" }, - { doff(htype), TT_NUMBER|TF_STATIC|TF_RO, 1, 1, "htype" }, - { doff(hlen), TT_NUMBER|TF_STATIC|TF_RO, 1, 1, "hlen" }, - { doff(hops), TT_NUMBER|TF_STATIC|TF_RO, 1, 1, "hops" }, - { doff(xid), TT_NUMBER|TF_STATIC|TF_RO, 4, 1, "xid" }, - { doff(secs), TT_NUMBER|TF_STATIC|TF_RO, 2, 1, "secs" }, - { doff(flags), TT_NUMBER|TF_STATIC|TF_RO, 2, 1, "flags" }, - { doff(ciaddr), TT_IP|TF_STATIC|TF_RO, 1, 1, "ciaddr" }, - { doff(yiaddr), TT_IP|TF_STATIC|TF_RO, 1, 1, "yiaddr" }, - { doff(siaddr), TT_IP|TF_STATIC, 1, 1, "siaddr" }, - { doff(giaddr), TT_IP|TF_STATIC|TF_RO, 1, 1, "giaddr" }, - { doff(chaddr), TT_OCTET|TF_STATIC|TF_RO, 1, 16, "chaddr" }, - { doff(sname), TT_ASCII|TF_STATIC, 1, 64, "sname" }, - { doff(file), TT_ASCII|TF_STATIC, 1, 128, "file" }, -}; -#define N_STATIC arraysize(statictag) - -static tagdef_t alltagdef[N_STATIC + 254]; /* List of tag definitions. */ -#define tagdef (alltagdef+N_STATIC-1) /* Just the optional ones. */ - -#define tagdefined(tp) ((tp)->name != nil) - -static void inittagdef(void) -{ - /* Initialize the tag definitions from the "tag" commands in the config - * file. - */ - int t; - tagdef_t *tp; - static tagdef_t predef[] = { - { DHCP_TAG_NETMASK, TT_IP, 1, 1, "netmask" }, - { DHCP_TAG_GATEWAY, TT_IP, 1, 255, "gateway" }, - { DHCP_TAG_DNS, TT_IP, 1, 255, "DNSserver" }, - }; - static char *typenames[] = { "ascii", "boolean", "ip", "number", "octet" }; - config_t *cfg; - static u8_t rotags[] = { - DHCP_TAG_REQIP, DHCP_TAG_OVERLOAD, DHCP_TAG_TYPE, DHCP_TAG_SERVERID, - DHCP_TAG_REQPAR, DHCP_TAG_MESSAGE, DHCP_TAG_MAXDHCP - }; - - for (t= 1; t <= 254; t++) { - tp= &tagdef[t]; - tp->tag= t; - tp->type= TT_OCTET; - tp->name= nil; - } - - /* Set the static and "all Minix needs" tags. */ - memcpy(alltagdef, statictag, sizeof(statictag)); - for (tp= predef; tp < arraylimit(predef); tp++) tagdef[tp->tag] = *tp; - - /* Search for tag definitions in the config file. */ - for (cfg= dhcpconf; cfg != nil; cfg= cfg->next) { - config_t *cmd= cfg->list; - - if (strcasecmp(cmd->word, "tag") == 0) { - if (config_length(cmd) == 6 - && (cmd->next->flags & CFG_DULONG) - && config_isatom(cmd->next->next) - && config_isatom(cmd->next->next->next) - && (cmd->next->next->next->next->flags & CFG_DULONG) - && (cmd->next->next->next->next->next->flags & CFG_DULONG) - ) { - unsigned long tag, gran, max; - const char *name, *typename; - unsigned type; - - tag= strtoul(cmd->next->word, nil, 10); - name= cmd->next->next->word; - typename= cmd->next->next->next->word; - gran= strtoul(cmd->next->next->next->next->word, nil, 10); - max= strtoul(cmd->next->next->next->next->next->word, nil, 10); - - for (type= 0; type < arraysize(typenames); type++) { - if (strcasecmp(typename, typenames[type]) == 0) break; - } - - if (!(1 <= tag && tag <= 254) - || !(type < arraysize(typenames)) - || !((type == TT_NUMBER - && (gran == 1 || gran == 2 || gran == 4)) - || (type != TT_NUMBER && 1 <= gran && gran <= 16)) - || !(max <= 255) - ) { - fprintf(stderr, - "\"%s\", line %u: Tag definition is incorrect\n", - cmd->file, cmd->line); - exit(1); - } - - tp= &tagdef[(int)tag]; - tp->type= type; - tp->name= name; - tp->gran= gran; - tp->max= max; - } else { - fprintf(stderr, - "\"%s\", line %u: Usage: tag number name type granularity max\n", - cmd->file, cmd->line); - exit(1); - } - } - } - - /* Many DHCP tags are not for the user to play with. */ - for (t= 0; t < arraysize(rotags); t++) tagdef[rotags[t]].type |= TF_RO; -} - -static tagdef_t *tagdefbyname(const char *name) -{ - /* Find a tag definition by the name of the tag. Return null if not - * defined. - */ - tagdef_t *tp; - - for (tp= alltagdef; tp < arraylimit(alltagdef); tp++) { - if (tagdefined(tp) && strcasecmp(tp->name, name) == 0) return tp; - } - return nil; -} - -void initdhcpconf(void) -{ - /* Read/refresh configuration from the DHCP configuration file. */ - dhcpconf= config_read(configfile, 0, dhcpconf); - if (config_renewed(dhcpconf)) inittagdef(); -} - -static void configtag(dhcp_t *dp, config_t *cmd, ipaddr_t ifip) -{ - /* Add a tag to a DHCP packet from the config file. */ - tagdef_t *tp; - u8_t data[260], *d; - size_t i; - int delete= 0; - - if (strcasecmp(cmd->word, "no") == 0) { - if (config_length(cmd) != 2 || !config_isatom(cmd->next)) { - fprintf(stderr, "\"%s\", line %u: Usage: no tag-name\n", - cmd->file, cmd->line); - exit(1); - } - cmd= cmd->next; - delete= 1; - } - - if ((tp= tagdefbyname(cmd->word)) == nil) { - fprintf(stderr, "\"%s\", line %u: Unknown tag '%s'\n", - cmd->file, cmd->line, cmd->word); - exit(1); - } - - if (tp->type & TF_RO) { - fprintf(stderr, "\"%s\", line %u: Tag '%s' can't be configured\n", - cmd->file, cmd->line, cmd->word); - exit(1); - } - - i= 0; - d= data; - if (!delete) { - config_t *arg= cmd->next; - do { - switch (tp->type & TF_TYPE) { - case TT_ASCII: { - if (arg == nil || !config_isatom(arg) || arg->next != nil) { - fprintf(stderr, "\"%s\", line %u: Usage: %s string\n", - cmd->file, cmd->line, cmd->word); - exit(1); - } - strncpy((char *) data, arg->word, sizeof(data)); - d += i = strnlen((char *) data, sizeof(data)); - break;} - case TT_BOOLEAN: { - if (arg == nil || !config_isatom(arg) - || !(strcasecmp(arg->word, "false") == 0 - || strcasecmp(arg->word, "true") == 0) - ) { - fprintf(stderr, - "\"%s\", line %u: Usage: %s false|true ...\n", - cmd->file, cmd->line, cmd->word); - exit(1); - } - if (d < arraylimit(data)) { - *d++ = (arg->word[0] != 'f' && arg->word[0] != 'F'); - } - i++; - break;} - case TT_IP: { - ipaddr_t ip; - unsigned long len; - char *end; - - if (arg == nil || !config_isatom(arg)) { - fprintf(stderr, "\"%s\", line %u: Usage: %s host ...\n", - cmd->file, cmd->line, cmd->word); - exit(1); - } - if (arg->word[0] == '/' - && between(1, len= strtoul(arg->word+1, &end, 10), 31) - && *end == 0 - ) { - ip= htonl((0xFFFFFFFFUL << (32-len)) & 0xFFFFFFFFUL); - } else - if (!name2ip(&ip, arg->word, ifip)) { - fprintf(stderr, - "\"%s\", line %u: Can't translate %s to an IP address\n", - arg->file, arg->line, arg->word); - exit(1); - } - if (d <= arraylimit(data) - sizeof(ip)) { - memcpy(d, &ip, sizeof(ip)); - d += sizeof(ip); - } - i++; - break;} - case TT_NUMBER: { - unsigned long n; - int g; - - if (arg == nil || !(arg->flags & CFG_CLONG)) { - fprintf(stderr, "\"%s\", line %u: Usage: %s number ...\n", - cmd->file, cmd->line, cmd->word); - exit(1); - } - n= strtoul(arg->word, nil, 0); - g= tp->gran; - do { - if (d <= arraylimit(data)) *d++ = (n >> (--g * 8)) & 0xFF; - } while (g != 0); - i++; - break;} - case TT_OCTET: { - if (arg == nil || !config_isatom(arg) || arg->next != nil) { - fprintf(stderr, "\"%s\", line %u: Usage: %s hexdigits\n", - cmd->file, cmd->line, cmd->word); - exit(1); - } - i= ascii2octet(data, sizeof(data), arg->word); - if (i == -1) { - fprintf(stderr, - "\"%s\", line %u: %s: Bad hexdigit string\n", - arg->file, arg->line, arg->word); - exit(1); - } - d= data + i; - break;} - } - } while ((arg= arg->next) != nil); - - if (d > data + 255) { - fprintf(stderr, "\"%s\", line %u: Tag value is way too big\n", - cmd->file, cmd->line); - exit(1); - } - if ((tp->type & TF_TYPE) != TT_NUMBER && (i % tp->gran) != 0) { - fprintf(stderr, - "\"%s\", line %u: Expected a multiple of %d initializers\n", - cmd->file, cmd->line, tp->gran); - exit(1); - } - if (tp->max != 0 && i > tp->max) { - fprintf(stderr, - "\"%s\", line %u: Got %d initializers, can have only %d\n", - cmd->file, cmd->line, (int) i, tp->max); - exit(1); - } - } - if (tp->type & TF_STATIC) { - size_t len= tp->gran * tp->max; - if ((tp->type & TF_TYPE) == TT_IP) len *= sizeof(ipaddr_t); - memset(B(dp) + tp->tag, 0, len); - memcpy(B(dp) + tp->tag, data, (d - data)); - } else { - settag(dp, tp->tag, data, (d - data)); - } -} - -int makedhcp(dhcp_t *dp, u8_t *class, size_t calen, u8_t *client, size_t cilen, - ipaddr_t ip, ipaddr_t ifip, network_t *np) -{ - /* Fill in a DHCP packet at 'dp' for the host identified by the - * (class, client, ip) combination. Makedhcp is normally called twice, - * once to find the IP address (so ip == 0) and once again to find all - * data that goes with that IP address (ip != 0). On the first call the - * return value of this function should be ignored and only 'yiaddr' - * checked and used as 'ip' on the next pass. True is returned iff there - * is information for the client on the network at interface address - * 'ifip', by checking if the 'ip' and 'ifip' are on the same network. - * If np is nonnull then we are working for one of our own interfaces, so - * options can be set and adjourning interfaces can be programmed. - */ - config_t *todo[16]; - size_t ntodo= 0; - ipaddr_t hip, mask; - u8_t *pmask; - char *hostname; - u32_t distance= -1; - - initdhcpconf(); - - /* Start creating a packet. */ - dhcp_init(dp); - dp->op= DHCP_BOOTREPLY; - - /* The initial TODO list is the whole DHCP config. */ - todo[ntodo++]= dhcpconf; - - while (ntodo > 0) { - config_t *cmd, *follow; - - if (todo[ntodo-1] == nil) { ntodo--; continue; } - cmd= todo[ntodo-1]->list; - todo[ntodo-1]= todo[ntodo-1]->next; - - follow= nil; /* Macro or list to follow next? */ - - if (strcasecmp(cmd->word, "client") == 0) { - u8_t cfgid[CLID_MAX]; - size_t cfglen; - char *name; - int ifno; - u32_t d; - - if (between(3, config_length(cmd), 5) - && config_isatom(cmd->next) - && (cfglen= ascii2clid(cfgid, cmd->next->word)) != -1 - && config_isatom(cmd->next->next) - && (((ifno= ifname2if(cmd->next->next->word)) == -1 - && config_length(cmd) <= 4) - || ((ifno= ifname2if(cmd->next->next->word)) != -1 - && config_length(cmd) >= 4 - && config_isatom(cmd->next->next->next))) - ) { - if (cilen == cfglen && memcmp(client, cfgid, cilen) == 0 - && (ifno == -1 || np == nil || ifno == np->n) - ) { - config_t *atname= cmd->next->next; - if (ifno != -1) atname= atname->next; - name= (char *)atname->word; - - if (name2ip(&hip, name, ifip) && (ip == 0 || ip == hip)) { - d= ntohl(hip) ^ ntohl(ifip); - if (d < distance) { - dp->yiaddr= hip; - follow= atname->next; - distance= d; - } - } - } - } else { - fprintf(stderr, - "\"%s\", line %u: Usage: client ID [ip#] host [macro|{params}]\n", - cmd->file, cmd->line); - exit(1); - } - } else - if (strcasecmp(cmd->word, "class") == 0) { - config_t *clist; - int match; - - match= 0; - for (clist= cmd->next; clist != nil - && clist->next != nil - && config_isatom(clist); clist= clist->next) { - if (calen > 0 - && strncmp(clist->word, (char *) class, calen) == 0 - ) { - match= 1; - } - } - if (clist == cmd->next || clist->next != nil) { - fprintf(stderr, - "\"%s\", line %u: Usage: class class-name ... macro|{params}\n", - cmd->file, cmd->line); - } - if (match) follow= clist; - } else - if (strcasecmp(cmd->word, "host") == 0) { - if (config_length(cmd) == 3 - && config_isatom(cmd->next) - ) { - if (ip != 0) { - if (cidr_aton(cmd->next->word, &hip, &mask)) { - if (((hip ^ ip) & mask) == 0) { - if (!gettag(dp, DHCP_TAG_NETMASK, nil, nil)) { - settag(dp, DHCP_TAG_NETMASK, - &mask, sizeof(mask)); - } - dp->yiaddr= ip; - follow= cmd->next->next; - } - } else - if (name2ip(&hip, cmd->next->word, ifip)) { - if (hip == ip) { - dp->yiaddr= ip; - follow= cmd->next->next; - } - } - } - } else { - fprintf(stderr, - "\"%s\", line %u: Usage: host host-spec macro|{params}\n", - cmd->file, cmd->line); - exit(1); - } - } else - if (strcasecmp(cmd->word, "interface") == 0) { - if (between(3, config_length(cmd), 4) - && config_isatom(cmd->next) - && config_isatom(cmd->next->next) - ) { - network_t *ifnp; - - if (np != nil) { - if ((ifnp= if2net(ifname2if(cmd->next->word))) == nil) { - fprintf(stderr, - "\"%s\", line %u: Can't find interface %s\n", - cmd->next->file, cmd->next->line, cmd->next->word); - exit(1); - } - if (!name2ip(&hip, cmd->next->next->word, 0)) { - fprintf(stderr, - "\"%s\", line %u: Can't find IP address of %s\n", - cmd->next->next->file, cmd->next->next->line, - cmd->next->next->word); - exit(1); - } - ifnp->ip= hip; - if (ifnp == np) { - dp->yiaddr= hip; - follow= cmd->next->next->next; - } - } - } else { - fprintf(stderr, - "\"%s\", line %u: Usage: interface ip# host%s\n", - cmd->file, cmd->line, ntodo==1 ? " [macro|{params}]" : ""); - exit(1); - } - } else - if (strcasecmp(cmd->word, "macro") == 0) { - if (config_length(cmd) == 2 && config_isatom(cmd->next)) { - follow= cmd->next; - } else - if (ntodo > 1) { - fprintf(stderr, "\"%s\", line %u: Usage: macro macro-name\n", - cmd->file, cmd->line); - exit(1); - } - } else - if (strcasecmp(cmd->word, "tag") == 0) { - if (ntodo > 1) { - fprintf(stderr, - "\"%s\", line %u: A %s can't be defined here\n", - cmd->file, cmd->line, cmd->word); - exit(1); - } - } else - if (strcasecmp(cmd->word, "option") == 0) { - int ifno; - network_t *ifnp; - config_t *opt; - - if ((opt= cmd->next) != nil - && config_isatom(opt) - && (ifno= ifname2if(opt->word)) != -1 - ) { - if ((ifnp= if2net(ifno)) == nil) { - fprintf(stderr, - "\"%s\", line %u: Interface %s is not enabled\n", - opt->file, opt->line, opt->word); - exit(1); - } - opt= opt->next; - } else { - ifnp= np; - } - - if (between(1, config_length(opt), 2) - && config_isatom(opt) - && strcasecmp(opt->word, "server") == 0 - && (opt->next == nil - || strcasecmp(opt->next->word, "inform") == 0) - ) { - if (np != nil) { - ifnp->flags |= NF_SERVING; - if (opt->next != nil) ifnp->flags |= NF_INFORM; - } - } else - if (config_length(opt) == 2 - && config_isatom(opt) - && strcasecmp(opt->word, "relay") == 0 - && config_isatom(opt->next) - ) { - if (np != nil) { - if (!name2ip(&hip, opt->next->word, ifip)) { - fprintf(stderr, - "\"%s\", line %u: Can't find IP address of %s\n", - opt->next->file, opt->next->line, - opt->next->word); - exit(1); - } - ifnp->flags |= NF_RELAYING; - ifnp->server= hip; - } - } else - if (config_length(opt) == 1 - && config_isatom(opt) - && strcasecmp(opt->word, "possessive") == 0 - ) { - if (np != nil) ifnp->flags |= NF_POSSESSIVE; - } else - if (config_length(opt) == 2 - && config_isatom(opt) - && strcasecmp(opt->word, "hostname") == 0 - && config_isatom(opt->next) - ) { - if (np != nil) np->hostname= opt->next->word; - } else { - fprintf(stderr, "\"%s\", line %u: Unknown option\n", - cmd->file, cmd->line); - exit(1); - } - } else { - /* Must be an actual data carrying tag. */ - configtag(dp, cmd, ifip); - } - - if (follow != nil) { - /* A client/class/host entry selects a macro or list that must - * be followed next. - */ - config_t *macro; - - if (config_isatom(follow)) { /* Macro name */ - config_t *cfg; - - for (cfg= dhcpconf; cfg != nil; cfg= cfg->next) { - macro= cfg->list; - - if (strcasecmp(macro->word, "macro") == 0) { - if (config_length(macro) == 3 - && config_isatom(macro->next) - && config_issub(macro->next->next) - ) { - if (strcasecmp(macro->next->word, follow->word) == 0 - ) { - break; - } - } else { - fprintf(stderr, - "\"%s\", line %u: Usage: macro macro-name {params}\n", - macro->file, macro->line); - } - } - } - follow= cfg == nil ? nil : macro->next->next->list; - } else { - /* Simply a list of more tags and stuff. */ - follow= follow->list; - } - - if (ntodo == arraysize(todo)) { - fprintf(stderr, "\"%s\", line %u: Nesting is too deep\n", - follow->file, follow->line); - exit(1); - } - todo[ntodo++]= follow; - } - } - - /* Check if the IP and netmask are OK for the interface. */ - if (!gettag(dp, DHCP_TAG_NETMASK, &pmask, nil)) return 0; - memcpy(&mask, pmask, sizeof(mask)); - if (((ip ^ ifip) & mask) != 0) return 0; - - /* Fill in the hostname and/or domain. */ - if ((hostname= ip2name(ip)) != nil) { - char *domain; - - if ((domain= strchr(hostname, '.')) != nil) *domain++ = 0; - - if (!gettag(dp, DHCP_TAG_HOSTNAME, nil, nil)) { - settag(dp, DHCP_TAG_HOSTNAME, hostname, strlen(hostname)); - } - - if (domain != nil && !gettag(dp, DHCP_TAG_DOMAIN, nil, nil)) { - settag(dp, DHCP_TAG_DOMAIN, domain, strlen(domain)); - } - } - - return 1; -} - -static char *dhcpopname(int op) -{ - static char *onames[] = { "??\?", "REQUEST", "REPLY" }; - return onames[op < arraysize(onames) ? op : 0]; -} - -char *dhcptypename(int type) -{ - static char *tnames[] = { - "??\?", "DISCOVER", "OFFER", "REQUEST", "DECLINE", - "ACK", "NAK", "RELEASE", "INFORM" - }; - return tnames[type < arraysize(tnames) ? type : 0]; -} - -void printdhcp(dhcp_t *dp) -{ - /* Print the contents of a DHCP packet, usually for debug purposes. */ - tagdef_t *tp; - u8_t *data, *ovld; - size_t i, len; - - for (tp= alltagdef; tp < arraylimit(alltagdef); tp++) { - if (tp->type & TF_STATIC) { - data= B(dp) + tp->tag; - len= tp->gran * tp->max; - if ((tp->type & TF_TYPE) == TT_IP) len *= sizeof(ipaddr_t); - if (tp->tag == doff(chaddr)) len= dp->hlen; - - /* Don't show uninteresting stuff. */ - if (tp->tag == doff(htype) && dp->htype == DHCP_HTYPE_ETH) continue; - - if (tp->tag == doff(hlen) && dp->hlen == DHCP_HLEN_ETH) continue; - - if ((tp->tag == doff(file) || tp->tag == doff(sname)) - && gettag(dp, DHCP_TAG_OVERLOAD, &ovld, nil) - && (ovld[0] & (tp->tag == doff(file) ? 1 : 2)) - ) { - continue; - } - for (i= 0; i < len && data[i] == 0; i++) {} - if (i == len) continue; - } else { - if (!gettag(dp, tp->tag, &data, &len)) continue; - } - - if (tagdefined(tp)) { - printf("\t%s =", tp->name); - } else { - printf("\tT%d =", tp->tag); - } - - i= 0; - while (i < len) { - switch (tp->type & TF_TYPE) { - case TT_ASCII: { - printf(" \"%.*s\"", (int) len, data); - i= len; - break;} - case TT_BOOLEAN: { - printf(data[i++] == 0 ? " false" : " true"); - break;} - case TT_IP: { - ipaddr_t ip; - memcpy(&ip, data+i, sizeof(ip)); - printf(" %s", inet_ntoa(*(struct in_addr *)&ip)); - i += sizeof(ip); - break;} - case TT_NUMBER: { - u32_t n= 0; - int g= tp->gran; - - do n= (n << 8) | data[i++]; while (--g != 0); - printf(" %lu", (unsigned long) n); - if ((tp->type & TF_STATIC) && tp->tag == doff(op)) { - printf(" (%s)", dhcpopname(n)); - } - if (!(tp->type & TF_STATIC) && tp->tag == DHCP_TAG_TYPE) { - printf(" (%s)", dhcptypename(n)); - } - break;} - case TT_OCTET: { - if (i == 0) fputc(' ', stdout); - printf("%02X", data[i++]); - break;} - } - } - fputc('\n', stdout); - } -} diff --git a/minix/include/minix/paths.h b/minix/include/minix/paths.h index 8e0de4542..87f4fc064 100644 --- a/minix/include/minix/paths.h +++ b/minix/include/minix/paths.h @@ -8,11 +8,6 @@ #define _PATH_SYSTEM_CONF_DIR "/etc/system.conf.d" #define _PATH_SYSTEM_CONF_PKG_DIR "/usr/pkg/etc/system.conf.d" -#define _PATH_DHCPCONF "/etc/dhcp.conf" -#define _PATH_DHCPPID "/usr/run/dhcpd.pid" -#define _PATH_DHCPCACHE "/usr/adm/dhcp.cache" -#define _PATH_DHCPPOOL "/usr/adm/dhcp.pool" - #define _PATH_RAMDISK "/dev/ram" #define _PATH_DRIVERS "/service" diff --git a/minix/lib/libc/gen/dhcp_gettag.c b/minix/lib/libc/gen/dhcp_gettag.c deleted file mode 100644 index 3dcb6e827..000000000 --- a/minix/lib/libc/gen/dhcp_gettag.c +++ /dev/null @@ -1,55 +0,0 @@ -/* dhcp_gettag() Author: Kees J. Bot - * 1 Dec 2000 - */ -#define nil ((void*)0) -#include -#include -#include -#include -#include -#include - -#define arraysize(a) (sizeof(a) / sizeof((a)[0])) - -int dhcp_gettag(dhcp_t *dp, int searchtag, u8_t **pdata, size_t *plen) -{ - /* Find a tag in the options field, or possibly in the file or sname - * fields. Return true iff found, and return the data and/or length if - * their pointers are non-null. - */ - u8_t *p; - u8_t *optfield[3]; - size_t optlen[3]; - int i, tag, len; - - /* The DHCP magic number must be correct, or no tags. */ - if (dp->magic != DHCP_MAGIC) return 0; - - optfield[0]= dp->options; - optlen[0]= arraysize(dp->options); - optfield[1]= dp->file; - optlen[1]= 0; /* Unknown if used for options yet. */ - optfield[2]= dp->sname; - optlen[2]= 0; - - for (i= 0; i < 3; i++) { - p= optfield[i]; - while (p < optfield[i] + optlen[i]) { - tag= *p++; - if (tag == 255) break; - len= tag == 0 ? 0 : *p++; - if (tag == searchtag) { - if (pdata != nil) *pdata= p; - if (plen != nil) *plen= len; - return 1; - } - if (tag == DHCP_TAG_OVERLOAD) { - /* There are also options in the file or sname field. */ - if (*p & 1) optlen[1]= arraysize(dp->file); - if (*p & 2) optlen[1]= arraysize(dp->sname); - } - p += len; - } - } - return 0; -} diff --git a/minix/lib/libc/gen/dhcp_settag.c b/minix/lib/libc/gen/dhcp_settag.c deleted file mode 100644 index 7cba82d50..000000000 --- a/minix/lib/libc/gen/dhcp_settag.c +++ /dev/null @@ -1,57 +0,0 @@ -/* dhcp_init(), dhcp_settag() Author: Kees J. Bot - * 1 Dec 2000 - */ -#define nil ((void*)0) -#include -#include -#include -#include -#include -#include - -#define arraysize(a) (sizeof(a) / sizeof((a)[0])) -#define arraylimit(a) ((a) + arraysize(a)) - -void dhcp_init(dhcp_t *dp) -{ - /* Initialize a DHCP packet. */ - memset(dp, 0, offsetof(dhcp_t, magic)); - dp->magic= DHCP_MAGIC; - memset(dp->options, 255, sizeof(dp->options)); -} - -int dhcp_settag(dhcp_t *dp, int tag, void *data, size_t len) -{ - /* Add a tag to a DHCP packet. No padding. Only do the options field. - * (This is Minix, we don't need megabytes of silly bits of data.) - * The length may be zero to delete a tag. - */ - u8_t *p; - int n; - - if (tag <= 0 || tag >= 255) return 0; - - for (p= dp->options; p < arraylimit(dp->options) && *p != 255; p += n) { - n= 1 + 1 + p[1]; - if (*p == tag) { - /* The tag is already there, remove it so it gets replaced. */ - memmove(p, p + n, arraylimit(dp->options) - (p + n)); - memset(arraylimit(dp->options) - n, 255, n); - n= 0; - } - } - - /* Add tag. */ - if (len == 0) { - /* We're merely deleting a tag. */ - } else - if (p + 1 + 1 + len <= arraylimit(dp->options)) { - *p++ = tag; - *p++ = len; - memcpy(p, data, len); - } else { - /* Oops, it didn't fit? Is this really Minix??? */ - return 0; - } - return 1; -} diff --git a/minix/man/man5/configfile.5 b/minix/man/man5/configfile.5 index e9e151fdc..30cbb315e 100644 --- a/minix/man/man5/configfile.5 +++ b/minix/man/man5/configfile.5 @@ -71,9 +71,6 @@ A file that doesn't exist is seen as empty. .PP A generic configuration file can be read with the functions described in .BR configfile (3). -.SH EXAMPLES -Have a look at -.BR /etc/dhcp.conf . .SH "SEE ALSO" .BR configfile (3). .SH NOTES