summaryrefslogtreecommitdiff
path: root/debian/patches/pfinet_dhcp.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/pfinet_dhcp.patch')
-rw-r--r--debian/patches/pfinet_dhcp.patch560
1 files changed, 560 insertions, 0 deletions
diff --git a/debian/patches/pfinet_dhcp.patch b/debian/patches/pfinet_dhcp.patch
new file mode 100644
index 00000000..30c0902a
--- /dev/null
+++ b/debian/patches/pfinet_dhcp.patch
@@ -0,0 +1,560 @@
+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
+ 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'.
+
+---
+ pfinet/linux-src/net/ipv4/devinet.c | 2
+ pfinet/options.c | 381 ++++++++++++++++++++++++++----------
+ 2 files changed, 278 insertions(+), 105 deletions(-)
+
+--- a/pfinet/options.c
++++ b/pfinet/options.c
+@@ -60,23 +60,26 @@ 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
+- {"shutdown", 's', 0, 0, "Shut it down"},
+ {0}
+ };
+
+@@ -112,6 +115,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;
++
++ 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 @@ parse_hook_add_interface (struct parse_h
+ (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 @@ parse_opt (int opt, char *arg, struct ar
+ 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;
+@@ -217,29 +271,59 @@ parse_opt (int opt, char *arg, struct ar
+ 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 @@ parse_opt (int opt, char *arg, struct ar
+ 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 @@ 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))
+@@ -361,15 +454,20 @@ parse_opt (int opt, char *arg, struct ar
+ 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 @@ 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_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 @@ 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 +573,77 @@ 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++)
++ {
++ 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 +696,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
+--- a/pfinet/linux-src/net/ipv4/devinet.c
++++ b/pfinet/linux-src/net/ipv4/devinet.c
+@@ -214,10 +214,12 @@ inet_insert_ifa(struct in_device *in_dev
+ {
+ 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;