X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fipv6cp.c;h=3a370a0caa96fe55a5486c9a4c6730aeb2f8efc2;hp=e2055a445b32c77637008ed258462155511b2bb2;hb=8832e3ba208085ae3f15c0d48c2bb7a02bc9ae79;hpb=10a68fd183c5e16e95fce56e7b292f1436b1e714 diff --git a/pppd/ipv6cp.c b/pppd/ipv6cp.c index e2055a4..3a370a0 100644 --- a/pppd/ipv6cp.c +++ b/pppd/ipv6cp.c @@ -2,19 +2,14 @@ ipv6cp.c - PPP IPV6 Control Protocol. Copyright (C) 1999 Tommi Komulainen - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Redistribution and use in source and binary forms are permitted + provided that the above copyright notice and this paragraph are + duplicated in all such forms. The name of the author 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Original version, based on RFC2023 : @@ -95,10 +90,10 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ipv6cp.c,v 1.4 1999/08/25 04:15:51 paulus Exp $ + * $Id: ipv6cp.c,v 1.15 2001/03/22 00:42:33 paulus Exp $ */ -#define RCSID "$Id: ipv6cp.c,v 1.4 1999/08/25 04:15:51 paulus Exp $" +#define RCSID "$Id: ipv6cp.c,v 1.15 2001/03/22 00:42:33 paulus Exp $" /* * TODO: @@ -177,30 +172,40 @@ 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 option_t ipv6cp_option_list[] = { - { "ipv6", o_special, setifaceid, - "Set interface identifiers for IPV6" }, + { "ipv6", o_special, (void *)setifaceid, + "Set interface identifiers for IPV6", + OPT_A2PRINTER, (void *)printifaceid }, + + { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Enable IPv6 and IPv6CP", OPT_PRIO | 1 }, { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP" }, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB }, { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP" }, - { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Enable IPv6 and IPv6CP", 1 }, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, "Accept peer's interface identifier for us", 1 }, + { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, - "Use (default) IPv4 address as interface identifier", 0 }, + "Use (default) IPv4 address as interface identifier", 1 }, + +#if defined(SOL2) + { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, + "Use uniquely-available persistent value for link local address", 1 }, +#endif /* defined(SOL2) */ { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, - "Set timeout for IPv6CP" }, + "Set timeout for IPv6CP", OPT_PRIO }, { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, - "Set max #xmits for term-reqs" }, + "Set max #xmits for term-reqs", OPT_PRIO }, { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, - "Set max #xmits for conf-reqs" }, + "Set max #xmits for conf-reqs", OPT_PRIO }, { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, - "Set max #conf-naks for IPv6CP" }, + "Set max #conf-naks for IPv6CP", OPT_PRIO }, { NULL } }; @@ -273,10 +278,11 @@ static int setifaceid(argv) char **argv; { - char *comma, *arg; + char *comma, *arg, c; ipv6cp_options *wo = &ipv6cp_wantoptions[0]; struct in6_addr addr; - + static int prio_local, prio_remote; + #define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) @@ -288,16 +294,20 @@ setifaceid(argv) * If comma first character, then no local identifier */ if (comma != arg) { + c = *comma; *comma = '\0'; if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) { option_error("Illegal interface identifier (local): %s", arg); return 0; } - - eui64_copy(addr.s6_addr32[2], wo->ourid); - wo->opt_local = 1; - *comma = ','; + + if (option_priority >= prio_local) { + eui64_copy(addr.s6_addr32[2], wo->ourid); + wo->opt_local = 1; + prio_local = option_priority; + } + *comma = c; } /* @@ -308,13 +318,33 @@ setifaceid(argv) option_error("Illegal interface identifier (remote): %s", comma); return 0; } - eui64_copy(addr.s6_addr32[2], wo->hisid); - wo->opt_remote = 1; + if (option_priority >= prio_remote) { + eui64_copy(addr.s6_addr32[2], wo->hisid); + wo->opt_remote = 1; + prio_remote = option_priority; + } } + if (override_value("+ipv6", option_priority, option_source)) + ipv6cp_protent.enabled_flag = 1; return 1; } +static void +printifaceid(opt, printer, arg) + option_t *opt; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (wo->opt_local) + printer(arg, "%s", llv6_ntoa(wo->ourid)); + printer(arg, ","); + if (wo->opt_remote) + printer(arg, "%s", llv6_ntoa(wo->hisid)); +} + /* * Make a string representation of a network address. */ @@ -912,14 +942,14 @@ ipv6cp_reqci(f, inp, len, reject_if_disagree) orc = CONFREJ; break; } -#else - orc = CONFREJ; - break; -#endif ho->neg_vj = 1; ho->vj_protocol = cishort; break; +#else + orc = CONFREJ; + break; +#endif default: orc = CONFREJ; @@ -994,6 +1024,31 @@ ipv6_check_options() { ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + if (!ipv6cp_protent.enabled_flag) + return; + +#if defined(SOL2) + /* + * 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)) { + + /* + * On systems where there are no Ethernet interfaces used, there + * may be other ways to obtain a persistent id. Right now, it + * will fall back to using magic [see eui64_magic] below when + * an EUI-48 from MAC address can't be obtained. Other possibilities + * include obtaining EEPROM serial numbers, or some other unique + * yet persistent number. On Sparc platforms, this is possible, + * but too bad there's no standards yet for x86 machines. + */ + if (ether_to_eui64(&wo->ourid)) { + wo->opt_local = 1; + } + } +#endif + if (!wo->opt_local) { /* init interface identifier */ if (wo->use_ip && eui64_iszero(wo->ourid)) { eui64_setlo32(wo->ourid, ntohl(ipcp_wantoptions[0].ouraddr)); @@ -1030,9 +1085,14 @@ ipv6_demand_conf(u) { ipv6cp_options *wo = &ipv6cp_wantoptions[u]; -#if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC__))) +#if defined(__linux__) || defined(SOL2) || (defined(SVR4) && (defined(SNI) || defined(__USLC__))) +#if defined(SOL2) + if (!sif6up(u)) + return 0; +#else if (!sifup(u)) return 0; +#endif /* defined(SOL2) */ #endif if (!sif6addr(u, wo->ourid, wo->hisid)) return 0; @@ -1089,8 +1149,8 @@ ipv6cp_up(f) return; } } - script_setenv("LLLOCAL", llv6_ntoa(go->ourid)); - script_setenv("LLREMOTE", llv6_ntoa(ho->hisid)); + script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); + script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); #ifdef IPV6CP_COMP /* set tcp compression */ @@ -1129,7 +1189,7 @@ ipv6cp_up(f) /* * Set LL addresses */ -#if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) +#if !defined(__linux__) && !defined(SOL2) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) if (!sif6addr(f->unit, go->ourid, ho->hisid)) { if (debug) warn("sif6addr failed"); @@ -1139,14 +1199,23 @@ ipv6cp_up(f) #endif /* bring the interface up for IPv6 */ +#if defined(SOL2) + if (!sif6up(f->unit)) { + if (debug) + warn("sifup failed (IPV6)"); + ipv6cp_close(f->unit, "Interface configuration failed"); + return; + } +#else if (!sifup(f->unit)) { if (debug) warn("sifup failed (IPV6)"); ipv6cp_close(f->unit, "Interface configuration failed"); return; } +#endif /* defined(SOL2) */ -#if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC__))) +#if defined(__linux__) || defined(SOL2) || (defined(SVR4) && (defined(SNI) || defined(__USLC__))) if (!sif6addr(f->unit, go->ourid, ho->hisid)) { if (debug) warn("sif6addr failed"); @@ -1203,7 +1272,11 @@ ipv6cp_down(f) } else { sifnpmode(f->unit, PPP_IPV6, NPMODE_DROP); #if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC))) +#if defined(SOL2) + sif6down(f->unit); +#else sifdown(f->unit); +#endif /* defined(SOL2) */ #endif ipv6cp_clear_addrs(f->unit, ipv6cp_gotoptions[f->unit].ourid, @@ -1379,7 +1452,7 @@ ipv6cp_printpkt(p, plen, printer, arg) case TERMREQ: if (len > 0 && *p >= ' ' && *p < 0x7f) { printer(arg, " "); - print_string(p, len, printer, arg); + print_string((char *)p, len, printer, arg); p += len; len = 0; }