summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2010-04-19 12:22:10 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2010-04-19 12:22:10 +0000
commitc5112d7897b7a8b6c502d01dae6bd9dda00da84a (patch)
tree5acafccfa401f6711681837b491aa29dd20e9991
parentc78894bd18254ceb895a2d7e8dff8d1c36ebd286 (diff)
If interfaces are specified, get their rdomain and bind dhcpd into the same
domain with setrdomain(). This allows to run dhcpd on multiple rdomains. OK krw@
-rw-r--r--usr.sbin/dhcpd/dhcpd.c18
-rw-r--r--usr.sbin/dhcpd/dhcpd.h4
-rw-r--r--usr.sbin/dhcpd/dispatch.c37
3 files changed, 47 insertions, 12 deletions
diff --git a/usr.sbin/dhcpd/dhcpd.c b/usr.sbin/dhcpd/dhcpd.c
index da47b598910..dc2fa85a51c 100644
--- a/usr.sbin/dhcpd/dhcpd.c
+++ b/usr.sbin/dhcpd/dhcpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.c,v 1.38 2008/05/29 19:02:47 deraadt Exp $ */
+/* $OpenBSD: dhcpd.c,v 1.39 2010/04/19 12:22:09 claudio Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@cvs.openbsd.org>
@@ -71,7 +71,7 @@ struct syslog_data sdata = SYSLOG_DATA_INIT;
int
main(int argc, char *argv[])
{
- int ch, cftest = 0, daemonize = 1;
+ int ch, cftest = 0, daemonize = 1, rdomain = -1;
extern char *__progname;
char *sync_iface = NULL;
char *sync_baddr = NULL;
@@ -168,17 +168,21 @@ main(int argc, char *argv[])
if (cftest)
exit(0);
+ db_startup();
+ discover_interfaces(&rdomain);
+
+ if (rdomain != -1)
+ if (setrdomain(rdomain) == -1)
+ error("setrdomain (%m)");
+
+ icmp_startup(1, lease_pinged);
+
if (syncsend || syncrecv) {
syncfd = sync_init(sync_iface, sync_baddr, sync_port);
if (syncfd == -1)
err(1, "sync init");
}
- db_startup();
- discover_interfaces();
- icmp_startup(1, lease_pinged);
-
-
if ((pw = getpwnam("_dhcp")) == NULL)
error("user \"_dhcp\" not found");
diff --git a/usr.sbin/dhcpd/dhcpd.h b/usr.sbin/dhcpd/dhcpd.h
index 2614f73e245..075d8222ad0 100644
--- a/usr.sbin/dhcpd/dhcpd.h
+++ b/usr.sbin/dhcpd/dhcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.h,v 1.44 2010/01/02 04:21:16 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.45 2010/04/19 12:22:09 claudio Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998, 1999
@@ -625,7 +625,7 @@ extern struct protocol *protocols;
extern void (*bootp_packet_handler)(struct interface_info *,
struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *);
extern struct dhcpd_timeout *timeouts;
-void discover_interfaces(void);
+void discover_interfaces(int *);
void dispatch(void);
int locate_network(struct packet *);
void got_one(struct protocol *);
diff --git a/usr.sbin/dhcpd/dispatch.c b/usr.sbin/dhcpd/dispatch.c
index dae45e2713e..ff431c85fcb 100644
--- a/usr.sbin/dhcpd/dispatch.c
+++ b/usr.sbin/dhcpd/dispatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dispatch.c,v 1.25 2010/01/02 04:21:16 krw Exp $ */
+/* $OpenBSD: dispatch.c,v 1.26 2010/04/19 12:22:09 claudio Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998, 1999
@@ -56,6 +56,7 @@ void (*bootp_packet_handler)(struct interface_info *,
struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *);
static int interface_status(struct interface_info *ifinfo);
+int get_rdomain(char *);
/* Use getifaddrs() to get a list of all the attached interfaces.
For each interface that's of type INET and not the loopback interface,
@@ -63,14 +64,14 @@ static int interface_status(struct interface_info *ifinfo);
subnet it's on, and add it to the list of interfaces. */
void
-discover_interfaces(void)
+discover_interfaces(int *rdomain)
{
struct interface_info *tmp;
struct interface_info *last, *next;
struct subnet *subnet;
struct shared_network *share;
struct sockaddr_in foo;
- int ir = 0;
+ int ir = 0, ird;
struct ifreq *tif;
struct ifaddrs *ifap, *ifa;
@@ -83,6 +84,9 @@ discover_interfaces(void)
*/
if (interfaces != NULL)
ir = 1;
+ else
+ /* must specify an interface when rdomains are used */
+ *rdomain = 0;
/* Cycle through the list of interfaces looking for IP addresses. */
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
@@ -106,6 +110,15 @@ discover_interfaces(void)
if (tmp == NULL && ir)
continue;
+ ird = get_rdomain(ifa->ifa_name);
+ if (*rdomain == -1)
+ *rdomain = ird;
+ else if (*rdomain != ird && ir)
+ error("Interface %s is not in rdomain %d",
+ tmp->name, *rdomain);
+ else if (*rdomain != ird && !ir)
+ continue;
+
/* If there isn't already an interface by this name,
allocate one. */
if (tmp == NULL) {
@@ -608,3 +621,21 @@ remove_protocol(struct protocol *proto)
}
}
}
+
+int
+get_rdomain(char *name)
+{
+ int rv = 0, s;
+ struct ifreq ifr;
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ error("get_rdomain socket: %m");
+
+ bzero(&ifr, sizeof(ifr));
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFRTABLEID, (caddr_t)&ifr) != -1)
+ rv = ifr.ifr_rdomainid;
+
+ close(s);
+ return rv;
+}