this patch adds IPv6-support to the httpinfo plugin. Beside it fixes a double free...
authorAlina Friedrichsen <x-alina@gmx.net>
Tue, 18 Nov 2008 00:47:11 +0000 (01:47 +0100)
committerAlina Friedrichsen <x-alina@gmx.net>
Tue, 18 Nov 2008 00:47:11 +0000 (01:47 +0100)
lib/httpinfo/src/olsrd_httpinfo.c
lib/httpinfo/src/olsrd_plugin.c
lib/httpinfo/src/olsrd_plugin.h
src/ipcalc.c

index fb04018..2f59c7c 100644 (file)
@@ -189,7 +189,7 @@ static void build_about_body(struct autobuf *abuf);
 
 static void build_cfgfile_body(struct autobuf *abuf);
 
-static int check_allowed_ip(const struct allowed_net * const all_nets, const union olsr_ip_addr * const addr);
+static olsr_bool check_allowed_ip(const struct ip_prefix_list * const all_nets, const union olsr_ip_addr * const addr);
 
 static void build_ip_txt(struct autobuf *abuf, const olsr_bool want_link,
                         const char * const ipaddrstr, const int prefix_len);
@@ -201,6 +201,12 @@ static void section_title(struct autobuf *abuf, const char *title);
 
 static ssize_t writen(int fd, const void *buf, size_t count);
 
+#define IN6ADDR_V4MAPPED_LOOPBACK_INIT \
+        { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+              0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 } } }
+
+const struct in6_addr in6addr_v4mapped_loopback = IN6ADDR_V4MAPPED_LOOPBACK_INIT;
+
 static struct timeval start_time;
 static struct http_stats stats;
 static int client_sockets[MAX_CLIENTS];
