Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net IPv6CP support. if IPv6 link-local address is confi...



details:   https://anonhg.NetBSD.org/src/rev/da128fde5d4a
branches:  trunk
changeset: 485647:da128fde5d4a
user:      itojun <itojun%NetBSD.org@localhost>
date:      Tue May 02 12:43:16 2000 +0000

description:
IPv6CP support.  if IPv6 link-local address is configured to the interface,
the interface tries to negotiate ifid with the other end by using IPv6CP.

other changes:
- do not share ppp sequence number across protocols.
- if LCP proto-rej is received, drop the protocol mentioned by the message.
  this is to be friendly with non-IPv6 peer (if the peer complains due to
  lack of IPv6CP, drop IPv6CP).  this basically implements "RXJ+" state
  transition in the RFC.
- cleanup debugging message.  always print blank just before message.

CAVEAT:
- if the peer uses the same MAC address as our side (pretty unlikely)
  the code may go into req-rej loop.
- even though we negotiate ifid, we don't configure destination address
  onto the interface.  it is not really necessary to do so (IMHO).
- I've tested this code on a NetBSD 1.4.2 node, which was with fair amount
  of modifications.  not sure if the committed code does it right... (please
  test and send reports)

diffstat:

 sys/net/if_sppp.h     |   16 +-
 sys/net/if_spppsubr.c |  933 +++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 868 insertions(+), 81 deletions(-)

diffs (truncated from 1553 to 300 lines):

diff -r c0d7ff6c2855 -r da128fde5d4a sys/net/if_sppp.h
--- a/sys/net/if_sppp.h Tue May 02 12:39:03 2000 +0000
+++ b/sys/net/if_sppp.h Tue May 02 12:43:16 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_sppp.h,v 1.5 2000/03/23 07:03:25 thorpej Exp $      */
+/*     $NetBSD: if_sppp.h,v 1.6 2000/05/02 12:43:16 itojun Exp $       */
 
 /*
  * Defines for synchronous PPP/Cisco link level subroutines.
@@ -45,6 +45,7 @@
 };
 
 #define IDX_IPCP 1             /* idx into state table */
+#define IDX_IPV6CP 2           /* idx into state table */
 
 struct sipcp {
        u_long  opts;           /* IPCP options to send (bitfield) */
@@ -52,6 +53,10 @@
 #define IPCP_HISADDR_SEEN 1    /* have seen his address already */
 #define IPCP_MYADDR_DYN   2    /* my address is dynamically assigned */
 #define IPCP_MYADDR_SEEN  4    /* have seen his address already */
+#ifdef notdef
+#define IPV6CP_MYIFID_DYN   2  /* my ifid is dynamically assigned */
+#endif
+#define IPV6CP_MYIFID_SEEN  4  /* have seen his ifid already */
 };
 
 #define AUTHNAMELEN    32
@@ -68,8 +73,8 @@
        u_char  challenge[AUTHKEYLEN];  /* random challenge */
 };
 
-#define IDX_PAP                2
-#define IDX_CHAP       3
+#define IDX_PAP                3
+#define IDX_CHAP       4
 
 #define IDX_COUNT (IDX_CHAP + 1) /* bump this when adding cp's! */
 
@@ -92,8 +97,8 @@
        u_int   pp_flags;       /* use Cisco protocol instead of PPP */
        u_short pp_alivecnt;    /* keepalive packets counter */
        u_short pp_loopcnt;     /* loopback detection counter */
-       u_long  pp_seq;         /* local sequence number */
-       u_long  pp_rseq;        /* remote sequence number */
+       u_long  pp_seq[IDX_COUNT];      /* local sequence number */
+       u_long  pp_rseq[IDX_COUNT];     /* remote sequence number */
        enum ppp_phase pp_phase;        /* phase we're currently in */
        int     state[IDX_COUNT];       /* state machine */
        u_char  confid[IDX_COUNT];      /* id of last configuration request */
@@ -109,6 +114,7 @@
 #endif
        struct slcp lcp;                /* LCP params */
        struct sipcp ipcp;              /* IPCP params */
+       struct sipcp ipv6cp;            /* IPv6CP params */
        struct sauth myauth;            /* auth params, i'm peer */
        struct sauth hisauth;           /* auth params, i'm authenticator */
        /*
diff -r c0d7ff6c2855 -r da128fde5d4a sys/net/if_spppsubr.c
--- a/sys/net/if_spppsubr.c     Tue May 02 12:39:03 2000 +0000
+++ b/sys/net/if_spppsubr.c     Tue May 02 12:43:16 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_spppsubr.c,v 1.8 2000/04/12 10:51:15 itojun Exp $    */
+/*     $NetBSD: if_spppsubr.c,v 1.9 2000/05/02 12:43:16 itojun Exp $    */
 
 /*
  * Synchronous PPP/Cisco link level subroutines.
@@ -10,6 +10,9 @@
  * Heavily revamped to conform to RFC 1661.
  * Copyright (C) 1997, Joerg Wunsch.
  *
+ * RFC2472 IPv6CP support.
+ * Copyright (C) 2000, Jun-ichiro itojun Hagino <itojun%iijlab.net@localhost>.
+ *
  * This software is distributed with NO WARRANTIES, not even the implied
  * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  *
@@ -159,9 +162,12 @@
 #define LCP_OPT_ADDR_COMP      8       /* address/control field compression */
 
 #define IPCP_OPT_ADDRESSES     1       /* both IP addresses; deprecated */
