From: fendo <fendo@bi12info.com>
Date: Wed, 24 Apr 2013 20:42:38 +0000 (+0200)
Subject: Merge branch 'master' into samesversion
X-Git-Tag: 2.2.1-2sames3.8~2
X-Git-Url: http://git.sameswireless.fr/l2tpns.git/commitdiff_plain/12835e031e502885bce44c5e6b59fa12e0564ca0?ds=inline;hp=-c

Merge branch 'master' into samesversion
---

12835e031e502885bce44c5e6b59fa12e0564ca0
diff --combined l2tpns.c
index 17c440b,55621a5..84bb7a7
--- a/l2tpns.c
+++ b/l2tpns.c
@@@ -75,7 -75,7 +75,7 @@@ int cluster_sockfd = -1;	// Intra-clust
  int epollfd = -1;		// event polling
  time_t basetime = 0;		// base clock
  char hostname[MAXHOSTNAME] = "";	// us.
 -static int tunidx;		// ifr_ifindex of tun device
 +int tunidx;				// ifr_ifindex of tun device
  int nlseqnum = 0;		// netlink sequence number
  int min_initok_nlseqnum = 0;	// minimun seq number for messages after init is ok
  static int syslog_log = 0;	// are we logging to syslog
@@@ -92,7 -92,10 +92,7 @@@ uint16_t MSS = 0;		// TCP MS
  struct cli_session_actions *cli_session_actions = NULL;	// Pending session changes requested by CLI
  struct cli_tunnel_actions *cli_tunnel_actions = NULL;	// Pending tunnel changes required by CLI
  
 -union iphash {
 -	sessionidt sess;
 -	union iphash *idx;
 -} ip_hash[256];			// Mapping from IP address to session structures.
 +union iphash ip_hash[256];	// Mapping from IP address to session structures.
  
  struct ipv6radix {
  	sessionidt sess;
@@@ -149,6 -152,7 +149,7 @@@ config_descriptt config_values[] = 
  	CONFIG("throttle_speed", rl_rate, UNSIGNED_LONG),
  	CONFIG("throttle_buckets", num_tbfs, INT),
  	CONFIG("accounting_dir", accounting_dir, STRING),
+ 	CONFIG("account_all_origin", account_all_origin, BOOL),
  	CONFIG("dump_speed", dump_speed, BOOL),
  	CONFIG("multi_read_count", multi_read_count, INT),
  	CONFIG("scheduler_fifo", scheduler_fifo, BOOL),
@@@ -182,7 -186,7 +183,8 @@@
  	CONFIG("disable_sending_hello", disable_sending_hello, BOOL),
  	CONFIG("disable_no_spoof", disable_no_spoof, BOOL),
  	CONFIG("bind_multi_address", bind_multi_address, STRING),
 +	CONFIG("grp_txrate_average_time", grp_txrate_average_time, INT),
+ 	CONFIG("pppoe_only_equal_svc_name", pppoe_only_equal_svc_name, BOOL),
  	{ NULL, 0, 0, 0 }
  };
  
@@@ -211,7 -215,6 +213,7 @@@ tunnelt *tunnel = NULL;			// Array of t
  bundlet *bundle = NULL;			// Array of bundle structures.
  fragmentationt *frag = NULL;		// Array of fragmentation structures.
  sessiont *session = NULL;		// Array of session structures.
 +groupsesst *grpsession = NULL;		// Array of groupsesst structures.
  sessionlocalt *sess_local = NULL;	// Array of local per-session counters.
  radiust *radius = NULL;			// Array of radius structures.
  ippoolt *ip_address_pool = NULL;	// Array of dynamic IP addresses.
@@@ -222,6 -225,9 +224,6 @@@ struct Tstats *_statistics = NULL
  struct Tringbuffer *ringbuffer = NULL;
  #endif
  
 -static ssize_t netlink_send(struct nlmsghdr *nh);
 -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
 -static void cache_ipmap(in_addr_t ip, sessionidt s);
  static void uncache_ipmap(in_addr_t ip);
  static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s);
  static void free_ip_address(sessionidt s);
