--- dhcp-0.10/client6_parse.y.prefix_delegation_interface 2005-01-13 13:41:16.043928000 -0500 +++ dhcp-0.10/client6_parse.y 2005-01-13 13:41:16.803168000 -0500 @@ -94,7 +94,7 @@ %token REQUEST SEND %token RAPID_COMMIT PREFIX_DELEGATION DNS_SERVERS %token INFO_ONLY TEMP_ADDR -%token ADDRESS PREFIX IAID RENEW_TIME REBIND_TIME V_TIME P_TIME +%token ADDRESS PREFIX IAID RENEW_TIME REBIND_TIME V_TIME P_TIME PREFIX_DELEGATION_INTERFACE %token NUMBER SLASH EOS BCL ECL STRING INFINITY %token COMMA OPTION @@ -235,6 +235,15 @@ $$ = l; } + | PREFIX_DELEGATION_INTERFACE STRING EOS + { + struct cf_list *l; + char *pp = (char*)malloc(strlen($2)+1); + strcpy(pp,$2); + MAKE_CFLIST(l, DECL_PREFIX_DELEGATION_INTERFACE, pp, NULL ); + + $$ = l; + } ; dhcpoption: --- dhcp-0.10/client6_token.l.prefix_delegation_interface 2003-04-02 18:31:49.000000000 -0500 +++ dhcp-0.10/client6_token.l 2005-01-13 13:41:16.819152000 -0500 @@ -143,6 +143,7 @@ <S_CNF>prefer-life-time { DECHO; return (P_TIME); } <S_CNF>renew-time { DECHO; return (RENEW_TIME); } <S_CNF>rebind-time { DECHO; return (REBIND_TIME); } +<S_CNF>prefix-delegation-interface { DECHO; return (PREFIX_DELEGATION_INTERFACE); } /* request */ <S_CNF>request { DECHO; return (REQUEST); } --- dhcp-0.10/config.h.prefix_delegation_interface 2004-03-04 18:31:24.000000000 -0500 +++ dhcp-0.10/config.h 2005-01-13 13:41:16.836135000 -0500 @@ -51,6 +51,15 @@ int flags; }; +struct dhcp6_option { + TAILQ_ENTRY(dhcp6_option) link; + int type; + int len; + void *val; +}; + +TAILQ_HEAD(dhcp6_option_list, dhcp6_option); + /* per-interface information */ struct dhcp6_if { struct dhcp6_if *next; @@ -91,11 +100,12 @@ struct in6_addr linklocal; int server_pref; /* server preference (server only) */ - struct dhcp6_optconf *send_options; + struct dhcp6_list reqopt_list; /* request specific addresses list from client */ struct dhcp6_list addr_list; struct dhcp6_list prefix_list; + struct dhcp6_option_list option_list; struct dhcp6_serverinfo *current_server; struct dhcp6_serverinfo *servers; }; @@ -160,12 +170,12 @@ int server_pref; /* server preference (server only) */ struct dhcp6_iaid_info iaidinfo; - struct dhcp6_optconf *send_options; - struct dhcp6_optconf *allow_options; struct dhcp6_list prefix_list; struct dhcp6_list addr_list; struct dhcp6_list reqopt_list; + + struct dhcp6_option_list option_list; }; struct prefix_ifconf { @@ -199,14 +209,6 @@ struct dhcp6_list addr_binding_list; }; -/* DHCP option information */ -struct dhcp6_optconf { - struct dhcp6_optconf *next; - int type; - int len; - char *val; -}; - /* structures and definitions used in the config file parser */ struct cf_namelist { struct cf_namelist *next; @@ -277,7 +279,7 @@ enum {DECL_SEND, DECL_ALLOW, DECL_INFO_ONLY, DECL_TEMP_ADDR, DECL_REQUEST, DECL_DUID, DECL_PREFIX, DECL_PREFERENCE, DECL_IAID, DECL_RENEWTIME, DECL_REBINDTIME, - DECL_ADDRESS, DECL_LINKLOCAL, DECL_PREFIX_INFO, DECL_PREFIX_REQ, + DECL_ADDRESS, DECL_LINKLOCAL, DECL_PREFIX_INFO, DECL_PREFIX_REQ, DECL_PREFIX_DELEGATION_INTERFACE, DHCPOPT_PREFIX_DELEGATION, IFPARAM_SLA_ID, IFPARAM_SLA_LEN, DHCPOPT_RAPID_COMMIT, DHCPOPT_DNS, ADDRESS_LIST_ENT }; @@ -303,3 +305,5 @@ extern int cfparse (const char *); extern int resolv_parse (struct dns_list *); extern int get_if_rainfo(struct dhcp6_if *ifp); + +extern void *get_if_option( struct dhcp6_option_list *, int); --- dhcp-0.10/config.c.prefix_delegation_interface 2003-04-11 20:25:32.000000000 -0400 +++ dhcp-0.10/config.c 2005-01-13 13:41:27.417543000 -0500 @@ -57,9 +57,11 @@ static int add_options __P((int, struct dhcp6_ifconf *, struct cf_list *)); static int add_address __P((struct dhcp6_list *, struct dhcp6_addr *)); +static int add_option __P((struct dhcp6_option_list *, struct cf_list *)); +static int clear_option_list __P((struct dhcp6_option_list *)); + static void clear_ifconf __P((struct dhcp6_ifconf *)); static void clear_hostconf __P((struct host_conf *)); -static void clear_options __P((struct dhcp6_optconf *)); int configure_interface(const struct cf_namelist *iflist) @@ -88,6 +90,7 @@ ifc->server_pref = DH6OPT_PREF_UNDEF; TAILQ_INIT(&ifc->reqopt_list); TAILQ_INIT(&ifc->addr_list); + TAILQ_INIT(&ifc->option_list); for (cfl = ifp->params; cfl; cfl = cfl->next) { switch(cfl->type) { @@ -185,6 +188,13 @@ break; case DECL_PREFIX_INFO: break; + case DECL_PREFIX_DELEGATION_INTERFACE: + if (add_option(&ifc->option_list, cfl)){ + dprintf(LOG_ERR, "%s failed to configure prefix-delegation-interface for %s", + FNAME, ifc->ifname); + goto bad; + } + break; default: dprintf(LOG_ERR, "%s" "%s:%d " "invalid interface configuration", @@ -450,11 +460,6 @@ ifp->allow_flags = ifc->allow_flags; - clear_options(ifp->send_options); - - ifp->send_options = ifc->send_options; - ifc->send_options = NULL; - dhcp6_clear_list(&ifp->reqopt_list); ifp->reqopt_list = ifc->reqopt_list; TAILQ_INIT(&ifc->reqopt_list); @@ -467,6 +472,10 @@ ifp->prefix_list = ifc->prefix_list; TAILQ_INIT(&ifc->prefix_list); + clear_option_list(&ifp->option_list); + ifp->option_list = ifc->option_list; + TAILQ_INIT(&ifc->option_list); + ifp->server_pref = ifc->server_pref; memcpy(&ifp->iaidinfo, &ifc->iaidinfo, sizeof(ifp->iaidinfo)); @@ -492,7 +501,7 @@ ifc_next = ifc->next; free(ifc->ifname); - clear_options(ifc->send_options); + dhcp6_clear_list(&ifc->reqopt_list); free(ifc); @@ -519,19 +528,6 @@ } } -static void -clear_options(struct dhcp6_optconf *opt0) -{ - struct dhcp6_optconf *opt, *opt_next; - - for (opt = opt0; opt; opt = opt_next) { - opt_next = opt->next; - - free(opt->val); - free(opt); - } -} - static int add_options(int opcode, struct dhcp6_ifconf *ifc, struct cf_list *cfl0) @@ -647,3 +643,54 @@ return (0); } +int add_option (struct dhcp6_option_list *opts, struct cf_list *cfl) +{ + struct dhcp6_option *opt ; + + if ( get_if_option( opts, cfl->type ) != 0L ) + return (-1); + + switch (cfl->type) + { + case DECL_PREFIX_DELEGATION_INTERFACE: + opt = (struct dhcp6_option*)malloc(sizeof(struct dhcp6_option)); + opt->type = cfl->type; + if ( cfl->ptr != 0L ) + { + opt->len = strlen((char*)(cfl->ptr))+1; + opt->val = malloc(opt->len); + memcpy(opt->val, cfl->ptr, opt->len); + }else + { + opt->val = malloc(1); + opt->len = 0; + *((char*)(opt->val))='\0'; + } + TAILQ_INSERT_TAIL(opts, opt, link); + break; + default: + break; + } + return (0); +} + +int clear_option_list (struct dhcp6_option_list *opts) +{ + struct dhcp6_option *opt; + while ((opt = TAILQ_FIRST(opts)) != NULL) { + TAILQ_REMOVE(opts, opt, link); + free(opt); + } + return (0); +} + +void *get_if_option( struct dhcp6_option_list *opts, int type ) +{ + struct dhcp6_option *opt; + TAILQ_FOREACH( opt, opts, link) + { + if ( opt->type == type ) + return opt->val; + } + return 0L; +} --- dhcp-0.10/radvd_token.l.prefix_delegation_interface 2005-01-13 13:41:16.744227000 -0500 +++ dhcp-0.10/radvd_token.l 2005-01-13 13:41:16.870101000 -0500 @@ -112,14 +112,24 @@ BEGIN S_INTERFACE;} <S_INTERFACE>{string} { + char *requested_if; fprintf(dhcp6_radvd_file, yytext); - if (strcmp(yytext, dhcp6_if->ifname)!=0) - BEGIN INITIAL; - else { + if ( ( ( (requested_if = get_if_option(&(dhcp6_if->option_list), + DECL_PREFIX_DELEGATION_INTERFACE + ) + ) != 0L + ) + &&( strcmp(yytext, requested_if) == 0) + ) + ||((requested_if == 0L) && (strcmp(yytext, dhcp6_if->ifname)==0)) + ) + { TAILQ_INIT(&ori_prefix_list); TAILQ_INIT(&previous_prefix_list); - BEGIN S_IFNAME;} - } + BEGIN S_IFNAME; + }else + BEGIN INITIAL; +} <S_IFNAME>{comment} { if (strstr(yytext, DHCP6_MARK) != NULL) { --- dhcp-0.10/dhcp6c.conf.5.prefix_delegation_interface 2003-03-28 15:16:36.000000000 -0500 +++ dhcp-0.10/dhcp6c.conf.5 2005-01-13 13:41:16.887084000 -0500 @@ -171,6 +171,13 @@ If this option is used in a "request [dhcpoptions];" declaration, dhcp6c requests a Prefix Delegation to the DHCPv6 servers. +.nf +.B prefix\-delegation\-interface <interface name> +Specifies the name of the interface definition in radvd.conf +that dhcp6c will write the 'prefix' declaration for. By default, +dhcp6c will write a radvd.conf prefix declaration for the interface +on which it receives the prefix delegation lease. + .SH EXAMPLES .PP This is a sample of the dhcp6c.conf file.