Hi Michael,

I've finally found some time to have a look at Christian's patch.  

On Tue, Nov 20, 2007 at 02:18:58PM +0100, Michael Banck wrote:
> Hrm, I have the feeling this patch broke just setting /servers/socket/2
> to "/hurd/pfinet" (what corresponds to the lo device in Linux?):
> 
> [EMAIL PROTECTED]:~$ gdb /hurd/pfinet
> GNU gdb 6.4.90-debian
> Copyright (C) 2006 Free Software Foundation, Inc.
> GDB is free software, covered by the GNU General Public License, and you are
> welcome to change it and/or distribute copies of it under certain conditions.
> Type "show copying" to see the conditions.
> There is absolutely no warranty for GDB.  Type "show warranty" for details.
> This GDB was configured as "i486-gnu"...(no debugging symbols found)
> 
> (gdb) r
> Starting program: /hurd/pfinet 
> NET4: Linux TCP/IP 1.0 for NET4.0
> IP Protocols: ICMP, UDP, TCP
> TCP: Hash tables configured (ehash 65536 bhash 65536)
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x08080d9d in trivfs_append_args ()
> (gdb) bt 1
> #0  0x08080d9d in trivfs_append_args ()
> (More stack frames follow...)
> 
> I can try to record a full backtrace with debugging symbols if that
> helps.

I was able to reproduce this and fixed it.  Find a modified version of
the patch along.

I've furthermore stripped the `--shutdown' option, which didn't work
anyways.  It was just mentioned in the help text.  I don't think that it
should be implemented, since `settrans -g' is thought for that, imho.

Besides that I slightly changed the behaviour of e.g. `pfinet -i eth2'
to automatically set up ip address `0.0.0.0' and dhcp routing.

There are still two issues with multi-interface mode:

 * If you do `pfinet -i eth0 -i eth2' followed by `dhclient eth2', the
   latter won't work as expected (it will send discoveries on eth0).
   This is dhclient doesn't bind the interface correctly.

 * Set `pfinet -i eth0 -a 192.168.7.23 -m 255.255.255.0 -g 192.168.7.1 \
   -i eth2 -a 192.168.5.23 -m 255.255.255.0', now 192.168.7.1 acts as
   the default gateway.  Now use fsysopts to change the gateway to
   192.168.5.1 on eth2, works as expected.  However another change back
   to 192.168.7.1 won't work (it doesn't error out, but simply doesn't
   do it) ...

I'll have a look at these the next days and do a few more tests.  Apart
from the above I think the patch is fine and should be committed if
fixed.

cheers,
  stesie
? .swp
? ChangeLog.frag
? cscope.out
? free-fix.diff
? pfinet-20071014.diff
? timer-debug.diff
? linux-src/net/ipv4/cscope.out
? linux-src/net/ipv6/cscope.out
Index: ChangeLog
===================================================================
RCS file: /sources/hurd/hurd/pfinet/ChangeLog,v
retrieving revision 1.86
diff -u -r1.86 ChangeLog
--- ChangeLog	14 Oct 2007 02:26:10 -0000	1.86
+++ ChangeLog	20 Nov 2007 20:27:08 -0000
@@ -1,3 +1,28 @@
+2007-10-14  Christian Dietrich  <[EMAIL PROTECTED]>
+	* options.c (options): Marked -a, -g -m, -p, -A, -G
+	OPTION_ARG_OPTIONAL. Adding -d option.
+	(parse_interface_copy_device): New function.
+	(parse_opt): When selecting another interface with -i 
+	set the options from e.g. a prior fsysopts call as default
+	values. For -a, -g, -p, -g, -A, -G set the optional 
+	argument as value. When there is no argument, delete the
+	value (e.g. unset default gateway). Delete delete default gateways
+	only if the set gateway is on an interface modified in this call.
+	Add always an route for dhcp packages on all devices. By doing
+	this we can send dhcp renew packages.
+	(trivfs_append_args): Add --gateway only once.
+
+2007-10-14  Marco Gerards  <[EMAIL PROTECTED]>
+	* options.c (options): Add the option `dhcp'.
+	(parse_hook_add_interface): Initialize the `dhcp' member for the
+	parse hook.
+	(parse_opt): In case pfinet is started with the argument `--dhcp',
+	set the address to `0.0.0.0', the netmask to `255.0.0.0' and add
+	the route for `0.0.0.0' so broadcasting works.
+
+	* linux-src/net/ipv4/devinet.c (inet_insert_ifa) [_HURD_]: Don't
+	fail when the address is `0.0.0.0'.
+      
 2007-10-14  Stefan Siegl  <[EMAIL PROTECTED]>
 
 	* options.c (ipv6_get_dflt_router) [CONFIG_IPV6]: New function.
