summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Banck <mbanck@debian.org>2007-11-19 15:16:01 +0000
committerMichael Banck <mbanck@debian.org>2007-11-19 15:16:01 +0000
commit80b43d2d039465ada92f995060995b05f036dc11 (patch)
tree2ed86128479e564d8b4b005e09710570c2636b35
parent01801d97a7d7cfb167c1fa7f385cc16a7fa19bf2 (diff)
* debian/patches/pfinet_dhcp.patch: Updated with new patch by Christian
Dietrich.
-rw-r--r--debian/changelog2
-rw-r--r--debian/patches/pfinet_dhcp.patch571
2 files changed, 488 insertions, 85 deletions
diff --git a/debian/changelog b/debian/changelog
index 4bfddd8d..f6402f7a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -23,6 +23,8 @@ hurd (20071119-1) UNRELEASED; urgency=low
* debian/hurd.dirs: Added servers/socket.
* debian/patches/diskfs_no_inherit_dir_group.patch: Update with better
patch by Thomas Schwinge.
+ * debian/patches/pfinet_dhcp.patch: Updated with new patch by Christian
+ Dietrich.
-- Michael Banck <mbanck@debian.org> Thu, 16 Aug 2007 16:55:53 +0200
diff --git a/debian/patches/pfinet_dhcp.patch b/debian/patches/pfinet_dhcp.patch
index 39f87a50..e707cdf9 100644
--- a/debian/patches/pfinet_dhcp.patch
+++ b/debian/patches/pfinet_dhcp.patch
@@ -1,4 +1,19 @@
-2005-01-06 Marco Gerards <metgerards@student.han.nl>
+2007-10-14 Christian Dietrich <stettberger@dokucode.de>
+
+ * 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 <metgerards@student.han.nl>
* options.c (options): Add the option `dhcp'.
(parse_hook_add_interface): Initialize the `dhcp' member for the
@@ -9,107 +24,495 @@
* linux-src/net/ipv4/devinet.c (inet_insert_ifa) [_HURD_]: Don't
fail when the address is `0.0.0.0'.
-
-
---- pfinet/options.c.orig 2007-11-19 15:11:07.000000000 +0100
-+++ pfinet/options.c 2007-11-19 15:53:11.000000000 +0100
-@@ -76,6 +76,7 @@
- {"address6", 'A', "ADDR/LEN",0, "Set the global IPv6 address"},
- {"gateway6", 'G', "ADDRESS", 0, "Set the IPv6 default gateway"},
+
+Index: options.c
+===================================================================
+RCS file: /sources/hurd/hurd/pfinet/options.c,v
+retrieving revision 1.14
+diff -p -u -r1.14 options.c
+--- pfinet/options.c 14 Oct 2007 02:26:10 -0000 1.14
++++ pfinet/options.c 22 Oct 2007 20:49:02 -0000
+@@ -60,23 +60,27 @@ extern struct inet6_dev *ipv6_find_idev
+ 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
-+ {"dhcp", 'd', 0 , 0, "Prepare pfinet for dhcp"},
- {"shutdown", 's', 0, 0, "Shut it down"},
+- {"shutdown", 's', 0, 0, "Shut it down"},
++ {"shutdown", 's', 0, 0, "Shut it down"},
{0}
};
-@@ -93,6 +94,9 @@
- /* New values to apply to it. (IPv4) */
- uint32_t address, netmask, peer, gateway;
-+ /* Set to one if the interface is configured for DHCP. */
-+ int dhcp;
+@@ -112,6 +116,50 @@ struct parse_hook
+ 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;
+
- #ifdef CONFIG_IPV6
- /* New IPv6 configuration to apply. */
- struct inet6_ifaddr address6;
-@@ -130,6 +134,7 @@
- h->curint->netmask = INADDR_NONE;
- h->curint->peer = INADDR_NONE;
- h->curint->gateway = INADDR_NONE;
-+ h->curint->dhcp = 0;
++ 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
+@@ -185,8 +233,7 @@ parse_opt (int opt, char *arg, struct ar
+ switch (opt)
+ {
+- struct parse_interface *in;
+- uint32_t gateway;
++ struct parse_interface *in, *gw4_in;
#ifdef CONFIG_IPV6
- memset (&h->curint->address6, 0, sizeof (struct inet6_ifaddr));
-@@ -234,6 +239,11 @@
- "%s: Illegal or undefined network address", arg);
- }
+ struct parse_interface *gw6_in;
+ char *ptr;
+@@ -216,31 +263,64 @@ parse_opt (int opt, char *arg, struct ar
+ 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 || ((state->next < state->argc)
++ && (*state->argv[state->next] != '-')
++ ? (arg = state->argv[state->next++]) : 0))
++ {
++ 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 'd':
-+ h->curint->dhcp = 1;
-+ h->curint->address = ADDR ("0.0.0.0", "address");
-+ h->curint->netmask = ADDR ("255.0.0.0", "netmask");
-+ break;
case 'm':
- h->curint->netmask = ADDR (arg, "netmask"); break;
+- h->curint->netmask = ADDR (arg, "netmask"); break;
++ if (arg || ((state->next < state->argc)
++ && (*state->argv[state->next] != '-')
++ ? (arg = state->argv[state->next++]) : 0))
++ h->curint->netmask = ADDR (arg, "netmask");
++ else
++ h->curint->netmask = INADDR_NONE;
++ break;
case 'p':
-@@ -474,6 +484,55 @@
+- h->curint->peer = ADDR (arg, "peer"); break;
++ if (arg || ((state->next < state->argc)
++ && (*state->argv[state->next] != '-')
++ ? (arg = state->argv[state->next++]) : 0))
++ h->curint->peer = ADDR (arg, "peer");
++ else
++ h->curint->peer = INADDR_NONE;
++ break;
+ case 'g':
+- h->curint->gateway = ADDR (arg, "gateway"); break;
+-
++ if (arg || ((state->next < state->argc)
++ && (*state->argv[state->next] != '-')
++ ? (arg = state->argv[state->next++]) : 0))
++ {
++ /* 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 +334,48 @@ parse_opt (int opt, char *arg, struct ar
+ break;
+
+ case 'A':
+- 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);
+- }
+-
+- 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);
++ if (arg || ((state->next < state->argc)
++ && (*state->argv[state->next] != '-')
++ ? (arg = state->argv[state->next++]) : 0))
++ {
++ 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);
++ }
++
++ 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
++ 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 || ((state->next < state->argc)
++ && (*state->argv[state->next] != '-')
++ ? (arg = state->argv[state->next++]) : 0))
++ {
++ 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 +415,19 @@ parse_opt (int opt, char *arg, struct ar
+ /* 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))
+@@ -377,24 +468,24 @@ parse_opt (int opt, char *arg, struct ar
+ 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_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 +509,40 @@ parse_opt (int opt, char *arg, struct ar
+ 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 +565,73 @@ parse_opt (int opt, char *arg, struct ar
+ 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++)
-+ if (in->dhcp)
-+ {
-+ 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;
-+
-+ dst = (struct sockaddr_in *) &route.rt_dst;
-+
-+ dev = dev_get (in->device->name);
-+ if (!dev)
-+ {
-+ __mutex_unlock (&global_lock);
-+ FAIL (ENODEV, 17, 0, "unknown device");
-+ }
-+
-+ /* Simulate the SIOCADDRT behavior. */
-+ bzero (&route, sizeof (struct rtentry));
-+ bzero (&req.rtm, sizeof req.rtm);
-+ bzero (&rta, sizeof rta);
-+ req.nlh.nlmsg_type = RTM_NEWROUTE;
-+ req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
-+ 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");
-+ }
-+ }
-+
++ {
++ 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;
++
++ 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. */
-diff -u -p -r1.8 devinet.c
+@@ -526,8 +684,9 @@ trivfs_append_args (struct trivfs_contro
+ 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 -p -u -r1.8 devinet.c
--- pfinet/linux-src/net/ipv4/devinet.c 18 Jul 2001 17:37:13 -0000 1.8
-+++ pfinet/linux-src/net/ipv4/devinet.c 6 Jan 2005 18:52:32 -0000
++++ pfinet/linux-src/net/ipv4/devinet.c 22 Oct 2007 20:49:04 -0000
@@ -214,10 +214,12 @@ inet_insert_ifa(struct in_device *in_dev
{
struct in_ifaddr *ifa1, **ifap, **last_primary;
@@ -123,5 +526,3 @@ diff -u -p -r1.8 devinet.c
ifa->ifa_flags &= ~IFA_F_SECONDARY;
last_primary = &in_dev->ifa_list;
-
-