@@@ -250,9 -256,8 +252,9 @@@ static clockt now(double *f
  	if (f) *f = t.tv_sec + t.tv_usec / 1000000.0;
  	if (t.tv_sec != time_now)
  	{
 -	    time_now = t.tv_sec;
 -	    time_changed++;
 +		time_now = t.tv_sec;
 +		time_changed++;
 +		grp_time_changed();
  	}
  
  	// Time in milliseconds
@@@ -611,7 -616,7 +613,7 @@@ static void initnetlink(void
  	}
  }
  
 -static ssize_t netlink_send(struct nlmsghdr *nh)
 +ssize_t netlink_send(struct nlmsghdr *nh)
  {
  	struct sockaddr_nl nladdr;
  	struct iovec iov;
@@@ -647,7 -652,7 +649,7 @@@ static ssize_t netlink_recv(void *buf, 
  }
  
  /* adapted from iproute2 */
 -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen)
 +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen)
  {
  	int len = RTA_LENGTH(alen);
  	struct rtattr *rta;
@@@ -1025,7 -1030,7 +1027,7 @@@ sessionidt sessionbyipv6(struct in6_add
  //
  // (It's actually cached in network order)
  //
 -static void cache_ipmap(in_addr_t ip, sessionidt s)
 +void cache_ipmap(in_addr_t ip, sessionidt s)
  {
  	in_addr_t nip = htonl(ip);	// MUST be in network order. I.e. MSB must in be ((char *) (&ip))[0]
  	uint8_t *a = (uint8_t *) &nip;
@@@ -1407,7 -1412,6 +1409,7 @@@ static void update_session_out_stat(ses
  void processipout(uint8_t *buf, int len)
  {
  	sessionidt s;
 +	groupidt g;
  	sessiont *sp;
  	tunnelidt t;
  	in_addr_t ip;
@@@ -1444,31 -1448,7 +1446,31 @@@
  	}
  
  	ip = *(uint32_t *)(buf + 16);
 -	if (!(s = sessionbyip(ip)))
 +	if ((g = grp_groupbyip(ip)))
 +	{
 +		s = grp_getnextsession(g, ip);
 +		if (!s)
 +		{
 +			// Is this a packet for a session that doesn't exist?
 +			static int rate = 0;	// Number of ICMP packets we've sent this second.
 +			static int last = 0;	// Last time we reset the ICMP packet counter 'rate'.
 +
 +			if (last != time_now)
 +			{
 +				last = time_now;
 +				rate = 0;
 +			}
 +
 +			if (rate++ < config->icmp_rate) // Only send a max of icmp_rate per second.
 +			{
 +				LOG(4, 0, 0, "IP: Sending ICMP host unreachable to %s\n", fmtaddr(*(in_addr_t *)(buf + 12), 0));
 +				host_unreachable(*(in_addr_t *)(buf + 12), *(uint16_t *)(buf + 4),
 +					config->bind_address ? config->bind_address : my_address, buf, len);
 +			}
 +			return;
 +		}
 +	}
 +	else if (!(s = sessionbyip(ip)))
  	{
  		// Is this a packet for a session that doesn't exist?
  		static int rate = 0;	// Number of ICMP packets we've sent this second.
@@@ -2099,7 -2079,7 +2101,7 @@@ void sessionshutdown(sessionidt s, cha
  		session[s].die = TIME + 150; // Clean up in 15 seconds
  
  	if (session[s].ip)
 -	{                          // IP allocated, clear and unroute
 +	{	// IP allocated, clear and unroute
  		int r;
  		int routed = 0;
  		for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
@@@ -2299,8 -2279,6 +2301,8 @@@ static void sessionclear(sessionidt s
  // kill a session now
  void sessionkill(sessionidt s, char *reason)
  {
 +	groupidt g;
 +
  	CSTAT(sessionkill);
  
  	if (!session[s].opened) // not alive
@@@ -2329,12 -2307,6 +2331,12 @@@
  	}
  
  	LOG(2, s, session[s].tunnel, "Kill session %d (%s): %s\n", s, session[s].user, reason);
 +
 +	if ((g = grp_groupbysession(s)))
 +	{
 +		grp_removesession(g, s);
 +	}
 +
  	sessionclear(s);
  	cluster_send_session(s);
  }
@@@ -3726,7 -3698,7 +3728,7 @@@ static void regular_cleanups(double per
  
  		// No data in ECHO_TIMEOUT seconds, send LCP ECHO
  		if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= config->echo_timeout) &&
 -			(time_now - sess_local[s].last_echo >= ECHO_TIMEOUT))
 +			(time_now - sess_local[s].last_echo >= config->echo_timeout))
  		{
  			uint8_t b[MAXETHER];
  
@@@ -4663,8 -4635,6 +4665,8 @@@ static void initdata(int optdebug, cha
  #endif /* BGP */
  
  	lac_initremotelnsdata();
 +
 +	grp_initdata();
  }
  
  static int assign_ip_address(sessionidt s)
@@@ -4970,6 -4940,21 +4972,21 @@@ static int dump_session(FILE **f, sessi
  		}
  
  		LOG(3, 0, 0, "Dumping accounting information to %s\n", filename);
+ 		if(config->account_all_origin)
+ 		{
+ 		fprintf(*f, "# dslwatch.pl dump file V1.01\n"
+ 			"# host: %s\n"
+ 			"# endpoint: %s\n"
+ 			"# time: %ld\n"
+ 			"# uptime: %ld\n"
+ 			"# format: username ip qos uptxoctets downrxoctets origin(L=LAC, R=Remote LNS, P=PPPOE)\n",
+ 			hostname,
+ 			fmtaddr(config->iftun_n_address[tunnel[s->tunnel].indexudp] ? config->iftun_n_address[tunnel[s->tunnel].indexudp] : my_address, 0),
+ 			now,
+ 			now - basetime);
+ 		}
+ 		else
+ 		{
  		fprintf(*f, "# dslwatch.pl dump file V1.01\n"
  			"# host: %s\n"
  			"# endpoint: %s\n"
@@@ -4980,15 -4965,29 +4997,29 @@@
  			fmtaddr(config->iftun_n_address[tunnel[s->tunnel].indexudp] ? config->iftun_n_address[tunnel[s->tunnel].indexudp] : my_address, 0),
  			now,
  			now - basetime);
+ 		}
  	}
  
  	LOG(4, 0, 0, "Dumping accounting information for %s\n", s->user);
+ 	if(config->account_all_origin)
+ 	{
+ 	fprintf(*f, "%s %s %d %u %u %s\n",
+ 		s->user,						// username
+ 		fmtaddr(htonl(s->ip), 0),				// ip
+ 		(s->throttle_in || s->throttle_out) ? 2 : 1,		// qos
+ 		(uint32_t) s->cin_delta,				// uptxoctets
+ 		(uint32_t) s->cout_delta,				// downrxoctets
+ 		(s->tunnel == TUNNEL_ID_PPPOE)?"P":(tunnel[s->tunnel].isremotelns?"R":"L"));	// Origin
+ 	}
+ 	else if (!tunnel[s->tunnel].isremotelns && (s->tunnel != TUNNEL_ID_PPPOE))
+ 	{
  	fprintf(*f, "%s %s %d %u %u\n",
  		s->user,						// username
  		fmtaddr(htonl(s->ip), 0),				// ip
  		(s->throttle_in || s->throttle_out) ? 2 : 1,		// qos
  		(uint32_t) s->cin_delta,				// uptxoctets
  		(uint32_t) s->cout_delta);				// downrxoctets
+ 	}
  
  	s->cin_delta = s->cout_delta = 0;
  
@@@ -5176,9 -5175,6 +5207,9 @@@ int main(int argc, char *argv[]
  			LOG(0, 0, 0, "Can't lock pages: %s\n", strerror(errno));
  	}
  
 +	//LOG(3, 0, 0, "Debug sizeof struct: sessiont %lu, tunnelt %lu, bundlet %lu, groupsesst %lu\n",
 +	//	sizeof(sessiont), sizeof(tunnelt), sizeof(bundlet), sizeof(groupsesst));
 +
  	mainloop();
  
  	/* remove plugins (so cleanup code gets run) */
@@@ -5652,7 -5648,6 +5683,7 @@@ int sessionsetup(sessionidt s, tunnelid
  	if (!session[s].bundle || (bundle[session[s].bundle].num_of_links == 1))
  	{
  		int routed = 0;
 +		groupidt g;
  
  		// Add the route for this session.
  		for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
@@@ -5675,12 -5670,6 +5706,12 @@@
  		}
  		else
  			cache_ipmap(session[s].ip, s);
 +
 +		if ((g = grp_groupbysession(s)))
 +		{
 +			grp_setgrouproute(g, 1);
 +			cluster_send_groupe(g);
 +		}
  	}
  
  	sess_local[s].lcp_authtype = 0; // RADIUS authentication complete
diff --combined l2tpns.h
index bce434f,8c306d3..ee355b0
--- a/l2tpns.h
+++ b/l2tpns.h
@@@ -24,9 -24,6 +24,9 @@@
  #define MAXADDRESS	20		// Maximum length for the Endpoint Discrminiator address
  #define MAXSESSION	60000		// could be up to 65535
  #define MAXTBFS		6000		// Maximum token bucket filters. Might need up to 2 * session.
 +#define MAXSESSINGRP	12		// Maximum number of member links in grouped session
 +#define MAXGROUPE		300	// could be up to 65535, Maximum number of grouped session
 +#define MAXROUTEINGRP	15		// max static routes per group
  
  // Tunnel Id reserved for pppoe
  #define TUNNEL_ID_PPPOE	1
@@@ -217,7 -214,6 +217,7 @@@ enum 
  typedef uint16_t sessionidt;
  typedef uint16_t bundleidt;
  typedef uint16_t tunnelidt;
 +typedef uint16_t groupidt;
  typedef uint32_t clockt;
  typedef uint8_t hasht[16];
  
@@@ -335,39 -331,10 +335,39 @@@ typedef struc
  	struct in6_addr ipv6route;	// Static IPv6 route
  	sessionidt forwardtosession;	// LNS id_session to forward
  	uint8_t src_hwaddr[ETH_ALEN];	// MAC addr source (for pppoe sessions 6 bytes)
 -	char reserved[4];		// Space to expand structure without changing HB_VERSION
 +	char reserved[4];				// Space to expand structure without changing HB_VERSION
  }
  sessiont;
  
 +typedef struct
 +{
 +	uint32_t tx_rate;
 +	uint32_t prev_coutgrp;
 +	sessionidt sid;
 +	uint8_t weight;
 +}
 +groupsesslistt;
 +
 +typedef struct
 +{
 +	int state;				// current state (groupestate enum)
 +	uint32_t time_changed;
 +	groupidt prev;
 +	sessionidt smax;
 +	sessionidt smin;
 +	groupsesslistt sesslist[MAXSESSINGRP];
 +	routet route[MAXROUTEINGRP];		// static routes
 +	uint8_t nbroutesgrp;
 +	uint8_t nbsession;
 +}
 +groupsesst;
 +
 +union iphash
 +{
 +	sessionidt sess;
 +	union iphash *idx;
 +};			// Mapping from IP address to session structures.
 +
  typedef struct
  {
          int state;                              // current state (bundlestate enum)
@@@ -550,13 -517,6 +550,13 @@@ enu
  	BUNDLEUNDEF,		// Undefined
  };
  
 +enum
 +{
 +	GROUPEFREE,		// Not in use
 +	GROUPEOPEN,		// Active bundle
 +	GROUPEUNDEF		// Undefined
 +};
 +
  enum
  {
  	NULLCLASS = 0,		//End Point Discriminator classes
@@@ -736,6 -696,7 +736,7 @@@ typedef struc
  	int		num_tbfs;			// number of throttle buckets
  
  	char		accounting_dir[128];
+ 	int		account_all_origin; // Accouting all origin (LAC data + Remote LNS Data + PPPOE data)
  	in_addr_t	bind_address;
  	in_addr_t	peer_address;
  	int		send_garp;			// Set to true to garp for vip address on startup
@@@ -764,10 -725,8 +765,10 @@@
  	int		cluster_undefined_sessions;	// How many sessions we're yet to receive from the master.
  	int		cluster_undefined_bundles;	// How many bundles we're yet to receive from the master.
  	int		cluster_undefined_tunnels;	// How many tunnels we're yet to receive from the master.
 +	int		cluster_undefined_groupes;	// How many groupes we're yet to receive from the master.
  	int		cluster_highest_sessionid;
  	int		cluster_highest_bundleid;
 +	int		cluster_highest_groupeid;
  	int		cluster_highest_tunnelid;
  	clockt		cluster_last_hb;		// Last time we saw a heartbeat from the master.
  	int		cluster_last_hb_ver;		// Heartbeat version last seen from master
@@@ -815,6 -774,7 +816,7 @@@
  	char pppoe_service_name[64];	// pppoe service name
  	char pppoe_ac_name[64];
  	uint8_t pppoe_hwaddr[ETH_ALEN];	// MAC addr of interface pppoe to bind
+ 	int pppoe_only_equal_svc_name; // Accept only PADI with service-name equal to server
  	int disable_sending_hello; // Disable l2tp sending HELLO message for Apple compatibility.
  	int disable_no_spoof; // Disable no spoof (permit load balancing client --> internet)
  	int nbudpfd; // number UDP file handle
@@@ -823,7 -783,6 +825,7 @@@
  	in_addr_t bind_n_address[MAX_BINDADDR];
  	in_addr_t iftun_n_address[MAX_BINDADDR];
  	char bind_multi_address[256];
 +	int grp_txrate_average_time; // caculation txrate average time (default 10s)
  } configt;
  
  enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IPv4, IPv6 };
@@@ -987,27 -946,12 +989,27 @@@ int ip_filter(uint8_t *buf, int len, ui
  int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc);
  int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc);
  int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc);
 +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
 +ssize_t netlink_send(struct nlmsghdr *nh);
 +void cache_ipmap(in_addr_t ip, sessionidt s);
 +
  tunnelidt lac_new_tunnel();
  void lac_tunnelclear(tunnelidt t);
  void lac_send_SCCRQ(tunnelidt t, uint8_t * auth, unsigned int auth_len);
  void lac_send_ICRQ(tunnelidt t, sessionidt s);
  void lac_tunnelshutdown(tunnelidt t, char *reason, int result, int error, char *msg);
  
 +// grpsess.c
 +sessionidt grp_getnextsession(groupidt g, in_addr_t ip);
 +void grp_initdata(void);
 +void grp_processvendorspecific(sessionidt s, uint8_t *pvs);
 +groupidt grp_groupbysession(sessionidt s);
 +groupidt grp_groupbyip(in_addr_t ip);
 +void grp_setgrouproute(groupidt g, int add);
 +void grp_time_changed(void);
 +void grp_removesession(groupidt g, sessionidt s);
 +int grp_cluster_load_groupe(groupidt g, groupsesst *new);
 +
  #undef LOG
  #undef LOG_HEX
  #define LOG(D, s, t, f, ...)	({ if (D <= config->debug) _log(D, s, t, f, ## __VA_ARGS__); })
@@@ -1042,8 -986,6 +1044,8 @@@ extern bundlet *bundle
  extern sessiont *session;
  extern sessionlocalt *sess_local;
  extern ippoolt *ip_address_pool;
 +extern groupsesst *grpsession;
 +extern groupidt gnextgrpid;
  #define sessionfree (session[0].next)
  
  
@@@ -1056,8 -998,6 +1058,8 @@@ extern struct Tstats *_statistics
  extern in_addr_t my_address;
  extern int clifd;
  extern int epollfd;
 +extern int tunidx;		// ifr_ifindex of tun device
 +extern union iphash ip_hash[256];
  
  struct event_data {
  	enum {
diff --combined pppoe.c
index 61b881b,4d442cc..40e898e
--- a/pppoe.c
+++ b/pppoe.c
@@@ -21,7 -21,6 +21,7 @@@
  #include <netpacket/packet.h>
  #include <arpa/inet.h>
  #include <linux/if_pppox.h>
 +#include <linux/rtnetlink.h>
  
  #include "l2tpns.h"
  #include "cluster.h"
@@@ -503,20 -502,27 +503,27 @@@ static void pppoe_recv_PADI(uint8_t *pa
  		return;
  
  	len = ntohs(hdr->length);
- 	for (n = 0; n < len; n += sizeof(*tag) + ntohs(tag->tag_len)) {
+ 	for (n = 0; n < len; n += sizeof(*tag) + ntohs(tag->tag_len))
+ 	{
  		tag = (struct pppoe_tag *)(pack + ETH_HLEN + sizeof(*hdr) + n);
  		if (n + sizeof(*tag) + ntohs(tag->tag_len) > len)
  			return;
- 		switch (ntohs(tag->tag_type)) {
+ 		switch (ntohs(tag->tag_type))
+ 		{
  			case TAG_END_OF_LIST:
  				break;
  			case TAG_SERVICE_NAME:
- 				if (*config->pppoe_service_name && tag->tag_len)
+ 				if (config->pppoe_only_equal_svc_name && *config->pppoe_service_name && !tag->tag_len)
+ 				{
+ 					break;
+ 				}
+ 				else if (*config->pppoe_service_name && tag->tag_len)
  				{
  					if (ntohs(tag->tag_len) != strlen(config->pppoe_service_name))
  						break;
  					if (memcmp(tag->tag_data, config->pppoe_service_name, ntohs(tag->tag_len)))
  						break;
+ 					service_name_tag = tag;
  					service_match = 1;
  				}
  				else