On Tue, Aug 7, 2018 at 5:49 AM, Charles Myers <charles.my...@spirent.com>
wrote:

> Signed-off-by: Charles Myers <charles.my...@spirent.com>
> ---
>  bsd/porting/networking.cc | 178 ++++++++++++++++++++++++++++++
> +++++++++++++++-
>  bsd/porting/networking.hh |   8 +++
>  bsd/porting/route.cc      |  86 ++++++++++++++++++----
>  bsd/sys/netinet/in.cc     |  10 +++
>  bsd/sys/netinet/in.h      |   1 +
>  loader.cc                 |  76 +++++++++++++++-----
>  6 files changed, 327 insertions(+), 32 deletions(-)
>
> diff --git a/bsd/porting/networking.cc b/bsd/porting/networking.cc
> index 016106c..e2767a7 100644
> --- a/bsd/porting/networking.cc
> +++ b/bsd/porting/networking.cc
> @@ -17,6 +17,15 @@
>  #include <bsd/sys/net/route.h>
>  #include <bsd/sys/netinet/in.h>
>  #include <bsd/sys/netinet/in_var.h>
> +#ifdef INET6
> +#include <bsd/sys/netinet6/in6.h>
> +#include <bsd/sys/netinet6/in6_var.h>
> +#include <bsd/sys/netinet6/nd6.h>
> +#include <bsd/sys/netinet6/ip6_var.h>
> +
> +// FIXME: inet_pton() is from musl which uses different AF_INET6
>
+#define LINUX_AF_INET6 10
>

We already have this exact #define in bsd/sys/compat/linux/linux_socket.h,
can we include that instead?

