Merge from master
authorfendo <fendo@bi12info.com>
Tue, 26 Feb 2013 08:59:45 +0000 (09:59 +0100)
committerfendo <fendo@bi12info.com>
Tue, 26 Feb 2013 08:59:45 +0000 (09:59 +0100)
1  2 
debian/changelog
l2tpns.c
l2tpns.h

diff --combined debian/changelog
@@@ -1,9 -1,10 +1,17 @@@
 -l2tpns (2.2.1-2fdn3.6) unstable; urgency=low
++l2tpns (2.2.1-2sames3.7) unstable; urgency=low
++  * Merge from master
+   * Fix Warning: dereferencing type-punned pointer will break strict...
+   * Fix: Tunnel creation does not work when the length of the hostname is odd. (revert fix: Add a uint16_t control buffer type, as a union)
+  -- Fernando Alves <fernando.alves@sameswireless.fr>  Tue, 26 Feb 2013 09:07:16 +0100
 +l2tpns (2.2.1-2sames3.6) unstable; urgency=low
 +
 +  * Sames l2tpns version.
 +
 + -- Fernando Alves <fernando.alves@sameswireless.fr>  Tue, 12 Feb 2013 20:20:17 +0100
 +
  l2tpns (2.2.1-2fdn3.5) unstable; urgency=low
  
    * Update debian/changelog
diff --combined l2tpns.c
+++ b/l2tpns.c
@@@ -81,7 -81,7 +81,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
@@@ -98,7 -98,10 +98,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;
@@@ -189,7 -192,6 +189,7 @@@ config_descriptt config_values[] = 
        CONFIG("pppoe_ac_name", pppoe_ac_name, STRING),
        CONFIG("disable_sending_hello", disable_sending_hello, BOOL),
        CONFIG("disable_no_spoof", disable_no_spoof, BOOL),
 +      CONFIG("grp_txrate_average_time", grp_txrate_average_time, INT),
        { NULL, 0, 0, 0 }
  };
  
@@@ -218,7 -220,6 +218,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.
@@@ -229,6 -230,9 +229,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);
@@@ -257,9 -261,8 +257,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
@@@ -618,7 -621,7 +618,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;
@@@ -654,7 -657,7 +654,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;
@@@ -1000,7 -1003,7 +1000,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;
@@@ -1372,7 -1375,6 +1372,7 @@@ static void update_session_out_stat(ses
  {
        increment_counter(&sp->cout, &sp->cout_wrap, len); // byte count
        sp->cout_delta += len;
 +      sp->coutgrp_delta += len;
        sp->pout++;
        sp->last_data = time_now;
  
  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.
@@@ -1782,7 -1759,6 +1782,7 @@@ static void processipv6out(uint8_t * bu
  
        increment_counter(&sp->cout, &sp->cout_wrap, len); // byte count
        sp->cout_delta += len;
 +      sp->coutgrp_delta += len;
        sp->pout++;
        udp_tx += len;
  
@@@ -1832,7 -1808,6 +1832,7 @@@ static void send_ipout(sessionidt s, ui
  
        increment_counter(&sp->cout, &sp->cout_wrap, len); // byte count
        sp->cout_delta += len;
 +      sp->coutgrp_delta += len;
        sp->pout++;
        udp_tx += len;
  
  static void control16(controlt * c, uint16_t avp, uint16_t val, uint8_t m)
  {
        uint16_t l = (m ? 0x8008 : 0x0008);
-       c->buf16[c->length/2 + 0] = htons(l);
-       c->buf16[c->length/2 + 1] = htons(0);
-       c->buf16[c->length/2 + 2] = htons(avp);
-       c->buf16[c->length/2 + 3] = htons(val);
+       *(uint16_t *) (c->buf + c->length + 0) = htons(l);
+       *(uint16_t *) (c->buf + c->length + 2) = htons(0);
+       *(uint16_t *) (c->buf + c->length + 4) = htons(avp);
+       *(uint16_t *) (c->buf + c->length + 6) = htons(val);
        c->length += 8;
  }
  
  static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m)
  {
        uint16_t l = (m ? 0x800A : 0x000A);
-       c->buf16[c->length/2 + 0] = htons(l);
-       c->buf16[c->length/2 + 1] = htons(0);
-       c->buf16[c->length/2 + 2] = htons(avp);
-       *(uint32_t *) &c->buf[c->length + 6] = htonl(val);
+       *(uint16_t *) (c->buf + c->length + 0) = htons(l);
+       *(uint16_t *) (c->buf + c->length + 2) = htons(0);
+       *(uint16_t *) (c->buf + c->length + 4) = htons(avp);
+       *(uint32_t *) (c->buf + c->length + 6) = htonl(val);
        c->length += 10;
  }
  
  static void controls(controlt * c, uint16_t avp, char *val, uint8_t m)
  {
        uint16_t l = ((m ? 0x8000 : 0) + strlen(val) + 6);
-       c->buf16[c->length/2 + 0] = htons(l);
-       c->buf16[c->length/2 + 1] = htons(0);
-       c->buf16[c->length/2 + 2] = htons(avp);
-       memcpy(&c->buf[c->length + 6], val, strlen(val));
+       *(uint16_t *) (c->buf + c->length + 0) = htons(l);
+       *(uint16_t *) (c->buf + c->length + 2) = htons(0);
+       *(uint16_t *) (c->buf + c->length + 4) = htons(avp);
+       memcpy(c->buf + c->length + 6, val, strlen(val));
        c->length += 6 + strlen(val);
  }
  
  static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m)
  {
        uint16_t l = ((m ? 0x8000 : 0) + len + 6);
-       c->buf16[c->length/2 + 0] = htons(l);
-       c->buf16[c->length/2 + 1] = htons(0);
-       c->buf16[c->length/2 + 2] = htons(avp);
-       memcpy(&c->buf[c->length + 6], val, len);
+       *(uint16_t *) (c->buf + c->length + 0) = htons(l);
+       *(uint16_t *) (c->buf + c->length + 2) = htons(0);
+       *(uint16_t *) (c->buf + c->length + 4) = htons(avp);
+       memcpy(c->buf + c->length + 6, val, len);
        c->length += 6 + len;
  }
  
@@@ -1897,7 -1872,8 +1897,8 @@@ static controlt *controlnew(uint16_t mt
        }
        assert(c);
        c->next = 0;
-       c->buf16[0] = htons(0xC802); // flags/ver
+       c->buf[0] = 0xC8; // flags
+       c->buf[1] = 0x02; // ver
        c->length = 12;
        control16(c, 0, mtype, 1);
        return c;
@@@ -1923,10 -1899,10 +1924,10 @@@ static void controlnull(tunnelidt t
  // add a control message to a tunnel, and send if within window
  static void controladd(controlt *c, sessionidt far, tunnelidt t)
  {
-       c->buf16[1] = htons(c->length); // length
-       c->buf16[2] = htons(tunnel[t].far); // tunnel
-       c->buf16[3] = htons(far); // session
-       c->buf16[4] = htons(tunnel[t].ns); // sequence
+       *(uint16_t *) (c->buf + 2) = htons(c->length); // length
+       *(uint16_t *) (c->buf + 4) = htons(tunnel[t].far); // tunnel
+       *(uint16_t *) (c->buf + 6) = htons(far); // session
+       *(uint16_t *) (c->buf + 8) = htons(tunnel[t].ns); // sequence
        tunnel[t].ns++;              // advance sequence
        // link in message in to queue
        if (tunnel[t].controlc)
@@@ -2079,7 -2055,7 +2080,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++)
@@@ -2279,8 -2255,6 +2280,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
  #endif
  
        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);
  }
@@@ -3715,7 -3683,7 +3716,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];
  
