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 /usr.sbin | |
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.
Diffstat (limited to 'usr.sbin')
-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 |
9 files changed, 243 insertions, 130 deletions
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; |