summaryrefslogtreecommitdiffstats
path: root/debian/patches/0006-Add-new-feature-dhcp6c-profiles.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/0006-Add-new-feature-dhcp6c-profiles.patch')
-rw-r--r--debian/patches/0006-Add-new-feature-dhcp6c-profiles.patch626
1 files changed, 626 insertions, 0 deletions
diff --git a/debian/patches/0006-Add-new-feature-dhcp6c-profiles.patch b/debian/patches/0006-Add-new-feature-dhcp6c-profiles.patch
new file mode 100644
index 0000000..e3a458a
--- /dev/null
+++ b/debian/patches/0006-Add-new-feature-dhcp6c-profiles.patch
@@ -0,0 +1,626 @@
+From: Jeremie Corbier <jeremie+debian@famille-corbier.net>
+Date: Tue, 6 Apr 2010 15:51:14 +0200
+Subject: Add new feature: dhcp6c profiles
+
+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.
+
+Signed-off-by: Jeremie Corbier <jeremie@famille-corbier.net>
+---
+ cfparse.y | 23 +++-
+ cftoken.l | 10 ++
+ config.c | 334 +++++++++++++++++++++++++++++++++-------------------------
+ config.h | 3 +
+ dhcp6c.8 | 9 ++
+ dhcp6c.c | 5 +-
+ dhcp6c.conf.5 | 7 ++
+ 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 1e897d2..1953f76 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