Index: options.c
===================================================================
RCS file: /sources/hurd/hurd/pfinet/options.c,v
retrieving revision 1.14
diff -u -r1.14 options.c
--- options.c	14 Oct 2007 02:26:10 -0000	1.14
+++ options.c	20 Nov 2007 20:27:14 -0000
@@ -60,23 +60,26 @@
 extern int inet6_addr_add (int ifindex, struct in6_addr *pfx, int plen);
 extern int inet6_addr_del (int ifindex, struct in6_addr *pfx, int plen);
 
+#ifdef CONFIG_IPV6
+static struct rt6_info * ipv6_get_dflt_router (void);
+#endif
+
 
 /* Pfinet options.  Used for both startup and runtime.  */
 static const struct argp_option options[] =
 {
-  {"interface", 'i', "DEVICE",  0,  "Network interface to use", 1},
+  {"interface", 'i', "DEVICE",   0,  "Network interface to use", 1},
   {0,0,0,0,"These apply to a given interface:", 2},
-  {"address",   'a', "ADDRESS", 0, "Set the network address"},
-  {"netmask",   'm', "MASK",    0, "Set the netmask"},
-  {"peer",      'p', "ADDRESS", 0, "Set the peer address"},
-  {"gateway",   'g', "ADDRESS", 0, "Set the default gateway"},
-  {"ipv4",      '4', "NAME",    0, "Put active IPv4 translator on NAME"},
+  {"address",   'a', "ADDRESS",  OPTION_ARG_OPTIONAL, "Set the network address"},
+  {"netmask",   'm', "MASK",     OPTION_ARG_OPTIONAL, "Set the netmask"},
+  {"peer",      'p', "ADDRESS",  OPTION_ARG_OPTIONAL, "Set the peer address"},
+  {"gateway",   'g', "ADDRESS",  OPTION_ARG_OPTIONAL, "Set the default gateway"},
+  {"ipv4",      '4', "NAME",     0, "Put active IPv4 translator on NAME"},
 #ifdef CONFIG_IPV6  
-  {"ipv6",      '6', "NAME",    0, "Put active IPv6 translator on NAME"},
-  {"address6",  'A', "ADDR/LEN",0, "Set the global IPv6 address"},
-  {"gateway6",  'G', "ADDRESS", 0, "Set the IPv6 default gateway"},
+  {"ipv6",      '6', "NAME",     0, "Put active IPv6 translator on NAME"},
+  {"address6",  'A', "ADDR/LEN", OPTION_ARG_OPTIONAL, "Set the global IPv6 address"},
+  {"gateway6",  'G', "ADDRESS",  OPTION_ARG_OPTIONAL, "Set the IPv6 default gateway"},
 #endif
-  {"shutdown",  's', 0,         0, "Shut it down"},
   {0}
 };
 
@@ -112,6 +115,50 @@
   struct parse_interface *curint;
 };
 
