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