X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/53f1a814a14f348ecf1405d406303e1125205504..728b8416cfad1cec0ffdf17c871ff1e6b0c386fd:/ppp.c?ds=sidebyside

diff --git a/ppp.c b/ppp.c
index 922f591..d2411a6 100644
--- a/ppp.c
+++ b/ppp.c
@@ -1,6 +1,6 @@
 // L2TPNS PPP Stuff
 
-char const *cvs_id_ppp = "$Id: ppp.c,v 1.77 2005/08/29 06:17:53 bodea Exp $";
+char const *cvs_id_ppp = "$Id: ppp.c,v 1.85 2005/11/04 14:41:50 bodea Exp $";
 
 #include <stdio.h>
 #include <string.h>
@@ -88,7 +88,7 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 	if (session[s].ip || !(r = radiusnew(s)))
 	{
 		// respond now, either no RADIUS available or already authenticated
-		uint8_t b[MAXCONTROL];
+		uint8_t b[MAXETHER];
 		uint8_t id = p[1];
 		uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP);
 		if (!p) return;
@@ -300,7 +300,7 @@ static void dumplcp(uint8_t *p, int l)
 				else if (length == 5)
 				{
 					int proto = ntohs(*(uint16_t *)(o + 2));
-					int algo = *(uint8_t *)(o + 4);
+					int algo = *(o + 4);
 					LOG(4, 0, 0, "    %s 0x%x 0x%x (%s)\n", ppp_lcp_option(type), proto, algo,
 						(proto == PPPCHAP && algo == 5) ? "CHAP MD5"  : "UNSUPPORTED");
 				}
@@ -374,7 +374,7 @@ static void lcp_restart(sessionidt s)
 	change_state(s, ccp, Dead);
 }
 
-static uint8_t *ppp_rej(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
+static uint8_t *ppp_conf_rej(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
 	uint8_t **response, uint8_t *queued, uint8_t *packet, uint8_t *option)
 {
 	if (!*response || **response != ConfigRej)
@@ -397,7 +397,7 @@ static uint8_t *ppp_rej(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
 	return queued + option[1];
 }
 
-static uint8_t *ppp_nak(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
+static uint8_t *ppp_conf_nak(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
 	uint8_t **response, uint8_t *queued, uint8_t *packet, uint8_t *option,
 	uint8_t *value, size_t vlen)
 {
@@ -415,13 +415,13 @@ static uint8_t *ppp_nak(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
 	    	if (*nak_sent < config->ppp_max_failure) // reject queued
 			return queued;
 
-		return ppp_rej(s, buf, blen, mtype, response, 0, packet, option);
+		return ppp_conf_rej(s, buf, blen, mtype, response, 0, packet, option);
 	}
 
 	if (!*response)
 	{
 	    	if (*nak_sent >= config->ppp_max_failure)
-			return ppp_rej(s, buf, blen, mtype, response, 0, packet, option);
+			return ppp_conf_rej(s, buf, blen, mtype, response, 0, packet, option);
 
 		queued = *response = makeppp(buf, blen, packet, 2, s, session[s].tunnel, mtype);
 		if (!queued)
@@ -444,10 +444,35 @@ static uint8_t *ppp_nak(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
 	return queued + vlen;
 }
 
+static void ppp_code_rej(sessionidt s, tunnelidt t, uint16_t proto,
+	char *pname, uint8_t *p, uint16_t l, uint8_t *buf, size_t size)
+{
+	uint8_t *q;
+	int mru = session[s].mru;
+	if (mru > size) mru = size;
+
+	l += 4;
+	if (l > mru) l = mru;
+
+	q = makeppp(buf, size, 0, 0, s, t, proto);
+	if (!q) return;
+
+	*q = CodeRej;
+	*(q + 1) = ++sess_local[s].lcp_ident;
+	*(uint16_t *)(q + 2) = htons(l);
+	memcpy(q + 4, p, l - 4);
+
+	LOG(2, s, t, "Unexpected %s code %s\n", pname, ppp_code(*p));
+	LOG(3, s, t, "%s: send %s\n", pname, ppp_code(*q));
+	if (config->debug > 3) dumplcp(q, l);
+
+	tunnelsend(buf, l + (q - buf), t);
+}
+
 // Process LCP messages
 void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 {
-	uint8_t b[MAXCONTROL];
+	uint8_t b[MAXETHER];
 	uint8_t *q = NULL;
 	uint32_t magicno = 0;
 	uint16_t hl;
@@ -558,7 +583,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 						break;
 
 					LOG(3, s, t, "    Remote requesting asyncmap.  Rejecting.\n");
-					q = ppp_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, asyncmap, sizeof(asyncmap));
+					q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, asyncmap, sizeof(asyncmap));
 					break;
 
 				case 3: // Authentication-Protocol
@@ -596,14 +621,14 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 						alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authprefer);
 						if (alen < 2) break; // paranoia
 
-						q = ppp_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2);
+						q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2);
 						if (q && *response == ConfigNak &&
 							config->radius_authtypes != config->radius_authprefer)
 						{
 							// alternate type
 						    	alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authtypes & ~config->radius_authprefer);
 							if (alen < 2) break;
-							q = ppp_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2);
+							q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2);
 						}
 
 						break;
