diff options
Diffstat (limited to 'usr.sbin/rrenumd')
| -rw-r--r-- | usr.sbin/rrenumd/Makefile | 36 | ||||
| -rw-r--r-- | usr.sbin/rrenumd/Makefile.depend | 18 | ||||
| -rw-r--r-- | usr.sbin/rrenumd/lexer.l | 270 | ||||
| -rw-r--r-- | usr.sbin/rrenumd/parser.y | 671 | ||||
| -rw-r--r-- | usr.sbin/rrenumd/rrenumd.8 | 101 | ||||
| -rw-r--r-- | usr.sbin/rrenumd/rrenumd.c | 659 | ||||
| -rw-r--r-- | usr.sbin/rrenumd/rrenumd.conf.5 | 367 | ||||
| -rw-r--r-- | usr.sbin/rrenumd/rrenumd.h | 60 |
8 files changed, 2182 insertions, 0 deletions
diff --git a/usr.sbin/rrenumd/Makefile b/usr.sbin/rrenumd/Makefile new file mode 100644 index 000000000000..f2a0415b8607 --- /dev/null +++ b/usr.sbin/rrenumd/Makefile @@ -0,0 +1,36 @@ +# Copyright (c) 1996 WIDE Project. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modifications, are permitted provided that the above copyright notice +# and this paragraph are duplicated in all such forms and that any +# documentation, advertising materials, and other materials related to +# such distribution and use acknowledge that the software was developed +# by the WIDE Project, Japan. The name of the Project may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' +# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT +# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE. +# + +PROG= rrenumd +MAN= rrenumd.conf.5 rrenumd.8 +SRCS= rrenumd.c parser.y lexer.l + +CFLAGS+= -DIPSEC -I. -I${.CURDIR} +YFLAGS= -d + +WARNS?= 2 + +LIBADD= ipsec + +CLEANFILES= y.tab.h +SRCS+= y.tab.h +y.tab.h: parser.y + +.if defined(YACCDEBUG) +CFLAGS+= -DYYDEBUG +YFLAGS+= -t -v +.endif + +.include <bsd.prog.mk> diff --git a/usr.sbin/rrenumd/Makefile.depend b/usr.sbin/rrenumd/Makefile.depend new file mode 100644 index 000000000000..48f9c6dc2589 --- /dev/null +++ b/usr.sbin/rrenumd/Makefile.depend @@ -0,0 +1,18 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + include \ + include/arpa \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + lib/libipsec \ + usr.bin/yacc.host \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/rrenumd/lexer.l b/usr.sbin/rrenumd/lexer.l new file mode 100644 index 000000000000..f94a1afea128 --- /dev/null +++ b/usr.sbin/rrenumd/lexer.l @@ -0,0 +1,270 @@ +/* $KAME: lexer.l,v 1.7 2000/11/08 02:40:53 itojun Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +%{ +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/queue.h> + +#include <string.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/icmp6.h> + +#include <arpa/inet.h> + +#include "y.tab.h" + +int lineno = 1; + +#define LINEBUF_SIZE 1000 +char linebuf[LINEBUF_SIZE]; + +int parse(FILE **); +void yyerror(const char *); +int yylex(void); +%} + +%option noyywrap +%option nounput + +/* common section */ +nl \n +ws [ \t]+ +digit [0-9] +letter [0-9A-Za-z] +hexdigit [0-9A-Fa-f] +special [()+\|\?\*,] +dot \. +hyphen \- +colon \: +slash \/ +bcl \{ +ecl \} +semi \; +usec {dot}{digit}{1,6} +comment \#.* +qstring \"[^"]*\" +decstring {digit}+ +hexpair {hexdigit}{hexdigit} +hexstring 0[xX]{hexdigit}+ +octetstring {octet}({dot}{octet})+ +ipv4addr {digit}{1,3}({dot}{digit}{1,3}){0,3} +ipv6addr {hexdigit}{0,4}({colon}{hexdigit}{0,4}){2,7} +ipaddrmask {slash}{digit}{1,3} +keyword {letter}{letter}+ +name {letter}(({letter}|{digit}|{hyphen})*({letter}|{digit}))* +hostname {name}(({dot}{name})+{dot}?)? + +timeval {digit}{0,2} +days d{timeval} +hours h{timeval} +minutes m{timeval} +seconds s{timeval} + +mprefix match_prefix|match-prefix +uprefix use_prefix|use-prefix + +%% + /* rrenumd keywords */ +debug { + return(DEBUG_CMD); + } +dest { + return(DEST_CMD); + } +retry { + return(RETRY_CMD); + } +seqnum { + return(SEQNUM_CMD); + } +add { + yylval.num = RPM_PCO_ADD; + return(ADD); + } +change { + yylval.num = RPM_PCO_CHANGE; + return(CHANGE); + } +setglobal { + yylval.num = RPM_PCO_SETGLOBAL; + return(SETGLOBAL); + } +{mprefix} { + return(MATCH_PREFIX_CMD); + } +maxlen { + return(MAXLEN_CMD); + } +minlen { + return(MINLEN_CMD); + } +{uprefix} { + return(USE_PREFIX_CMD); + } +keeplen { + return(KEEPLEN_CMD); + } + +vltime { + return(VLTIME_CMD); + } +pltime { + return(PLTIME_CMD); + } +raf_onlink { + return(RAF_ONLINK_CMD); + } +raf_auto { + return(RAF_AUTO_CMD); + } +rrf_decrvalid { + return(RAF_DECRVALID_CMD); + } +rrf_decrprefd { + return(RAF_DECRPREFD_CMD); + } +{days} { + yytext++; + yylval.num = atoi(yytext); + return(DAYS); + } +{hours} { + yytext++; + yylval.num = atoi(yytext); + return(HOURS); + } +{minutes} { + yytext++; + yylval.num = atoi(yytext); + return(MINUTES); + } +{seconds} { + yytext++; + yylval.num = atoi(yytext); + return(SECONDS); + } +infinity { + return(INFINITY); + } + +on { + yylval.num = 1; + return(ON); + } +off { + yylval.num = 0; + return(OFF); + } + + /* basic rules */ +{ws} ; +{nl} { + lineno++; + } +{semi} { + return EOS; + } +{bcl} { + return BCL; + } +{ecl} { + return ECL; + } +{qstring} { + yylval.cs.cp = yytext; + yylval.cs.len = yyleng; + return QSTRING; + } +{decstring} { + yylval.cs.cp = yytext; + yylval.cs.len = yyleng; + return DECSTRING; + } +{name} { + yylval.cs.cp = yytext; + yylval.cs.len = yyleng; + return NAME; + } +{ipv4addr} { + memset(&yylval.addr4, 0, sizeof(struct in_addr)); + if (inet_pton(AF_INET, yytext, + &yylval.addr4) == 1) { + return IPV4ADDR; + } else { + return ERROR; + } + } +{ipv6addr} { + memset(&yylval.addr6, 0, sizeof(struct in6_addr)); + if (inet_pton(AF_INET6, yytext, + &yylval.addr6) == 1) { + return IPV6ADDR; + } else { + return ERROR; + } + } +{ipaddrmask} { + yytext++; + yylval.num = atoi(yytext); + return(PREFIXLEN); + } +{hostname} { + yylval.cs.cp = yytext; + yylval.cs.len = yyleng; + return HOSTNAME; + } +%% + +int parse(FILE **fp) +{ + extern int yyparse(void); + + yyin = *fp; + + if (yyparse()) + return(-1); + + return(0); + +} + +void +yyerror(const char *s) +{ + printf("%s: at %s in line %d\n", s, yytext, lineno); +} diff --git a/usr.sbin/rrenumd/parser.y b/usr.sbin/rrenumd/parser.y new file mode 100644 index 000000000000..94f6b15555c5 --- /dev/null +++ b/usr.sbin/rrenumd/parser.y @@ -0,0 +1,671 @@ +/* $KAME: parser.y,v 1.8 2000/11/08 03:03:34 jinmei Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +%{ +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/queue.h> + +#include <net/if.h> + +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/icmp6.h> + +#include <limits.h> +#include <netdb.h> +#include <string.h> +#include <stdio.h> + +#include "rrenumd.h" + +struct config_is_set { + u_short cis_dest : 1; +} cis; + +struct dst_list *dl_head; +struct payload_list *pl_head, ple_cur; +u_int retry; +char errbuf[LINE_MAX]; + +extern int lineno; +extern void yyerror(const char *s); +extern int yylex(void); +static struct payload_list * pllist_lookup(int seqnum); +static void pllist_enqueue(struct payload_list *pl_entry); + +#define MAX_RETRYNUM 10 /* upper limit of retry in this rrenumd program */ +#define MAX_SEQNUM 256 /* upper limit of seqnum in this rrenumd program */ +#define NOSPEC -1 + +%} + +%union { + u_long num; + struct { + char *cp; + int len; + } cs; + struct in_addr addr4; + struct in6_addr addr6; + struct { + struct in6_addr addr; + u_char plen; + } prefix; + struct dst_list *dl; + struct payload_list *pl; + struct sockaddr *sa; +} + +%token <num> ADD CHANGE SETGLOBAL +%token DEBUG_CMD DEST_CMD RETRY_CMD SEQNUM_CMD +%token MATCH_PREFIX_CMD MAXLEN_CMD MINLEN_CMD +%token USE_PREFIX_CMD KEEPLEN_CMD +%token VLTIME_CMD PLTIME_CMD +%token RAF_ONLINK_CMD RAF_AUTO_CMD RAF_DECRVALID_CMD RAF_DECRPREFD_CMD +%token <num> DAYS HOURS MINUTES SECONDS INFINITY +%token <num> ON OFF +%token BCL ECL EOS ERROR +%token <cs> NAME HOSTNAME QSTRING DECSTRING +%token <addr4> IPV4ADDR +%token <addr6> IPV6ADDR +%token <num> PREFIXLEN + +%type <num> retrynum seqnum rrenum_cmd +%type <num> prefixlen maxlen minlen keeplen vltime pltime +%type <num> lifetime days hours minutes seconds +%type <num> decstring +%type <num> raf_onlink raf_auto raf_decrvalid raf_decrprefd flag +%type <dl> dest_addrs dest_addr sin sin6 +%type <pl> rrenum_statement +%type <cs> ifname +%type <prefix> prefixval + +%% +config: + /* empty */ + | statements + ; + +statements: + statement + | statements statement + ; + +statement: + debug_statement + | destination_statement + | rrenum_statement_without_seqnum + | rrenum_statement_with_seqnum + | error EOS + { + yyerrok; + } + | EOS + ; + +debug_statement: + DEBUG_CMD flag EOS + { +#if YYDEBUG + yydebug = $2; +#endif /* YYDEBUG */ + } + ; + +destination_statement: + DEST_CMD dest_addrs retrynum EOS + { + dl_head = $2; + retry = $3; + } + ; + +dest_addrs: + dest_addr + | dest_addrs dest_addr + { + $2->dl_next = $1; + $$ = $2; + } + ; + +dest_addr : + sin + { + with_v4dest = 1; + } + | sin6 + { + with_v6dest = 1; + } + | sin6 ifname + { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)$1->dl_dst; + sin6->sin6_scope_id = if_nametoindex($2.cp); + with_v6dest = 1; + $$ = $1; + } + | HOSTNAME + { + struct sockaddr_storage *ss; + struct addrinfo hints, *res; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_RAW; + hints.ai_protocol = 0; + error = getaddrinfo($1.cp, 0, &hints, &res); + if (error) { + snprintf(errbuf, sizeof(errbuf), + "name resolution failed for %s:%s", + $1.cp, gai_strerror(error)); + yyerror(errbuf); + } + ss = (struct sockaddr_storage *)malloc(sizeof(*ss)); + memset(ss, 0, sizeof(*ss)); + memcpy(ss, res->ai_addr, res->ai_addr->sa_len); + freeaddrinfo(res); + + $$ = (struct dst_list *) + malloc(sizeof(struct dst_list)); + memset($$, 0, sizeof(struct dst_list)); + $$->dl_dst = (struct sockaddr *)ss; + } + ; + +sin: + IPV4ADDR + { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)malloc(sizeof(*sin)); + memset(sin, 0, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr = $1; + + $$ = (struct dst_list *) + malloc(sizeof(struct dst_list)); + memset($$, 0, sizeof(struct dst_list)); + $$->dl_dst = (struct sockaddr *)sin; + } + ; + +sin6: + IPV6ADDR + { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)malloc(sizeof(*sin6)); + memset(sin6, 0, sizeof(*sin6)); + sin6->sin6_len = sizeof(*sin6); + sin6->sin6_family = AF_INET6; + sin6->sin6_addr = $1; + + $$ = (struct dst_list *) + malloc(sizeof(struct dst_list)); + memset($$, 0, sizeof(struct dst_list)); + $$->dl_dst = (struct sockaddr *)sin6; + } + +ifname: + NAME + { + $$.cp = strdup($1.cp); + $$.len = $1.len; + } + | QSTRING + { + $1.cp[$1.len - 1] = 0; + $$.cp = strdup(&$1.cp[1]); + $$.len = $1.len - 2; + } + ; + +retrynum: + /* empty */ + { + $$ = 2; + } + | RETRY_CMD decstring + { + if ($2 > MAX_RETRYNUM) + $2 = MAX_RETRYNUM; + $$ = $2; + } + ; + +rrenum_statement_with_seqnum: + SEQNUM_CMD seqnum + { + if (pllist_lookup($2)) { + snprintf(errbuf, sizeof(errbuf), + "duplicate seqnum %ld specified at %d", + $2, lineno); + yyerror(errbuf); + } + } + BCL rrenum_statement EOS ECL EOS + { + $5->pl_irr.rr_seqnum = $2; + pllist_enqueue($5); + } + ; + +seqnum: + /* empty */ + { + $$ = 0; + } + | decstring + { + if ($1 > MAX_SEQNUM) { + snprintf(errbuf, sizeof(errbuf), + "seqnum %ld is illegal for this program. " + "should be between 0 and %d", + $1, MAX_SEQNUM); + yyerror(errbuf); + } + $$ = $1; + } + ; + +rrenum_statement_without_seqnum: + rrenum_statement EOS + { + if (pllist_lookup(0)) { + snprintf(errbuf, sizeof(errbuf), + "duplicate seqnum %d specified at %d", + 0, lineno); + yyerror(errbuf); + } + $1->pl_irr.rr_seqnum = 0; + pllist_enqueue($1); + } + ; + +rrenum_statement: + match_prefix_definition use_prefix_definition + { + $$ = (struct payload_list *) + malloc(sizeof(struct payload_list)); + memcpy($$, &ple_cur, sizeof(ple_cur)); + } + ; + +match_prefix_definition: + rrenum_cmd MATCH_PREFIX_CMD prefixval maxlen minlen + { + struct rr_pco_match *rpm; + + rpm = &ple_cur.pl_rpm; + memset(rpm, 0, sizeof(*rpm)); + + rpm->rpm_code = $1; + rpm->rpm_prefix = $3.addr; + rpm->rpm_matchlen = $3.plen; + rpm->rpm_maxlen = $4; + rpm->rpm_minlen = $5; + } + ; + +rrenum_cmd: + /* empty */ + { + $$ = RPM_PCO_ADD; + } + | ADD + | CHANGE + | SETGLOBAL + ; + +prefixval: + IPV6ADDR prefixlen + { + $$.addr = $1; + $$.plen = $2; + } + ; + +prefixlen: + /* empty */ + { + $$ = 64; + } + | PREFIXLEN + ; + +maxlen: + /* empty */ + { + $$ = 128; + } + | MAXLEN_CMD decstring + { + if ($2 > 128) + $2 = 128; + $$ = $2; + } + ; + +minlen: + /* empty */ + { + $$ = 0; + } + | MINLEN_CMD decstring + { + if ($2 > 128) + $2 = 128; + $$ = $2; + } + ; + +use_prefix_definition: + /* empty */ + { + struct icmp6_router_renum *irr; + struct rr_pco_match *rpm; + struct rr_pco_use *rpu; + + irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; + rpm = (struct rr_pco_match *)(irr + 1); + rpu = (struct rr_pco_use *)(rpm + 1); + memset(rpu, 0, sizeof(*rpu)); + } + | USE_PREFIX_CMD prefixval keeplen use_prefix_values + { + struct icmp6_router_renum *irr; + struct rr_pco_match *rpm; + struct rr_pco_use *rpu; + + irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; + rpm = (struct rr_pco_match *)(irr + 1); + rpu = (struct rr_pco_use *)(rpm + 1); + + rpu->rpu_prefix = $2.addr; + rpu->rpu_uselen = $2.plen; + rpu->rpu_keeplen = $3; + } + ; + +use_prefix_values: + /* empty */ + { + struct icmp6_router_renum *irr; + struct rr_pco_match *rpm; + struct rr_pco_use *rpu; + + irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; + rpm = (struct rr_pco_match *)(irr + 1); + rpu = (struct rr_pco_use *)(rpm + 1); + memset(rpu, 0, sizeof(*rpu)); + + rpu->rpu_vltime = htonl(DEF_VLTIME); + rpu->rpu_pltime = htonl(DEF_PLTIME); + rpu->rpu_ramask = 0; + rpu->rpu_flags = 0; + } + | BCL vltime pltime raf_onlink raf_auto raf_decrvalid raf_decrprefd ECL + { + struct icmp6_router_renum *irr; + struct rr_pco_match *rpm; + struct rr_pco_use *rpu; + + irr = (struct icmp6_router_renum *)&ple_cur.pl_irr; + rpm = (struct rr_pco_match *)(irr + 1); + rpu = (struct rr_pco_use *)(rpm + 1); + memset(rpu, 0, sizeof(*rpu)); + + rpu->rpu_vltime = $2; + rpu->rpu_pltime = $3; + if ($4 == NOSPEC) { + rpu->rpu_ramask &= + ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; + } else { + rpu->rpu_ramask |= + ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; + if ($4 == ON) { + rpu->rpu_raflags |= + ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; + } else { + rpu->rpu_raflags &= + ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK; + } + } + if ($5 == NOSPEC) { + rpu->rpu_ramask &= + ICMP6_RR_PCOUSE_RAFLAGS_AUTO; + } else { + rpu->rpu_ramask |= + ICMP6_RR_PCOUSE_RAFLAGS_AUTO; + if ($5 == ON) { + rpu->rpu_raflags |= + ICMP6_RR_PCOUSE_RAFLAGS_AUTO; + } else { + rpu->rpu_raflags &= + ~ICMP6_RR_PCOUSE_RAFLAGS_AUTO; + } + } + rpu->rpu_flags = 0; + if ($6 == ON) { + rpu->rpu_flags |= + ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME; + } + if ($7 == ON) { + rpu->rpu_flags |= + ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME; + } + } + ; + +keeplen: + /* empty */ + { + $$ = 0; + } + | KEEPLEN_CMD decstring + { + if ($2 > 128) + $2 = 128; + $$ = $2; + } + ; + + +vltime: + /* empty */ + { + $$ = htonl(DEF_VLTIME); + } + | VLTIME_CMD lifetime + { + $$ = htonl($2); + } + ; + +pltime: + /* empty */ + { + $$ = htonl(DEF_PLTIME); + } + | PLTIME_CMD lifetime + { + $$ = htonl($2); + } + +raf_onlink: + /* empty */ + { + $$ = NOSPEC; + } + | RAF_ONLINK_CMD flag + { + $$ = $2; + } + ; + +raf_auto: + /* empty */ + { + $$ = NOSPEC; + } + | RAF_AUTO_CMD flag + { + $$ = $2; + } + ; + +raf_decrvalid: + /* empty */ + { + $$ = NOSPEC; + } + | RAF_DECRVALID_CMD flag + { + $$ = $2; + } + ; + +raf_decrprefd: + /* empty */ + { + $$ = NOSPEC; + } + | RAF_DECRPREFD_CMD flag + { + $$ = $2; + } + ; + +flag: + ON { $$ = ON; } + | OFF { $$ = OFF; } + ; + +lifetime: + decstring + | INFINITY + { + $$ = 0xffffffff; + } + | days hours minutes seconds + { + int d, h, m, s; + + d = $1 * 24 * 60 * 60; + h = $2 * 60 * 60; + m = $3 * 60; + s = $4; + $$ = d + h + m + s; + } + ; + +days: + /* empty */ + { + $$ = 0; + } + | DAYS + ; + +hours: + /* empty */ + { + $$ = 0; + } + | HOURS + ; + +minutes: + /* empty */ + { + $$ = 0; + } + | MINUTES + ; + +seconds: + /* empty */ + { + $$ = 0; + } + | SECONDS + ; + +decstring: + DECSTRING + { + int dval; + + dval = atoi($1.cp); + $$ = dval; + } + ; + +%% + +static struct payload_list * +pllist_lookup(int seqnum) +{ + struct payload_list *pl; + for (pl = pl_head; pl && pl->pl_irr.rr_seqnum != seqnum; + pl = pl->pl_next) + continue; + return (pl); +} + +static void +pllist_enqueue(struct payload_list *pl_entry) +{ + struct payload_list *pl, *pl_last; + + pl_last = NULL; + for (pl = pl_head; + pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum; + pl_last = pl, pl = pl->pl_next) + continue; + if (pl_last) + pl_last->pl_next = pl_entry; + else + pl_head = pl_entry; + + return; +} diff --git a/usr.sbin/rrenumd/rrenumd.8 b/usr.sbin/rrenumd/rrenumd.8 new file mode 100644 index 000000000000..418e4eeb68e8 --- /dev/null +++ b/usr.sbin/rrenumd/rrenumd.8 @@ -0,0 +1,101 @@ +.\" $KAME: rrenumd.8,v 1.6 2001/01/22 02:06:24 itojun Exp $ +.\" +.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the project nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 7, 1998 +.Dt RRENUMD 8 +.Os +.Sh NAME +.Nm rrenumd +.Nd router renumbering daemon +.Sh SYNOPSIS +.Nm +.Op Fl df +.Oo +.Fl c Ar conf_file | Fl s +.Oc +.Sh DESCRIPTION +The +.Nm +utility transmits router renumbering request packets, +to renumber the routers in the site network. +.Pp +On KAME-based systems, +router renumbering requests are received and processed by +.Xr rtadvd 8 . +For other systems, refer to relevant documents. +.Pp +The program will daemonize itself on invocation. +It reads configuration information from standard input if +.Fl s +is specified, or from +.Ar conf_file +if +.Fl c Ar conf_file +is specified. +.Pp +The contents of configuration information are described in +.Xr rrenumd.conf 5 . +.Pp +After successful configuration, +.Nm +sends router renumbering +messages periodically to configured destinations. +Messages contain prefixes configured to be renumbered. +.Bl -tag -width indent +.\" +.It Fl d +Debug mode. +.It Fl f +Foreground mode. +Do not become daemon. +.It Fl s +Script mode. +Configuration information is obtained from standard input. +.It Fl c Ar conf_file +Specify a configuration file where configuration information is kept. +.El +.Sh EXIT STATUS +The program exits with 0 on success, and non-zero on failures. +.Sh SEE ALSO +.Xr rrenumd.conf 5 , +.Xr rtadvd 8 +.Sh STANDARDS +.Rs +.%A Matt Crawford +.%R RFC +.%N 2894 +.%D August 2000 +.%T "Router Renumbering for IPv6" +.Re +.Sh HISTORY +The +.Nm +utility first appeared in KAME IPv6 protocol stack kit. +.\" .Sh BUGS +.\" (to be written) diff --git a/usr.sbin/rrenumd/rrenumd.c b/usr.sbin/rrenumd/rrenumd.c new file mode 100644 index 000000000000..152cf6346fd9 --- /dev/null +++ b/usr.sbin/rrenumd/rrenumd.c @@ -0,0 +1,659 @@ +/* $KAME: rrenumd.c,v 1.20 2000/11/08 02:40:53 itojun Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/time.h> + +#include <string.h> + +#include <net/route.h> + +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> +#include <netinet/icmp6.h> + +#include <arpa/inet.h> + +#ifdef IPSEC +#include <netipsec/ipsec.h> +#endif + +#include <stdio.h> +#include <err.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> + +#include "rrenumd.h" + +#define LL_ALLROUTERS "ff02::2" +#define SL_ALLROUTERS "ff05::2" + +#define RR_MCHLIM_DEFAULT 64 + +#ifndef IN6_IS_SCOPE_LINKLOCAL +#define IN6_IS_SCOPE_LINKLOCAL(a) \ + ((IN6_IS_ADDR_LINKLOCAL(a)) || \ + (IN6_IS_ADDR_MC_LINKLOCAL(a))) +#endif /* IN6_IS_SCOPE_LINKLOCAL */ + +struct flags { + u_long debug : 1; + u_long fg : 1; +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + u_long policy : 1; +#else /* IPSEC_POLICY_IPSEC */ + u_long auth : 1; + u_long encrypt : 1; +#endif /* IPSEC_POLICY_IPSEC */ +#endif /*IPSEC*/ +}; + +struct msghdr sndmhdr; +struct msghdr rcvmhdr; +struct sockaddr_in6 from; +struct sockaddr_in6 sin6_ll_allrouters; + +int s4, s6; +int with_v4dest, with_v6dest; +struct in6_addr prefix; /* ADHOC */ +int prefixlen = 64; /* ADHOC */ + +extern int parse(FILE **); + +static void show_usage(void); +static void init_sin6(struct sockaddr_in6 *, const char *); +#if 0 +static void join_multi(const char *); +#endif +static void init_globals(void); +static void config(FILE **); +#ifdef IPSEC_POLICY_IPSEC +static void sock6_open(struct flags *, char *); +static void sock4_open(struct flags *, char *); +#else +static void sock6_open(struct flags *); +static void sock4_open(struct flags *); +#endif +static void rrenum_output(struct payload_list *, struct dst_list *); +static void rrenum_snd_eachdst(struct payload_list *); +#if 0 +static void rrenum_snd_fullsequence(void); +#endif +static void rrenum_input(int); +int main(int, char *[]); + + +/* Print usage. Don't call this after daemonized. */ +static void +show_usage() +{ + fprintf(stderr, "usage: rrenumd [-c conf_file|-s] [-df" +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + "] [-P policy" +#else /* IPSEC_POLICY_IPSEC */ + "AE" +#endif /* IPSEC_POLICY_IPSEC */ +#endif /* IPSEC */ + "]\n"); + exit(1); +} + +static void +init_sin6(struct sockaddr_in6 *sin6, const char *addr_ascii) +{ + memset(sin6, 0, sizeof(*sin6)); + sin6->sin6_len = sizeof(*sin6); + sin6->sin6_family = AF_INET6; + if (inet_pton(AF_INET6, addr_ascii, &sin6->sin6_addr) != 1) + ; /* XXX do something */ +} + +#if 0 /* XXX: not necessary ?? */ +static void +join_multi(const char *addrname) +{ + struct ipv6_mreq mreq; + + if (inet_pton(AF_INET6, addrname, &mreq.ipv6mr_multiaddr.s6_addr) + != 1) { + syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", + __func__); + exit(1); + } + /* ADHOC: currently join only one */ + { + if ((mreq.ipv6mr_interface = if_nametoindex(ifname)) == 0) { + syslog(LOG_ERR, "<%s> ifname %s should be invalid: %s", + __func__, ifname, strerror(errno)); + exit(1); + } + if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mreq, + sizeof(mreq)) < 0) { + syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP on %s: %s", + __func__, ifname, strerror(errno)); + exit(1); + } + } +} +#endif + +static void +init_globals() +{ + static struct iovec rcviov; + static u_char rprdata[4500]; /* maximal MTU of connected links */ + static u_char *rcvcmsgbuf = NULL; + static u_char *sndcmsgbuf = NULL; + int sndcmsglen, rcvcmsglen; + + /* init ll_allrouters */ + init_sin6(&sin6_ll_allrouters, LL_ALLROUTERS); + + /* initialize msghdr for receiving packets */ + rcviov.iov_base = (caddr_t)rprdata; + rcviov.iov_len = sizeof(rprdata); + rcvmhdr.msg_namelen = sizeof(struct sockaddr_in6); + rcvmhdr.msg_iov = &rcviov; + rcvmhdr.msg_iovlen = 1; + rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + + CMSG_SPACE(sizeof(int)); + if (rcvcmsgbuf == NULL && + (rcvcmsgbuf = (u_char *)malloc(rcvcmsglen)) == NULL) { + syslog(LOG_ERR, "<%s>: malloc failed", __func__); + exit(1); + } + rcvmhdr.msg_control = (caddr_t)rcvcmsgbuf; + rcvmhdr.msg_controllen = rcvcmsglen; + + /* initialize msghdr for sending packets */ + sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); + sndmhdr.msg_iovlen = 1; + sndcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + + CMSG_SPACE(sizeof(int)); + if (sndcmsgbuf == NULL && + (sndcmsgbuf = (u_char *)malloc(sndcmsglen)) == NULL) { + syslog(LOG_ERR, "<%s>: malloc failed", __func__); + exit(1); + } + sndmhdr.msg_control = (caddr_t)sndcmsgbuf; + sndmhdr.msg_controllen = sndcmsglen; +} + +static void +config(FILE **fpp) +{ + struct payload_list *pl; + struct iovec *iov; + struct icmp6_router_renum *irr; + struct rr_pco_match *rpm; + + if (parse(fpp) < 0) { + syslog(LOG_ERR, "<%s> parse failed", __func__); + exit(1); + } + + /* initialize fields not configured by parser */ + for (pl = pl_head; pl; pl = pl->pl_next) { + iov = (struct iovec *)&pl->pl_sndiov; + irr = (struct icmp6_router_renum *)&pl->pl_irr; + rpm = (struct rr_pco_match *)&pl->pl_rpm; + + irr->rr_type = ICMP6_ROUTER_RENUMBERING; + irr->rr_code = 0; + /* + * now we don't support multiple PCOs in a rr message. + * so segment number is not supported. + */ + /* TODO: rr flags config in parser */ + irr->rr_flags |= ICMP6_RR_FLAGS_SPECSITE; + /* TODO: max delay config in parser */ + + /* + * means only 1 use_prefix is contained as router-renum-05.txt. + * now we don't support multiple PCOs in a rr message, + * nor multiple use_prefix in one PCO. + */ + rpm->rpm_len = 4*1 +3; + rpm->rpm_ordinal = 0; + iov->iov_base = (caddr_t)irr; + iov->iov_len = sizeof(struct icmp6_router_renum) + + sizeof(struct rr_pco_match) + + sizeof(struct rr_pco_use); + } +} + +static void +sock6_open(struct flags *flags +#ifdef IPSEC_POLICY_IPSEC + , char *policy +#endif /* IPSEC_POLICY_IPSEC */ + ) +{ + struct icmp6_filter filt; + int on; +#ifdef IPSEC +#ifndef IPSEC_POLICY_IPSEC + int optval; +#endif +#endif + + if (with_v6dest == 0) + return; + if (with_v6dest && + (s6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { + syslog(LOG_ERR, "<%s> socket(v6): %s", __func__, + strerror(errno)); + exit(1); + } + + /* + * join all routers multicast addresses. + */ +#if 0 /* XXX: not necessary ?? */ + join_multi(LL_ALLROUTERS); + join_multi(SL_ALLROUTERS); +#endif + + /* set icmpv6 filter */ + ICMP6_FILTER_SETBLOCKALL(&filt); + ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt); + if (setsockopt(s6, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, + sizeof(filt)) < 0) { + syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s", + __func__, strerror(errno)); + exit(1); + } + + /* specify to tell receiving interface */ + on = 1; + if (setsockopt(s6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, + sizeof(on)) < 0) { + syslog(LOG_ERR, "<%s> IPV6_RECVPKTINFO: %s", + __func__, strerror(errno)); + exit(1); + } + +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + if (flags->policy) { + char *buf; + buf = ipsec_set_policy(policy, strlen(policy)); + if (buf == NULL) + errx(1, "%s", ipsec_strerror()); + /* XXX should handle in/out bound policy. */ + if (setsockopt(s6, IPPROTO_IPV6, IPV6_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) + err(1, "setsockopt(IPV6_IPSEC_POLICY)"); + free(buf); + } +#else /* IPSEC_POLICY_IPSEC */ + if (flags->auth) { + optval = IPSEC_LEVEL_REQUIRE; + if (setsockopt(s6, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, + &optval, sizeof(optval)) == -1) { + syslog(LOG_ERR, "<%s> IPV6_AUTH_TRANS_LEVEL: %s", + __func__, strerror(errno)); + exit(1); + } + } + if (flags->encrypt) { + optval = IPSEC_LEVEL_REQUIRE; + if (setsockopt(s6, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, + &optval, sizeof(optval)) == -1) { + syslog(LOG_ERR, "<%s> IPV6_ESP_TRANS_LEVEL: %s", + __func__, strerror(errno)); + exit(1); + } + } +#endif /* IPSEC_POLICY_IPSEC */ +#endif /* IPSEC */ +} + +static void +sock4_open(struct flags *flags +#ifdef IPSEC_POLICY_IPSEC + , char *policy +#endif /* IPSEC_POLICY_IPSEC */ + ) +{ +#ifdef IPSEC +#ifndef IPSEC_POLICY_IPSEC + int optval; +#endif +#endif + + if (with_v4dest == 0) + return; + if ((s4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { + syslog(LOG_ERR, "<%s> socket(v4): %s", __func__, + strerror(errno)); + exit(1); + } + +#if 0 /* XXX: not necessary ?? */ + /* + * join all routers multicast addresses. + */ + some_join_function(); +#endif + +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + if (flags->policy) { + char *buf; + buf = ipsec_set_policy(policy, strlen(policy)); + if (buf == NULL) + errx(1, "%s", ipsec_strerror()); + /* XXX should handle in/out bound policy. */ + if (setsockopt(s4, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) + err(1, "setsockopt(IP_IPSEC_POLICY)"); + free(buf); + } +#else /* IPSEC_POLICY_IPSEC */ + if (flags->auth) { + optval = IPSEC_LEVEL_REQUIRE; + if (setsockopt(s4, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, + &optval, sizeof(optval)) == -1) { + syslog(LOG_ERR, "<%s> IP_AUTH_TRANS_LEVEL: %s", + __func__, strerror(errno)); + exit(1); + } + } + if (flags->encrypt) { + optval = IPSEC_LEVEL_REQUIRE; + if (setsockopt(s4, IPPROTO_IP, IP_ESP_TRANS_LEVEL, + &optval, sizeof(optval)) == -1) { + syslog(LOG_ERR, "<%s> IP_ESP_TRANS_LEVEL: %s", + __func__, strerror(errno)); + exit(1); + } + } +#endif /* IPSEC_POLICY_IPSEC */ +#endif /* IPSEC */ +} + +static void +rrenum_output(struct payload_list *pl, struct dst_list *dl) +{ + int i, msglen = 0; + struct cmsghdr *cm; + struct in6_pktinfo *pi; + struct sockaddr_in6 *sin6 = NULL; + + sndmhdr.msg_name = (caddr_t)dl->dl_dst; + if (dl->dl_dst->sa_family == AF_INET6) + sin6 = (struct sockaddr_in6 *)dl->dl_dst; + + if (sin6 != NULL && + IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { + int hoplimit = RR_MCHLIM_DEFAULT; + + cm = CMSG_FIRSTHDR(&sndmhdr); + /* specify the outgoing interface */ + cm->cmsg_level = IPPROTO_IPV6; + cm->cmsg_type = IPV6_PKTINFO; + cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + pi = (struct in6_pktinfo *)CMSG_DATA(cm); + memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/ + pi->ipi6_ifindex = sin6->sin6_scope_id; + msglen += CMSG_LEN(sizeof(struct in6_pktinfo)); + + /* specify the hop limit of the packet if dest is link local */ + /* not defined by router-renum-05.txt, but maybe its OK */ + cm = CMSG_NXTHDR(&sndmhdr, cm); + cm->cmsg_level = IPPROTO_IPV6; + cm->cmsg_type = IPV6_HOPLIMIT; + cm->cmsg_len = CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); + msglen += CMSG_LEN(sizeof(int)); + } + sndmhdr.msg_controllen = msglen; + if (sndmhdr.msg_controllen == 0) + sndmhdr.msg_control = 0; + + sndmhdr.msg_iov = &pl->pl_sndiov; + i = sendmsg(dl->dl_dst->sa_family == AF_INET ? s4 : s6, &sndmhdr, 0); + + if (i < 0 || i != sndmhdr.msg_iov->iov_len) + syslog(LOG_ERR, "<%s> sendmsg: %s", __func__, + strerror(errno)); +} + +static void +rrenum_snd_eachdst(struct payload_list *pl) +{ + struct dst_list *dl; + + for (dl = dl_head; dl; dl = dl->dl_next) { + rrenum_output(pl, dl); + } +} + +#if 0 +static void +rrenum_snd_fullsequence() +{ + struct payload_list *pl; + + for (pl = pl_head; pl; pl = pl->pl_next) { + rrenum_snd_eachdst(pl); + } +} +#endif + +static void +rrenum_input(int s) +{ + int i; + struct icmp6_router_renum *rr; + + /* get message */ + if ((i = recvmsg(s, &rcvmhdr, 0)) < 0) { + syslog(LOG_ERR, "<%s> recvmsg: %s", __func__, + strerror(errno)); + return; + } + if (s == s4) + i -= sizeof(struct ip); + if (i < sizeof(struct icmp6_router_renum)) { + syslog(LOG_ERR, "<%s> packet size(%d) is too short", + __func__, i); + return; + } + if (s == s4) { + struct ip *ip = (struct ip *)rcvmhdr.msg_iov->iov_base; + + rr = (struct icmp6_router_renum *)(ip + 1); + } else /* s == s6 */ + rr = (struct icmp6_router_renum *)rcvmhdr.msg_iov->iov_base; + + switch(rr->rr_code) { + case ICMP6_ROUTER_RENUMBERING_COMMAND: + /* COMMAND will be processed by rtadvd */ + break; + case ICMP6_ROUTER_RENUMBERING_RESULT: + /* TODO: receiving result message */ + break; + default: + syslog(LOG_ERR, "<%s> received unknown code %d", + __func__, rr->rr_code); + break; + } +} + +int +main(int argc, char *argv[]) +{ + FILE *fp = stdin; + fd_set fdset; + struct timeval timeout; + int ch, i, maxfd = 0, send_counter = 0; + struct flags flags; + struct payload_list *pl; +#ifdef IPSEC_POLICY_IPSEC + char *policy = NULL; +#endif + + memset(&flags, 0, sizeof(flags)); + openlog("rrenumd", LOG_PID, LOG_DAEMON); + + /* get options */ + while ((ch = getopt(argc, argv, "c:sdf" +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + "P:" +#else /* IPSEC_POLICY_IPSEC */ + "AE" +#endif /* IPSEC_POLICY_IPSEC */ +#endif /* IPSEC */ + )) != -1){ + switch (ch) { + case 'c': + if((fp = fopen(optarg, "r")) == NULL) { + syslog(LOG_ERR, + "<%s> config file %s open failed", + __func__, optarg); + exit(1); + } + break; + case 's': + fp = stdin; + break; + case 'd': + flags.debug = 1; + break; + case 'f': + flags.fg = 1; + break; +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + case 'P': + flags.policy = 1; + policy = strdup(optarg); + break; +#else /* IPSEC_POLICY_IPSEC */ + case 'A': + flags.auth = 1; + break; + case 'E': + flags.encrypt = 1; + break; +#endif /* IPSEC_POLICY_IPSEC */ +#endif /*IPSEC*/ + default: + show_usage(); + } + } + argc -= optind; + argv += optind; + + /* set log level */ + if (flags.debug == 0) + (void)setlogmask(LOG_UPTO(LOG_ERR)); + if (flags.debug == 1) + (void)setlogmask(LOG_UPTO(LOG_INFO)); + + /* init global variables */ + init_globals(); + + config(&fp); + + sock6_open(&flags +#ifdef IPSEC_POLICY_IPSEC + , policy +#endif /* IPSEC_POLICY_IPSEC */ + ); + sock4_open(&flags +#ifdef IPSEC_POLICY_IPSEC + , policy +#endif /* IPSEC_POLICY_IPSEC */ + ); + + if (!flags.fg) + daemon(0, 0); + + FD_ZERO(&fdset); + if (with_v6dest) { + FD_SET(s6, &fdset); + if (s6 > maxfd) + maxfd = s6; + } + if (with_v4dest) { + FD_SET(s4, &fdset); + if (s4 > maxfd) + maxfd = s4; + } + + /* ADHOC: timeout each 30seconds */ + memset(&timeout, 0, sizeof(timeout)); + + /* init temporary payload_list and send_counter*/ + pl = pl_head; + send_counter = retry + 1; + while (1) { + struct fd_set select_fd = fdset; /* reinitialize */ + + if ((i = select(maxfd + 1, &select_fd, NULL, NULL, + &timeout)) < 0){ + syslog(LOG_ERR, "<%s> select: %s", + __func__, strerror(errno)); + continue; + } + if (i == 0) { /* timeout */ + if (pl == NULL) + exit(0); + rrenum_snd_eachdst(pl); + send_counter--; + timeout.tv_sec = 30; + if (send_counter == 0) { + timeout.tv_sec = 0; + pl = pl->pl_next; + send_counter = retry + 1; + } + } + if (FD_ISSET(s4, &select_fd)) + rrenum_input(s4); + if (FD_ISSET(s6, &select_fd)) + rrenum_input(s6); + } +} diff --git a/usr.sbin/rrenumd/rrenumd.conf.5 b/usr.sbin/rrenumd/rrenumd.conf.5 new file mode 100644 index 000000000000..f12d6d900c88 --- /dev/null +++ b/usr.sbin/rrenumd/rrenumd.conf.5 @@ -0,0 +1,367 @@ +.\" $KAME: rrenumd.conf.5,v 1.8 2001/02/06 02:17:23 jinmei Exp $ +.\" +.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the project nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd November 5, 1998 +.Dt RRENUMD.CONF 5 +.Os +.Sh NAME +.\" +.Nm rrenumd.conf +.Nd configuration file for router renumbering daemon +.\" +.Sh DESCRIPTION +The rrenumd config file describes how the router renumbering packet +must be constructed and to which destinations it should be sent. +This file consists of a sequence of statements terminated by a semi-colon (`;'). +Statements are composed of tokens +separated by white space, which can be any combination of blanks, tabs +and newlines. +This structure simplifies identification of +the parts of the configuration associated with each other. +Lines beginning with +.Ql # +are comments. +.\" +.Sh Meta Syntax +Keywords and special characters that the parser expects exactly are +displayed using the +.Ic bold +font. +Parameters are specifying with +.Ar underline . +Parameters shown in +square brackets (`[' and `]') are used to show optional +keywords and parameters. +The vertical bar (`|') is used to indicate +between a choice of optional parameters. +Curly braces (`{' and +`}') are used to group keywords and parameters when necessary. +.\" +.Sh Interface specification +There are some statements that may or have to specify interface. +Interfaces are specified in the form of "name unit", such as +.Ar lo0 +and +.Ar ep1 . +.\" +.Sh Configuration Statements +.Bl -tag -width Ds +.\" +.It Ic debug on|off ; +Enables configuration file parser debugging. +If +.Ic on +is specified, +then debugging is enabled, +If +.Ic off +is specified, +then debugging is disabled. +It is disabled by default. +.\" +.It Ic dest Ar dest-list Op Ar retrycmd ; +Specifies destinations to which router renumbering messages should be +sent. +.Ar dest-list +can be any combination of single or multiple numerical IPv6 addrs, +or Full Qualified Domain Names. +.Ar retrycmd +has following syntax. +.\" +.Bl -tag -width Ds +.It Ic retry Ar retry-num +.Ar retry-num +specifies how many router renumbering messages are sent repeatedly. +.El +.It Op Ic add|change|setglobal +.Cm match-prefix Ar match-prefix-val +.Bk -words +.Op /match-prefix-len +.Ek +.Bk -words +.Op Cm maxlen Ar maxlen-val +.Ek +.Bk -words +.Op Cm minlen Ar minlen-val +.Ek +.Bk -words +.Op Cm use-prefix Ar use-prefix-val +.Ek +.Bk -words +.Op /use-prefix-len +.Ek +.Bk -words +.Op Cm keeplen Ar keeplen-val +.Ek +.Bk -words +.Op Ar use-prefix-values ; +.Ek +.Pp +Specifies contents of sending router renumbering message with seqnum 0. +If +.Cm add|change|setglobal +is not specified, then +.Cm add +is assumed. +.Ar use-prefix-values +has following syntax. +.Pp +{ +.Op Cm vltime Ar vltime-val +.Bk -words +.Op Cm pltime Ar pltime-val +.Ek +.Bk -words +.Op Cm raf_onlink Cm on|off +.Ek +.Bk -words +.Op Cm raf_auto Cm on|off +.Ek +.Bk -words +.Op Cm rrf_decrprefd Cm on|off +.Ek +.Bk -words +.Op Cm rrf_decrvalid Cm on|off +.Ek +} +.Pp +Each value has following meaning. +.Pp +.Bl -tag -width Ds -compact +.It Cm match-prefix Ar match-prefix-val Op /match-prefix-len +Specify +.Ar match-prefix-val +that is used for matching with preassigned prefixes to which +.Cm add|change|setglobal +command should be applied. +.Ar /match-prefix-len +Specify the starting part of +.Ar match-prefix-val +to be used for matching with preassigned prefixes, as decimal bit number. +.It Cm maxlen Ar maxlen-val +Specify the maximum length of prefixes which is allowed to be +matched to +.Ar match-prefix-val , +as decimal bit number. +.It Cm minlen Ar minlen-val +Specify the minimum length of prefixes which is allowed to be matched to +.Ar match-prefix-val , +as decimal bit number. +.It Cm use-prefix Ar use-prefix-val Op /usr-prefix-len +Specify +.Ar use-prefix-val +that is used for prefixes to be added on +.Cm add|change|setglobal +command. +.Ar /use-prefix-len +Specify the starting part of +.Ar use-prefix-val +copied to the starting part of prefixes to be added on +.Cm add|change|setglobal +command, as decimal bit number. +.It Cm keeplen Ar keeplen-val +Specify the medium part of +.Ar use-prefix-val +just next to the starting part specified by +.Ar use-prefix-len , +as decimal bit number. +Contiguous bits part in the same bit position of an existent prefix +matched with +.Ar match-prefix-val +is copied to the same bit position of prefixes to be added. +.It Cm vltime Ar vmtime-val +Assign an +.Ar time +as prefix valid life time for a prefix to be added. +Valid value for +.Ar time +is decimal seconds number or special format as "d00h00m00s00", +where 00 can take any decimal number, and "d" means days, "h" means hours, +"m" means minutes, "s" means seconds. +And alternatively, special keyword +"infinity" can be also be specified. +.It Cm pltime Ar pltime-val +Assign an +.Ar time +as prefix preferred life time for a prefix to be added. +Valid value for +.Ar time +is same as for +.Ar vltime-val . +.It Cm raf_onlink Cm on|off +Let the prefix to be added to have on-link or off-link nature +for the assigned interface. +If +.Cm on +is specified, the prefix have on-link nature +(e.g.\& the prefix +belong to the link). +If +.Cm off +is specified, the prefix have off-link nature +(e.g.\& the +prefix does not belong to the link). +.It Cm raf_auto Cm on|off +Enable or disable the autonomous address auto configuration +for the prefix to be added. +If +.Cm on +is specified, autonomous address auto configuration is +enabled. +If +.Cm off +is specified, it is disabled. +.It Cm rrf_decrprefd Cm on|off +Enable or disable the decrementation of the pltime. +If +.Cm on +is specified, decrementation of the pltime is enabled. +If +.Cm off +is specified, decrementation of the pltime is disabled. +.It Cm rrf_decrvalid Cm on|off +Enable or disable the decrementation of the vltime. +If +.Cm on +is specified, decrementation of the vltime is enabled. +If +.Cm off +is specified, decrementation of the vltime is disabled. +.El +.\" +.It seqnum Ar seqnum-val { Ar rrenum-cmd } ; +Specifies contents of sending router renumbering message with some +specific seqnum. +Multiple of this statement can be specified if they +have different +.Ar seqnum-val +each other. +.Ar rrenum-cmd +has just same syntax with above add|change|setglobal statement. +.El +.\" +.Sh EXAMPLES +For each configuration file example shown below, we suppose +every IPv6 subnet has its own prefix beginning with +fec0:0:0::/48 and with its own subnet number +(in this case, +subnet number is 7th and 8th octet value of the prefix). +.Pp +If you want to assign prefixes beginning with 3ffe:501:ffff::/48 +to each subnet, then following configuration will be enough, +if each of your routers supports IPv6 multicast forwarding. +The subnet number of the existing fec0:0:0::/48 prefix and the +newly assigned 3ffe:501:ffff::/48 prefix will be same. +.\" +.Bd -literal -offset indent +dest ff05::2; + +add match-prefix fec0:0:0:: /48 use-prefix 3ffe:501:ffff:: /48 keeplen 16; +.Ed +.Pp +.\" +If your routers do not support IPv6 multicast forwarding, +you will need to specify each destination at +.Cm dest +command. +.\" +.Bd -literal -offset indent +dest fec0:0:0:1:260:8ff:fe24:fb3a fec0:0:0:2:200:eff:fe2e:dfe1 fec0:0:0:3:5254:ff:fedc:5217; + +add match-prefix fec0:0:0:: /48 use-prefix 3ffe:501:ffff:: /48 keeplen 16; +.Ed +.Pp +.\" +If you are going to do renumbering, then following procedure will be natural. +.Bl -enum -offset indent +.It +Assign a new prefix. +.It +Set old prefix lifetimes to some appropriate transition +period. +In the following example we use 1 week for valid +lifetime, and 0 for preferred lifetime. +Also, enable old prefix lifetime expiration +(By default, it is static and does not expire). +.It +After the transition period, old prefixes should become +invalid, and may have been deleted. +To make sure that they are deleted, send new router +renumbering message, which specifies old prefixes as match +prefix, and no use prefix. +.El +.Pp +.\" +The following configuration file will do 1 and 2. +.\" +.Bd -literal -offset indent +dest ff05::2; + +seqnum 0 { + add match-prefix fec0:0:0:: /48 use-prefix 3ffe:501:fffe:: /48 keeplen 16; + }; + +seqnum 1 { + change match-prefix 3ffe:501:ffff:: /48 use-prefix 3ffe:501:ffff:: /48 keeplen 16 vltime d7 pltime 0 rrf_decrvalid on rrf_decrprefd on; + }; +.Ed +.Pp +.\" +And the following configuration file will do 3 +(should be +used for the router renumbering message to be sent 1 week +afterward). +.\" +.Bd -literal -offset indent +dest ff05::2; + +change match-prefix 3ffe:501:ffff:: /48; +.Ed +.Pp +.\" +In the above example, only +.Cm add +and +.Cm change +commands are used, and there is no example for +.Cm setglobal +command. +.Cm setglobal +command is almost same with +.Cm change +command except that it deletes all pre-defined IPv6 global address. +.Sh SEE ALSO +.Xr prefix 8 , +.Xr rrenumd 8 +.Sh HISTORY +The +.Nm +configuration file was first appeared in KAME IPv6 protocol stack kit. +.\" .Sh BUGS +.\" (to be written) diff --git a/usr.sbin/rrenumd/rrenumd.h b/usr.sbin/rrenumd/rrenumd.h new file mode 100644 index 000000000000..521d3e48fada --- /dev/null +++ b/usr.sbin/rrenumd/rrenumd.h @@ -0,0 +1,60 @@ +/* $KAME: rrenumd.h,v 1.2 2000/07/03 02:54:09 itojun Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by WIDE Project and + * its contributors. + * 4. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct dst_list { + struct dst_list * dl_next; + struct sockaddr * dl_dst; +}; + +extern struct dst_list *dl_head; + +struct payload_list { + struct payload_list * pl_next; + struct iovec pl_sndiov; + struct icmp6_router_renum + pl_irr; + struct rr_pco_match pl_rpm; + /* currently, support only 1 rr_pco_use field per packet */ + struct rr_pco_use pl_rpu; +}; + +extern struct payload_list *pl_head; +extern u_int retry; +extern int with_v4dest, with_v6dest; + +#define DEF_VLTIME 2592000 +#define DEF_PLTIME 604800 |
