Merge from master
authorfendo <fendo@bi12info.com>
Tue, 21 May 2013 09:54:43 +0000 (11:54 +0200)
committerfendo <fendo@bi12info.com>
Tue, 21 May 2013 09:54:43 +0000 (11:54 +0200)
1  2 
l2tpns.c
l2tpns.h
ppp.c

diff --combined 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;
@@@ -183,8 -186,8 +183,9 @@@ config_descriptt config_values[] = 
        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),
+       CONFIG("multi_hostname", multi_hostname, STRING),
        { NULL, 0, 0, 0 }
  };
  
@@@ -213,7 -216,6 +214,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.
@@@ -224,6 -226,9 +225,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);
@@@ -252,9 -257,8 +253,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
@@@ -613,7 -617,7 +614,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;
@@@ -649,7 -653,7 +650,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;
@@@ -1027,7 -1031,7 +1028,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;
@@@ -1409,7 -1413,6 +1410,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;
        }
  
        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.
@@@ -2101,7 -2080,7 +2102,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++)
@@@ -2301,8 -2280,6 +2302,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
        }
  
        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);
  }
@@@ -3096,7 -3067,7 +3097,7 @@@ void processudp(uint8_t *buf, int len, 
                                                controlt *c = controlnew(2); // sending SCCRP
                                                control16(c, 2, version, 1); // protocol version
                                                control32(c, 3, 3, 1); // framing
-                                               controls(c, 7, hostname, 1); // host name
+                                               controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name
                                                if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Send Challenge response
                                                control16(c, 9, t, 1); // assigned tunnel
                                                controladd(c, 0, t); // send the resply
                                                        {
                                                                LOG(3, s, t, "sending SCCCN to REMOTE LNS\n");
                                                                controlt *c = controlnew(3); // sending SCCCN
-                                                               controls(c, 7, hostname, 1); // host name
+                                                               controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name
                                                                controls(c, 8, Vendor_name, 1); // Vendor name
                                                                control16(c, 2, version, 1); // protocol version
                                                                control32(c, 3, 3, 1); // framing Capabilities
@@@ -3734,7 -3705,7 +3735,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];
  
@@@ -4671,8 -4642,6 +4672,8 @@@ static void initdata(int optdebug, cha
  #endif /* BGP */
  
        lac_initremotelnsdata();
 +
 +      grp_initdata();
  }
  
  static int assign_ip_address(sessionidt s)
@@@ -5213,9 -5182,6 +5214,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) */
@@@ -5461,6 -5427,8 +5462,8 @@@ static void update_config(
                                config->iftun_n_address[config->nbmultiaddress] = htonl(ip);
                                config->nbmultiaddress++;
                                LOG(1, 0, 0, "Bind address %s\n", fmtaddr(htonl(ip), 0));
+                               if (config->nbmultiaddress >= MAX_BINDADDR) break;
                        }
  
                        sip = n;
                config->iftun_n_address[0] = config->iftun_address;
        }
  
+       if (*config->multi_hostname)
+       {
+               char *shost = config->multi_hostname;
+               char *n = shost;
+               char *e = config->multi_hostname + strlen(config->multi_hostname);
+               config->nbmultihostname = 0;
+               while (*shost && (shost < e))
+               {
+                       while ((n < e) && (*n == ' ' || *n == '\t')) n++;
+                       i = 0;
+                       while (n < e && (*n != ',') && (*n != '\t'))
+                       {
+                               config->multi_n_hostname[config->nbmultihostname][i] = *n;
+                               n++;i++;
+                       }
+                       if (i > 0)
+                       {
+                               config->multi_n_hostname[config->nbmultihostname][i] = 0;
+                               LOG(1, 0, 0, "Bind Hostname %s\n", config->multi_n_hostname[config->nbmultihostname]);
+                               config->nbmultihostname++;
+                               if (config->nbmultihostname >= MAX_NBHOSTNAME) break;
+                       }
+               }
+               if (config->nbmultihostname >= 1)
+               {
+                       strcpy(hostname, config->multi_n_hostname[0]);
+                       strcpy(config->hostname, hostname);
+               }
+       }
        if (!*config->pppoe_ac_name)
                strncpy(config->pppoe_ac_name, DEFAULT_PPPOE_AC_NAME, sizeof(config->pppoe_ac_name) - 1);
  