@@ -252,41 +258,66 @@ static const struct dynamic_file_entry dynamic_files[] = {
 static int
 get_http_socket(int port)
 {
-  struct sockaddr_in addr;
+  struct sockaddr_storage sst;
   olsr_u32_t yes = 1;
+  socklen_t addrlen;
 
   /* Init ipc socket */
-  int s = socket(AF_INET, SOCK_STREAM, 0);
+  int s = socket(olsr_cnf->ip_version, SOCK_STREAM, 0);
   if (s == -1) {
+#ifndef NODEBUG
     olsr_printf(1, "(HTTPINFO)socket %s\n", strerror(errno));
+#endif
     return -1;
   }
 
   if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
+#ifndef NODEBUG
     olsr_printf(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
-    close(s);
+#endif
+    CLOSE(s);
     return -1;
   }
 
   /* Bind the socket */
 
   /* complete the socket structure */
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = INADDR_ANY;
-  addr.sin_port = htons(port);
+  memset(&sst, 0, sizeof(sst));
+  if (olsr_cnf->ip_version == AF_INET) {
+      struct sockaddr_in *addr4 = (struct sockaddr_in *)&sst;
+      addr4->sin_family = AF_INET;
+      addrlen = sizeof(*addr4);
+#ifdef SIN6_LEN
+      addr4->sin_len = addrlen;
+#endif
+      addr4->sin_addr.s_addr = INADDR_ANY;
+      addr4->sin_port = htons(port);
+  } else {
+      struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&sst;
+      addr6->sin6_family = AF_INET6;
+      addrlen = sizeof(*addr6);
+#ifdef SIN6_LEN
+      addr6->sin6_len = addrlen;
+#endif
+      addr6->sin6_addr = in6addr_any;
+      addr6->sin6_port = htons(port);
+  }
 
   /* bind the socket to the port number */
-  if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
+  if (bind(s, (struct sockaddr *)&sst, addrlen) == -1) {
+#ifndef NODEBUG
     olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
-    close(s);
+#endif
+    CLOSE(s);
     return -1;
   }
 
   /* show that we are willing to listen */
   if (listen(s, 1) == -1) {
+#ifndef NODEBUG
     olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
-    close(s);
+#endif
+    CLOSE(s);
     return -1;
   }
 
@@ -324,8 +355,9 @@ olsrd_plugin_init(void)
 static void
 parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flags __attribute__((unused)))
 {
-  struct sockaddr_in pin;
+  struct sockaddr_storage pin;
   socklen_t addrlen;
+  const union olsr_ip_addr *ipaddr;
   char req[MAX_HTTPREQ_SIZE];
   //static char body[HTML_BUFSIZE];
   struct autobuf body, header;
@@ -335,6 +367,9 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
   unsigned int c = 0;
   int r = 1 /*, size = 0 */;
 
+  abuf_init(&body, 0);
+  abuf_init(&header, 0);
+
   if (curr_clients >= MAX_CLIENTS) {
     return;
   }
@@ -343,21 +378,36 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
   addrlen = sizeof(pin);
   client_sockets[curr_clients] = accept(fd, (struct sockaddr *)&pin, &addrlen);
   if (client_sockets[curr_clients] == -1) {
+#ifndef NODEBUG
     olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
+#endif
+    goto close_connection;
+  }
+
+  if(((struct sockaddr *)&pin)->sa_family != olsr_cnf->ip_version) {
+#ifndef NODEBUG
+    olsr_printf(1, "(HTTPINFO) Connection with wrong IP version?!\n");
+#endif
     goto close_connection;
   }
 
-  if (!check_allowed_ip(allowed_nets, (union olsr_ip_addr *)&pin.sin_addr.s_addr)) {
+  if(olsr_cnf->ip_version == AF_INET) {
+    const struct sockaddr_in *addr4 = (struct sockaddr_in *)&pin;
+    ipaddr = (const union olsr_ip_addr *)&addr4->sin_addr;
+  } else {
+    const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pin;
+    ipaddr = (const union olsr_ip_addr *)&addr6->sin6_addr;
+  }
+
+  if (!check_allowed_ip(allowed_nets, ipaddr)) {
     struct ipaddr_str strbuf;
     olsr_printf(0, "HTTP request from non-allowed host %s!\n",
-                olsr_ip_to_string(&strbuf, (union olsr_ip_addr *)&pin.sin_addr.s_addr));
+                olsr_ip_to_string(&strbuf, ipaddr));
     goto close_connection;
   }
 
   memset(req, 0, sizeof(req));
   //memset(body, 0, sizeof(body));
-  abuf_init(&body, 0);
-  abuf_init(&header, 0);
 
   while ((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < sizeof(req)-1)) {
       c++;
@@ -1154,18 +1204,32 @@ static void build_cfgfile_body(struct autobuf *abuf)
 #endif
 }
 
-static int check_allowed_ip(const struct allowed_net * const all_nets, const union olsr_ip_addr * const addr)
+static olsr_bool check_allowed_ip(const struct ip_prefix_list * const all_nets, const union olsr_ip_addr * const addr)
 {
-    const struct allowed_net *alln;
-    for (alln = all_nets; alln != NULL; alln = alln->next) {
-        if ((addr->v4.s_addr & alln->mask.v4.s_addr) == (alln->net.v4.s_addr & alln->mask.v4.s_addr)) {
-            return 1;
-        }
+  const struct ip_prefix_list *ipcn;
+
+  if (olsr_cnf->ip_version == AF_INET) {
+    if (addr->v4.s_addr == ntohl(INADDR_LOOPBACK)) {
+      return OLSR_TRUE;
     }
-    return 0;
-}
+  } else {
+    if(ip6equal(&addr->v6, &in6addr_loopback)) {
+      return OLSR_TRUE;
+    }
+    else if(ip6equal(&addr->v6, &in6addr_v4mapped_loopback)) {
+      return OLSR_TRUE;
+    }
+  }
 
+  /* check nets */
+  for (ipcn = all_nets; ipcn != NULL; ipcn = ipcn->next) {
+    if (ip_in_net(addr, &ipcn->net)) { 
+      return OLSR_TRUE;
+    }
+  }
 
+  return OLSR_FALSE;
+}
 
 #if 0
 /*
index 46b9afc..2e6b616 100644 (file)
 
 int http_port = 0;
 int resolve_ip_addresses = 0;
-struct allowed_net *allowed_nets = NULL;
+struct ip_prefix_list *allowed_nets = NULL;
 
 static void my_init(void) __attribute__ ((constructor));
 static void my_fini(void) __attribute__ ((destructor));
 
-static int add_plugin_ipnet(const char *value, void *data, set_plugin_parameter_addon);
-static int add_plugin_ipaddr(const char *value, void *data, set_plugin_parameter_addon);
+static int add_plugin_ipnet4(const char *value, void *data, set_plugin_parameter_addon);
+static int add_plugin_ipnet6(const char *value, void *data, set_plugin_parameter_addon);
+static int add_plugin_ipaddr4(const char *value, void *data, set_plugin_parameter_addon);
+static int add_plugin_ipaddr6(const char *value, void *data, set_plugin_parameter_addon);
 
-static int insert_plugin_ipnet(const char *sz_net, const char *sz_mask, struct allowed_net **all_nets);
+static int insert_plugin_ipnet(sa_family_t ip_version, const char *sz_net, const char *sz_mask, struct ip_prefix_list **all_nets);
+static int add_plugin_ipnet(sa_family_t ip_version, const char *value, struct ip_prefix_list **all_nets);
 
 /*
  * Defines the version of the plugin interface that is used
@@ -103,8 +106,12 @@ static void my_fini(void)
 
 static const struct olsrd_plugin_parameters plugin_parameters[] = {
     { .name = "port",   .set_plugin_parameter = &set_plugin_port,      .data = &http_port },
-    { .name = "host",   .set_plugin_parameter = &add_plugin_ipaddr,    .data = &allowed_nets },
-    { .name = "net",    .set_plugin_parameter = &add_plugin_ipnet,     .data = &allowed_nets },
+    { .name = "host4",   .set_plugin_parameter = &add_plugin_ipaddr4,  .data = &allowed_nets },
+    { .name = "net4",    .set_plugin_parameter = &add_plugin_ipnet4,   .data = &allowed_nets },
+    { .name = "host",   .set_plugin_parameter = &add_plugin_ipaddr4,   .data = &allowed_nets },
+    { .name = "net",    .set_plugin_parameter = &add_plugin_ipnet4,    .data = &allowed_nets },
+    { .name = "host6",   .set_plugin_parameter = &add_plugin_ipaddr6,  .data = &allowed_nets },
+    { .name = "net6",    .set_plugin_parameter = &add_plugin_ipnet6,   .data = &allowed_nets },
     { .name = "resolve",.set_plugin_parameter = &set_plugin_boolean,          .data = &resolve_ip_addresses },
 };
 
@@ -114,40 +121,65 @@ void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params,
     *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
 }
 
-static int insert_plugin_ipnet(const char *sz_net, const char *sz_mask, struct allowed_net **all_nets)
+static int insert_plugin_ipnet(sa_family_t ip_version, const char *sz_net, const char *sz_mask, struct ip_prefix_list **all_nets)
 {
-    struct allowed_net *an;
-
-    an = olsr_malloc(sizeof(*an), __func__);
-    if (an == NULL) {
-        fprintf(stderr, "(HTTPINFO) register param net out of memory!\n");
-        exit(0);
+    union olsr_ip_addr net;
+    union olsr_ip_addr netmask;
+    long prefix_len;
+
+    if(inet_pton(ip_version, sz_net, &net) <= 0) return 1;
+
+    if(ip_version == AF_INET) {
+      if(inet_pton(AF_INET, sz_mask, &netmask) <= 0) return 1;
+      prefix_len = olsr_netmask_to_prefix(&netmask);
+    } else {
+      prefix_len = strtoul(sz_mask, NULL, 10);
+      if(prefix_len < 0 || prefix_len > 128) return 1;
     }
 
-    if(inet_aton(sz_net, &an->net.v4) == 0 || 
-       inet_aton(sz_mask, &an->mask.v4) == 0) {
-        free(an);
-       return 1;
+    if(ip_version != olsr_cnf->ip_version) {
+      if(ip_version == AF_INET) {
+        memmove(&net.v6.s6_addr[12], &net.v4.s_addr, sizeof(in_addr_t));
+        memset(&net.v6.s6_addr[0], 0x00, 10 * sizeof(uint8_t));
+        memset(&net.v6.s6_addr[10], 0xff, 2 * sizeof(uint8_t));
+        prefix_len += 96;
+      }
+      else return 1;
     }
-    an->next = *all_nets;
-    *all_nets = an;
+
+    ip_prefix_list_add(all_nets, &net, prefix_len);
+
     return 0;
 }
 
-static int add_plugin_ipnet(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+static int add_plugin_ipnet(sa_family_t ip_version, const char *value, struct ip_prefix_list **all_nets)
 {
     char sz_net[100], sz_mask[100]; /* IPv6 in the future */
 
     if(sscanf(value, "%99s %99s", sz_net, sz_mask) != 2) {
-        olsr_printf(1, "(HTTPINFO) Error parsing net param \"%s\"!\n", value);
-        return 0;
+        return 1;
     }
-    return insert_plugin_ipnet(sz_net, sz_mask, data);
+    return insert_plugin_ipnet(ip_version, sz_net, sz_mask, all_nets);
+}
+
+static int add_plugin_ipnet4(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    return add_plugin_ipnet(AF_INET, value, data);
+}
+
+static int add_plugin_ipnet6(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    return add_plugin_ipnet(AF_INET6, value, data);
+}
+
+static int add_plugin_ipaddr4(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    return insert_plugin_ipnet(AF_INET, value, "255.255.255.255", data);
 }
 
-static int add_plugin_ipaddr(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+static int add_plugin_ipaddr6(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
 {
-    return insert_plugin_ipnet(value, "255.255.255.255", data);
+    return insert_plugin_ipnet(AF_INET6, value, "128", data);
 }
 
 /*
index d52e528..ae986c9 100644 (file)
@@ -81,7 +81,7 @@ struct allowed_net {
     struct allowed_net      *next;
 };
 
-extern struct allowed_net    *allowed_nets;
+extern struct ip_prefix_list *allowed_nets;
 
 
 /****************************************************************************
index 7cff17c..5a74bdd 100644 (file)
@@ -119,13 +119,13 @@ int ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net
 {
   int rv;
   if(olsr_cnf->ip_version == AF_INET) {
-    olsr_u32_t netmask = ~0 << (32 - net->prefix_len);
+    olsr_u32_t netmask = ntohl(~0 << (32 - net->prefix_len));
     rv = (ipaddr->v4.s_addr & netmask) == (net->prefix.v4.s_addr & netmask);
   } else {
     /* IPv6 */
     olsr_u32_t netmask;
-    const olsr_u32_t *i = (const olsr_u32_t *)&ipaddr->v6;
-    const olsr_u32_t *n = (const olsr_u32_t *)&net->prefix.v6;
+    const olsr_u32_t *i = (const olsr_u32_t *)&ipaddr->v6.s6_addr;
+    const olsr_u32_t *n = (const olsr_u32_t *)&net->prefix.v6.s6_addr;
     unsigned int prefix_len;
     for (prefix_len = net->prefix_len; prefix_len > 32; prefix_len -= 32) {
       if (*i != *n) {
@@ -134,7 +134,7 @@ int ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net
       i++;
       n++;
     }
-    netmask = ~0 << (32 - prefix_len);
+    netmask = ntohl(~0 << (32 - prefix_len));
     rv = (*i & netmask) == (*n & netmask);
   }
   return rv;