+static void
+parse_interface_copy_device(struct device *src,
+                            struct parse_interface *dst)
+{
+  uint32_t broad;
+  struct rt_key key = { 0 };
+  struct inet6_dev *idev = NULL;
+  struct fib_result res;
+
+  inquire_device (src, &dst->address, &dst->netmask, 
+                  &dst->peer, &broad);
+  /* Get gateway */
+  dst->gateway = INADDR_NONE;
+  key.oif = src->ifindex;
+  if (! main_table->tb_lookup (main_table, &key, &res)
+      && FIB_RES_GW(res) != INADDR_ANY)
+    dst->gateway = FIB_RES_GW (res);
+#ifdef CONFIG_IPV6
+  if (trivfs_protid_portclasses[PORTCLASS_INET6] != MACH_PORT_NULL)
+    idev = ipv6_find_idev(src);
+
+  if (idev)
+  {
+    struct inet6_ifaddr *ifa = idev->addr_list;
+    
+    /* Look for IPv6 default router and add it to the interface,
+     * if it belongs to it.
+     */
+    struct rt6_info *rt6i = ipv6_get_dflt_router();
+    if (rt6i->rt6i_dev == src) 
+      memcpy (&dst->gateway6, &rt6i->rt6i_gateway, sizeof (struct in6_addr));
+    /* Search for global address and set it in dst */
+    do 
+    {
+      if (!IN6_IS_ADDR_LINKLOCAL (&ifa->addr)) {
+        memcpy (&dst->address6, ifa, sizeof (struct inet6_ifaddr));
+        break;
+      }
+    }
+    while ((ifa = ifa->if_next));
+  }
+#endif
+}
+
 /* Adds an empty interface slot to H, and sets H's current interface to it, or
    returns an error. */
 static error_t
@@ -122,6 +169,7 @@
 	     (h->num_interfaces + 1) * sizeof (struct parse_interface));
   if (! new)
     return ENOMEM;
+
   h->interfaces = new;
   h->num_interfaces++;
   h->curint = new + h->num_interfaces - 1;
@@ -183,10 +231,16 @@
      if (addr == INADDR_NONE) PERR (EINVAL, "Malformed %s", type);	      \
      addr; })
 