@@ -621,7 +646,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
 				default: // Reject any unknown options
 					LOG(3, s, t, "    Rejecting unknown PPP LCP option %d\n", type);
-					q = ppp_rej(s, b, sizeof(b), PPPLCP, &response, q, p, o);
+					q = ppp_conf_rej(s, b, sizeof(b), PPPLCP, &response, q, p, o);
 			}
 			x -= length;
 			o += length;
@@ -711,12 +736,12 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 				case 1: // Maximum-Receive-Unit
 					if (*p == ConfigNak)
 					{
-						session[s].mru = ntohs(*(uint16_t *)(o + 2));
-						LOG(3, s, t, "    Remote requested MRU of %u\n", session[s].mru);
+						sess_local[s].ppp_mru = ntohs(*(uint16_t *)(o + 2));
+						LOG(3, s, t, "    Remote requested MRU of %u\n", sess_local[s].ppp_mru);
 					}
 					else
 					{
-						session[s].mru = 0;
+						sess_local[s].ppp_mru = 0;
 						LOG(3, s, t, "    Remote rejected MRU negotiation\n");
 					}
 
@@ -866,24 +891,9 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 	{
 		// Ignore it, last_packet time is set earlier than this.
 	}
-	else
+	else if (*p != CodeRej)
 	{
-		int code = *p;
-		int mru = session[s].mru;
-		if (!mru)
-			mru = DEFAULT_MRU;
-
-		if (l > mru) l = mru;
-
-		*p = CodeRej;
-		q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP);
-		if (!q) return;
-
-		LOG(2, s, t, "Unexpected LCP code %s\n", ppp_code(code));
-		LOG(3, s, t, "LCP: send %s\n", ppp_code(*q));
-		if (config->debug > 3) dumplcp(q, l);
-
-		tunnelsend(b, l + (q - b), t);
+		ppp_code_rej(s, t, PPPLCP, "LCP", p, l, b, sizeof(b));
 	}
 }
 
@@ -893,11 +903,17 @@ static void ipcp_open(sessionidt s, tunnelidt t)
 
 	change_state(s, ipcp, Opened);
 
-	if (!session[s].walled_garden)
+	if (!(session[s].walled_garden || session[s].flags & SESSION_STARTED))
 	{
 		uint16_t r = radiusnew(s);
 		if (r)
+		{
 			radiussend(r, RADIUSSTART); // send radius start
+
+			// don't send further Start records if IPCP is restarted
+			session[s].flags |= SESSION_STARTED;
+			cluster_send_session(s);
+		}
 	}
 
 	// start IPv6 if configured and still in passive state
