diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2011-10-15 03:24:12 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2011-10-15 03:24:12 +0000 |
commit | 0fc580053976b92a57e7ef7a3d4c3dba5cbeed93 (patch) | |
tree | 9d042d6965d8c827f56535353f9042aa2ede9b3a | |
parent | 3915fb613669eb3791b0f720e3d5baa758e7e012 (diff) |
Added "provision for rewound PPP frames" that allows receiving
reorder packets to pass to the upper layer without reorder. It
will improve performance (throughput or loss rate) for PPTP or
L2TP(/IPesc) on networks that latency is unstable such as mobile
network.
As our test environment (bandwidth: 6Mbps, latency: 50ms for 97% of
traffic and 52ms for rest of traffic), throughput has changed from
0.76MB to 2.17MB on file upload by PPTP connected Windows Vista
ftp.exe.
Developed by UMEZAWA Takeshi at IIJ.
ok jmatthew@
tested jmatthew@ and myself.
-rw-r--r-- | sys/net/if_pppx.c | 10 | ||||
-rw-r--r-- | sys/net/pipex.c | 206 | ||||
-rw-r--r-- | sys/net/pipex.h | 7 | ||||
-rw-r--r-- | sys/net/pipex_local.h | 15 | ||||
-rw-r--r-- | usr.sbin/npppd/l2tp/l2tp.h | 7 | ||||
-rw-r--r-- | usr.sbin/npppd/l2tp/l2tp_call.c | 9 | ||||
-rw-r--r-- | usr.sbin/npppd/l2tp/l2tp_ctrl.c | 29 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/fsm.h | 4 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/mppe.c | 213 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/ppp.c | 25 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/ppp.h | 9 | ||||
-rw-r--r-- | usr.sbin/npppd/pptp/pptp.h | 12 | ||||
-rw-r--r-- | usr.sbin/npppd/pptp/pptp_call.c | 65 |
13 files changed, 415 insertions, 196 deletions
diff --git a/sys/net/if_pppx.c b/sys/net/if_pppx.c index 09e1133feae..f4f12ce9333 100644 --- a/sys/net/if_pppx.c +++ b/sys/net/if_pppx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pppx.c,v 1.11 2011/08/21 09:00:15 jmatthew Exp $ */ +/* $OpenBSD: if_pppx.c,v 1.12 2011/10/15 03:24:11 yasuoka Exp $ */ /* * Copyright (c) 2010 Claudio Jeker <claudio@openbsd.org> @@ -805,9 +805,13 @@ pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req) #endif #ifdef PIPEX_MPPE if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) - pipex_mppe_req_init(&req->pr_mppe_recv, &session->mppe_recv); + pipex_session_init_mppe_recv(session, + req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits, + req->pr_mppe_recv.master_key); if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) - pipex_mppe_req_init(&req->pr_mppe_send, &session->mppe_send); + pipex_session_init_mppe_send(session, + req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits, + req->pr_mppe_send.master_key); if (pipex_session_is_mppe_required(session)) { if (!pipex_session_is_mppe_enabled(session) || diff --git a/sys/net/pipex.c b/sys/net/pipex.c index 93955f394d7..87be24931e3 100644 --- a/sys/net/pipex.c +++ b/sys/net/pipex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pipex.c,v 1.21 2011/07/09 04:11:15 dhill Exp $ */ +/* $OpenBSD: pipex.c,v 1.22 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -119,9 +119,6 @@ int pipex_debug = 0; /* systcl net.inet.ip.pipex_debug */ /* PPP compression == MPPE is assumed, so don't answer CCP Reset-Request. */ #define PIPEX_NO_CCP_RESETACK 1 -/* see the comment on pipex_mppe_input() */ -#define WORKAROUND_OUT_OF_SEQUENCE_PPP_FRAMING 1 - /************************************************************************ * Core functions ************************************************************************/ @@ -394,9 +391,13 @@ pipex_add_session(struct pipex_session_req *req, #endif #ifdef PIPEX_MPPE if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) - pipex_mppe_req_init(&req->pr_mppe_recv, &session->mppe_recv); + pipex_session_init_mppe_recv(session, + req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits, + req->pr_mppe_recv.master_key); if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) - pipex_mppe_req_init(&req->pr_mppe_send, &session->mppe_send); + pipex_session_init_mppe_send(session, + req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits, + req->pr_mppe_send.master_key); if (pipex_session_is_mppe_required(session)) { if (!pipex_session_is_mppe_enabled(session) || @@ -609,6 +610,9 @@ pipex_destroy_session(struct pipex_session *session) pipex_timer_stop(); splx(s); + + if (session->mppe_recv.old_session_keys) + free(session->mppe_recv.old_session_keys, M_TEMP); free(session, M_TEMP); return (0); @@ -1614,6 +1618,7 @@ pipex_pptp_input(struct mbuf *m0, struct pipex_session *session) struct ip *ip; struct pipex_gre_header *gre; struct pipex_pptp_session *pptp_session; + int rewind = 0; KASSERT(m0->m_pkthdr.len >= PIPEX_IPGRE_HDRLEN); pptp_session = &session->proto.pptp; @@ -1650,11 +1655,11 @@ pipex_pptp_input(struct mbuf *m0, struct pipex_session *session) if (ack + 1 == pptp_session->snd_una) { /* ack has not changed before */ } else if (SEQ32_LT(ack, pptp_session->snd_una)) { - reason = "ack out of sequence"; - goto inseq; + /* OoO ack packets should not be dropped. */ + rewind = 1; } else if (SEQ32_GT(ack, pptp_session->snd_nxt)) { reason = "ack for unknown sequence"; - goto inseq; + goto out_seq; } else { ack++; pptp_session->snd_una = ack; @@ -1665,8 +1670,12 @@ pipex_pptp_input(struct mbuf *m0, struct pipex_session *session) goto not_ours; } if (SEQ32_LT(seq, pptp_session->rcv_nxt)) { - reason = "out of sequence"; - goto inseq; + rewind = 1; + if (SEQ32_LT(seq, + pptp_session->rcv_nxt - PIPEX_REWIND_LIMIT)) { + reason = "out of sequence"; + goto out_seq; + } } else if (SEQ32_GE(seq, pptp_session->rcv_nxt + pptp_session->maxwinsz)) { pipex_session_log(session, LOG_DEBUG, @@ -1678,18 +1687,24 @@ pipex_pptp_input(struct mbuf *m0, struct pipex_session *session) seq++; nseq = SEQ32_SUB(seq, pptp_session->rcv_nxt); - pptp_session->rcv_nxt = seq; - - if (SEQ32_SUB(seq, pptp_session->rcv_acked) > - roundup(pptp_session->winsz, 2) / 2) /* Send ack only packet. */ - pipex_pptp_output(NULL, session, 0, 1); + if (!rewind) { + pptp_session->rcv_nxt = seq; + if (SEQ32_SUB(seq, pptp_session->rcv_acked) > + roundup(pptp_session->winsz, 2) / 2) /* Send ack only packet. */ + pipex_pptp_output(NULL, session, 0, 1); + } if ((m0 = pipex_common_input(session, m0, hlen, (int)ntohs(gre->len))) == NULL) { /* ok, The packet is for PIPEX */ - session->proto.pptp.rcv_gap += nseq; - return (m0); + if (!rewind) + session->proto.pptp.rcv_gap += nseq; + return (NULL); } + + if (rewind) + goto out_seq; + not_ours: /* revert original seq/ack values */ seq--; @@ -1720,7 +1735,7 @@ not_ours: } return (m0); -inseq: +out_seq: pipex_session_log(session, LOG_DEBUG, "Received bad data packet: %s: seq=%u(%u-%u) ack=%u(%u-%u)", reason, seq, pptp_session->rcv_nxt, @@ -2054,6 +2069,7 @@ pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session) int length, offset, hlen, nseq; u_char *cp, *nsp, *nrp; uint16_t flags, ns = 0, nr = 0; + int rewind = 0; length = offset = ns = nr = 0; l2tp_session = &session->proto.l2tp; @@ -2098,13 +2114,17 @@ pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session) SEQ16_LE(nr, l2tp_session->ns_nxt)) /* update 'ns_una' only if the ns is in valid range */ l2tp_session->ns_una = nr; - - if (SEQ16_LT(ns, l2tp_session->nr_nxt)) - goto out_seq; + if (SEQ16_LT(ns, l2tp_session->nr_nxt)) { + rewind = 1; + if (SEQ16_LT(ns, + l2tp_session->nr_nxt - PIPEX_REWIND_LIMIT)) + goto out_seq; + } ns++; nseq = SEQ16_SUB(ns, l2tp_session->nr_nxt); - l2tp_session->nr_nxt = ns; + if (!rewind) + l2tp_session->nr_nxt = ns; } if (flags & PIPEX_L2TP_FLAG_OFFSET) GETSHORT(offset, cp); @@ -2113,10 +2133,14 @@ pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session) hlen += off0 + offset; if ((m0 = pipex_common_input(session, m0, hlen, length)) == NULL) { /* ok, The packet is for PIPEX */ - session->proto.l2tp.nr_gap += nseq; + if (!rewind) + session->proto.l2tp.nr_gap += nseq; return (NULL); } + if (rewind) + goto out_seq; + /* * overwrite sequence numbers to adjust a gap between pipex and * userland. @@ -2279,17 +2303,23 @@ pipex_l2tp_userland_output(struct mbuf *m0, struct pipex_session *session) * MPPE ***********************************************************************/ #define PIPEX_COHERENCY_CNT_MASK 0x0fff - Static void -pipex_mppe_req_init(struct pipex_mppe_req *mppe_req, struct pipex_mppe *mppe) +pipex_mppe_init(struct pipex_mppe *mppe, int stateless, int keylenbits, + u_char *master_key, int has_oldkey) { - if (mppe_req->stateless) + memset(mppe, 0, sizeof(struct pipex_mppe)); + if (stateless) mppe->stateless = 1; - memcpy(mppe->master_key, mppe_req->master_key, - sizeof(mppe->master_key)); + if (has_oldkey) + mppe->old_session_keys = + malloc(PIPEX_MPPE_KEYLEN * PIPEX_MPPE_NOLDKEY, + M_TEMP, M_WAITOK); + else + mppe->old_session_keys = NULL; + memcpy(mppe->master_key, master_key, sizeof(mppe->master_key)); - mppe->keylenbits = mppe_req->keylenbits; - switch (mppe_req->keylenbits) { + mppe->keylenbits = keylenbits; + switch (keylenbits) { case 40: case 56: mppe->keylen = 8; @@ -2302,7 +2332,25 @@ pipex_mppe_req_init(struct pipex_mppe_req *mppe_req, struct pipex_mppe *mppe) GetNewKeyFromSHA(mppe->master_key, mppe->master_key, mppe->keylen, mppe->session_key); pipex_mppe_reduce_key(mppe); - rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen); + pipex_mppe_setkey(mppe); +} + +void +pipex_session_init_mppe_recv(struct pipex_session *session, int stateless, + int keylenbits, u_char *master_key) +{ + pipex_mppe_init(&session->mppe_recv, stateless, keylenbits, + master_key, stateless); + session->ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED; +} + +void +pipex_session_init_mppe_send(struct pipex_session *session, int stateless, + int keylenbits, u_char *master_key) +{ + pipex_mppe_init(&session->mppe_send, stateless, keylenbits, + master_key, 0); + session->ppp_flags |= PIPEX_PPP_MPPE_ENABLED; } #include <crypto/sha1.h> @@ -2354,17 +2402,23 @@ Static void mppe_key_change(struct pipex_mppe *mppe) { u_char interim[16]; - struct pipex_mppe keychg; /* just for rc4ctx */ + struct rc4_ctx keychg; memset(&keychg, 0, sizeof(keychg)); GetNewKeyFromSHA(mppe->master_key, mppe->session_key, mppe->keylen, interim); - rc4_keysetup(&keychg.rc4ctx, interim, mppe->keylen); - rc4_crypt(&keychg.rc4ctx, interim, mppe->session_key, mppe->keylen); + rc4_keysetup(&keychg, interim, mppe->keylen); + rc4_crypt(&keychg, interim, mppe->session_key, mppe->keylen); pipex_mppe_reduce_key(mppe); + + if (mppe->old_session_keys) { + int idx = mppe->coher_cnt & PIPEX_MPPE_OLDKEYMASK; + memcpy(mppe->old_session_keys[idx], + mppe->session_key, PIPEX_MPPE_KEYLEN); + } } Static void @@ -2375,6 +2429,7 @@ pipex_mppe_input(struct mbuf *m0, struct pipex_session *session) uint16_t coher_cnt; struct mbuf *m1; u_char *cp; + int rewind = 0; /* pullup */ PIPEX_PULLUP(m0, sizeof(coher_cnt)); @@ -2403,7 +2458,6 @@ pipex_mppe_input(struct mbuf *m0, struct pipex_session *session) /* adjust mbuf */ m_adj(m0, sizeof(coher_cnt)); -#ifdef WORKAROUND_OUT_OF_SEQUENCE_PPP_FRAMING /* * L2TP data session may be used without sequencing, PPP frames may * arrive in disorder. The 'coherency counter' of MPPE detects such @@ -2421,22 +2475,29 @@ pipex_mppe_input(struct mbuf *m0, struct pipex_session *session) if (coher_cnt < mppe->coher_cnt) coher_cnt0 += 0x1000; if (coher_cnt0 - mppe->coher_cnt > 0x0f00) { - pipex_session_log(session, LOG_DEBUG, - "Workaround the out-of-sequence PPP framing problem: " - "%d => %d", mppe->coher_cnt, coher_cnt); - goto drop; + if (!mppe->stateless || + coher_cnt0 - mppe->coher_cnt + <= 0x1000 - PIPEX_MPPE_NOLDKEY) { + pipex_session_log(session, LOG_DEBUG, + "Workaround the out-of-sequence PPP framing problem: " + "%d => %d", mppe->coher_cnt, coher_cnt); + goto drop; + } + rewind = 1; } } -#endif + if (mppe->stateless != 0) { - mppe_key_change(mppe); - while (mppe->coher_cnt != coher_cnt) { + if (!rewind) { mppe_key_change(mppe); - mppe->coher_cnt++; - mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK; - pktloss++; + while (mppe->coher_cnt != coher_cnt) { + mppe->coher_cnt++; + mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK; + mppe_key_change(mppe); + pktloss++; + } } - flushed = 1; + pipex_mppe_setoldkey(mppe, coher_cnt); } else { if (flushed) { if (coher_cnt < mppe->coher_cnt) { @@ -2461,26 +2522,27 @@ pipex_mppe_input(struct mbuf *m0, struct pipex_session *session) mppe_key_change(mppe); flushed = 1; } + if (flushed) + pipex_mppe_setkey(mppe); } -#ifndef WORKAROUND_OUT_OF_SEQUENCE_PPP_FRAMING + if (pktloss > 1000) { pipex_session_log(session, LOG_DEBUG, "%d packets loss.", pktloss); } -#endif - if (flushed) - rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen); /* decrypt ppp payload */ for (m1 = m0; m1; m1 = m1->m_next) { cp = mtod(m1, u_char *); len = m1->m_len; - rc4_crypt(&mppe->rc4ctx, cp, cp, len); + pipex_mppe_crypt(mppe, len, cp, cp); } - /* update coher_cnt */ - mppe->coher_cnt++; - mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK; + if (!rewind) { + /* update coher_cnt */ + mppe->coher_cnt++; + mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK; + } pipex_ppp_input(m0, session, 1); @@ -2547,7 +2609,7 @@ pipex_mppe_output(struct mbuf *m0, struct pipex_session *session, } if (flushed) - rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen); + pipex_mppe_setkey(mppe); PIPEX_MPPE_DBG((session, LOG_DEBUG, "out coher_cnt=%03x %s%s", mppe->coher_cnt, (flushed) ? "[flushed]" : "", @@ -2572,7 +2634,7 @@ pipex_mppe_output(struct mbuf *m0, struct pipex_session *session, len -= offsetof(struct mppe_header, protocol); cp += offsetof(struct mppe_header, protocol); } - rc4_crypt(&mppe->rc4ctx, cp, cp, len); + pipex_mppe_crypt(mppe, len, cp, cp); } pipex_ppp_output(m0, session, PPP_COMP); @@ -2939,7 +3001,35 @@ pipex_sockaddr_compar_addr(struct sockaddr *a, struct sockaddr *b) sizeof(struct in6_addr)); } panic("pipex_sockaddr_compar_addr: unknown address family"); - return -1; + + return (-1); +} + +Static inline int +pipex_mppe_setkey(struct pipex_mppe *mppe) +{ + rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen); + + return (0); +} + +Static inline int +pipex_mppe_setoldkey(struct pipex_mppe *mppe, uint16_t coher_cnt) +{ + KASSERT(mppe->old_session_keys != NULL); + + rc4_keysetup(&mppe->rc4ctx, + mppe->old_session_keys[coher_cnt & PIPEX_MPPE_OLDKEYMASK], + mppe->keylen); + + return (0); +} + +Static inline void +pipex_mppe_crypt(struct pipex_mppe *mppe, int len, u_char *indata, + u_char *outdata) +{ + rc4_crypt(&mppe->rc4ctx, indata, outdata, len); } int diff --git a/sys/net/pipex.h b/sys/net/pipex.h index 391e69ea54d..cddbbefc893 100644 --- a/sys/net/pipex.h +++ b/sys/net/pipex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pipex.h,v 1.9 2011/07/08 18:30:17 yasuoka Exp $ */ +/* $OpenBSD: pipex.h,v 1.10 2011/10/15 03:24:11 yasuoka Exp $ */ /* * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -216,6 +216,11 @@ struct pipex_session *pipex_l2tp_userland_lookup_session_ipv4 (struct mbuf *, s struct pipex_session *pipex_l2tp_userland_lookup_session_ipv6 (struct mbuf *, struct in6_addr); struct mbuf *pipex_l2tp_userland_output (struct mbuf *, struct pipex_session *); int pipex_ioctl (struct pipex_iface_context *, int, caddr_t); +void pipex_session_init_mppe_recv(struct pipex_session *, int, +int, u_char *); +void pipex_session_init_mppe_send(struct pipex_session *, int, +int, u_char *); + __END_DECLS #endif /* _KERNEL */ diff --git a/sys/net/pipex_local.h b/sys/net/pipex_local.h index 11be4715ec8..dcbf9c1ef35 100644 --- a/sys/net/pipex_local.h +++ b/sys/net/pipex_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pipex_local.h,v 1.12 2011/07/08 19:34:04 yasuoka Exp $ */ +/* $OpenBSD: pipex_local.h,v 1.13 2011/10/15 03:24:11 yasuoka Exp $ */ /* * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -37,6 +37,8 @@ #define PIPEX_PPPOE 1 #define PIPEX_MPPE 1 +#define PIPEX_REWIND_LIMIT 64 + #define PIPEX_ENABLED 0x0001 #ifndef LOG_PPPAC @@ -59,6 +61,9 @@ #define NNBY 8 /* number of bits of a byte */ #endif +#define PIPEX_MPPE_NOLDKEY 64 /* should be power of two */ +#define PIPEX_MPPE_OLDKEYMASK (PIPEX_MPPE_NOLDKEY - 1) + #ifdef PIPEX_MPPE /* mppe rc4 key */ struct pipex_mppe { @@ -71,6 +76,7 @@ struct pipex_mppe { struct rc4_ctx rc4ctx; u_char master_key[PIPEX_MPPE_KEYLEN]; /* master key of MPPE */ u_char session_key[PIPEX_MPPE_KEYLEN]; /* session key of MPPE */ + u_char (*old_session_keys)[PIPEX_MPPE_KEYLEN]; /* old session keys */ }; #endif /* PIPEX_MPPE */ @@ -402,7 +408,7 @@ Static struct pipex_session *pipex_l2tp_userland_lookup_session(struct mbuf *, #endif #ifdef PIPEX_MPPE -Static void pipex_mppe_req_init (struct pipex_mppe_req *, struct pipex_mppe *); +Static void pipex_mppe_init (struct pipex_mppe *, int, int, u_char *, int); Static void GetNewKeyFromSHA (u_char *, u_char *, int, u_char *); Static void pipex_mppe_reduce_key (struct pipex_mppe *); Static void mppe_key_change (struct pipex_mppe *); @@ -410,8 +416,9 @@ Static void pipex_mppe_input (struct mbuf *, struct pipex_sessi Static void pipex_mppe_output (struct mbuf *, struct pipex_session *, uint16_t); Static void pipex_ccp_input (struct mbuf *, struct pipex_session *); Static int pipex_ccp_output (struct pipex_session *, int, int); -Static inline int rc4_key(struct pipex_mppe *, int, u_char *); -Static inline void rc4(struct pipex_mppe *, int, u_char *, u_char *); +Static inline int pipex_mppe_setkey(struct pipex_mppe *); +Static inline int pipex_mppe_setoldkey(struct pipex_mppe *, uint16_t); +Static inline void pipex_mppe_crypt(struct pipex_mppe *, int, u_char *, u_char *); #endif Static struct mbuf *adjust_tcp_mss (struct mbuf *, int); diff --git a/usr.sbin/npppd/l2tp/l2tp.h b/usr.sbin/npppd/l2tp/l2tp.h index db30d79ee89..d1927478bbd 100644 --- a/usr.sbin/npppd/l2tp/l2tp.h +++ b/usr.sbin/npppd/l2tp/l2tp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tp.h,v 1.4 2010/09/24 14:50:30 yasuoka Exp $ */ +/* $OpenBSD: l2tp.h,v 1.5 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -30,7 +30,7 @@ /*@file * header file for the L2TP module */ -/* $Id: l2tp.h,v 1.4 2010/09/24 14:50:30 yasuoka Exp $ */ +/* $Id: l2tp.h,v 1.5 2011/10/15 03:24:11 yasuoka Exp $ */ /************************************************************************ * Protocol Constants @@ -283,6 +283,7 @@ ((l2tpd_listener *)slist_get(&(ctrl)->l2tpd->listener, \ (ctrl)->listener_index))->phy_label +#define L2TP_CALL_DELAY_LIMIT 64 /** datatype represents L2TP daemon */ struct _l2tpd; @@ -457,7 +458,7 @@ int l2tp_call_init (l2tp_call *, l2tp_ctrl *); void l2tp_call_destroy (l2tp_call *, int); void l2tp_call_admin_disconnect(l2tp_call *); int l2tp_call_recv_packet (l2tp_ctrl *, l2tp_call *, int, u_char *, int); -void l2tp_call_ppp_input (l2tp_call *, u_char *, int); +void l2tp_call_ppp_input (l2tp_call *, u_char *, int, int); void l2tp_ctrl_destroy (l2tp_ctrl *); l2tp_ctrl *l2tp_ctrl_create (void); diff --git a/usr.sbin/npppd/l2tp/l2tp_call.c b/usr.sbin/npppd/l2tp/l2tp_call.c index 3507ac983ee..935af5f65e3 100644 --- a/usr.sbin/npppd/l2tp/l2tp_call.c +++ b/usr.sbin/npppd/l2tp/l2tp_call.c @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tp_call.c,v 1.7 2011/01/20 23:12:33 jasper Exp $ */ +/* $OpenBSD: l2tp_call.c,v 1.8 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: l2tp_call.c,v 1.7 2011/01/20 23:12:33 jasper Exp $ */ +/* $Id: l2tp_call.c,v 1.8 2011/10/15 03:24:11 yasuoka Exp $ */ /**@file L2TP LNS call */ #include <sys/types.h> #include <sys/param.h> @@ -860,13 +860,14 @@ l2tp_call_state_string(l2tp_call *_this) /* input packet to ppp */ void -l2tp_call_ppp_input(l2tp_call *_this, u_char *pkt, int pktlen) +l2tp_call_ppp_input(l2tp_call *_this, u_char *pkt, int pktlen, int delayed) { int rval; npppd_ppp *ppp; ppp = _this->ppp; - rval = ppp->recv_packet(ppp, pkt, pktlen, 0); + rval = ppp->recv_packet(ppp, pkt, pktlen, + delayed ? PPP_IO_FLAGS_DELAYED : 0); if (_this->ppp == NULL) /* ppp is freed */ return; diff --git a/usr.sbin/npppd/l2tp/l2tp_ctrl.c b/usr.sbin/npppd/l2tp/l2tp_ctrl.c index 1259eb7a347..11c9a47b4a3 100644 --- a/usr.sbin/npppd/l2tp/l2tp_ctrl.c +++ b/usr.sbin/npppd/l2tp/l2tp_ctrl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: l2tp_ctrl.c,v 1.6 2011/01/20 23:12:33 jasper Exp $ */ +/* $OpenBSD: l2tp_ctrl.c,v 1.7 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -26,7 +26,7 @@ * SUCH DAMAGE. */ /**@file Control connection processing functions for L2TP LNS */ -/* $Id: l2tp_ctrl.c,v 1.6 2011/01/20 23:12:33 jasper Exp $ */ +/* $Id: l2tp_ctrl.c,v 1.7 2011/10/15 03:24:11 yasuoka Exp $ */ #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> @@ -903,6 +903,8 @@ l2tp_ctrl_input(l2tpd *_this, int listener_index, struct sockaddr *peer, } } if (!is_ctrl) { + int delayed = 0; + /* L2TP data */ if (ctrl->state != L2TP_CTRL_STATE_ESTABLISHED) { l2tp_ctrl_log(ctrl, LOG_WARNING, @@ -929,16 +931,23 @@ l2tp_ctrl_input(l2tpd *_this, int listener_index, struct sockaddr *peer, if (hdr.s != 0) { if (SEQ_LT(hdr.ns, call->rcv_nxt)) { - /* sequence number seems to rewind */ - /* XXX: need to log? */ - L2TP_CTRL_DBG((ctrl, LOG_DEBUG, - "receive a out of sequence data packet: " - "%u < %u. ", hdr.ns, call->rcv_nxt)); - return; + if (SEQ_LT(hdr.ns, + call->rcv_nxt - L2TP_CALL_DELAY_LIMIT)) { + /* sequence number seems to be delayed */ + /* XXX: need to log? */ + L2TP_CTRL_DBG((ctrl, LOG_DEBUG, + "receive a out of sequence " + "data packet: %u < %u.", + hdr.ns, call->rcv_nxt)); + return; + } + delayed = 1; + } else { + call->rcv_nxt = hdr.ns + 1; } - call->rcv_nxt = hdr.ns + 1; } - l2tp_call_ppp_input(call, pkt, pktlen); + + l2tp_call_ppp_input(call, pkt, pktlen, delayed); return; } diff --git a/usr.sbin/npppd/npppd/fsm.h b/usr.sbin/npppd/npppd/fsm.h index 1ada8c850fa..3d8b109b3e6 100644 --- a/usr.sbin/npppd/npppd/fsm.h +++ b/usr.sbin/npppd/npppd/fsm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fsm.h,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */ +/* $OpenBSD: fsm.h,v 1.4 2011/10/15 03:24:11 yasuoka Exp $ */ /* $NetBSD: fsm.h,v 1.10 2000/09/23 22:39:35 christos Exp $ */ /* @@ -40,6 +40,8 @@ #define TERMREQ 5 /* Termination Request */ #define TERMACK 6 /* Termination Ack */ #define CODEREJ 7 /* Code Reject */ +#define RESETREQ 14 /* Reset Request */ +#define RESETACK 15 /* Reset Ack */ struct evtimer_wrap { void *ctx; diff --git a/usr.sbin/npppd/npppd/mppe.c b/usr.sbin/npppd/npppd/mppe.c index ae6b389e61c..8365293332b 100644 --- a/usr.sbin/npppd/npppd/mppe.c +++ b/usr.sbin/npppd/npppd/mppe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mppe.c,v 1.4 2010/07/02 21:20:57 yasuoka Exp $ */ +/* $OpenBSD: mppe.c,v 1.5 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: mppe.c,v 1.4 2010/07/02 21:20:57 yasuoka Exp $ */ +/* $Id: mppe.c,v 1.5 2011/10/15 03:24:11 yasuoka Exp $ */ /**@file * * The implementation of MPPE(Microsoft Point-To-Point Encryption Protocol) @@ -73,11 +73,24 @@ #define SESS_KEY_LEN(len) (len < 16)? 8 : 16 +#define COHER_EQ(a, b) ((((a) - (b)) & 0xfff) == 0) +#define COHER_LT(a, b) (((int16_t)(((a) - (b)) << 4)) < 0) +#define COHER_GT(a, b) COHER_LT((b), (a)) +#define COHER_NE(a, b) (!COHER_EQ((a), (b))) +#define COHER_LE(a, b) (!COHER_GE((b), (a))) +#define COHER_GE(a, b) (!COHER_LT((a), (b))) + + static const char *mppe_bits_to_string __P((uint32_t)); static void mppe_log __P((mppe *, uint32_t, const char *, ...)) __printflike(3,4); -static int rc4_key __P((mppe *, mppe_rc4_t *, int, u_char *)); -static void rc4_destroy __P((mppe *, mppe_rc4_t *)); -static void rc4 __P((mppe *, mppe_rc4_t *, int, u_char *, u_char *)); +static int mppe_rc4_init __P((mppe *, mppe_rc4_t *, int)); +static int mppe_rc4_setkey __P((mppe *, mppe_rc4_t *)); +static int mppe_rc4_setoldkey __P((mppe *, mppe_rc4_t *, uint16_t)); +static void mppe_rc4_destroy __P((mppe *, mppe_rc4_t *)); +static void mppe_rc4_encrypt __P((mppe *, mppe_rc4_t *, int, u_char *, u_char *)); +static void *rc4_create_ctx __P((void)); +static int rc4_key __P((void *, int, u_char *)); +static void rc4 __P((void *, int, u_char *, u_char *)); static void GetNewKeyFromSHA __P((u_char *, u_char *, int, u_char *)); /** @@ -159,9 +172,8 @@ mppe_config_done: void mppe_fini(mppe *_this) { - rc4_destroy(_this, &_this->send); - rc4_destroy(_this, &_this->recv); - rc4_destroy(_this, &_this->keychg); + mppe_rc4_destroy(_this, &_this->send); + mppe_rc4_destroy(_this, &_this->recv); } static void @@ -180,13 +192,24 @@ static void mppe_key_change(mppe *_mppe, mppe_rc4_t *_this) { u_char interim[16]; + void *keychg; + + keychg = rc4_create_ctx(); GetNewKeyFromSHA(_this->master_key, _this->session_key, _this->keylen, interim); - rc4_key(_mppe, &_mppe->keychg, _this->keylen, interim); - rc4(_mppe, &_mppe->keychg, _this->keylen, interim, _this->session_key); + rc4_key(keychg, _this->keylen, interim); + rc4(keychg, _this->keylen, interim, _this->session_key); mppe_reduce_key(_this); + + if (_this->old_session_keys) { + int idx = _this->coher_cnt % MPPE_NOLDKEY; + memcpy(_this->old_session_keys[idx], + _this->session_key, MPPE_KEYLEN); + } + + free(keychg); } /** @@ -232,6 +255,9 @@ mppe_start(mppe *_this) _this->recv.keybits = 128; } + mppe_rc4_init(_this, &_this->send, 0); + mppe_rc4_init(_this, &_this->recv, _this->recv.stateless); + GetNewKeyFromSHA(_this->recv.master_key, _this->recv.master_key, _this->recv.keylen, _this->recv.session_key); GetNewKeyFromSHA(_this->send.master_key, _this->send.master_key, @@ -240,10 +266,8 @@ mppe_start(mppe *_this) mppe_reduce_key(&_this->recv); mppe_reduce_key(&_this->send); - rc4_key(_this, &_this->recv, _this->recv.keylen, - _this->recv.session_key); - rc4_key(_this, &_this->send, _this->send.keylen, - _this->send.session_key); + mppe_rc4_setkey(_this, &_this->recv); + mppe_rc4_setkey(_this, &_this->send); } @@ -321,9 +345,7 @@ mppe_create_our_bits(mppe *_this, uint32_t peer_bits) return our_bits; } -#define RESET_REQ 0x0e -#define RESET_ACK 0x0f -#define COHRENCY_CNT_MASK 0x0fff; +#define COHERENCY_CNT_MASK 0x0fff; /** * receiving packets via MPPE. @@ -334,6 +356,8 @@ mppe_input(mppe *_this, u_char *pktp, int len) int pktloss, encrypt, flushed, m, n; uint16_t coher_cnt; u_char *pktp0, *opktp, *opktp0; + uint16_t proto; + int delayed = 0; encrypt = 0; flushed = 0; @@ -345,7 +369,7 @@ mppe_input(mppe *_this, u_char *pktp, int len) flushed = (coher_cnt & 0x8000)? 1 : 0; encrypt = (coher_cnt & 0x1000)? 1 : 0; - coher_cnt &= COHRENCY_CNT_MASK; + coher_cnt &= COHERENCY_CNT_MASK; pktloss = 0; MPPE_DBG((_this, DEBUG_LEVEL_2, "in coher_cnt=%03x/%03x %s%s", @@ -357,7 +381,7 @@ mppe_input(mppe *_this, u_char *pktp, int len) "Received unexpected MPPE packet. (no ecrypt)"); return; } -#ifdef WORKAROUND_OUT_OF_SEQUENCE_PPP_FRAMING + /* * In L2TP/IPsec implementation, in case that the ppp frame sequence * is not able to reconstruct and the ppp frame is out of sequence, it @@ -374,21 +398,29 @@ mppe_input(mppe *_this, u_char *pktp, int len) if (coher_cnt < _this->recv.coher_cnt) coher_cnt0 += 0x1000; if (coher_cnt0 - _this->recv.coher_cnt > 0x0f00) { - mppe_log(_this, LOG_INFO, - "Workaround the out-of-sequence PPP framing problem: " - "%d => %d", _this->recv.coher_cnt, coher_cnt); - return; + if (!_this->recv.stateless || + coher_cnt0 - _this->recv.coher_cnt + <= 0x1000 - MPPE_NOLDKEY) { + mppe_log(_this, LOG_INFO, + "Workaround the out-of-sequence PPP framing problem: " + "%d => %d", _this->recv.coher_cnt, coher_cnt); + return; + } + delayed = 1; } } -#endif + if (_this->recv.stateless != 0) { - mppe_key_change(_this, &_this->recv); - while (_this->recv.coher_cnt != coher_cnt) { + if (!delayed) { mppe_key_change(_this, &_this->recv); - _this->recv.coher_cnt++; - _this->recv.coher_cnt &= COHRENCY_CNT_MASK; - pktloss++; + while (_this->recv.coher_cnt != coher_cnt) { + _this->recv.coher_cnt++; + _this->recv.coher_cnt &= COHERENCY_CNT_MASK; + mppe_key_change(_this, &_this->recv); + pktloss++; + } } + mppe_rc4_setoldkey(_this, &_this->recv, coher_cnt); flushed = 1; } else { if (flushed) { @@ -402,7 +434,7 @@ mppe_input(mppe *_this, u_char *pktp, int len) while (m++ < n) mppe_key_change(_this, &_this->recv); - coher_cnt &= COHRENCY_CNT_MASK; + coher_cnt &= COHERENCY_CNT_MASK; _this->recv.coher_cnt = coher_cnt; } else if (_this->recv.coher_cnt != coher_cnt) { _this->recv.resetreq = 1; @@ -414,7 +446,7 @@ mppe_input(mppe *_this, u_char *pktp, int len) PUTLONG(_this->ppp->ccp.mppe_p_bits, opktp); ppp_output(_this->ppp, PPP_PROTO_NCP | NCP_CCP, - RESET_REQ, _this->recv.resetreq, opktp0, + RESETREQ, _this->recv.resetreq, opktp0, opktp - opktp0); return; } @@ -422,8 +454,11 @@ mppe_input(mppe *_this, u_char *pktp, int len) mppe_key_change(_this, &_this->recv); flushed = 1; } + if (flushed) { + mppe_rc4_setkey(_this, &_this->recv); + } } -#ifndef WORKAROUND_OUT_OF_SEQUENCE_PPP_FRAMING + if (pktloss > 1000) { /* * In case of many packets losing or out of sequence. @@ -433,16 +468,28 @@ mppe_input(mppe *_this, u_char *pktp, int len) */ mppe_log(_this, LOG_WARNING, "%d packets loss", pktloss); } -#endif - if (flushed) { - rc4_key(_this, &_this->recv, _this->recv.keylen, - _this->recv.session_key); - } - rc4(_this, &_this->recv, len - 2, pktp, pktp); + mppe_rc4_encrypt(_this, &_this->recv, len - 2, pktp, pktp); + + if (!delayed) { + _this->recv.coher_cnt++; + _this->recv.coher_cnt &= COHERENCY_CNT_MASK; + } - _this->recv.coher_cnt++; - _this->recv.coher_cnt &= COHRENCY_CNT_MASK; + if (pktp[0] & 1) + proto = pktp[0]; + else + proto = pktp[0] << 8 | pktp[1]; + /* + * According to RFC3078 section 3, + * MPPE only accept protocol number 0021-00FA. + * If decrypted protocol number is out of range, + * it indicates loss of coherency. + */ + if (!(proto & 1) || proto < 0x21 || proto > 0xfa) { + mppe_log(_this, LOG_INFO, "MPPE coherency is lost"); + return; /* drop frame */ + } _this->ppp->recv_packet(_this->ppp, pktp, len - 2, PPP_IO_FLAGS_MPPE_ENCRYPTED); @@ -491,15 +538,14 @@ mppe_pkt_output(mppe *_this, uint16_t proto, u_char *pktp, int len) } if (flushed) { - rc4_key(_this, &_this->send, _this->send.keylen, - _this->send.session_key); + mppe_rc4_setkey(_this, &_this->send); } MPPE_DBG((_this, DEBUG_LEVEL_2, "out coher_cnt=%03x %s%s", _this->send.coher_cnt, (flushed)? "[flushed]" : "", (encrypt)? "[encrypt]" : "")); - coher_cnt = _this->send.coher_cnt & COHRENCY_CNT_MASK; + coher_cnt = _this->send.coher_cnt & COHERENCY_CNT_MASK; if (flushed) coher_cnt |= 0x8000; if (encrypt) @@ -507,12 +553,12 @@ mppe_pkt_output(mppe *_this, uint16_t proto, u_char *pktp, int len) PUTSHORT(coher_cnt, outp); proto = htons(proto); - rc4(_this, &_this->send, 2, (u_char *)&proto, outp); - rc4(_this, &_this->send, len, pktp, outp + 2); + mppe_rc4_encrypt(_this, &_this->send, 2, (u_char *)&proto, outp); + mppe_rc4_encrypt(_this, &_this->send, len, pktp, outp + 2); ppp_output(_this->ppp, PPP_PROTO_MPPE, 0, 0, outp0, len + 4); _this->send.coher_cnt++; - _this->send.coher_cnt &= COHRENCY_CNT_MASK; + _this->send.coher_cnt &= COHERENCY_CNT_MASK; } static void @@ -577,35 +623,25 @@ static u_char SHAPad1[] = { /************************************************************************ * implementations of OpenSSL version ************************************************************************/ +static void * +rc4_create_ctx(void) +{ + return malloc(sizeof(RC4_KEY)); +} static int -rc4_key(mppe *_mppe, mppe_rc4_t *_this, int lkey, u_char *key) +rc4_key(void *rc4ctx, int lkey, u_char *key) { - if (_this->rc4ctx == NULL) { - if ((_this->rc4ctx = malloc(sizeof(RC4_KEY))) == NULL) { - mppe_log(_mppe, LOG_ERR, "malloc() failed at %s: %m", - __func__); - return 1; - } - } - RC4_set_key((RC4_KEY *)_this->rc4ctx, lkey, key); + RC4_set_key(rc4ctx, lkey, key); return 0; } static void -rc4(mppe *_mppe, mppe_rc4_t *_this, int len, u_char *indata, u_char *outdata) +rc4(void *rc4ctx, int len, u_char *indata, u_char *outdata) { - RC4((RC4_KEY *)_this->rc4ctx, len, indata, outdata); -} - -static void -rc4_destroy(mppe *_mppe, mppe_rc4_t *_this) -{ - if (_this->rc4ctx != NULL) - free(_this->rc4ctx); - _this->rc4ctx = NULL; + RC4(rc4ctx, len, indata, outdata); } static void @@ -626,3 +662,50 @@ GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength, MoveMemory(InterimKey, Digest, SessionKeyLength); } + +static int +mppe_rc4_init(mppe *_mppe, mppe_rc4_t *_this, int has_oldkey) +{ + if ((_this->rc4ctx = rc4_create_ctx()) == NULL) { + mppe_log(_mppe, LOG_ERR, "malloc() failed at %s: %m", + __func__); + return 1; + } + + if (has_oldkey) + _this->old_session_keys = + malloc(MPPE_KEYLEN * MPPE_NOLDKEY); + else + _this->old_session_keys = NULL; + + return 0; +} + +static int +mppe_rc4_setkey(mppe *_mppe, mppe_rc4_t *_this) +{ + return rc4_key(_this->rc4ctx, _this->keylen, _this->session_key); +} + +static int +mppe_rc4_setoldkey(mppe *_mppe, mppe_rc4_t *_this, uint16_t coher_cnt) +{ + return rc4_key(_this->rc4ctx, _this->keylen, + _this->old_session_keys[coher_cnt % MPPE_NOLDKEY]); +} + +static void +mppe_rc4_encrypt(mppe *_mppe, mppe_rc4_t *_this, int len, u_char *indata, u_char *outdata) +{ + rc4(_this->rc4ctx, len, indata, outdata); +} + +static void +mppe_rc4_destroy(mppe *_mppe, mppe_rc4_t *_this) +{ + if (_this->rc4ctx != NULL) + free(_this->rc4ctx); + if (_this->old_session_keys != NULL) + free(_this->old_session_keys); + _this->rc4ctx = NULL; +} diff --git a/usr.sbin/npppd/npppd/ppp.c b/usr.sbin/npppd/npppd/ppp.c index fc772df8f5c..68c4aa210c5 100644 --- a/usr.sbin/npppd/npppd/ppp.c +++ b/usr.sbin/npppd/npppd/ppp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ppp.c,v 1.8 2011/07/06 20:52:28 yasuoka Exp $ */ +/* $OpenBSD: ppp.c,v 1.9 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: ppp.c,v 1.8 2011/07/06 20:52:28 yasuoka Exp $ */ +/* $Id: ppp.c,v 1.9 2011/10/15 03:24:11 yasuoka Exp $ */ /**@file * This file provides PPP(Point-to-Point Protocol, RFC 1661) and * {@link :: _npppd_ppp PPP instance} related functions. @@ -716,11 +716,14 @@ ppp_ccp_opened(npppd_ppp *_this) void ppp_ccp_stopped(npppd_ppp *_this) { - if (_this->mppe.required) - ppp_stop(_this, NULL); +#ifdef USE_NPPPD_MPPE + if (_this->mppe.required) { + ppp_stop(_this, NULL); + return; + } +#endif #ifdef USE_NPPPD_PIPEX - else - ppp_on_network_pipex(_this); + ppp_on_network_pipex(_this); #endif } @@ -730,7 +733,8 @@ ppp_ccp_stopped(npppd_ppp *_this) /** * Receive the PPP packet. * @param flags Indicate information of received packet by bit flags. - * {@link ::PPP_IO_FLAGS_MPPE_ENCRYPTED} may be used. + * {@link ::PPP_IO_FLAGS_MPPE_ENCRYPTED} and + * {@link ::PPP_IO_FLAGS_DELAYED} may be used. * @return return 0 on success. return 1 on failure. */ static int @@ -792,6 +796,13 @@ ppp_recv_packet(npppd_ppp *_this, unsigned char *pkt, int lpkt, int flags) GETSHORT(proto, inp); } + /* + * if the PPP frame is reordered, drop it + * unless proto is reorder-tolerant + */ + if (flags & PPP_IO_FLAGS_DELAYED && proto != PPP_PROTO_IP) + return 1; + if (_this->log_dump_in != 0 && debug_get_debugfp() != NULL) { char buf[256]; diff --git a/usr.sbin/npppd/npppd/ppp.h b/usr.sbin/npppd/npppd/ppp.h index 1b3879ef761..604a1a05719 100644 --- a/usr.sbin/npppd/npppd/ppp.h +++ b/usr.sbin/npppd/npppd/ppp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ppp.h,v 1.6 2011/07/06 20:52:28 yasuoka Exp $ */ +/* $OpenBSD: ppp.h,v 1.7 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -380,6 +380,8 @@ typedef int (*npppd_iofunc) ( /** Flag indicates the orignal packet was encrypted by MPPE */ #define PPP_IO_FLAGS_MPPE_ENCRYPTED 0x0001 +/** Flag indicates the orignal packet was delayed */ +#define PPP_IO_FLAGS_DELAYED 0x0002 typedef void (*npppd_voidfunc) ( npppd_ppp *ppp @@ -387,6 +389,8 @@ typedef void (*npppd_voidfunc) ( #ifdef USE_NPPPD_MPPE +#define MPPE_NOLDKEY 64 + typedef struct _mppe_rc4 { void *rc4ctx; @@ -403,6 +407,7 @@ typedef struct _mppe_rc4 { uint8_t master_key[MPPE_KEYLEN]; uint8_t session_key[MPPE_KEYLEN]; + uint8_t (*old_session_keys)[MPPE_KEYLEN]; } mppe_rc4_t; /** Type for MPPE */ @@ -423,7 +428,7 @@ typedef struct _mppe { reserved :11; uint16_t keylenbits; - mppe_rc4_t send, recv, keychg; + mppe_rc4_t send, recv; } mppe; #endif diff --git a/usr.sbin/npppd/pptp/pptp.h b/usr.sbin/npppd/pptp/pptp.h index db704aa0f79..bbefc5af350 100644 --- a/usr.sbin/npppd/pptp/pptp.h +++ b/usr.sbin/npppd/pptp/pptp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pptp.h,v 1.5 2011/01/20 23:12:33 jasper Exp $ */ +/* $OpenBSD: pptp.h,v 1.6 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -180,11 +180,11 @@ #define PPTP_CALL_INITIAL_PPD 0 #endif -/* PPTP_CALL_NMAX_INSEQ specifies N packets was backwarded, - * when sequence# backwarded */ -#ifndef PPTP_CALL_NMAX_INSEQ -#define PPTP_CALL_NMAX_INSEQ 64 -#endif +/** + * PPTP_CALL_DELAY_LIMIT indicates how many sequence number can be rewinded + * by reordering. + */ +#define PPTP_CALL_DELAY_LIMIT 64 /* pptp call state machine */ #define PPTP_CALL_STATE_IDLE 0 diff --git a/usr.sbin/npppd/pptp/pptp_call.c b/usr.sbin/npppd/pptp/pptp_call.c index 66cf2599ae0..9dd069c3bc5 100644 --- a/usr.sbin/npppd/pptp/pptp_call.c +++ b/usr.sbin/npppd/pptp/pptp_call.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pptp_call.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */ +/* $OpenBSD: pptp_call.c,v 1.4 2011/10/15 03:24:11 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: pptp_call.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */ +/* $Id: pptp_call.c,v 1.4 2011/10/15 03:24:11 yasuoka Exp $ */ /**@file PPTP Call */ /* currently it supports PAC mode only */ #include <sys/types.h> @@ -80,7 +80,7 @@ static int pptp_call_bind_ppp (pptp_call *); static void pptp_call_log (pptp_call *, int, const char *, ...); static void pptp_call_OCRQ_string (struct pptp_ocrq *, char *, int); static void pptp_call_OCRP_string (struct pptp_ocrp *, char *, int); -static void pptp_call_ppp_input (pptp_call *, unsigned char *, int); +static void pptp_call_ppp_input (pptp_call *, unsigned char *, int, int); static char * pptp_call_state_string(int); static int pptp_call_ppp_output (npppd_ppp *, unsigned char *, int, int); @@ -474,6 +474,7 @@ pptp_call_gre_input(pptp_call *_this, uint32_t seq, uint32_t ack, { int log_prio; const char *reason; + int delayed = 0; PPTP_CALL_ASSERT(_this != NULL); @@ -500,14 +501,7 @@ pptp_call_gre_input(pptp_call *_this, uint32_t seq, uint32_t ack, if (ack + 1 == _this->snd_una) { /* nothing to do */ } else if (SEQ_LT(ack, _this->snd_una)) { - /* ack sequence# was rewinded */ - if (abs(ack - _this->snd_una) < PPTP_CALL_NMAX_INSEQ) { - /* packet reordered ? */ - log_prio = LOG_DEBUG; - } - reason = "ack out of sequence"; - goto bad_pkt; - /* FALLTHROUGH */ + delayed = 1; } else if (SEQ_GT(ack, _this->snd_nxt)) { reason = "ack for unknown sequence."; goto bad_pkt; @@ -522,11 +516,12 @@ pptp_call_gre_input(pptp_call *_this, uint32_t seq, uint32_t ack, /* check sequence# */ if (SEQ_LT(seq, _this->rcv_nxt)) { - /* reorderd, delayed delivery? */ - if (abs(seq - _this->rcv_nxt) < PPTP_CALL_NMAX_INSEQ) - log_prio = LOG_DEBUG; - reason = "out of sequence"; - goto bad_pkt; + /* delayed delivery? */ + if (SEQ_LT(seq, _this->rcv_nxt - PPTP_CALL_DELAY_LIMIT)) { + reason = "out of sequence"; + goto bad_pkt; + } + delayed = 1; } else if (SEQ_GE(seq, _this->rcv_nxt + _this->maxwinsz)){ /* MUST Process them */ /* XXX FIXME: if over 4096 packets lost, it can not @@ -537,21 +532,27 @@ pptp_call_gre_input(pptp_call *_this, uint32_t seq, uint32_t ack, _this->rcv_nxt + _this->maxwinsz - 1, SEQ_SUB(seq, _this->rcv_nxt)); } - seq++; - /* XXX : TODO: should it counts lost packets ppp->ierrors - * and update ppp->ierrors counter? */ - _this->rcv_nxt = seq; - - if (SEQ_SUB(seq, _this->rcv_acked) > RUPDIV(_this->winsz, 2)) { - /* - * Multi-packet acknowledgement. - * send ack when it reachs to half of window size - */ - PPTP_CALL_DBG((_this, LOG_DEBUG, "rcv window size=%u %u %u\n", - SEQ_SUB(seq, _this->rcv_acked), seq, _this->rcv_acked)); - pptp_call_gre_output(_this, 0, 1, NULL, 0); + + if (!delayed) { + seq++; + /* XXX : TODO: should it counts lost packets ppp->ierrors + * and update ppp->ierrors counter? */ + _this->rcv_nxt = seq; + + if (SEQ_SUB(seq, _this->rcv_acked) > RUPDIV(_this->winsz, 2)) { + /* + * Multi-packet acknowledgement. + * send ack when it reachs to half of window size + */ + PPTP_CALL_DBG((_this, LOG_DEBUG, + "rcv window size=%u %u %u\n", + SEQ_SUB(seq, _this->rcv_acked), seq, + _this->rcv_acked)); + pptp_call_gre_output(_this, 0, 1, NULL, 0); + } } - pptp_call_ppp_input(_this, pkt, pktlen); + + pptp_call_ppp_input(_this, pkt, pktlen, delayed); return; bad_pkt: @@ -658,7 +659,7 @@ pptp_call_notify_down(pptp_call *_this) /* input packet to ppp */ static void -pptp_call_ppp_input(pptp_call *_this, u_char *pkt, int pktlen) +pptp_call_ppp_input(pptp_call *_this, u_char *pkt, int pktlen, int delayed) { int rval; npppd_ppp *ppp; @@ -669,7 +670,7 @@ pptp_call_ppp_input(pptp_call *_this, u_char *pkt, int pktlen) "Received ppp frame but ppp is not assigned yet"); return; } - rval = ppp->recv_packet(ppp, pkt, pktlen, 0); + rval = ppp->recv_packet(ppp, pkt, pktlen, delayed ? PPP_IO_FLAGS_DELAYED : 0); if (_this->ppp == NULL) /* ppp is freed */ return; |