@@@ -4694,8 -4662,6 +4695,8 @@@ static void initdata(int optdebug, cha
  #ifdef LAC
        lac_initremotelnsdata();
  #endif
 +
 +      grp_initdata();
  }
  
  static int assign_ip_address(sessionidt s)
@@@ -5617,7 -5583,6 +5618,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);
 +              }
        }
  
        sess_local[s].lcp_authtype = 0; // RADIUS authentication complete
diff --combined l2tpns.h
+++ b/l2tpns.h
  #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 MAXGRPINSESS  12              // Maximum number of member links in session group
 +#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
@@@ -211,7 -207,6 +211,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];
  
@@@ -252,10 -247,7 +252,7 @@@ typedef struct controls           // control mes
  {
        struct controls *next;  // next in queue
        uint16_t length;        // length
-       union {
-               uint8_t buf[MAXCONTROL];
-               uint16_t buf16[MAXCONTROL/2];
-       } __attribute__ ((__transparent_union__));
+       uint8_t buf[MAXCONTROL];
  }
  controlt;
  
@@@ -333,40 -325,14 +330,40 @@@ typedef struc
  #ifdef LAC
        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
 +      uint32_t coutgrp_delta;
  #else
        uint8_t src_hwaddr[ETH_ALEN];   // MAC addr source (for pppoe sessions 6 bytes)
 -      char reserved[6];               // Space to expand structure without changing HB_VERSION
 +      uint32_t coutgrp_delta;
 +      char reserved[2];               // Space to expand structure without changing HB_VERSION
  #endif
  }
  sessiont;
  
 +typedef struct
 +{
 +      uint32_t tx_rate;
 +      sessionidt sid;
 +      uint8_t weight;
 +}
 +groupsessionidt;
 +
 +typedef struct
 +{
 +      uint32_t time_changed;
 +      groupidt prev;
 +      groupsessionidt 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)
@@@ -812,7 -778,6 +809,7 @@@ typedef struc
        uint8_t pppoe_hwaddr[ETH_ALEN]; // MAC addr of interface pppoe to bind
        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 grp_txrate_average_time; // caculation txrate average time (default 10s)
  } configt;
  
  enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IPv4, IPv6 };
@@@ -978,10 -943,6 +975,10 @@@ 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);
 +
  #ifdef LAC
  tunnelidt lac_new_tunnel();
  void lac_tunnelclear(tunnelidt t);
@@@ -990,16 -951,6 +987,16 @@@ void lac_send_ICRQ(tunnelidt t, session
  void lac_tunnelshutdown(tunnelidt t, char *reason, int result, int error, char *msg);
  #endif
  
 +// 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);
 +
  #undef LOG
  #undef LOG_HEX
  #define LOG(D, s, t, f, ...)  ({ if (D <= config->debug) _log(D, s, t, f, ## __VA_ARGS__); })
@@@ -1034,7 -985,6 +1031,7 @@@ extern bundlet *bundle
  extern sessiont *session;
  extern sessionlocalt *sess_local;
  extern ippoolt *ip_address_pool;
 +extern groupsesst *grpsession;
  #define sessionfree (session[0].next)
  
  
@@@ -1047,8 -997,6 +1044,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 {