Skip to content

Commit

Permalink
Fix dhcpd handling with respect to rdoamins
Browse files Browse the repository at this point in the history
Run dhcpd in the correct rdomain when rdomain is != 0 and start dhcpd with
a list of interfaces on its command line. All interfaces must be in the
same rdomain; dhcpd will then set its own rdomain accordingly.

Use a separate DHCP lease database per rdomain just in case a given MAC
and IP tuple appears in multiple rdomains.

earlier version ok + testing by Tom
  • Loading branch information
stspdotname committed Sep 15, 2023
1 parent 85c6a75 commit dd054fe
Showing 1 changed file with 86 additions and 2 deletions.
88 changes: 86 additions & 2 deletions ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/syslimits.h>
#include <net/if.h>
#include "externs.h"
#include "editing.h"
#include "ctl.h"
Expand Down Expand Up @@ -87,6 +88,7 @@ void edit_crontab(char *);
void install_crontab(char *);
void edit_motd(char *);
void call_editor(char *, char **, char *);
void start_dhcpd(char *, char *, char *, char *, char *);
int edit_file(char *, mode_t, char *, char **);
void ctl_symlink(char *, char *, char *);
int rule_writeline(char *, mode_t, char *);
Expand Down Expand Up @@ -437,8 +439,8 @@ struct ctl ctl_nppp[] = {
/* dhcpd */
struct ctl2 ctl_dhcp[] = {
{ "enable", "enable DHCPd daemon",
{ DHCPD, "-c", REQTEMP, "-l", DHCPLEASES, NULL }, { NULL, }, NULL,
DB_X_ENABLE, T_EXEC },
{ DHCPD, "-c", REQTEMP, "-l", DHCPLEASES, NULL }, { NULL, },
start_dhcpd, DB_X_ENABLE, T_HANDLER },
{ "disable", "disable DHCPd daemon",
{ PKILL, table, "dhcpd", NULL }, { NULL, }, NULL,
DB_X_DISABLE, T_EXEC },
Expand Down Expand Up @@ -1180,3 +1182,85 @@ rmtemp(char *file)
printf("%% Unable to remove temporary file %s: %s\n",
file, strerror(errno));
}

void
start_dhcpd(char *arg0, char *arg1, char *arg2, char *arg3, char *arg4)
{
struct if_nameindex *ifn_list, *ifnp;
char **dhcpd_args = NULL;
size_t niface = 0;
int ifs, i;
char leasedb[PATH_MAX];

/*
* For rdomains other than zero dhcpd(8) expects a list of
* interfaces on its command line. If no interface arguments
* are given then dhcpd will move itself into rdomain zero
* so we really must specify a list here.
*
* All named interfaces must be part of the same rdomain. We
* provide the list of all interfaces in our current rdomain.
* dhcpd will listen on any with matching subnets in dhcpd.conf.
*/
if ((ifn_list = if_nameindex()) == NULL) {
printf("%% %s: if_nameindex failed\n", __func__);
return;
}

if ((ifs = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("%% %s socket: %s\n", __func__, strerror(errno));
goto done;
}

for (ifnp = ifn_list; ifnp->if_name != NULL; ifnp++) {
int flags, rdomain;

flags = get_ifflags(ifnp->if_name, ifs);
if ((flags & IFF_LOOPBACK) ||
(flags & IFF_POINTOPOINT) ||
(!(flags & IFF_BROADCAST)))
continue;

rdomain = get_rdomain(ifs, ifnp->if_name);
if (rdomain == cli_rtable)
niface++;
}

dhcpd_args = calloc(5 + niface + 1, sizeof(char *));
if (dhcpd_args == NULL) {
printf("%% calloc: %s\n", strerror(errno));
goto done;
}

i = 0;
dhcpd_args[i++] = arg0; /* dhcpd */
dhcpd_args[i++] = arg1; /* -c */
dhcpd_args[i++] = arg2; /* dhcpd.conf */
dhcpd_args[i++] = arg3; /* -l */
if (cli_rtable != 0) {
snprintf(leasedb, sizeof(leasedb), "%s.%d",
arg4, cli_rtable);
dhcpd_args[i++] = leasedb; /* rdomain's leasedb */
} else
dhcpd_args[i++] = arg4; /* default leasedb */

for (ifnp = ifn_list; ifnp->if_name != NULL; ifnp++) {
int flags, rdomain;

flags = get_ifflags(ifnp->if_name, ifs);
if ((flags & IFF_LOOPBACK) ||
(flags & IFF_POINTOPOINT) ||
(!(flags & IFF_BROADCAST)))
continue;

rdomain = get_rdomain(ifs, ifnp->if_name);
if (rdomain == cli_rtable)
dhcpd_args[i++] = ifnp->if_name;
}
dhcpd_args[i] = NULL;

cmdargs(arg0, dhcpd_args);
done:
if_freenameindex(ifn_list);
free(dhcpd_args);
}

1 comment on commit dd054fe

@smytht
Copy link
Collaborator

@smytht smytht commented on dd054fe Sep 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense thanks Stefan

Please sign in to comment.