I think you should remove the "FIXME" - this is the correct behavior of
inet_pton and other User-facing
functions, which take the Linux versions of the ABI - and unfortunately
while in Linux and BSD AF_INET
is the same, AF_INET6 is not :-(

Instead of a "FIXME" here you can explain at the point you use
LINUX_AF_INET6 below, why you use it.


> +#endif // INET6
>  #include <bsd/sys/sys/socket.h>
>  #include <bsd/sys/sys/socketvar.h>
>
> @@ -61,6 +70,18 @@ int if_set_mtu(std::string if_name, u16 mtu)
>
>  int start_if(std::string if_name, std::string ip_addr, std::string
> mask_addr)
>  {
> +    return if_add_addr(if_name, ip_addr, mask_addr);
> +}
> +
> +int stop_if(std::string if_name, std::string ip_addr)
> +{
> +    std::string mask_addr;
>

If you intend to use an empty string, you can (I think) also just use ""
below, and don't need to name it (but you can, if you want...).

> +
> +    return if_del_addr(if_name, ip_addr, mask_addr);
> +}
> +
> +int if_add_ipv4_addr(std::string if_name, std::string ip_addr,
> std::string mask_addr)
> +{
>      int error, success;
>      struct bsd_ifreq oldaddr;
>      struct in_aliasreq ifra;
> @@ -99,7 +120,9 @@ int start_if(std::string if_name, std::string ip_addr,
> std::string mask_addr)
>          error = EINVAL;
>          goto out;
>      }
> +    mask->sin_family = AF_INET;
>      mask->sin_len = sizeof(struct bsd_sockaddr_in);
> +
>      broadcast->sin_family      = AF_INET;
>      broadcast->sin_len         = sizeof(struct bsd_sockaddr_in);
>      broadcast->sin_addr.s_addr = (addr->sin_addr.s_addr &
> @@ -117,7 +140,7 @@ out:
>      return (error);
>  }
>
> -int stop_if(std::string if_name, std::string ip_addr)
> +int if_del_ipv4_addr(std::string if_name, std::string ip_addr)
>  {
>      int error, success;
>      struct in_aliasreq ifra;
> @@ -155,6 +178,157 @@ out:
>      return (error);
>  }
>
> +#ifdef INET6
> +
> +int if_add_ipv6_addr(std::string if_name, std::string ip_addr,
> std::string netmask)
> +{
> +    int error, success;
> +    struct in6_ifreq oldaddr;
> +    struct in6_aliasreq ifra;
> +    struct bsd_sockaddr_in6* addr      = &ifra.ifra_addr;
> +    struct bsd_sockaddr_in6* mask      = &ifra.ifra_prefixmask;
> +    //struct bsd_sockaddr_in6* dst       = &ifra.ifra_dstaddr;
> +    struct ifnet* ifp;
> +
> +    if (if_name.empty() || ip_addr.empty() || netmask.empty()) {
> +        return (EINVAL);
> +    }
> +
> +    bzero(&ifra, sizeof(struct in6_aliasreq));
> +    ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
> +    ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
> +
> +    /* IF Name */
> +    strncpy(ifra.ifra_name, if_name.c_str(), IFNAMSIZ);
> +    ifp = ifunit_ref(if_name.c_str());
> +    if (!ifp) {
> +        return (ENOENT);
> +    }
> +
> +    /* IP Address */
> +    if ((success = inet_pton(LINUX_AF_INET6, ip_addr.c_str(),
> &addr->sin6_addr)) != 1) {
>

Maybe the comment about the peculiar AF parameter of inet_pton belongs
here, not about (but as a comment, not a FIXME)

+        bsd_log(ERR, "Failed converting IPv6 address %s\n",
> ip_addr.c_str());
> +        error = EINVAL;
> +        goto out;
> +    }
> +    addr->sin6_family = AF_INET6;
> +    addr->sin6_len = sizeof(struct bsd_sockaddr_in6);
> +
> +    /* Mask */
> +    if (inet_pton(LINUX_AF_INET6, netmask.c_str(), &mask->sin6_addr) !=
> 1) {
> +        /* Interpret it as a prefix length */
> +        long prefix_len = strtol(netmask.c_str(), NULL, 0);
> +        if (prefix_len < 0 || prefix_len > 128) {
> +            error = EINVAL;
> +            goto out;
> +        }
> +        in6_prefixlen2mask(&mask->sin6_addr, prefix_len);
> +    }
> +    mask->sin6_family = AF_INET6;
> +    mask->sin6_len = sizeof(struct bsd_sockaddr_in6);
> +
> +    strncpy(oldaddr.ifr_name, if_name.c_str(), IFNAMSIZ);
> +    error = in6_control(NULL, SIOCGIFADDR_IN6, (caddr_t)&oldaddr, ifp,
> NULL);
> +    if (!error) {
> +        in6_control(NULL, SIOCDIFADDR_IN6, (caddr_t)&oldaddr, ifp, NULL);
> +    }
> +    error = in6_control(NULL, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, NULL);
> +
> +out:
> +    if_rele(ifp);
> +    return (error);
> +}
> +
> +int if_del_ipv6_addr(std::string if_name, std::string ip_addr,
> std::string netmask)
> +{
> +    int error, success;
> +    struct in6_aliasreq ifra;
> +    struct bsd_sockaddr_in6* addr      = &ifra.ifra_addr;
> +    struct bsd_sockaddr_in6* mask      = &ifra.ifra_prefixmask;
> +    struct ifnet* ifp;
> +
> +    if (if_name.empty() || ip_addr.empty() || netmask.empty())
> +        return (EINVAL);
> +
> +    bzero(&ifra, sizeof(struct in6_aliasreq));
> +
> +    /* IF Name */
> +    strncpy(ifra.ifra_name, if_name.c_str(), IFNAMSIZ);
> +    ifp = ifunit_ref(if_name.c_str());
> +    if (!ifp) {
> +        return (ENOENT);
> +    }
> +
> +    /* IP Address */
> +    if ((success = inet_pton(LINUX_AF_INET6, ip_addr.c_str(),
> &addr->sin6_addr)) != 1) {
> +        bsd_log(ERR, "Failed converting IPv6 address %s\n",
> ip_addr.c_str());
> +        error = EINVAL;
> +        goto out;
> +    }
> +    addr->sin6_family = AF_INET6;
> +    addr->sin6_len = sizeof(struct bsd_sockaddr_in6);
> +
> +    /* Mask */
> +    if (inet_pton(LINUX_AF_INET6, netmask.c_str(), &mask->sin6_addr) !=
> 1) {
> +        /* Interpret it as a prefix length */
> +        long prefix_len = strtol(netmask.c_str(), NULL, 0);
> +        if (prefix_len < 0 || prefix_len > 128) {
> +            error = EINVAL;
> +            goto out;
> +        }
> +        in6_prefixlen2mask(&mask->sin6_addr, prefix_len);
> +    }
> +    mask->sin6_family = AF_INET6;
> +    mask->sin6_len = sizeof(struct bsd_sockaddr_in6);
> +
> +    error = in6_control(NULL, SIOCDIFADDR_IN6, (caddr_t)&ifra, ifp, NULL);
> +
> +out:
> +    if_rele(ifp);
> +    return (error);
> +}
> +
> +int set_ipv6_accept_rtadv(bool enable)
> +{
> +    V_ip6_accept_rtadv = enable ? 1 : 0;
> +    return 0;
> +}
> +
> +bool get_ipv6_accept_rtadv(void)
> +{
> +    return (V_ip6_accept_rtadv != 0);
> +}
> +
> +#endif // INET6
> +
> +int if_add_addr(std::string if_name, std::string ip_addr, std::string
> mask_addr)
> +{
> +    struct in_addr v4;
> +    if (inet_pton(AF_INET, ip_addr.c_str(), &v4)) {
>

This is also supposed to be LINUX_AF_INET, but it's the same :-)

+        return if_add_ipv4_addr(if_name, ip_addr, mask_addr);
> +    }
> +#ifdef INET6
> +    else {
> +        return if_add_ipv6_addr(if_name, ip_addr, mask_addr);
> +    }
> +#endif
> +    return EINVAL;
> +}
> +
> +int if_del_addr(std::string if_name, std::string ip_addr, std::string
> mask_addr)
> +{
> +    struct in_addr v4;
> +    if (inet_pton(AF_INET, ip_addr.c_str(), &v4)) {
> +        return if_del_ipv4_addr(if_name, ip_addr);
> +    }
> +#ifdef INET6
> +    else {
> +        return if_del_ipv6_addr(if_name, ip_addr, mask_addr);
> +    }
> +#endif
> +    return EINVAL;
> +}
> +
>  int ifup(std::string if_name)
>  {
>      int error;
> @@ -194,4 +368,6 @@ std::string if_ip(std::string if_name) {
>      }
>      return inet_ntoa(((bsd_sockaddr_in*)&(addr.ifr_addr))->sin_addr);
>  }
> +
> +
>  }
> diff --git a/bsd/porting/networking.hh b/bsd/porting/networking.hh
> index 8d06fe2..e25cb00 100644
> --- a/bsd/porting/networking.hh
> +++ b/bsd/porting/networking.hh
> @@ -22,6 +22,14 @@ namespace osv {
>      int stop_if(std::string if_name, std::string ip_addr);
>      int ifup(std::string if_name);
>      std::string if_ip(std::string if_name);
> +
> +    int if_add_addr(std::string if_name, std::string ip_addr, std::string
> netmask);
> +    int if_del_addr(std::string if_name, std::string ip_addr, std::string
> netmask);
> +
> +#ifdef INET6
> +    int set_ipv6_accept_rtadv(bool enable);
> +    bool get_ipv6_accept_rtadv(void);
> +#endif
>  }
>
>  #endif /* __NETWORKING_H__ */
> diff --git a/bsd/porting/route.cc b/bsd/porting/route.cc
> index b1f9d50..794a0a5 100644
> --- a/bsd/porting/route.cc
> +++ b/bsd/porting/route.cc
> @@ -41,6 +41,10 @@
>  #include <bsd/sys/sys/socket.h>
>  #include <bsd/sys/sys/socketvar.h>
>  #include <bsd/sys/sys/sysctl.h>
> +#ifdef INET6
> +#include <bsd/sys/netinet6/in6.h>
> +#include <bsd/sys/netinet6/in6_var.h>
> +#endif
>
>  int sysctl_rtsock(SYSCTL_HANDLER_ARGS) ;
>
> @@ -172,6 +176,59 @@ static struct mbuf*  osv_route_arp_rtmsg(int if_idx,
> int cmd, const char* ip,
>      return (m);
>  }
>
> +static int osv_sockaddr_from_string(struct bsd_sockaddr_storage *addr,
> const char *str)
> +{
> +    struct bsd_sockaddr_in *sa4 = (struct bsd_sockaddr_in*)addr;
> +    if (inet_pton(AF_INET, str, (void*)&sa4->sin_addr)) {
> +        sa4->sin_len = sizeof(*sa4);
> +        sa4->sin_family = AF_INET;
> +        sa4->sin_port = 0;
> +        return 1;
> +    }
> +#ifdef INET6
> +    struct bsd_sockaddr_in6 *sa6 = (struct bsd_sockaddr_in6*)addr;
> +    if (inet_pton(AF_INET6, str, (void*)&sa6->sin6_addr)) {
> +        sa6->sin6_len = sizeof(*sa6);
> +        sa6->sin6_family = AF_INET6;
> +        sa6->sin6_port = 0;
> +        sa6->sin6_flowinfo = 0;
> +        sa6->sin6_scope_id = 0;
> +        return 1;
> +    }
> +#endif
> +    return 0;
> +}
> +
> +static int osv_sockaddr_from_prefix_len(int af, struct
> bsd_sockaddr_storage *addr, int prefix_len)
> +{
> +    switch(af){
> +    case AF_INET:
> +        {
> +            struct bsd_sockaddr_in *sa4 = (struct bsd_sockaddr_in *)addr;
> +            sa4->sin_len = sizeof(*sa4);
> +            sa4->sin_family = AF_INET;
> +            sa4->sin_port = 0;
> +            in_prefixlen2mask(&sa4->sin_addr, prefix_len);
> +        }
> +        return 1;
> +#ifdef INET6
> +    case AF_INET6:
> +        {
> +            struct bsd_sockaddr_in6 *sa6 = (struct bsd_sockaddr_in6
> *)addr;
> +            sa6->sin6_len = sizeof(*sa6);
> +            sa6->sin6_family = AF_INET6;
> +            sa6->sin6_port = 0;
> +            sa6->sin6_flowinfo = 0;
> +            sa6->sin6_scope_id = 0;
> +            in6_prefixlen2mask(&sa6->sin6_addr, prefix_len);
> +        }
> +        return 1;
> +#endif
> +    default:
> +        return 0;
> +    }
> +}
> +
>  /* Compose a routing message to be sent on socket */
>  static struct mbuf*  osv_route_rtmsg(int cmd, const char* destination,
>      const char* gateway, const char* netmask, int flags, gw_type type)
> @@ -185,10 +242,10 @@ static struct mbuf*  osv_route_rtmsg(int cmd, const
> char* destination,
>      struct bsd_ifaddr *ifa;
>      bool is_link = type == gw_type::link;
>
> -    /* IPv4: Addresses */
> -    struct bsd_sockaddr_in dst;
> -    struct bsd_sockaddr_in gw;
> -    struct bsd_sockaddr_in mask;
> +    /* IP: Addresses */
> +    struct bsd_sockaddr_storage dst;
> +    struct bsd_sockaddr_storage gw;
> +    struct bsd_sockaddr_storage mask;
>
>      /* Link: Address*/
>      struct bsd_sockaddr_dl sdl;
> @@ -215,9 +272,7 @@ static struct mbuf*  osv_route_rtmsg(int cmd, const
> char* destination,
>      bzero(&sdl, sizeof(sdl));
>      bzero(&mask, sizeof(mask));
>
> -    dst.sin_family = AF_INET;
> -    dst.sin_len = sizeof(struct bsd_sockaddr_in);
> -    inet_aton(destination, &dst.sin_addr);
> +    osv_sockaddr_from_string(&dst, destination);
>
>      if (is_link) {
>          /* Get ifindex from name */
> @@ -234,15 +289,20 @@ static struct mbuf*  osv_route_rtmsg(int cmd, const
> char* destination,
>          memcpy(ea, IF_LLADDR(ifp), ETHER_ADDR_LEN);
>          if_rele(ifp);
>      } else {
> -        gw.sin_family = AF_INET;
> -        gw.sin_len = sizeof(struct bsd_sockaddr_in);
> -        inet_aton(gateway, &gw.sin_addr);
> +        osv_sockaddr_from_string(&gw, gateway);
>      }
>
>      if (netmask) {
> -        mask.sin_family = AF_INET;
> -        mask.sin_len = sizeof(struct bsd_sockaddr_in);
> -        inet_aton(netmask, &mask.sin_addr);
> +        if (osv_sockaddr_from_string(&mask, netmask) == 0) {
> +            // Try parsing it as a prefix length
> +            char *p_end = NULL;
> +            long prefix_len = strtol(netmask, &p_end, 0);
> +            if (p_end == netmask) {
> +                 // Bad netmask string.  Probably safer to treat it as a
> host route.
> +                 prefix_len = (((struct bsd_sockaddr *)&dst)->sa_family
> == AF_INET6) ? 128 : 32;
> +            }
> +            osv_sockaddr_from_prefix_len(((struct bsd_sockaddr
> *)&dst)->sa_family, &mask, prefix_len);
> +        }
>      }
>
>      /*
> diff --git a/bsd/sys/netinet/in.cc b/bsd/sys/netinet/in.cc
> index f7c1934..c0c37cd 100644
> --- a/bsd/sys/netinet/in.cc
> +++ b/bsd/sys/netinet/in.cc
> @@ -1673,3 +1673,13 @@ in_domifdetach(struct ifnet *ifp, void *aux)
>         lltable_free(ii->ii_llt);
>         free(ii);
>  }
> +
> +void
> +in_prefixlen2mask(struct in_addr *maskp, int plen)
> +{
> +       if (plen == 0)
> +               maskp->s_addr = 0;
> +       else
> +               maskp->s_addr = htonl(0xffffffff << (32 - plen));
> +}
> +
> diff --git a/bsd/sys/netinet/in.h b/bsd/sys/netinet/in.h
> index 43291b7..672e613 100644
> --- a/bsd/sys/netinet/in.h
> +++ b/bsd/sys/netinet/in.h
> @@ -470,6 +470,7 @@ const char *inet_ntoa_r(struct in_addr ina, char *buf,
> socklen_t); /* in libkern
>  const char *inet_ntop(int, const void *, char *, socklen_t); /* in
> libkern */
>  int     inet_pton(int af, const char *, void *); /* in libkern */
>  void    in_ifdetach(struct ifnet *);
> +void in_prefixlen2mask(struct in_addr *maskp, int plen);
>  __END_DECLS
>
>  #define        in_hosteq(s, t) ((s).s_addr == (t).s_addr)
> diff --git a/loader.cc b/loader.cc
> index 3f88ebd..5e04c83 100644
> --- a/loader.cc
> +++ b/loader.cc
> @@ -5,6 +5,8 @@
>   * BSD license as described in the LICENSE file in the top-level
> directory.
>   */
>
> +#include <bsd/porting/netport.h>
> +
>  #include "fs/fs.hh"
>  #include <bsd/init.hh>
>  #include <bsd/net.hh>
> @@ -137,8 +139,8 @@ static bool opt_verbose = false;
>  static std::string opt_chdir;
>  static bool opt_bootchart = false;
>  static std::vector<std::string> opt_ip;
> -static std::string opt_defaultgw;
> -static std::string opt_nameserver;
> +static std::vector<std::string> opt_defaultgw;
> +static std::vector<std::string> opt_nameserver;
>  static std::string opt_redirect;
>  static std::chrono::nanoseconds boot_delay;
>  bool opt_assign_net = false;
> @@ -177,8 +179,8 @@ void parse_options(int loader_argc, char** loader_argv)
>          ("cwd", bpo::value<std::vector<std::string>>(), "set current
> working directory")
>          ("bootchart", "perform a test boot measuring a time distribution
> of the various operations\n")
>          ("ip", bpo::value<std::vector<std::string>>(), "set static IP on
> NIC")
> -        ("defaultgw", bpo::value<std::string>(), "set default gateway
> address")
> -        ("nameserver", bpo::value<std::string>(), "set nameserver
> address")
> +        ("defaultgw", bpo::value<std::vector<std::string>>(), "set
> default gateway address")
>
+        ("nameserver", bpo::value<std::vector<std::string>>(), "set
> nameserver address")
>
         ("delay", bpo::value<float>()->default_value(0), "delay in seconds
> before boot")
>          ("redirect", bpo::value<std::string>(), "redirect stdout and
> stderr to file")
>          ("disable_rofs_cache", "disable ROFS memory cache")
> @@ -287,11 +289,11 @@ void parse_options(int loader_argc, char**
> loader_argv)
>      }
>
>      if (vars.count("defaultgw")) {
> -        opt_defaultgw = vars["defaultgw"].as<std::string>();
> +        opt_defaultgw = vars["defaultgw"].as<std::vector<std::string>>();
>      }
>
>      if (vars.count("nameserver")) {
> -        opt_nameserver = vars["nameserver"].as<std::string>();
> +        opt_nameserver = vars["nameserver"].as<std::
> vector<std::string>>();
>      }
>
>      if (vars.count("redirect")) {
> @@ -365,40 +367,77 @@ void* do_main_thread(void *_main_args)
>          }
>      }
>
> +#ifdef INET6
> +    // Enable IPv6 StateLess Address AutoConfiguration (SLAAC)
> +    osv::set_ipv6_accept_rtadv(true);
> +#endif
> +
>      bool has_if = false;
>      osv::for_each_if([&has_if] (std::string if_name) {
>          if (if_name == "lo0")
>              return;
>
>          has_if = true;
> -        // Start DHCP by default and wait for an IP
> -        if (osv::start_if(if_name, "0.0.0.0", "255.255.255.0") != 0 ||
> -            osv::ifup(if_name) != 0)
> +
> +        if (osv::ifup(if_name) != 0)
>              debug("Could not initialize network interface.\n");
> +
> +        if (opt_ip.size() == 0) {
> +            // Start DHCP by default and wait for an IP
> +            if (osv::if_add_addr(if_name, "0.0.0.0", "255.255.255.0") !=
> 0)
> +                debug("Could not add 0.0.0.0 IP to interface.\n");
> +        }
>      });
>      if (has_if) {
>          if (opt_ip.size() == 0) {
>              dhcp_start(true);
>          } else {
> +            // Add interface IP addresses
>              for (auto t : opt_ip) {
>                  std::vector<std::string> tmp;
> -                boost::split(tmp, t, boost::is_any_of(" ,"),
> boost::token_compress_on);
> +                boost::split(tmp, t, boost::is_any_of(" ,/"),
> boost::token_compress_on);
>                  if (tmp.size() != 3)
>                      abort("incorrect parameter on --ip");
>
> -                printf("%s: %s\n",tmp[0].c_str(),tmp[1].c_str());
> +                printf("%s: %s %s\n",tmp[0].c_str(),tmp[1].c_str(),
> tmp[2].c_str());
>
> -                if (osv::start_if(tmp[0], tmp[1], tmp[2]) != 0)
> -                    debug("Could not initialize network interface.\n");
> +                if (osv::if_add_addr(tmp[0], tmp[1], tmp[2]) != 0)
> +                    debug("Could not add IP address to interface.\n");
>              }
> +            // Add default gateway routes
> +            // One default route is allowed for IPv4 and one for IPv6
>              if (opt_defaultgw.size() != 0) {
> -                osv_route_add_network("0.0.0.0",
> -                                      "0.0.0.0",
> -                                      opt_defaultgw.c_str());
> +                bool has_defaultgw_v4=false, has_defaultgw_v6=false;
> +                for (auto t : opt_defaultgw) {
> +                    auto addr = boost::asio::ip::address::from_string(t);
> +                    if (addr.is_v4()) {
> +                        if (!has_defaultgw_v4) {
> +                            osv_route_add_network("0.0.0.0",
> +                                                  "0.0.0.0",
> +                                                  t.c_str());
> +                            has_defaultgw_v4 = true;
> +                        }
> +                    }
> +                    else {
> +                        if (!has_defaultgw_v6) {
> +                            osv_route_add_network("::",
> +                                                  "::",
> +                                                  t.c_str());
> +                            has_defaultgw_v6 = true;
> +                        }
> +                    }
> +                }
>              }
> +            // Add nameserver addresses
>              if (opt_nameserver.size() != 0) {
> -                auto addr = boost::asio::ip::address_v4::
> from_string(opt_nameserver);
> -                osv::set_dns_config({addr}, std::vector<std::string>());
> +                std::vector<boost::asio::ip::address> dns_servers;
> +                for (auto t : opt_nameserver) {
> +                    auto addr = boost::asio::ip::address::from_string(t);
> +                    dns_servers.push_back(addr);
> +                }
> +                if (!dns_servers.empty()) {
> +                    osv::set_dns_config(dns_servers,
> std::vector<std::string>());
> +                }
>              }
>          }
>      }
> @@ -465,6 +504,7 @@ void* do_main_thread(void *_main_args)
>          for (int i = 0; i < count; i++) {
>              if (!strcmp(".", namelist[i]->d_name) ||
>                      !strcmp("..", namelist[i]->d_name)) {
> +                free(namelist[i]);
>

Not related to this patch, but looks correct :-)

                 continue;
>              }
>              std::string fn("/init/");
> --
> 2.7.4
>
> --
> You received this message because you are subscribed to the Google Groups
> "OSv Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to osv-dev+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to