From 35f10d93f4f2bbd5791dc0996a36f0ba8386576d Mon Sep 17 00:00:00 2001
From: fendo <fendo@bi12info.com>
Date: Sat, 15 Dec 2012 00:00:13 +0100
Subject: [PATCH 1/1] Final development LAC functionality. Fix Possible ring
 buffer overflow.

---
 Docs/manual.html | 22 +++++++++++++++++-----
 Makefile         | 12 ++++++++----
 l2tplac.c        |  2 +-
 l2tpns.c         | 24 ++++++++++++++++--------
 l2tpns.h         |  2 ++
 ppp.c            |  2 +-
 radius.c         | 39 +++++++++++++++++++++++++++++++++++----
 7 files changed, 80 insertions(+), 23 deletions(-)

diff --git a/Docs/manual.html b/Docs/manual.html
index f52ad29..d6930dd 100644
--- a/Docs/manual.html
+++ b/Docs/manual.html
@@ -252,15 +252,22 @@ session is established.
 </LI>
 
 <LI><B>bind_address</B> (ip address)<BR>
-When the tun interface is created, it is assigned the address
-specified here.  If no address is given, 1.1.1.1 is used.  Packets
-containing user traffic should be routed via this address if given,
-otherwise the primary address of the machine.
+It's the listen address of the l2tp udp protocol sent and received
+to LAC. This address is also assigned to the tun interface if no
+iftun_address is specified. Packets containing user traffic should be
+routed via this address if given, otherwise the primary address of the
+machine.
+</LI>
+
+<LI><B>iftun_address</B> (ip address)<BR>
+This parameter is used when you want a tun interface address different
+from the address of "bind_address" (For use in cases of specific configuration).
+If no address is given to iftun_address and bind_address, 1.1.1.1 is used.
 </LI>
 
 <LI><B>peer_address</B> (ip address)<BR>
 Address to send to clients as the default gateway.
-</L1>
+</LI>
 
 <LI><B>send_garp</B> (boolean)<BR>
 Determines whether or not to send a gratuitous ARP for the
@@ -368,6 +375,11 @@ Drop sessions who have not responded within idle_echo_timeout seconds
 (default: 240 (seconds))
 </LI>
 
+<LI><B>bind_address_remotelns</B> (ip address)<BR>
+Address of the interface to listen the remote LNS tunnels.
+If no address is given, all interfaces are listened (Any Address).
+</LI>
+
 <LI><B>bind_portremotelns</B> (short)<BR>
 Port to bind for the Remote LNS (default: 65432).
 </LI>
diff --git a/Makefile b/Makefile
index e915e9b..36ba2e1 100644
--- a/Makefile
+++ b/Makefile
@@ -112,20 +112,24 @@ install: all
 
 ## Dependencies: (autogenerated) ##
 arp.o: arp.c l2tpns.h
-cli.o: cli.c l2tpns.h constants.h util.h cluster.h tbf.h ll.h bgp.h
+cli.o: cli.c l2tpns.h constants.h util.h cluster.h tbf.h ll.h bgp.h \
+ l2tplac.h
 cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h bgp.h
 constants.o: constants.c constants.h
 control.o: control.c l2tpns.h control.h
 icmp.o: icmp.c l2tpns.h
 l2tpns.o: l2tpns.c md5.h l2tpns.h cluster.h plugin.h ll.h constants.h \
-  control.h util.h tbf.h bgp.h
+ control.h util.h tbf.h bgp.h l2tplac.h
 ll.o: ll.c ll.h
 md5.o: md5.c md5.h
-ppp.o: ppp.c l2tpns.h constants.h plugin.h util.h tbf.h cluster.h
-radius.o: radius.c md5.h constants.h l2tpns.h plugin.h util.h cluster.h
+ppp.o: ppp.c l2tpns.h constants.h plugin.h util.h tbf.h cluster.h \
+ l2tplac.h
+radius.o: radius.c md5.h constants.h l2tpns.h plugin.h util.h cluster.h \
+ l2tplac.h
 tbf.o: tbf.c l2tpns.h util.h tbf.h
 util.o: util.c l2tpns.h bgp.h
 bgp.o: bgp.c l2tpns.h bgp.h util.h
+l2tplac.o: l2tplac.c md5.h l2tpns.h util.h l2tplac.h
 autosnoop.so: autosnoop.c l2tpns.h plugin.h
 autothrottle.so: autothrottle.c l2tpns.h plugin.h
 garden.so: garden.c l2tpns.h plugin.h control.h