-#define IPCP_OPT_COMPRESSION   2       /* IP compression protocol (VJ) */
+#define IPCP_OPT_COMPRESSION   2       /* IPv6 compression protocol */
 #define IPCP_OPT_ADDRESS       3       /* local IP address */
 
+#define IPV6CP_OPT_IFID                1       /* interface identifier */
+#define IPV6CP_OPT_COMPRESSION 2       /* IPv6 compression protocol */
+
 #define PAP_REQ                        1       /* PAP name/password request */
 #define PAP_ACK                        2       /* PAP acknowledge */
 #define PAP_NAK                        3       /* PAP fail */
@@ -340,6 +346,21 @@
 static void sppp_ipcp_tlf(struct sppp *sp);
 static void sppp_ipcp_scr(struct sppp *sp);
 
+static void sppp_ipv6cp_init(struct sppp *sp);
+static void sppp_ipv6cp_up(struct sppp *sp);
+static void sppp_ipv6cp_down(struct sppp *sp);
+static void sppp_ipv6cp_open(struct sppp *sp);
+static void sppp_ipv6cp_close(struct sppp *sp);
+static void sppp_ipv6cp_TO(void *sp);
+static int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len);
+static void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len);
+static void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len);
+static void sppp_ipv6cp_tlu(struct sppp *sp);
+static void sppp_ipv6cp_tld(struct sppp *sp);
+static void sppp_ipv6cp_tls(struct sppp *sp);
+static void sppp_ipv6cp_tlf(struct sppp *sp);
+static void sppp_ipv6cp_scr(struct sppp *sp);
+
 static void sppp_pap_input(struct sppp *sp, struct mbuf *m);
 static void sppp_pap_init(struct sppp *sp);
 static void sppp_pap_open(struct sppp *sp);
@@ -363,6 +384,9 @@
 static const char *sppp_cp_type_name(u_char type);
 static const char *sppp_dotted_quad(u_long addr);
 static const char *sppp_ipcp_opt_name(u_char opt);
+#ifdef INET6
+static const char *sppp_ipv6cp_opt_name(u_char opt);
+#endif
 static const char *sppp_lcp_opt_name(u_char opt);
 static const char *sppp_phase_name(enum ppp_phase phase);
 static const char *sppp_proto_name(u_short proto);
@@ -377,6 +401,15 @@
 static void sppp_print_string(const char *p, u_short len);
 static void sppp_qflush(struct ifqueue *ifq);
 static void sppp_set_ip_addr(struct sppp *sp, u_long src);
+#ifdef INET6
+static void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src,
+                               struct in6_addr *dst, struct in6_addr *srcmask);
+#ifdef IPV6CP_MYIFID_DYN
+static void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src);
+static void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src);
+#endif
+static void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src);
+#endif
 
 /* our control protocol descriptors */
 static const struct cp lcp = {
@@ -395,6 +428,20 @@
        sppp_ipcp_scr
 };
 