@@@ -5689,7 -5690,6 +5725,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++)
                }
                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
@@@ -6560,7 -6554,7 +6596,7 @@@ void lac_send_SCCRQ(tunnelidt t, uint8_
  
        // Sent SCCRQ - Start Control Connection Request
        controlt *c = controlnew(1); // sending SCCRQ
-       controls(c, 7, hostname, 1); // host name
+       controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name
        controls(c, 8, Vendor_name, 1); // Vendor name
        control16(c, 2, version, 1); // protocol version
        control32(c, 3, 3, 1); // framing Capabilities
diff --combined 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
@@@ -72,6 -69,8 +72,8 @@@
  // Multi bind address constants
  #define MAX_UDPFD 4
  #define MAX_BINDADDR MAX_UDPFD
+ // + 1 for the LAC Hostname
+ #define MAX_NBHOSTNAME (MAX_UDPFD + 1)
  // 4 + 1 for the udplac
  #define INIT_TABUDPFD {-1, -1, -1, -1, -1}
  #define INIT_TABUDPVAR {0, 0, 0, 0, 0}
@@@ -217,7 -216,6 +219,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 -333,10 +337,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 -519,6 +552,13 @@@ enu
        BUNDLEUNDEF,            // Undefined
  };
  
 +enum
 +{
 +      GROUPEFREE,             // Not in use
 +      GROUPEOPEN,             // Active bundle
 +      GROUPEUNDEF             // Undefined
 +};
 +
  enum
  {
        NULLCLASS = 0,          //End Point Discriminator classes
@@@ -765,10 -727,8 +767,10 @@@ typedef struc
        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
        int nbudpfd; // number UDP file handle
        int nbmultiaddress; // number multi address to bind
        int indexlacudpfd;      // Index UDP LAC file handle (in udpfd[])
+       int nbmultihostname;    // number hostname, normally the same number as the nbudpfd
++      int grp_txrate_average_time; // caculation txrate average time (default 10s)
        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)
+       char multi_hostname[512];
+       char multi_n_hostname[MAX_NBHOSTNAME][MAXHOSTNAME];     // list hostname
  } configt;
  
  enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IPv4, IPv6 };
@@@ -989,27 -951,12 +994,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__); })
@@@ -1044,8 -991,6 +1049,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)
  
  
@@@ -1058,8 -1003,6 +1063,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 ppp.c
--- 1/ppp.c
--- 2/ppp.c
+++ b/ppp.c
@@@ -5,9 -5,6 +5,9 @@@
  #include <unistd.h>
  #include <errno.h>
  #include <stdlib.h>
 +#include <sys/socket.h>
 +#include <linux/rtnetlink.h>
 +
  #include "l2tpns.h"
  #include "constants.h"
  #include "plugin.h"
@@@ -2510,9 -2507,9 +2510,9 @@@ void sendchap(sessionidt s, tunnelidt t
        q[1] = radius[r].id;                    // ID
        q[4] = 16;                              // value size (size of challenge)
        memcpy(q + 5, radius[r].auth, 16);      // challenge
-       strcpy((char *) q + 21, hostname);      // our name
-       *(uint16_t *) (q + 2) = htons(strlen(hostname) + 21); // length
-       tunnelsend(b, strlen(hostname) + 21 + (q - b), t); // send it
+       strcpy((char *) q + 21, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname); // our name
+       *(uint16_t *) (q + 2) = htons(strlen(config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname) + 21); // length
+       tunnelsend(b, strlen(config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname) + 21 + (q - b), t); // send it
  }
  
  // fill in a L2TP message with a PPP frame,