diff --git a/l2tplac.c b/l2tplac.c
index f073ecc..3851fa0 100644
--- a/l2tplac.c
+++ b/l2tplac.c
@@ -236,7 +236,7 @@ void lac_save_rad_tag_tunnels(sessionidt s)
 				if (pconfigrlns[idrlns].state == CONFRLNSFREE)
 				{
 					pconfigrlns[idrlns].ip = ptunnelrlns[idtag].tunnel_server_endpoint;
-					pconfigrlns[idrlns].port = L2TPPORT; //Default L2TP poart
+					pconfigrlns[idrlns].port = L2TPPORT; //Default L2TP port
 					strcpy(pconfigrlns[idrlns].l2tp_secret, ptunnelrlns[idtag].tunnel_password);
 					strcpy(pconfigrlns[idrlns].tunnel_assignment_id, ptunnelrlns[idtag].tunnel_assignment_id);
 
diff --git a/l2tpns.c b/l2tpns.c
index 694726d..9dbde7a 100644
--- a/l2tpns.c
+++ b/l2tpns.c
@@ -178,8 +178,10 @@ config_descriptt config_values[] = {
 #endif
 	CONFIG("echo_timeout", echo_timeout, INT),
 	CONFIG("idle_echo_timeout", idle_echo_timeout, INT),
+	CONFIG("iftun_address", iftun_address, IPv4),
 #ifdef LAC
 	CONFIG("disable_lac_func", disable_lac_func, BOOL),
+	CONFIG("bind_address_remotelns", bind_address_remotelns, IPv4),
 	CONFIG("bind_portremotelns", bind_portremotelns, SHORT),
 #endif
 	{ NULL, 0, 0, 0 },
@@ -292,7 +294,7 @@ void _log(int level, sessionidt s, tunnelidt t, const char *format, ...)
 		ringbuffer->buffer[ringbuffer->tail].session = s;
 		ringbuffer->buffer[ringbuffer->tail].tunnel = t;
 		va_start(ap, format);
-		vsnprintf(ringbuffer->buffer[ringbuffer->tail].message, 4095, format, ap);
+		vsnprintf(ringbuffer->buffer[ringbuffer->tail].message, MAX_LOG_LENGTH, format, ap);
 		va_end(ap);
 	}
 #endif
@@ -747,8 +749,8 @@ static void inittun(void)
 		req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_UNIVERSE;
 		req.ifmsg.ifaddr.ifa_index = tunidx;
 
-		if (config->bind_address)
-			ip = config->bind_address;
+		if (config->iftun_address)
+			ip = config->iftun_address;
 		else
 			ip = 0x01010101; // 1.1.1.1
 		netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip));
@@ -878,6 +880,7 @@ static void initudp(void)
 	memset(&addr, 0, sizeof(addr));
 	addr.sin_family = AF_INET;
 	addr.sin_port = htons(config->bind_portremotelns);