@@ -911,7 +927,7 @@ static void ipcp_open(sessionidt s, tunnelidt t)
 // Process IPCP messages
 void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 {
-	uint8_t b[MAXCONTROL];
+	uint8_t b[MAXETHER];
 	uint8_t *q = 0;
 	uint16_t hl;
 
@@ -985,7 +1001,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 				if (memcmp(o + 2, &addr, (sizeof addr)))
 				{
 					uint8_t *oq = q;
-					q = ppp_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
+					q = ppp_conf_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
 					if (!q || (q != oq && *response == ConfigRej))
 					{
 						sessionshutdown(s, "Can't negotiate IPCP.", 3, 0);
@@ -1001,7 +1017,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 				addr = htonl(session[s].dns1);
 				if (memcmp(o + 2, &addr, (sizeof addr)))
 				{
-					q = ppp_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
+					q = ppp_conf_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
 					if (!q) return;
 				}
 
@@ -1013,7 +1029,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 				addr = htonl(session[s].dns1);
 				if (memcmp(o + 2, &addr, sizeof(addr)))
 				{
-					q = ppp_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
+					q = ppp_conf_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
 					if (!q) return;
 				}
 
@@ -1021,7 +1037,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
 			default:
 				LOG(2, s, t, "    Rejecting PPP IPCP Option type %d\n", *o);
-				q = ppp_rej(s, b, sizeof(b), PPPIPCP, &response, q, p, o);
+				q = ppp_conf_rej(s, b, sizeof(b), PPPIPCP, &response, q, p, o);
 				if (!q) return;
 			}
 
@@ -1109,22 +1125,9 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 		tunnelsend(b, l + (q - b), t);
 		change_state(s, ipcp, Stopped);
 	}
-	else
+	else if (*p != CodeRej)
 	{
-		int code = *p;
-		int mru = session[s].mru;
-		if (!mru)
-			mru = DEFAULT_MRU;
-
-		if (l > mru) l = mru;
-
-		*p = CodeRej;
-		q = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP);
-		if (!q) return;
-
-		LOG(2, s, t, "Unexpected IPCP code %s\n", ppp_code(code));
-		LOG(3, s, t, "IPCP: send %s\n", ppp_code(*q));
-		tunnelsend(b, l + (q - b), t);
+		ppp_code_rej(s, t, PPPIPCP, "IPCP", p, l, b, sizeof(b));
 	}
 }
 
@@ -1143,7 +1146,7 @@ static void ipv6cp_open(sessionidt s, tunnelidt t)
 // Process IPV6CP messages
 void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 {
-	uint8_t b[MAXCONTROL];
+	uint8_t b[MAXETHER];
 	uint8_t *q = 0;
 	uint16_t hl;
 
@@ -1173,16 +1176,6 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
 	LOG(3, s, t, "IPV6CP: recv %s\n", ppp_code(*p));
 
-	if (!config->ipv6_prefix.s6_addr[0])
-	{
-	    	LOG(2, s, t, "IPV6CP: %s rejected (not configured)\n", ppp_code(*p));
-		*p = ProtocolRej;
-		q = makeppp(b, sizeof(b),  p, l, s, t, PPPIPV6CP);
-		if (!q) return;
-		tunnelsend(b, l + (q - b), t);
-		return;
-	}
-
 	if (!session[s].ip)
 	{
 		LOG(3, s, t, "IPV6CP: no IPv4 address (IPCP in state %s)\n", ppp_state(session[s].ppp.ipcp));
@@ -1234,7 +1227,7 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
 				if (memcmp(o + 2, ident, sizeof(ident)))
 				{
-					q = ppp_nak(s, b, sizeof(b), PPPIPV6CP, &response, q, p, o, ident, sizeof(ident));
+					q = ppp_conf_nak(s, b, sizeof(b), PPPIPV6CP, &response, q, p, o, ident, sizeof(ident));
 					if (!q) return;
 				}
 
@@ -1242,7 +1235,7 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
 			default:
 				LOG(2, s, t, "    Rejecting PPP IPV6CP Option type %d\n", *o);
-				q = ppp_rej(s, b, sizeof(b), PPPIPV6CP, &response, q, p, o);
+				q = ppp_conf_rej(s, b, sizeof(b), PPPIPV6CP, &response, q, p, o);
 				if (!q) return;
 			}
 
@@ -1330,22 +1323,9 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 		tunnelsend(b, l + (q - b), t);
 		change_state(s, ipv6cp, Stopped);
 	}
-	else
+	else if (*p != CodeRej)
 	{
-		int code = *p;
-		int mru = session[s].mru;
-		if (!mru)
-			mru = DEFAULT_MRU;
-
-		if (l > mru) l = mru;
-
-		*p = CodeRej;
-		q = makeppp(b, sizeof(b), p, l, s, t, PPPIPV6CP);
-		if (!q) return;
-
-		LOG(2, s, t, "Unexpected IPV6CP code %s\n", ppp_code(code));
-		LOG(3, s, t, "IPV6CP: send %s\n", ppp_code(*q));
-		tunnelsend(b, l + (q - b), t);
+		ppp_code_rej(s, t, PPPIPV6CP, "IPV6CP", p, l, b, sizeof(b));
 	}
 }
 
@@ -1361,6 +1341,13 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
 	LOG_HEX(5, "IP", p, l);
 
+	if (l < 20)
+	{
+		LOG(1, s, t, "IP packet too short %d\n", l);
+		STAT(tunnel_rx_errors);
+		return ;
+	}
+
 	ip = ntohl(*(uint32_t *)(p + 12));
 
 	if (l > MAXETHER)
@@ -1384,6 +1371,14 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 	if (session[s].filter_in && !ip_filter(p, l, session[s].filter_in - 1))
 		return;
 
