X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fipv6cp.c;h=d80ae216814e9017e65e629aaf15d038d61e4c39;hp=356ff84ead4103cb846c31c6e806786b166a33e5;hb=f1a34da3b2f5336e4993a729e5ac2130d0e0595a;hpb=3a5c9a8fbc8970375cd881151d44e4b6fe249c6a diff --git a/pppd/ipv6cp.c b/pppd/ipv6cp.c index 356ff84..d80ae21 100644 --- a/pppd/ipv6cp.c +++ b/pppd/ipv6cp.c @@ -134,12 +134,8 @@ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $ */ -#define RCSID "$Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $" - /* * TODO: * @@ -168,7 +164,6 @@ #include "magic.h" #include "pathnames.h" -static const char rcsid[] = RCSID; /* global vars */ ipv6cp_options ipv6cp_wantoptions[NUM_PPP]; /* Options that we want to request */ @@ -178,13 +173,14 @@ ipv6cp_options ipv6cp_hisoptions[NUM_PPP]; /* Options that we ack'd */ int no_ifaceid_neg = 0; /* local vars */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ static int ipv6cp_is_up; /* Hook for a plugin to know when IPv6 protocol has come up */ -void (*ipv6_up_hook) __P((void)) = NULL; +void (*ipv6_up_hook)(void) = NULL; /* Hook for a plugin to know when IPv6 protocol has come down */ -void (*ipv6_down_hook) __P((void)) = NULL; +void (*ipv6_down_hook)(void) = NULL; /* Notifiers for when IPCPv6 goes up and down */ struct notifier *ipv6_up_notifier = NULL; @@ -193,16 +189,16 @@ struct notifier *ipv6_down_notifier = NULL; /* * Callbacks for fsm code. (CI = Configuration Information) */ -static void ipv6cp_resetci __P((fsm *)); /* Reset our CI */ -static int ipv6cp_cilen __P((fsm *)); /* Return length of our CI */ -static void ipv6cp_addci __P((fsm *, u_char *, int *)); /* Add our CI */ -static int ipv6cp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ -static int ipv6cp_nakci __P((fsm *, u_char *, int, int));/* Peer nak'd our CI */ -static int ipv6cp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ -static int ipv6cp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ -static void ipv6cp_up __P((fsm *)); /* We're UP */ -static void ipv6cp_down __P((fsm *)); /* We're DOWN */ -static void ipv6cp_finished __P((fsm *)); /* Don't need lower layer */ +static void ipv6cp_resetci (fsm *); /* Reset our CI */ +static int ipv6cp_cilen (fsm *); /* Return length of our CI */ +static void ipv6cp_addci (fsm *, u_char *, int *); /* Add our CI */ +static int ipv6cp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */ +static int ipv6cp_nakci (fsm *, u_char *, int, int);/* Peer nak'd our CI */ +static int ipv6cp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */ +static int ipv6cp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */ +static void ipv6cp_up (fsm *); /* We're UP */ +static void ipv6cp_down (fsm *); /* We're DOWN */ +static void ipv6cp_finished (fsm *); /* Don't need lower layer */ fsm ipv6cp_fsm[NUM_PPP]; /* IPV6CP fsm structure */ @@ -227,9 +223,9 @@ static fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ /* * Command-line options. */ -static int setifaceid __P((char **arg)); -static void printifaceid __P((option_t *, - void (*)(void *, char *, ...), void *)); +static int setifaceid (char **arg); +static void printifaceid (option_t *, + void (*)(void *, char *, ...), void *); static option_t ipv6cp_option_list[] = { { "ipv6", o_special, (void *)setifaceid, @@ -245,6 +241,17 @@ static option_t ipv6cp_option_list[] = { { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, "Accept peer's interface identifier for us", 1 }, + { "ipv6cp-accept-remote", o_bool, &ipv6cp_allowoptions[0].accept_remote, + "Accept peer's interface identifier for itself", 1 }, + + { "defaultroute6", o_bool, &ipv6cp_wantoptions[0].default_route, + "Add default IPv6 route", OPT_ENABLE|1, &ipv6cp_allowoptions[0].default_route }, + { "nodefaultroute6", o_bool, &ipv6cp_allowoptions[0].default_route, + "disable defaultroute6 option", OPT_A2CLR, + &ipv6cp_wantoptions[0].default_route }, + { "-defaultroute6", o_bool, &ipv6cp_allowoptions[0].default_route, + "disable defaultroute6 option", OPT_ALIAS | OPT_A2CLR, + &ipv6cp_wantoptions[0].default_route }, { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, "Use (default) IPv4 address as interface identifier", 1 }, @@ -268,18 +275,18 @@ static option_t ipv6cp_option_list[] = { /* * Protocol entry points from main code. */ -static void ipv6cp_init __P((int)); -static void ipv6cp_open __P((int)); -static void ipv6cp_close __P((int, char *)); -static void ipv6cp_lowerup __P((int)); -static void ipv6cp_lowerdown __P((int)); -static void ipv6cp_input __P((int, u_char *, int)); -static void ipv6cp_protrej __P((int)); -static int ipv6cp_printpkt __P((u_char *, int, - void (*) __P((void *, char *, ...)), void *)); -static void ipv6_check_options __P((void)); -static int ipv6_demand_conf __P((int)); -static int ipv6_active_pkt __P((u_char *, int)); +static void ipv6cp_init (int); +static void ipv6cp_open (int); +static void ipv6cp_close (int, char *); +static void ipv6cp_lowerup (int); +static void ipv6cp_lowerdown (int); +static void ipv6cp_input (int, u_char *, int); +static void ipv6cp_protrej (int); +static int ipv6cp_printpkt (u_char *, int, + void (*) (void *, char *, ...), void *); +static void ipv6_check_options (void); +static int ipv6_demand_conf (int); +static int ipv6_active_pkt (u_char *, int); struct protent ipv6cp_protent = { PPP_IPV6CP, @@ -292,7 +299,7 @@ struct protent ipv6cp_protent = { ipv6cp_close, ipv6cp_printpkt, NULL, - 0, + 1, "IPV6CP", "IPV6", ipv6cp_option_list, @@ -301,9 +308,9 @@ struct protent ipv6cp_protent = { ipv6_active_pkt }; -static void ipv6cp_clear_addrs __P((int, eui64_t, eui64_t)); -static void ipv6cp_script __P((char *)); -static void ipv6cp_script_done __P((void *)); +static void ipv6cp_clear_addrs (int, eui64_t, eui64_t); +static void ipv6cp_script (char *); +static void ipv6cp_script_done (void *); /* * Lengths of configuration options. @@ -329,8 +336,7 @@ static pid_t ipv6cp_script_pid; * setifaceid - set the interface identifiers manually */ static int -setifaceid(argv) - char **argv; +setifaceid(char **argv) { char *comma, *arg, c; ipv6cp_options *wo = &ipv6cp_wantoptions[0]; @@ -387,10 +393,7 @@ setifaceid(argv) char *llv6_ntoa(eui64_t ifaceid); static void -printifaceid(opt, printer, arg) - option_t *opt; - void (*printer) __P((void *, char *, ...)); - void *arg; +printifaceid(option_t *opt, void (*printer) (void *, char *, ...), void *arg) { ipv6cp_options *wo = &ipv6cp_wantoptions[0]; @@ -405,8 +408,7 @@ printifaceid(opt, printer, arg) * Make a string representation of a network address. */ char * -llv6_ntoa(ifaceid) - eui64_t ifaceid; +llv6_ntoa(eui64_t ifaceid) { static char b[64]; @@ -419,8 +421,7 @@ llv6_ntoa(ifaceid) * ipv6cp_init - Initialize IPV6CP. */ static void -ipv6cp_init(unit) - int unit; +ipv6cp_init(int unit) { fsm *f = &ipv6cp_fsm[unit]; ipv6cp_options *wo = &ipv6cp_wantoptions[unit]; @@ -434,7 +435,8 @@ ipv6cp_init(unit) memset(wo, 0, sizeof(*wo)); memset(ao, 0, sizeof(*ao)); - wo->accept_local = 1; + wo->accept_local = 0; + wo->accept_remote = 0; wo->neg_ifaceid = 1; ao->neg_ifaceid = 1; @@ -444,6 +446,10 @@ ipv6cp_init(unit) wo->vj_protocol = IPV6CP_COMP; #endif + /* + * XXX This controls whether the user may use the defaultroute option. + */ + ao->default_route = 1; } @@ -451,8 +457,7 @@ ipv6cp_init(unit) * ipv6cp_open - IPV6CP is allowed to come up. */ static void -ipv6cp_open(unit) - int unit; +ipv6cp_open(int unit) { fsm_open(&ipv6cp_fsm[unit]); } @@ -462,9 +467,7 @@ ipv6cp_open(unit) * ipv6cp_close - Take IPV6CP down. */ static void -ipv6cp_close(unit, reason) - int unit; - char *reason; +ipv6cp_close(int unit, char *reason) { fsm_close(&ipv6cp_fsm[unit], reason); } @@ -474,8 +477,7 @@ ipv6cp_close(unit, reason) * ipv6cp_lowerup - The lower layer is up. */ static void -ipv6cp_lowerup(unit) - int unit; +ipv6cp_lowerup(int unit) { fsm_lowerup(&ipv6cp_fsm[unit]); } @@ -485,8 +487,7 @@ ipv6cp_lowerup(unit) * ipv6cp_lowerdown - The lower layer is down. */ static void -ipv6cp_lowerdown(unit) - int unit; +ipv6cp_lowerdown(int unit) { fsm_lowerdown(&ipv6cp_fsm[unit]); } @@ -496,10 +497,7 @@ ipv6cp_lowerdown(unit) * ipv6cp_input - Input IPV6CP packet. */ static void -ipv6cp_input(unit, p, len) - int unit; - u_char *p; - int len; +ipv6cp_input(int unit, u_char *p, int len) { fsm_input(&ipv6cp_fsm[unit], p, len); } @@ -511,8 +509,7 @@ ipv6cp_input(unit, p, len) * Pretend the lower layer went down, so we shut up. */ static void -ipv6cp_protrej(unit) - int unit; +ipv6cp_protrej(int unit) { fsm_lowerdown(&ipv6cp_fsm[unit]); } @@ -522,8 +519,7 @@ ipv6cp_protrej(unit) * ipv6cp_resetci - Reset our CI. */ static void -ipv6cp_resetci(f) - fsm *f; +ipv6cp_resetci(fsm *f) { ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit]; ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; @@ -531,8 +527,12 @@ ipv6cp_resetci(f) wo->req_ifaceid = wo->neg_ifaceid && ipv6cp_allowoptions[f->unit].neg_ifaceid; if (!wo->opt_local) { - eui64_magic_nz(wo->ourid); + wo->accept_local = 1; + if (!demand) + eui64_magic_nz(wo->ourid); } + if (!wo->opt_remote) + wo->accept_remote = 1; *go = *wo; eui64_zero(go->hisid); /* last proposed interface identifier */ @@ -543,8 +543,7 @@ ipv6cp_resetci(f) * ipv6cp_cilen - Return length of our CI. */ static int -ipv6cp_cilen(f) - fsm *f; +ipv6cp_cilen(fsm *f) { ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; @@ -560,10 +559,7 @@ ipv6cp_cilen(f) * ipv6cp_addci - Add our desired CIs to a packet. */ static void -ipv6cp_addci(f, ucp, lenp) - fsm *f; - u_char *ucp; - int *lenp; +ipv6cp_addci(fsm *f, u_char *ucp, int *lenp) { ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; int len = *lenp; @@ -608,10 +604,7 @@ ipv6cp_addci(f, ucp, lenp) * 1 - Ack was good. */ static int -ipv6cp_ackci(f, p, len) - fsm *f; - u_char *p; - int len; +ipv6cp_ackci(fsm *f, u_char *p, int len) { ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; u_short cilen, citype, cishort; @@ -679,11 +672,7 @@ bad: * 1 - Nak was good. */ static int -ipv6cp_nakci(f, p, len, treat_as_reject) - fsm *f; - u_char *p; - int len; - int treat_as_reject; +ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; u_char citype, cilen, *next; @@ -817,10 +806,7 @@ bad: * ipv6cp_rejci - Reject some of our CIs. */ static int -ipv6cp_rejci(f, p, len) - fsm *f; - u_char *p; - int len; +ipv6cp_rejci(fsm *f, u_char *p, int len) { ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; u_char cilen; @@ -892,11 +878,7 @@ bad: * CONFNAK; returns CONFREJ if it can't return CONFACK. */ static int -ipv6cp_reqci(f, inp, len, reject_if_disagree) - fsm *f; - u_char *inp; /* Requested CIs */ - int *len; /* Length of requested CIs */ - int reject_if_disagree; +ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit]; ipv6cp_options *ho = &ipv6cp_hisoptions[f->unit]; @@ -960,7 +942,7 @@ ipv6cp_reqci(f, inp, len, reject_if_disagree) orc = CONFREJ; /* Reject CI */ break; } - if (!eui64_iszero(wo->hisid) && + if (!eui64_iszero(wo->hisid) && !wo->accept_remote && !eui64_equals(ifaceid, wo->hisid) && eui64_iszero(go->hisid)) { @@ -1074,12 +1056,47 @@ endswitch: } +/* + * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI + * + * walks the list of valid ethernet interfaces, starting with devnam + * (for PPPoE it is ethernet interface), and convert the first + * found 48-bit MAC address into EUI 64. caller also assumes that + * the system has a properly configured Ethernet interface for this + * function to return non-zero. + */ +static int +ether_to_eui64(eui64_t *p_eui64) +{ + u_char addr[6]; + + if (get_if_hwaddr(addr, devnam) < 0 && get_first_ether_hwaddr(addr) < 0) { + error("ipv6cp: no persistent id can be found"); + return 0; + } + + /* + * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1] + */ + p_eui64->e8[0] = addr[0] | 0x02; + p_eui64->e8[1] = addr[1]; + p_eui64->e8[2] = addr[2]; + p_eui64->e8[3] = 0xFF; + p_eui64->e8[4] = 0xFE; + p_eui64->e8[5] = addr[3]; + p_eui64->e8[6] = addr[4]; + p_eui64->e8[7] = addr[5]; + + return 1; +} + + /* * ipv6_check_options - check that any IP-related options are OK, * and assign appropriate defaults. */ static void -ipv6_check_options() +ipv6_check_options(void) { ipv6cp_options *wo = &ipv6cp_wantoptions[0]; @@ -1090,7 +1107,7 @@ ipv6_check_options() * Persistent link-local id is only used when user has not explicitly * configure/hard-code the id */ - if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { + if ((wo->use_persistent) && (!wo->opt_local)) { /* * On systems where there are no Ethernet interfaces used, there @@ -1124,11 +1141,6 @@ ipv6_check_options() wo->opt_remote = 1; } } - - if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { - option_error("local/remote LL address required for demand-dialling\n"); - exit(EXIT_OPTION_ERROR); - } } @@ -1137,11 +1149,19 @@ ipv6_check_options() * IPV6CP were up, for use with dial-on-demand. */ static int -ipv6_demand_conf(u) - int u; +ipv6_demand_conf(int u) { ipv6cp_options *wo = &ipv6cp_wantoptions[u]; + if (eui64_iszero(wo->hisid)) { + /* make up an arbitrary identifier for the peer */ + eui64_magic_nz(wo->hisid); + } + if (eui64_iszero(wo->ourid)) { + /* make up an arbitrary identifier for us */ + eui64_magic_nz(wo->ourid); + } + if (!sif6up(u)) return 0; if (!sif6addr(u, wo->ourid, wo->hisid)) @@ -1152,8 +1172,10 @@ ipv6_demand_conf(u) #endif if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) return 0; + if (wo->default_route) + if (sif6defaultroute(u, wo->ourid, wo->hisid)) + default_route_set[u] = 1; - notice("ipv6_demand_conf"); notice("local LL address %s", llv6_ntoa(wo->ourid)); notice("remote LL address %s", llv6_ntoa(wo->hisid)); @@ -1167,8 +1189,7 @@ ipv6_demand_conf(u) * Configure the IPv6 network interface appropriately and bring it up. */ static void -ipv6cp_up(f) - fsm *f; +ipv6cp_up(fsm *f) { ipv6cp_options *ho = &ipv6cp_hisoptions[f->unit]; ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; @@ -1221,7 +1242,7 @@ ipv6cp_up(f) if (! eui64_equals(ho->hisid, wo->hisid)) warn("Remote LL address changed to %s", llv6_ntoa(ho->hisid)); - ipv6cp_clear_addrs(f->unit, go->ourid, ho->hisid); + ipv6cp_clear_addrs(f->unit, wo->ourid, wo->hisid); /* Set the interface to the new addresses */ if (!sif6addr(f->unit, go->ourid, ho->hisid)) { @@ -1231,6 +1252,10 @@ ipv6cp_up(f) return; } + /* assign a default route through the interface if required */ + if (ipv6cp_wantoptions[f->unit].default_route) + if (sif6defaultroute(f->unit, go->ourid, ho->hisid)) + default_route_set[f->unit] = 1; } demand_rexmit(PPP_IPV6); sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); @@ -1252,6 +1277,11 @@ ipv6cp_up(f) } sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); + /* assign a default route through the interface if required */ + if (ipv6cp_wantoptions[f->unit].default_route) + if (sif6defaultroute(f->unit, go->ourid, ho->hisid)) + default_route_set[f->unit] = 1; + notice("local LL address %s", llv6_ntoa(go->ourid)); notice("remote LL address %s", llv6_ntoa(ho->hisid)); } @@ -1281,8 +1311,7 @@ ipv6cp_up(f) * and delete routes through it. */ static void -ipv6cp_down(f) - fsm *f; +ipv6cp_down(fsm *f) { IPV6CPDEBUG(("ipv6cp: down")); update_link_stats(f->unit); @@ -1331,10 +1360,7 @@ ipv6cp_down(f) * proxy neighbour discovery entries, etc. */ static void -ipv6cp_clear_addrs(unit, ourid, hisid) - int unit; - eui64_t ourid; - eui64_t hisid; +ipv6cp_clear_addrs(int unit, eui64_t ourid, eui64_t hisid) { cif6addr(unit, ourid, hisid); } @@ -1344,8 +1370,7 @@ ipv6cp_clear_addrs(unit, ourid, hisid) * ipv6cp_finished - possibly shut down the lower layers. */ static void -ipv6cp_finished(f) - fsm *f; +ipv6cp_finished(fsm *f) { np_finished(f->unit, PPP_IPV6); } @@ -1356,8 +1381,7 @@ ipv6cp_finished(f) * has finished. */ static void -ipv6cp_script_done(arg) - void *arg; +ipv6cp_script_done(void *arg) { ipv6cp_script_pid = 0; switch (ipv6cp_script_state) { @@ -1382,8 +1406,7 @@ ipv6cp_script_done(arg) * interface-name tty-name speed local-LL remote-LL. */ static void -ipv6cp_script(script) - char *script; +ipv6cp_script(char *script) { char strspeed[32], strlocal[32], strremote[32]; char *argv[8]; @@ -1414,11 +1437,8 @@ static char *ipv6cp_codenames[] = { }; static int -ipv6cp_printpkt(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer) __P((void *, char *, ...)); - void *arg; +ipv6cp_printpkt(u_char *p, int plen, + void (*printer) (void *, char *, ...), void *arg) { int code, id, len, olen; u_char *pstart, *optend; @@ -1521,9 +1541,7 @@ ipv6cp_printpkt(p, plen, printer, arg) #define get_tcpflags(x) (((unsigned char *)(x))[13]) static int -ipv6_active_pkt(pkt, len) - u_char *pkt; - int len; +ipv6_active_pkt(u_char *pkt, int len) { u_char *tcp;