+static const struct cp ipv6cp = {
+       PPP_IPV6CP, IDX_IPV6CP,
+#ifdef INET6   /*don't run IPv6CP if there's no IPv6 support*/
+       CP_NCP,
+#else
+       0,
+#endif
+       "ipv6cp",
+       sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close,
+       sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak,
+       sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf,
+       sppp_ipv6cp_scr
+};
+
 static const struct cp pap = {
        PPP_PAP, IDX_PAP, CP_AUTH, "pap",
        sppp_null, sppp_null, sppp_pap_open, sppp_pap_close,
@@ -414,6 +461,7 @@
 static const struct cp *cps[IDX_COUNT] = {
        &lcp,                   /* IDX_LCP */
        &ipcp,                  /* IDX_IPCP */
+       &ipv6cp,                /* IDX_IPV6CP */
        &pap,                   /* IDX_PAP */
        &chap,                  /* IDX_CHAP */
 };
@@ -473,8 +521,8 @@
                default:
                        if (sp->state[IDX_LCP] == STATE_OPENED)
                                sppp_cp_send (sp, PPP_LCP, PROTO_REJ,
-                                       ++sp->pp_seq, m->m_pkthdr.len + 2,
-                                       &h->protocol);
+                                   ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2,
+                                   &h->protocol);
                        if (debug)
                                log(LOG_DEBUG,
                                    SPP_FMT "invalid input protocol "
@@ -512,12 +560,13 @@
 #endif
 #ifdef INET6
                case PPP_IPV6CP:
-                       /* TBD */
+                       if (sp->pp_phase == PHASE_NETWORK)
+                               sppp_cp_input(&ipv6cp, sp, m);
                        m_freem (m);
                        return;
+
                case PPP_IPV6:
-                       /* XXX should check IPv6CP */
-                       if (sp->pp_phase == PHASE_NETWORK) {
+                       if (sp->state[IDX_IPV6CP] == STATE_OPENED) {
                                schednetisr (NETISR_IPV6);
                                inq = &ip6intrq;
                        }
@@ -771,8 +820,7 @@
                         * ENETDOWN, as opposed to ENOBUFS.
                         */
                        h->protocol = htons(PPP_IPV6);
-                       /* XXX should check IPv6CP */
-                       if (sp->pp_phase != PHASE_NETWORK)
+                       if (sp->state[IDX_IPV6CP] != STATE_OPENED)
                                rv = ENETDOWN;
                }
                break;
@@ -857,14 +905,15 @@
        sp->pp_cpq.ifq_maxlen = 20;
        sp->pp_loopcnt = 0;
        sp->pp_alivecnt = 0;
-       sp->pp_seq = 0;
-       sp->pp_rseq = 0;
+       bzero(&sp->pp_seq[0], sizeof(sp->pp_seq));
+       bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq));
        sp->pp_phase = PHASE_DEAD;
        sp->pp_up = lcp.Up;
        sp->pp_down = lcp.Down;
 
        sppp_lcp_init(sp);
        sppp_ipcp_init(sp);
+       sppp_ipv6cp_init(sp);
        sppp_pap_init(sp);
        sppp_chap_init(sp);
 }
@@ -1131,8 +1180,8 @@
                break;
        case CISCO_KEEPALIVE_REQ:
                sp->pp_alivecnt = 0;
-               sp->pp_rseq = ntohl (h->par1);
-               if (sp->pp_seq == sp->pp_rseq) {
+               sp->pp_rseq[IDX_LCP] = ntohl (h->par1);
+               if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) {
                        /* Local and remote sequence numbers are equal.
                         * Probably, the line is in loopback mode. */
                        if (sp->pp_loopcnt >= MAXALIVECNT) {
@@ -1148,9 +1197,9 @@
 
                        /* Generate new local sequence number */
 #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
-                       sp->pp_seq = random();
+                       sp->pp_seq[IDX_LCP] = random();
 #else
-                       sp->pp_seq ^= time.tv_sec ^ time.tv_usec;
+                       sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec;
 #endif
                        break;
                }
@@ -1530,13 +1579,12 @@
                }
                break;
        case CODE_REJ:
-       case PROTO_REJ:
                /* XXX catastrophic rejects (RXJ-) aren't handled yet. */
                log(LOG_INFO,
-                   SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, "
+                   SPP_FMT "%s: ignoring RXJ (%s) for code ?, "
                    "danger will robinson\n",
                    SPP_ARGS(ifp), cp->name,
-                   sppp_cp_type_name(h->type), ntohs(*((u_short *)p)));
+                   sppp_cp_type_name(h->type));
                switch (sp->state[cp->protoidx]) {
                case STATE_CLOSED:
                case STATE_STOPPED:
@@ -1557,6 +1605,65 @@
                        ++ifp->if_ierrors;
                }
                break;
+       case PROTO_REJ:
+           {
+               int catastrophic;
+               const struct cp *upper;
+               int i;
+               u_int16_t proto;
+
+               catastrophic = 0;
+               upper = NULL;
+               proto = ntohs(*((u_int16_t *)p));
+               for (i = 0; i < IDX_COUNT; i++) {
+                       if (cps[i]->proto == proto) {
+                               upper = cps[i];
+                               break;
+                       }
+               }
+               if (upper == NULL)
+                       catastrophic++;
+
+               log(LOG_INFO,
+                   SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n",
+                   SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+',
+                   sppp_cp_type_name(h->type), proto,
+                   upper ? upper->name : "unknown",
+                   upper ? sppp_state_name(sp->state[upper->protoidx]) : "?");
+
+               /*
+                * if we got RXJ+ against conf-req, the peer does not implement
+                * this particular protocol type.  terminate the protocol.
+                */
+               if (upper && !catastrophic) {
+                       if (sp->state[upper->protoidx] == STATE_REQ_SENT) {
+                               upper->Close(sp);



Home | Main Index | Thread Index | Old Index