+	// adjust MSS on SYN and SYN,ACK packets with options
+	if ((ntohs(*(uint16_t *) (p + 6)) & 0x1fff) == 0 && p[9] == IPPROTO_TCP) // first tcp fragment
+	{
+		int ihl = (p[0] & 0xf) * 4; // length of IP header
+		if (l >= ihl + 20 && (p[ihl + 13] & TCP_FLAG_SYN) && ((p[ihl + 12] >> 4) > 5))
+			adjust_tcp_mss(s, t, p, l, p + ihl);
+	}
+
 	// Add on the tun header
 	p -= 4;
 	*(uint32_t *) p = htonl(PKTIP);
@@ -1575,7 +1570,7 @@ void send_ipin(sessionidt s, uint8_t *buf, int len)
 // Process CCP messages
 void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 {
-	uint8_t b[MAXCONTROL];
+	uint8_t b[MAXETHER];
 	uint8_t *q;
 
 	CSTAT(processccp);
@@ -1691,29 +1686,16 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 		tunnelsend(b, l + (q - b), t);
 		change_state(s, ccp, Stopped);
 	}
-	else
+	else if (*p != CodeRej)
 	{
-		int code = *p;
-		int mru = session[s].mru;
-		if (!mru)
-			mru = DEFAULT_MRU;
-
-		if (l > mru) l = mru;
-
-		*p = CodeRej;
-		q = makeppp(b, sizeof(b), p, l, s, t, PPPCCP);
-		if (!q) return;
-
-		LOG(2, s, t, "Unexpected CCP code %s\n", ppp_code(code));
-		LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
-		tunnelsend(b, l + (q - b), t);
+		ppp_code_rej(s, t, PPPCCP, "CCP", p, l, b, sizeof(b));
 	}
 }
 
 // send a CHAP challenge
 void sendchap(sessionidt s, tunnelidt t)
 {
-	uint8_t b[MAXCONTROL];
+	uint8_t b[MAXETHER];
 	uint16_t r;
 	uint8_t *q;
 
@@ -1771,12 +1753,12 @@ uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, sessionidt s, tunnelid
 	*(uint16_t *) (b + 2) = htons(tunnel[t].far); // tunnel
 	*(uint16_t *) (b + 4) = htons(session[s].far); // session
 	b += 6;
-	if (mtype == PPPLCP || !(session[s].l2tp_flags & SESSIONACFC))
+	if (mtype == PPPLCP || !(session[s].flags & SESSION_ACFC))
 	{
 		*(uint16_t *) b = htons(0xFF03); // HDLC header
 		b += 2;
 	}
-	if (mtype < 0x100 && session[s].l2tp_flags & SESSIONPFC)
+	if (mtype < 0x100 && session[s].flags & SESSION_PFC)
 		*b++ = mtype;
 	else
 	{
@@ -1840,14 +1822,14 @@ void sendlcp(sessionidt s, tunnelidt t)
 
 	l = q;
 	*l++ = ConfigReq;
-	*l++ = (time_now % 255) + 1; // ID
+	*l++ = ++sess_local[s].lcp_ident; // ID
 
 	l += 2; //Save space for length
 
-	if (session[s].mru)
+	if (sess_local[s].ppp_mru)
 	{
 		*l++ = 1; *l++ = 4; // Maximum-Receive-Unit (length 4)
-		*(uint16_t *) l = htons(session[s].mru); l += 2;
+		*(uint16_t *) l = htons(sess_local[s].ppp_mru); l += 2;
 	}
 
 	if (authtype)
@@ -1863,6 +1845,7 @@ void sendlcp(sessionidt s, tunnelidt t)
 	if (config->debug > 3) dumplcp(q, l - q);
 
 	tunnelsend(b, (l - b), t);
+	restart_timer(s, lcp);
 }
 
 // Send CCP request for no compression
@@ -1876,9 +1859,10 @@ void sendccp(sessionidt s, tunnelidt t)
 	LOG(3, s, t, "CCP: send ConfigReq (no compression)\n");
 
 	*q = ConfigReq;
-	*(uint8_t *)(q + 1) = (time_now % 255) + 1; // ID
+	*(q + 1) = ++sess_local[s].lcp_ident; // ID
 	*(uint16_t *)(q + 2) = htons(4); // Length
 
 	LOG_HEX(5, "PPPCCP", q, 4);
 	tunnelsend(b, (q - b) + 4 , t);
+	restart_timer(s, ccp);
 }