]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/ipv6cp.c
pppd: Fix SIGSEGV in EAP-TLS code when TLS verify method is not specified
[ppp.git] / pppd / ipv6cp.c
index c01b84639e674246224812914afb13c29b3deb5a..d80ae216814e9017e65e629aaf15d038d61e4c39 100644 (file)
  * 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: 
  *
@@ -181,10 +177,10 @@ 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,
@@ -279,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,
@@ -312,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.
@@ -340,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];
@@ -398,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];
 
@@ -416,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];
 
@@ -430,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];
@@ -467,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]);
 }
@@ -478,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);
 }
@@ -490,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]);
 }
@@ -501,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]);
 }
@@ -512,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);
 }
@@ -527,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]);
 }
@@ -538,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];
@@ -548,7 +528,8 @@ ipv6cp_resetci(f)
     
     if (!wo->opt_local) {
        wo->accept_local = 1;
-       eui64_magic_nz(wo->ourid);
+       if (!demand)
+           eui64_magic_nz(wo->ourid);
     }
     if (!wo->opt_remote)
        wo->accept_remote = 1;
@@ -562,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];
 
@@ -579,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;
@@ -627,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;
@@ -698,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;
@@ -836,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;
@@ -911,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];
@@ -1093,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];
 
@@ -1109,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
@@ -1143,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);
-    }
 }
 
 
@@ -1156,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))
@@ -1175,7 +1176,6 @@ ipv6_demand_conf(u)
        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));
 
@@ -1189,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];
@@ -1243,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)) {
@@ -1312,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);
@@ -1362,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);
 }
@@ -1375,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);
 }
@@ -1387,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) {
@@ -1413,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];
@@ -1445,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;
@@ -1552,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;