+  if (!arg && state->next < state->argc
+      && (*state->argv[state->next] != '-'))
+    {
+      arg = state->argv[state->next];
+      state->next ++;
+    }
+
   switch (opt)
     {
-      struct parse_interface *in;
-      uint32_t gateway;
+      struct parse_interface *in, *gw4_in;
 #ifdef CONFIG_IPV6
       struct parse_interface *gw6_in;
       char *ptr;
@@ -216,30 +270,60 @@
 	err = find_device (arg, &in->device);
       if (err)
 	FAIL (err, 10, err, "%s", arg);

+      /* Set old interface values */
+      parse_interface_copy_device (in->device, in);
       break;
 
     case 'a':
-      h->curint->address = ADDR (arg, "address");
-      if (!IN_CLASSA (ntohl (h->curint->address))
-	  && !IN_CLASSB (ntohl (h->curint->address))
-	  && !IN_CLASSC (ntohl (h->curint->address)))
-	{
-	  if (IN_MULTICAST (ntohl (h->curint->address)))
-	    FAIL (EINVAL, 1, 0,
-		  "%s: Cannot set interface address to multicast address",
-		  arg);
-	  else
-	    FAIL (EINVAL, 1, 0,
-		  "%s: Illegal or undefined network address", arg);
-	}
+      if (arg)
+      {
+        h->curint->address = ADDR (arg, "address");
+        if (!IN_CLASSA (ntohl (h->curint->address))
+            && !IN_CLASSB (ntohl (h->curint->address))
+            && !IN_CLASSC (ntohl (h->curint->address)))
+          {
+            if (IN_MULTICAST (ntohl (h->curint->address)))
+              FAIL (EINVAL, 1, 0,
+                    "%s: Cannot set interface address to multicast address",
+                    arg);
+            else
+              FAIL (EINVAL, 1, 0,
+                    "%s: Illegal or undefined network address", arg);
+          }
+      } else { 
+        h->curint->address = ADDR ("0.0.0.0", "address");
+        h->curint->netmask = ADDR ("255.0.0.0", "netmask");
+        h->curint->gateway = INADDR_NONE;
+      }
       break;
+
     case 'm':
-      h->curint->netmask = ADDR (arg, "netmask"); break;
+      if (arg)
+        h->curint->netmask = ADDR (arg, "netmask"); 
+      else 
+        h->curint->netmask = INADDR_NONE;
+      break;
+
     case 'p':
-      h->curint->peer = ADDR (arg, "peer"); break;
+      if (arg)
+        h->curint->peer = ADDR (arg, "peer"); 
+      else 
+        h->curint->peer = INADDR_NONE;
+      break;
+
     case 'g':
-      h->curint->gateway = ADDR (arg, "gateway"); break;
+      if (arg)
+	{
+	  /* Remove an possible other default gateway */ 
+	  for (in = h->interfaces; in < h->interfaces + h->num_interfaces; 
+	       in++)
+	    in->gateway = INADDR_NONE;
+	  h->curint->gateway = ADDR (arg, "gateway");
+	}
+      else 
+        h->curint->gateway = INADDR_NONE;
+      break;
 
     case '4':
       pfinet_bind (PORTCLASS_INET, arg);
@@ -254,36 +338,46 @@
       break;
 
     case 'A':
-      if ((ptr = strchr (arg, '/'))) 
+      if (arg)
 	{
-	  h->curint->address6.prefix_len = atoi (ptr + 1);
-	  if (h->curint->address6.prefix_len > 128) 
-	    FAIL (EINVAL, 1, 0, "%s: The prefix-length is invalid", arg);
+	  if ((ptr = strchr (arg, '/'))) 
+	    {
+	      h->curint->address6.prefix_len = atoi (ptr + 1);
+	      if (h->curint->address6.prefix_len > 128) 
+		FAIL (EINVAL, 1, 0, "%s: The prefix-length is invalid", arg);
+	      
+	      *ptr = 0;
+	    }
+	  else
+	    {
+	      h->curint->address6.prefix_len = 64;
+	      fprintf (stderr, "No prefix-length given, "
+		       "defaulting to %s/64.\n", arg);
+	    }
 
-	  *ptr = 0;
+	  if (inet_pton (AF_INET6, arg, &h->curint->address6.addr) <= 0)
+	    PERR (EINVAL, "Malformed address");
+
+	  if (IN6_IS_ADDR_MULTICAST (&h->curint->address6.addr))
+	    FAIL (EINVAL, 1, 0, "%s: Cannot set interface address to "
+		  "multicast address", arg);
 	}
       else
-	{
-	  h->curint->address6.prefix_len = 64;
-	  fprintf (stderr, "No prefix-length given, defaulting to %s/64.\n",
-		   arg);
-	}
-
-      if (inet_pton (AF_INET6, arg, &h->curint->address6.addr) <= 0)
-	PERR (EINVAL, "Malformed address");
-
-      if (IN6_IS_ADDR_MULTICAST (&h->curint->address6.addr))
-	FAIL (EINVAL, 1, 0, "%s: Cannot set interface address to "
-	      "multicast address", arg);
+        memset (&h->curint->address6, 0, sizeof (struct inet6_ifaddr));
       break;
 
     case 'G':
-      if (inet_pton (AF_INET6, arg, &h->curint->gateway6) <= 0)
-	PERR (EINVAL, "Malformed gateway");
+      if (arg)
+	{
+	  if (inet_pton (AF_INET6, arg, &h->curint->gateway6) <= 0)
+	    PERR (EINVAL, "Malformed gateway");
 
-      if (IN6_IS_ADDR_MULTICAST (&h->curint->gateway6))
-	FAIL (EINVAL, 1, 0, "%s: Cannot set gateway to "
-	      "multicast address", arg);
+	  if (IN6_IS_ADDR_MULTICAST (&h->curint->gateway6))
+	    FAIL (EINVAL, 1, 0, "%s: Cannot set gateway to "
+		  "multicast address", arg);
+	}
+      else
+        memset (&h->curint->gateway6, 0, sizeof (struct in6_addr));
       break;
 #endif /* CONFIG_IPV6 */
 
@@ -323,20 +417,19 @@
 	  /* Specifying a netmask for an address-less interface is a no-no.  */
 	  FAIL (EDESTADDRREQ, 14, 0, "Cannot set netmask");
 #endif
-
-      gateway = INADDR_NONE;
 #ifdef CONFIG_IPV6
       gw6_in = NULL;
 #endif
+      gw4_in = NULL;
       for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
 	{
+          /* delete interface if it doesn't match the actual netmask */
+          if (! ( (h->curint->address & h->curint->netmask) 
+                  == (h->curint->gateway & h->curint->netmask))) 
+            h->curint->gateway = INADDR_NONE;
+
 	  if (in->gateway != INADDR_NONE)
-	    {
-	      if (gateway != INADDR_NONE)
-		FAIL (err, 15, 0, "Cannot have multiple default gateways");
-	      gateway = in->gateway;
-	      in->gateway = INADDR_NONE;
-	    }
+              gw4_in = in;
 
 #ifdef CONFIG_IPV6
 	  if (!IN6_IS_ADDR_UNSPECIFIED (&in->gateway6))
@@ -361,15 +454,20 @@
 	    idev = ipv6_find_idev(in->device);
 #endif
 
-	  if (in->address != INADDR_NONE || in->netmask != INADDR_NONE)
+	  if (in->address == INADDR_NONE && in->netmask == INADDR_NONE)
+	    {
+	      h->curint->address = ADDR ("0.0.0.0", "address");
+	      h->curint->netmask = ADDR ("255.0.0.0", "netmask");
+	    }
+
+	  if (in->device)
+	    err = configure_device (in->device, in->address, in->netmask,
+				    in->peer, INADDR_NONE);
+
+	  if (err)
 	    {
-	      err = configure_device (in->device, in->address, in->netmask,
-				      in->peer, INADDR_NONE);
-	      if (err)
-		{
-		  __mutex_unlock (&global_lock);
-		  FAIL (err, 16, 0, "cannot configure interface");
-		}
+	      __mutex_unlock (&global_lock);
+	      FAIL (err, 16, 0, "cannot configure interface");
 	    }
 
 #ifdef CONFIG_IPV6
@@ -377,24 +475,25 @@
 	    continue;
 
 	  /* First let's remove all non-local addresses. */
-	  struct inet6_ifaddr *ifa = idev->addr_list;
-
-	  while (ifa)
-	    {
-	      struct inet6_ifaddr *c_ifa = ifa;
-	      ifa = ifa->if_next;
-
-	      if (IN6_ARE_ADDR_EQUAL (&c_ifa->addr, &in->address6.addr))
-		memset (&in->address6, 0, sizeof (struct inet6_ifaddr));
-
-	      else if (!IN6_IS_ADDR_LINKLOCAL (&c_ifa->addr)
-		       && !IN6_IS_ADDR_SITELOCAL (&c_ifa->addr))
-		inet6_addr_del (in->device->ifindex, &c_ifa->addr,
-				c_ifa->prefix_len);
-	    }
-
-	  if (!IN6_IS_ADDR_UNSPECIFIED (&in->address6.addr))
-	    {
+ 	  struct inet6_ifaddr *ifa = idev->addr_list;
+ 
+ 	  while (ifa)
+  	    {
+ 	      struct inet6_ifaddr *c_ifa = ifa;
+ 	      ifa = ifa->if_next;
+ 
+ 	      if (!IN6_IS_ADDR_UNSPECIFIED (&in->address6.addr)
+		  && IN6_ARE_ADDR_EQUAL (&c_ifa->addr, &in->address6.addr))
+ 		memset (&in->address6, 0, sizeof (struct inet6_ifaddr));
+  
+ 	      else if (!IN6_IS_ADDR_LINKLOCAL (&c_ifa->addr)
+ 		       && !IN6_IS_ADDR_SITELOCAL (&c_ifa->addr))
+ 		inet6_addr_del (in->device->ifindex, &c_ifa->addr,
+ 				c_ifa->prefix_len);
+ 	    }
+ 
+ 	  if (!IN6_IS_ADDR_UNSPECIFIED (&in->address6.addr))
+ 	    {
 	      /* Now assign the new address */
 	      inet6_addr_add (in->device->ifindex, &in->address6.addr,
 			      in->address6.prefix_len);
@@ -418,33 +517,40 @@
 	req.nlh.nlmsg_seq = 0;
 	req.nlh.nlmsg_len = NLMSG_LENGTH (sizeof req.rtm);
 
-	bzero (&req.rtm, sizeof req.rtm);
-	bzero (&rta, sizeof rta);
+	memset (&req.rtm, 0, sizeof req.rtm);
+	memset (&rta, 0, sizeof rta);
 	req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
 	req.rtm.rtm_type = RTN_UNICAST;
 	req.rtm.rtm_protocol = RTPROT_STATIC;
-	rta.rta_gw = &gateway;
 
-	if (gateway == INADDR_NONE)
+	if (!gw4_in)
 	  {
-	    /* Delete any existing default route.  */
-	    req.nlh.nlmsg_type = RTM_DELROUTE;
-	    req.nlh.nlmsg_flags = 0;
-	    tb = fib_get_table (req.rtm.rtm_table);
-	    if (tb)
-	      {
-		err = - (*tb->tb_delete) (tb, &req.rtm, &rta, &req.nlh, 0);
-		if (err && err != ESRCH)
-		  {
-		    __mutex_unlock (&global_lock);
-		    FAIL (err, 17, 0, "cannot remove old default gateway");
-		  }
-		err = 0;
-	      }
+	    /* Delete any existing default route on configured devices  */
+            for (in = h->interfaces; in < h->interfaces + h->num_interfaces;
+                 in++) {
+              req.nlh.nlmsg_type = RTM_DELROUTE;
+              req.nlh.nlmsg_flags = 0;
+              rta.rta_oif = &in->device->ifindex;
+              tb = fib_get_table (req.rtm.rtm_table);
+              if (tb)
+                {
+                  err = - (*tb->tb_delete) 
+                    (tb, &req.rtm, &rta, &req.nlh, 0);
+                  if (err && err != ESRCH)
+                    {
+                      __mutex_unlock (&global_lock);
+                      FAIL (err, 17, 0, 
+                            "cannot remove old default gateway");
+                    }
+                  err = 0;
+                }
+            }
 	  }
 	else
 	  {
 	    /* Add a default route, replacing any existing one.  */
+            rta.rta_oif = &gw4_in->device->ifindex;
+            rta.rta_gw = &gw4_in->gateway;
 	    req.nlh.nlmsg_type = RTM_NEWROUTE;
 	    req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
 	    tb = fib_new_table (req.rtm.rtm_table);
@@ -467,13 +574,77 @@
 	  if (!gw6_in || rt6i->rt6i_dev != gw6_in->device
 	      || !IN6_ARE_ADDR_EQUAL (&rt6i->rt6i_gateway, &gw6_in->gateway6))
 	    {
-	      rt6_purge_dflt_routers (0);
+              /* Delete any existing default route on configured devices  */
+              for (in = h->interfaces; in < h->interfaces 
+                   + h->num_interfaces; in++) 
+                if (rt6i->rt6i_dev == in->device || gw6_in )
+                  rt6_purge_dflt_routers (0);
+
 	      if (gw6_in)
 		rt6_add_dflt_router (&gw6_in->gateway6, gw6_in->device);
 	    }
 	}
 #endif       
 
+      /*  Setup the routing required for DHCP. */
+      for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
+	{
+	  struct kern_rta rta;
+	  struct
+	  {
+	    struct nlmsghdr nlh;
+	    struct rtmsg rtm;
+	  } req;
+	  struct fib_table *tb;
+	  struct rtentry route;
+	  struct sockaddr_in *dst;
+	  struct device *dev;
+
+	  if (!in->device)
+	    continue;
+
+	  dst = (struct sockaddr_in *) &route.rt_dst;
+	  if (!in->device->name) 
+	    {
+	      __mutex_unlock (&global_lock);
+	      FAIL (ENODEV, 17, 0, "unknown device");
+	    }
+	  dev = dev_get (in->device->name);
+	  if (!dev)
+	    {
+	      __mutex_unlock (&global_lock);
+	      FAIL (ENODEV, 17, 0, "unknown device");
+	    }
+
+	  /* Simulate the SIOCADDRT behavior.  */
+	  memset (&route, 0, sizeof (struct rtentry));
+	  memset (&req.rtm, 0, sizeof req.rtm);
+	  memset (&rta, 0, sizeof rta);
+	  req.nlh.nlmsg_type = RTM_NEWROUTE;
+
+	  /* Append this routing for 0.0.0.0.  By this way we can send always
+	     dhcp messages (e.g dhcp renew). */
+	  req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE
+	    | NLM_F_APPEND;
+	  req.rtm.rtm_protocol = RTPROT_BOOT;
+	  req.rtm.rtm_scope = RT_SCOPE_LINK;
+	  req.rtm.rtm_type = RTN_UNICAST;
+	  rta.rta_dst = &dst->sin_addr.s_addr;
+	  rta.rta_oif = &dev->ifindex;
+
+	  tb = fib_new_table (req.rtm.rtm_table);
+	  if (tb)
+	    err = tb->tb_insert (tb, &req.rtm, &rta, &req.nlh, NULL);
+	  else
+	    err = ENOBUFS;
+
+	  if (err)
+	    {
+	      __mutex_unlock (&global_lock);
+	      FAIL (err, 17, 0, "cannot add route");
+	    }
+	}
+
       __mutex_unlock (&global_lock);
 
       /* Fall through to free hook.  */
@@ -526,8 +697,9 @@
         ADD_ADDR_OPT ("netmask", mask);
       if (peer != addr)
 	ADD_ADDR_OPT ("peer", peer);
-      key.iif = dev->ifindex;
-      if (! main_table->tb_lookup (main_table, &key, &res)) 
+      key.oif = dev->ifindex;
+      if (! main_table->tb_lookup (main_table, &key, &res)
+          && FIB_RES_GW(res) != INADDR_ANY)
 	ADD_ADDR_OPT ("gateway", FIB_RES_GW (res));
 
 #undef ADD_ADDR_OPT
Index: linux-src/net/ipv4/devinet.c
===================================================================
RCS file: /sources/hurd/hurd/pfinet/linux-src/net/ipv4/devinet.c,v
retrieving revision 1.8
diff -u -r1.8 devinet.c
--- linux-src/net/ipv4/devinet.c	18 Jul 2001 17:37:13 -0000	1.8
+++ linux-src/net/ipv4/devinet.c	20 Nov 2007 20:30:21 -0000
@@ -214,10 +214,12 @@
 {
 	struct in_ifaddr *ifa1, **ifap, **last_primary;
 
+#ifndef _HURD_
 	if (ifa->ifa_local == 0) {
 		inet_free_ifa(ifa);
 		return 0;
 	}
+#endif
 
 	ifa->ifa_flags &= ~IFA_F_SECONDARY;
 	last_primary = &in_dev->ifa_list;
_______________________________________________
Bug-hurd mailing list
Bug-hurd@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-hurd

Reply via email to