diff --git a/release/src/router/pppd/include/net/ppp-comp.h b/release/src/router/pppd/include/net/ppp-comp.h
index 704042c..6fb6e5f 100644
--- a/release/src/router/pppd/include/net/ppp-comp.h
+++ b/release/src/router/pppd/include/net/ppp-comp.h
@@ -195,6 +195,33 @@ struct compressor {
 #define LZS_EXT_BIT_FLUSHED	0x80	/* bit A */
 #define LZS_EXT_BIT_COMP	0x20	/* bit C */
 
+/* MPPE/MPPC definitions by J.D.*/
+#define MPPE_STATELESS          MPPE_H_BIT	/* configuration bit H */
+#define MPPE_40BIT              MPPE_L_BIT	/* configuration bit L */
+#define MPPE_56BIT              MPPE_M_BIT	/* configuration bit M */
+#define MPPE_128BIT             MPPE_S_BIT	/* configuration bit S */
+#define MPPE_MPPC               MPPE_C_BIT	/* configuration bit C */
+
+/*
+ * Definitions for Stac LZS.
+ */
+
+#define CI_LZS			17	/* config option for Stac LZS */
+#define CILEN_LZS		5	/* length of config option */
+
+#define LZS_OVHD		4	/* max. LZS overhead */
+#define LZS_HIST_LEN		2048	/* LZS history size */
+#define LZS_MAX_CCOUNT		0x0FFF	/* max. coherency counter value */
+
+#define LZS_MODE_NONE		0
+#define LZS_MODE_LCB		1
+#define LZS_MODE_CRC		2
+#define LZS_MODE_SEQ		3
+#define LZS_MODE_EXT		4
+
+#define LZS_EXT_BIT_FLUSHED	0x80	/* bit A */
+#define LZS_EXT_BIT_COMP	0x20	/* bit C */
+
 /*
  * Definitions for other, as yet unsupported, compression methods.
  */
diff --git a/release/src/router/pppd/pppd/ccp.c b/release/src/router/pppd/pppd/ccp.c
index 99eaa47..be3e2b9 100644
--- a/release/src/router/pppd/pppd/ccp.c
+++ b/release/src/router/pppd/pppd/ccp.c
@@ -370,6 +370,100 @@ setdeflate(argv)
     return 1;
 }
 
+#ifdef MPPE
+/*
+ * Functions called from config options
+ */
+/* 
+   MPPE suboptions:
+	required - require MPPE; disconnect if peer doesn't support it
+	stateless - use stateless mode
+	no40 - disable 40 bit keys
+	no56 - disable 56 bit keys
+	no128 - disable 128 bit keys
+*/
+int setmppe(char **argv)
+{
+    int i;
+    char *str, cmdbuf[16];
+
+    ccp_allowoptions[0].mppe = 1;
+    ccp_allowoptions[0].mppe_40 = 1;
+    ccp_allowoptions[0].mppe_56 = 1;
+    ccp_allowoptions[0].mppe_128 = 1;
+    ccp_allowoptions[0].mppe_stateless = 0;
+    ccp_wantoptions[0].mppe = 0;
+
+    str = *argv;
+
+    while (1) {
+	i = 0;
+	memset(cmdbuf, '\0', 16);
+	while ((i < 16) && (*str != ',') && (*str != '\0'))
+	    cmdbuf[i++] = *str++;
+	cmdbuf[i] = '\0';
+	if (!strncasecmp(cmdbuf, "no40", strlen("no40"))) {
+	    ccp_allowoptions[0].mppe_40 = 0;
+	    goto next_param;
+	} else if (!strncasecmp(cmdbuf, "no56", strlen("no56"))) {
+	    ccp_allowoptions[0].mppe_56 = 0;
+	    goto next_param;
+	} else if (!strncasecmp(cmdbuf, "no128", strlen("no128"))) {
+	    ccp_allowoptions[0].mppe_128 = 0;
+	    goto next_param;
+	} else if (!strncasecmp(cmdbuf, "stateless", strlen("stateless"))) {
+	    ccp_allowoptions[0].mppe_stateless = 1;
+	    goto next_param;
+	} else if (!strncasecmp(cmdbuf, "required", strlen("required"))) {
+	    ccp_wantoptions[0].mppe = 1;
+	    goto next_param;
+	} else {
+	    option_error("invalid parameter '%s' for mppe option", cmdbuf);
+	    return 0;
+	}
+
+    next_param:
+	if (*str == ',') {
+	    str++;
+	    continue;
+	}
+	if (*str == '\0') {
+	    if (!(ccp_allowoptions[0].mppe_40 || ccp_allowoptions[0].mppe_56 ||
+		  ccp_allowoptions[0].mppe_128)) {
+		if (ccp_wantoptions[0].mppe == 1) {
+		    option_error("You require MPPE but you have switched off "
+				 "all encryption key lengths.");
+		    return 0;
+		}
+		ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
+		ccp_wantoptions[0].mppe_stateless =
+		    ccp_allowoptions[0].mppe_stateless = 0;
+	    } else {
+		ccp_allowoptions[0].mppe = 1;
+		ccp_wantoptions[0].mppe_stateless =
+		    ccp_allowoptions[0].mppe_stateless;
+		if (ccp_wantoptions[0].mppe == 1) {
+		    ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40;
+		    ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56;
+		    ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128;
+		}
+	    }
+	    return 1;
+	}
+    }
+}
+
+int setnomppe(void)
+{
+    ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
+    ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40 = 0;
+    ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56 = 0;
+    ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128 = 0;
+    ccp_wantoptions[0].mppe_stateless = ccp_allowoptions[0].mppe_stateless = 0;
+    return 1;
+}
+#endif /* MPPE */
+
 /*
  * ccp_init - initialize CCP.
  */
@@ -2129,4 +2223,3 @@ ccp_rack_timeout(arg)
     } else
 	ccp_localstate[f->unit] &= ~RACK_PENDING;
 }
-
diff --git a/release/src/router/pppd/pppd/pppd.8 b/release/src/router/pppd/pppd/pppd.8
index c148652..c5e9425 100644
--- a/release/src/router/pppd/pppd/pppd.8
+++ b/release/src/router/pppd/pppd/pppd.8
@@ -649,9 +649,29 @@ option.  This option is currently only available under Linux.
 .B mppc
 Enables MPPC (Microsoft Point to Point Compression).  This is the default.
 .TP
-.B mppe\-stateful
-Allow MPPE to use stateful mode.  Stateless mode is still attempted first.
-The default is to disallow stateful mode.  
+.B mppc
+Enables MPPC (Microsoft Point to Point Compression).  This is the default.
+.TP
+.B mppe \fIsubopt1[,subopt2[,subopt3[..]]]
+Modify MPPE (Microsoft Point to Point Encryption) parameters. In order
+for MPPE to successfully come up, you must have authenticated with either
+MS-CHAP or MS-CHAPv2. By default MPPE is optional, it means that pppd will
+not propose MPPE to the peer, but will negotiate MPPE if peer wants that.
+You can change this using \fIrequired\fR suboption.
+This option is presently only supported under Linux, and only if your
+kernel has been configured to include MPPE support.
+.IP
+MPPE suboptions:
+.br
+\fIrequired\fR - require MPPE; disconnect if peer doesn't support it,
+.br
+\fIstateless\fR - try to negotiate stateless mode; default is stateful,
+.br
+\fIno40\fR - disable 40 bit keys,
+.br
+\fIno56\fR - disable 56 bit keys,
+.br
+\fIno128\fR - disable 128 bit keys
 .TP
 .B mpshortseq
 Enables the use of short (12-bit) sequence numbers in multilink