+	addr.sin_addr.s_addr = config->bind_address_remotelns;
 	udplacfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 	setsockopt(udplacfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
 	{
@@ -2177,7 +2180,7 @@ void sendipcp(sessionidt s, tunnelidt t)
 	q[4] = 3;				// ip address option
 	q[5] = 6;				// option length
 	*(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address :
-				 config->bind_address ? config->bind_address :
+				 config->iftun_address ? config->iftun_address :
 				 my_address; // send my IP
 
 	tunnelsend(buf, 10 + (q - buf), t); // send it
@@ -3062,6 +3065,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
 					tunnelshutdown(t, "Stopped", 0, 0, 0); // Shut down cleanly
 					break;
 				case 6:       // HELLO
+					LOG(3, s, t, "Received HELLO\n");
 					controlnull(t); // simply ACK
 					break;
 				case 7:       // OCRQ
@@ -3157,7 +3161,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
 
 					// Set multilink options before sending initial LCP packet
 					sess_local[s].mp_mrru = 1614;
-					sess_local[s].mp_epdis = ntohl(config->bind_address ? config->bind_address : my_address);
+					sess_local[s].mp_epdis = ntohl(config->iftun_address ? config->iftun_address : my_address);
 
 					sendlcp(s, t);
 					change_state(s, lcp, RequestSent);
@@ -4196,7 +4200,7 @@ static void mainloop(void)
 					if ((s = read(tunfd, p, size_bufp)) > 0)
 					{
 						processtun(p, s);
-					    	tun_pkts++;
+						tun_pkts++;
 					}
 					else
 					{
@@ -4228,7 +4232,7 @@ static void mainloop(void)
 			if (c >= config->multi_read_count)
 			{
 #ifdef LAC
-				LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun and %d cluster %d rmlns packets\n",
+				LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun %d cluster and %d rmlns packets\n",
 					config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts, udplac_pkts);
 #else
 				LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun and %d cluster packets\n",
@@ -4887,7 +4891,7 @@ static int dump_session(FILE **f, sessiont *s)
 			"# uptime: %ld\n"
 			"# format: username ip qos uptxoctets downrxoctets\n",
 			hostname,
-			fmtaddr(config->bind_address ? config->bind_address : my_address, 0),
+			fmtaddr(config->iftun_address ? config->iftun_address : my_address, 0),
 			now,
 			now - basetime);
 	}
@@ -5271,7 +5275,11 @@ static void update_config()
 #ifdef LAC
 	if(!config->bind_portremotelns)
 		config->bind_portremotelns = L2TPLACPORT;
+	if(!config->bind_address_remotelns)
+		config->bind_address_remotelns = INADDR_ANY;
 #endif
+	if(!config->iftun_address)
+		config->iftun_address = config->bind_address;
 
 	// re-initialise the random number source
 	initrandom(config->random_device);
diff --git a/l2tpns.h b/l2tpns.h
index 8143736..0d07ae3 100644
--- a/l2tpns.h
+++ b/l2tpns.h
@@ -761,10 +761,12 @@ typedef struct
 	int echo_timeout; // Time between last packet sent and LCP ECHO generation
 	int idle_echo_timeout; // Time between last packet seen and
 						   // Drop sessions who have not responded within IDLE_ECHO_TIMEOUT seconds
+	in_addr_t iftun_address;
 #ifdef LAC
 	int disable_lac_func;
 	int highest_rlnsid;
 	uint16_t bind_portremotelns;
+	in_addr_t bind_address_remotelns;
 #endif
 } configt;
 
diff --git a/ppp.c b/ppp.c
index 584ce61..236188e 100644
--- a/ppp.c
+++ b/ppp.c
@@ -558,7 +558,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 	if (session[s].die) // going down...
 		return;
 
-	LOG((*p == EchoReq || *p == EchoReply) ? 4 : 3, s, t,
+	LOG(((*p == EchoReq || *p == EchoReply) ? 4 : 3), s, t,
 		"LCP: recv %s\n", ppp_code(*p));
 
 	if (config->debug > 3) dumplcp(p, l);
diff --git a/radius.c b/radius.c
index 843931f..e783323 100644
--- a/radius.c
+++ b/radius.c
@@ -600,6 +600,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
 			run_plugins(PLUGIN_POST_AUTH, &packet);
 			r_code = packet.auth_allowed ? AccessAccept : AccessReject;
 
+#ifndef LAC
 			// process auth response
 			if (radius[r].chap)
 			{
@@ -631,6 +632,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
 				LOG(3, s, session[s].tunnel, "   PAP User %s authentication %s.\n", session[s].user,
 						(r_code == AccessAccept) ? "allowed" : "denied");
 			}
+#endif
 
 			if (r_code == AccessAccept)
 			{
@@ -958,14 +960,43 @@ void processrad(uint8_t *buf, int len, char socket_index)
 					{
 						session[s].route[ro].ip = 0;
 					}
-
-					// Restart LCP auth...
-					lcp_restart(s);
-					sendlcp(s, t);
 					break;
 				}
 			}
+
+			// process auth response
+			if (radius[r].chap)
+			{
+				// CHAP
+				uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP, 0, 0, 0);
+				if (!p) return;	// Abort!
+
+				*p = (r_code == AccessAccept) ? 3 : 4;     // ack/nak
+				p[1] = radius[r].id;
+				*(uint16_t *) (p + 2) = ntohs(4); // no message
+				tunnelsend(b, (p - b) + 4, t); // send it
+
+				LOG(3, s, session[s].tunnel, "   CHAP User %s authentication %s.\n", session[s].user,
+						(r_code == AccessAccept) ? "allowed" : "denied");
+			}
+			else
+			{
+				// PAP
+				uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP, 0, 0, 0);
+				if (!p) return;		// Abort!
+
+				// ack/nak
+				*p = r_code;
+				p[1] = radius[r].id;
+				*(uint16_t *) (p + 2) = ntohs(5);
+				p[4] = 0; // no message
+				tunnelsend(b, (p - b) + 5, t); // send it
+
+				LOG(3, s, session[s].tunnel, "   PAP User %s authentication %s.\n", session[s].user,
+						(r_code == AccessAccept) ? "allowed" : "denied");
+			}
 #endif
+
 			if (!session[s].dns1 && config->default_dns1)
 			{
 				session[s].dns1 = ntohl(config->default_dns1);
-- 
2.20.1