aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremie Corbier <jeremie.corbier@resel.enst-bretagne.fr>2008-12-29 08:50:16 +0100
committerBjørn Mork <bjorn@mork.no>2010-08-06 15:37:37 +0200
commitfbf66aa98a358cd35f58844e59e420534f36cac4 (patch)
tree870802d187f57b7310d4baa48b50c382d9f3f62f
parent35a72f9708bccef6092e37cdb2e31faf7ec04803 (diff)
200_dhcp6c-profiles.diff from the Debian package version 20080615-8:
"This patch enables users to define interface profiles so one can configure a group of interfaces the same way without having to provide an interface statement for each."
-rw-r--r--cfparse.y23
-rw-r--r--cftoken.l10
-rw-r--r--config.c334
-rw-r--r--config.h3
-rw-r--r--dhcp6c.89
-rw-r--r--dhcp6c.c5
-rw-r--r--dhcp6c.conf.57
7 files changed, 245 insertions, 146 deletions
diff --git a/cfparse.y b/cfparse.y
index dcac3d7..c79d131 100644
--- a/cfparse.y
+++ b/cfparse.y
@@ -83,6 +83,7 @@ extern void yyerror __P((char *, ...))
} while (0)
static struct cf_namelist *iflist_head, *hostlist_head, *iapdlist_head;
+static struct cf_namelist *profilelist_head;
static struct cf_namelist *addrpoollist_head;
static struct cf_namelist *authinfolist_head, *keylist_head;
static struct cf_namelist *ianalist_head;
@@ -102,6 +103,7 @@ static void cleanup_cflist __P((struct cf_list *));
%}
%token INTERFACE IFNAME
+%token PROFILE PROFILENAME
%token PREFIX_INTERFACE SLA_ID SLA_LEN DUID_ID
%token ID_ASSOC IA_PD IAID IA_NA
%token ADDRESS
@@ -133,7 +135,7 @@ static void cleanup_cflist __P((struct cf_list *));
}
%type <str> IFNAME HOSTNAME AUTHNAME KEYNAME DUID_ID STRING QSTRING IAID
-%type <str> POOLNAME
+%type <str> POOLNAME PROFILENAME
%type <num> NUMBER duration authproto authalg authrdm
%type <list> declaration declarations dhcpoption ifparam ifparams
%type <list> address_list address_list_ent dhcpoption_list
@@ -153,6 +155,7 @@ statements:
statement:
interface_statement
+ | profile_statement
| host_statement
| option_statement
| ia_statement
@@ -174,6 +177,18 @@ interface_statement:
}
;
+profile_statement:
+ PROFILE PROFILENAME BCL declarations ECL EOS
+ {
+ struct cf_namelist *profilelist;
+
+ MAKE_NAMELIST(profilelist, $2, $4);
+
+ if (add_namelist(profilelist, &profilelist_head))
+ return (-1);
+ }
+ ;
+
host_statement:
HOST HOSTNAME BCL declarations ECL EOS
{
@@ -1224,6 +1239,8 @@ cleanup()
{
cleanup_namelist(iflist_head);
iflist_head = NULL;
+ cleanup_namelist(profilelist_head);
+ profilelist_head = NULL;
cleanup_namelist(hostlist_head);
hostlist_head = NULL;
cleanup_namelist(iapdlist_head);
@@ -1318,6 +1335,9 @@ cf_post_config()
if (configure_pool(addrpoollist_head))
config_fail();
+ if (configure_profile(profilelist_head))
+ config_fail();
+
if (configure_interface(iflist_head))
config_fail();
@@ -1337,4 +1357,5 @@ void
cf_init()
{
iflist_head = NULL;
+ profilelist_head = NULL;
}
diff --git a/cftoken.l b/cftoken.l
index ad4128d..4c9ed10 100644
--- a/cftoken.l
+++ b/cftoken.l
@@ -111,6 +111,7 @@ ecl \}
%s S_CNF
%s S_IFACE
+%s S_PROFILE
%s S_PREF
%s S_HOST
%s S_DUID
@@ -137,6 +138,15 @@ ecl \}
return (IFNAME);
}
+ /* profile configuration */
+<S_CNF>profile { DECHO; BEGIN S_PROFILE; return (PROFILE); }
+<S_PROFILE>{string} {
+ DECHO;
+ yylval.str = strdup(yytext);
+ BEGIN S_CNF;
+ return (PROFILENAME);
+}
+
/* host configuration */
<S_CNF>host { DECHO; BEGIN S_HOST; return (HOST); }
<S_HOST>{string} {
diff --git a/config.c b/config.c
index 3721545..23598fc 100644
--- a/config.c
+++ b/config.c
@@ -61,6 +61,7 @@
#include <lease.h>
extern int errno;
+char *profile = NULL;
struct prefix_ifconf *prefix_ifconflist;
struct dhcp6_list siplist, sipnamelist, dnslist, dnsnamelist, ntplist;
@@ -70,6 +71,7 @@ struct dhcp6_list bcmcslist, bcmcsnamelist;
long long optrefreshtime;
static struct dhcp6_ifconf *dhcp6_ifconflist;
+static struct dhcp6_ifconf *dhcp6_profileconflist;
struct ia_conflist ia_conflist0;
static struct host_conf *host_conflist0, *host_conflist;
static struct keyinfo *key_list, *key_list0;
@@ -134,6 +136,8 @@ static void clear_iaconf __P((struct ia_conflist *));
static void clear_hostconf __P((struct host_conf *));
static void clear_keys __P((struct keyinfo *));
static void clear_authinfo __P((struct authinfo *));
+static int configure_interface_or_profile __P((struct cf_namelist *,
+ struct dhcp6_ifconf **));
static int configure_duid __P((char *, struct duid *));
static int configure_addr __P((struct cf_list *, struct dhcp6_list *, char *));
static int configure_domain __P((struct cf_list *, struct dhcp6_list *, char *));
@@ -149,170 +153,199 @@ configure_interface(iflist)
struct cf_namelist *iflist;
{
struct cf_namelist *ifp;
- struct dhcp6_ifconf *ifc;
- char *cp;
for (ifp = iflist; ifp; ifp = ifp->next) {
- struct cf_list *cfl;
-
if (if_nametoindex(ifp->name) == 0) {
debug_printf(LOG_ERR, FNAME, "invalid interface(%s): %s",
ifp->name, strerror(errno));
goto bad;
}
- if ((ifc = malloc(sizeof(*ifc))) == NULL) {
- debug_printf(LOG_ERR, FNAME,
- "memory allocation for %s failed", ifp->name);
+ if (configure_interface_or_profile(ifp, &dhcp6_ifconflist))
goto bad;
- }
- memset(ifc, 0, sizeof(*ifc));
- ifc->next = dhcp6_ifconflist;
- dhcp6_ifconflist = ifc;
+ }
+
+ return (0);
+bad:
+ clear_ifconf(dhcp6_ifconflist);
+ dhcp6_ifconflist = NULL;
+ return (-1);
+}
+
+int
+configure_profile(profilelist)
+ struct cf_namelist *profilelist;
+{
+ struct cf_namelist *profp;
- if ((ifc->ifname = strdup(ifp->name)) == NULL) {
- debug_printf(LOG_ERR, FNAME, "failed to copy ifname");
+ for (profp = profilelist; profp; profp = profp->next) {
+ if (configure_interface_or_profile(profp,
+ &dhcp6_profileconflist))
goto bad;
- }
+ }
- ifc->server_pref = DH6OPT_PREF_UNDEF;
- TAILQ_INIT(&ifc->reqopt_list);
- TAILQ_INIT(&ifc->iaconf_list);
+ return (0);
+bad:
+ clear_ifconf(dhcp6_profileconflist);
+ dhcp6_profileconflist = NULL;
+ return (-1);
+}
- for (cfl = ifp->params; cfl; cfl = cfl->next) {
- switch(cfl->type) {
- case DECL_REQUEST:
- if (dhcp6_mode != DHCP6_MODE_CLIENT) {
- debug_printf(LOG_INFO, FNAME, "%s:%d "
- "client-only configuration",
- configfilename,
- cfl->line);
- goto bad;
- }
- if (add_options(DHCPOPTCODE_REQUEST,
- ifc, cfl->list)) {
- goto bad;
- }
- break;
- case DECL_SEND:
- if (add_options(DHCPOPTCODE_SEND,
- ifc, cfl->list)) {
- goto bad;
- }
- break;
- case DECL_ALLOW:
- if (add_options(DHCPOPTCODE_ALLOW,
- ifc, cfl->list)) {
- goto bad;
- }
- break;
- case DECL_INFO_ONLY:
- if (dhcp6_mode != DHCP6_MODE_CLIENT) {
- debug_printf(LOG_INFO, FNAME, "%s:%d "
- "client-only configuration",
- configfilename, cfl->line);
- goto bad;
- }
- ifc->send_flags |= DHCIFF_INFO_ONLY;
- break;
- case DECL_PREFERENCE:
- if (dhcp6_mode != DHCP6_MODE_SERVER) {
- debug_printf(LOG_INFO, FNAME, "%s:%d "
- "server-only configuration",
- configfilename, cfl->line);
- goto bad;
- }
- ifc->server_pref = (int)cfl->num;
- if (ifc->server_pref < 0 ||
- ifc->server_pref > 255) {
- debug_printf(LOG_INFO, FNAME, "%s:%d "
- "bad value: %d",
+static int configure_interface_or_profile(ifp, conflist)
+ struct cf_namelist *ifp;
+ struct dhcp6_ifconf **conflist;
+{
+ struct dhcp6_ifconf *conf;
+ char *cp;
+ struct cf_list *cfl;
+
+ if ((conf = malloc(sizeof(*conf))) == NULL) {
+ debug_printf(LOG_ERR, FNAME,
+ "memory allocation for %s failed", ifp->name);
+ return (-1);
+ }
+ memset(conf, 0, sizeof(*conf));
+ conf->next = *conflist;
+ *conflist = conf;
+
+ if ((conf->ifname = strdup(ifp->name)) == NULL) {
+ debug_printf(LOG_ERR, FNAME, "failed to copy interface or "
+ "profile name");
+ return (-1);
+ }
+
+ conf->server_pref = DH6OPT_PREF_UNDEF;
+ TAILQ_INIT(&conf->reqopt_list);
+ TAILQ_INIT(&conf->iaconf_list);
+
+ for (cfl = ifp->params; cfl; cfl = cfl->next) {
+ switch(cfl->type) {
+ case DECL_REQUEST:
+ if (dhcp6_mode != DHCP6_MODE_CLIENT) {
+ debug_printf(LOG_INFO, FNAME, "%s:%d "
+ "client-only configuration",
+ configfilename,
+ cfl->line);
+ return (-1);
+ }
+ if (add_options(DHCPOPTCODE_REQUEST,
+ conf, cfl->list)) {
+ return (-1);
+ }
+ break;
+ case DECL_SEND:
+ if (add_options(DHCPOPTCODE_SEND,
+ conf, cfl->list)) {
+ return (-1);
+ }
+ break;
+ case DECL_ALLOW:
+ if (add_options(DHCPOPTCODE_ALLOW,
+ conf, cfl->list)) {
+ return (-1);
+ }
+ break;
+ case DECL_INFO_ONLY:
+ if (dhcp6_mode != DHCP6_MODE_CLIENT) {
+ debug_printf(LOG_INFO, FNAME, "%s:%d "
+ "client-only configuration",
+ configfilename, cfl->line);
+ return (-1);
+ }
+ conf->send_flags |= DHCIFF_INFO_ONLY;
+ break;
+ case DECL_PREFERENCE:
+ if (dhcp6_mode != DHCP6_MODE_SERVER) {
+ debug_printf(LOG_INFO, FNAME, "%s:%d "
+ "server-only configuration",
+ configfilename, cfl->line);
+ return (-1);
+ }
+ conf->server_pref = (int)cfl->num;
+ if (conf->server_pref < 0 ||
+ conf->server_pref > 255) {
+ debug_printf(LOG_INFO, FNAME, "%s:%d "
+ "bad value: %d",
+ configfilename, cfl->line,
+ conf->server_pref);
+ return (-1);
+ }
+ break;
+ case DECL_SCRIPT:
+ if (dhcp6_mode != DHCP6_MODE_CLIENT) {
+ debug_printf(LOG_INFO, FNAME, "%s:%d "
+ "client-only configuration",
+ configfilename, cfl->line);
+ return (-1);
+ }
+ if (conf->scriptpath) {
+ debug_printf(LOG_INFO, FNAME,
+ "%s:%d duplicated configuration",
+ configfilename, cfl->line);
+ return (-1);
+ }
+ cp = cfl->ptr;
+ conf->scriptpath = strdup(cp + 1);
+ if (conf->scriptpath == NULL) {
+ debug_printf(LOG_NOTICE, FNAME,
+ "failed to copy script path");
+ return (-1);
+ }
+ cp = conf->scriptpath;
+ if (*cp != '/') {
+ debug_printf(LOG_INFO, FNAME,
+ "script must be an absolute path");
+ return (-1);
+ }
+ cp += strlen(conf->scriptpath) - 1;
+ *cp = '\0'; /* clear the terminating quote */
+ break;
+ case DECL_ADDRESSPOOL:
+ {
+ struct dhcp6_poolspec* spec;
+ struct pool_conf* pool;
+
+ spec = (struct dhcp6_poolspec *)cfl->ptr;
+
+ for (pool = pool_conflist0; pool; pool = pool->next)
+ if (strcmp(spec->name, pool->name) == 0)
+ break;
+ if (pool == NULL) {
+ debug_printf(LOG_ERR, FNAME, "%s:%d "
+ "pool '%s' not found",
configfilename, cfl->line,
- ifc->server_pref);
- goto bad;
- }
- break;
- case DECL_SCRIPT:
- if (dhcp6_mode != DHCP6_MODE_CLIENT) {
- debug_printf(LOG_INFO, FNAME, "%s:%d "
- "client-only configuration",
- configfilename, cfl->line);
- goto bad;
- }
- if (ifc->scriptpath) {
- debug_printf(LOG_INFO, FNAME,
- "%s:%d duplicated configuration",
- configfilename, cfl->line);
- goto bad;
- }
- cp = cfl->ptr;
- ifc->scriptpath = strdup(cp + 1);
- if (ifc->scriptpath == NULL) {
- debug_printf(LOG_NOTICE, FNAME,
- "failed to copy script path");
- goto bad;
+ spec->name);
+ return (-1);
}
- cp = ifc->scriptpath;
- if (*cp != '/') {
- debug_printf(LOG_INFO, FNAME,
- "script must be an absolute path");
- goto bad;
+ if (spec->vltime != DHCP6_DURATION_INFINITE &&
+ (spec->pltime == DHCP6_DURATION_INFINITE ||
+ spec->pltime > spec->vltime)) {
+ debug_printf(LOG_ERR, FNAME, "%s:%d ",
+ configfilename, cfl->line,
+ "specified a larger preferred lifetime "
+ "than valid lifetime");
+ return (-1);
}
- cp += strlen(ifc->scriptpath) - 1;
- *cp = '\0'; /* clear the terminating quote */
- break;
- case DECL_ADDRESSPOOL:
- {
- struct dhcp6_poolspec* spec;
- struct pool_conf* pool;
-
- spec = (struct dhcp6_poolspec *)cfl->ptr;
-
- for (pool = pool_conflist0; pool; pool = pool->next)
- if (strcmp(spec->name, pool->name) == 0)
- break;
- if (pool == NULL) {
- debug_printf(LOG_ERR, FNAME, "%s:%d "
- "pool '%s' not found",
- configfilename, cfl->line,
- spec->name);
- goto bad;
- }
- if (spec->vltime != DHCP6_DURATION_INFINITE &&
- (spec->pltime == DHCP6_DURATION_INFINITE ||
- spec->pltime > spec->vltime)) {
- debug_printf(LOG_ERR, FNAME, "%s:%d ",
- configfilename, cfl->line,
- "specified a larger preferred lifetime "
- "than valid lifetime");
- goto bad;
- }
- ifc->pool = *spec;
- if ((ifc->pool.name = strdup(spec->name)) == NULL) {
- debug_printf(LOG_ERR, FNAME,
- "memory allocation failed");
- goto bad;
- }
- debug_printf(LOG_DEBUG, FNAME,
- "pool '%s' is specified to the interface '%s'",
- ifc->pool.name, ifc->ifname);
+ conf->pool = *spec;
+ if ((conf->pool.name = strdup(spec->name)) == NULL) {
+ debug_printf(LOG_ERR, FNAME,
+ "memory allocation failed");
+ return (-1);
}
- break;
- default:
- debug_printf(LOG_ERR, FNAME, "%s:%d "
- "invalid interface configuration",
- configfilename, cfl->line);
- goto bad;
+ debug_printf(LOG_DEBUG, FNAME,
+ "pool '%s' is specified to the interface '%s'",
+ conf->pool.name, conf->ifname);
}
+ break;
+ default:
+ debug_printf(LOG_ERR, FNAME, "%s:%d "
+ "invalid interface configuration",
+ configfilename, cfl->line);
+ return (-1);
}
}
return (0);
-
- bad:
- clear_ifconf(dhcp6_ifconflist);
- dhcp6_ifconflist = NULL;
- return (-1);
}
int
@@ -1275,6 +1308,8 @@ configure_cleanup()
clear_iaconf(&ia_conflist0);
clear_ifconf(dhcp6_ifconflist);
dhcp6_ifconflist = NULL;
+ clear_ifconf(dhcp6_profileconflist);
+ dhcp6_profileconflist = NULL;
clear_hostconf(host_conflist0);
host_conflist0 = NULL;
clear_keys(key_list0);
@@ -1322,8 +1357,17 @@ configure_commit()
if (strcmp(ifp->ifname, ifc->ifname) == 0)
break;
}
- if (ifc == NULL)
- continue;
+ if (ifc == NULL) {
+ if (profile == NULL)
+ continue;
+ for (ifc = dhcp6_profileconflist; ifc;
+ ifc = ifc->next) {
+ if (strcmp(profile, ifc->ifname) == 0)
+ break;
+ }
+ if (ifc == NULL)
+ continue;
+ }
/* copy new configuration */
ifp->send_flags = ifc->send_flags;
@@ -1349,6 +1393,8 @@ configure_commit()
clear_ifconf(dhcp6_ifconflist);
dhcp6_ifconflist = NULL;
+ clear_ifconf(dhcp6_profileconflist);
+ dhcp6_profileconflist = NULL;
/* clear unused IA configuration */
if (!TAILQ_EMPTY(&ia_conflist0)) {
diff --git a/config.h b/config.h
index bf6dae6..ea8d17c 100644
--- a/config.h
+++ b/config.h
@@ -285,6 +285,8 @@ dhcp6_mode_t;
extern const dhcp6_mode_t dhcp6_mode;
+extern char *profile;
+
extern struct dhcp6_if *dhcp6_if;
extern struct dhcp6_ifconf *dhcp6_iflist;
extern struct prefix_ifconf *prefix_ifconflist;
@@ -304,6 +306,7 @@ extern long long optrefreshtime;
extern struct dhcp6_if *ifinit __P((char *));
extern int ifreset __P((struct dhcp6_if *));
extern int configure_interface __P((struct cf_namelist *));
+extern int configure_profile __P((struct cf_namelist *));
extern int configure_host __P((struct cf_namelist *));
extern int configure_keys __P((struct cf_namelist *));
extern int configure_authinfo __P((struct cf_namelist *));
diff --git a/dhcp6c.8 b/dhcp6c.8
index 1d69c9d..acc8f46 100644
--- a/dhcp6c.8
+++ b/dhcp6c.8
@@ -39,6 +39,7 @@
.Op Fl c Ar configfile
.Op Fl Ddfi
.Op Fl p Ar pid-file
+.Op Fl P Ar profile
.Ar interface
.Op Ar interfaces...
.\"
@@ -92,6 +93,14 @@ Use
.Ar pid-file
to dump the process ID of
.Nm .
+.It Fl P Ar profile
+Use the given
+.Ar profile
+defined in the
+.Nm
+configuration file for
+.Ar interfaces
+which do not have a specific configuration.
.El
.Pp
The program will daemonize itself on invocation unless the
diff --git a/dhcp6c.c b/dhcp6c.c
index edeca80..35080e9 100644
--- a/dhcp6c.c
+++ b/dhcp6c.c
@@ -170,7 +170,7 @@ main(argc, argv)
else
progname++;
- while ((ch = getopt(argc, argv, "c:dDfik:p:")) != -1) {
+ while ((ch = getopt(argc, argv, "c:dDfik:p:P:")) != -1) {
switch (ch) {
case 'c':
conffile = optarg;
@@ -193,6 +193,9 @@ main(argc, argv)
case 'p':
pid_file = optarg;
break;
+ case 'P':
+ profile = optarg;
+ break;
default:
usage();
exit(0);
diff --git a/dhcp6c.conf.5 b/dhcp6c.conf.5
index 5fc03d3..3d5d25a 100644
--- a/dhcp6c.conf.5
+++ b/dhcp6c.conf.5
@@ -288,6 +288,13 @@ file, and be created by the same owner who runs the daemon.
.El
.El
.\"
+.Sh Profile statement
+Some setups may require to configure an interface independently from its name.
+Profiles are available for this particular purpose. They follow the same syntax
+as an interface statement except they can be arbitrarily named. It is then
+possible to choose which profile to use for a given interface on the command
+line.
+.\"
.Sh Identity association statement
Identity association
.Pq IA