[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[hurd] 34/37: Allow dhcp trafic and configuration
From: |
Samuel Thibault |
Subject: |
[hurd] 34/37: Allow dhcp trafic and configuration |
Date: |
Mon, 09 Feb 2015 09:59:12 +0000 |
This is an automated email from the git hooks/post-receive script.
sthibault pushed a commit to annotated tag upstream/hurd/0.5.git20150208
in repository hurd.
commit 2be6756dbbdd400b1734ee014aa1518201271482
Author: Samuel Thibault <address@hidden>
Date: Mon Feb 2 11:10:48 2015 +0100
Allow dhcp trafic and configuration
2007-10-14 Christian Dietrich <address@hidden>
* options.c (options): Marked -a, -g -m, -p, -A, -G
OPTION_ARG_OPTIONAL.
(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 <address@hidden>
* options.c (parse_opt): 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 | 336 +++++++++++++++++++++++++++---------
2 files changed, 258 insertions(+), 80 deletions(-)
diff --git a/pfinet/linux-src/net/ipv4/devinet.c
b/pfinet/linux-src/net/ipv4/devinet.c
index 0416ee8..a566743 100644
--- 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 *ifa)
{
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;
diff --git a/pfinet/options.c b/pfinet/options.c
index ff9db4b..daffcd5 100644
--- a/pfinet/options.c
+++ b/pfinet/options.c
@@ -60,21 +60,25 @@ extern struct inet6_dev *ipv6_find_idev (struct device
*dev);
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
{0}
};
@@ -111,6 +115,51 @@ 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
@@ -121,6 +170,7 @@ parse_hook_add_interface (struct parse_hook *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;
@@ -182,10 +232,16 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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,29 +272,61 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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 (arg)
{
- 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);
+ 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);
@@ -253,36 +341,46 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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;
+ }
+ 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 (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 (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)
+ {
+ 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 */
@@ -322,20 +420,19 @@ parse_opt (int opt, char *arg, struct argp_state *state)
/* 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))
@@ -360,15 +457,20 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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)
- {
- pthread_mutex_unlock (&global_lock);
- FAIL (err, 16, 0, "cannot configure interface");
- }
+ pthread_mutex_unlock (&global_lock);
+ FAIL (err, 16, 0, "cannot configure interface");
}
#ifdef CONFIG_IPV6
@@ -383,7 +485,8 @@ parse_opt (int opt, char *arg, struct argp_state *state)
struct inet6_ifaddr *c_ifa = ifa;
ifa = ifa->if_next;
- if (IN6_ARE_ADDR_EQUAL (&c_ifa->addr, &in->address6.addr))
+ 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)
@@ -422,28 +525,36 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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)
+ /* Delete any existing default route on configured devices */
+ for (in = h->interfaces; in < h->interfaces + h->num_interfaces;
+ in++)
{
- err = - (*tb->tb_delete) (tb, &req.rtm, &rta, &req.nlh, 0);
- if (err && err != ESRCH)
+ 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)
{
- pthread_mutex_unlock (&global_lock);
- FAIL (err, 17, 0, "cannot remove old default gateway");
+ err = - (*tb->tb_delete)
+ (tb, &req.rtm, &rta, &req.nlh, 0);
+ if (err && err != ESRCH)
+ {
+ pthread_mutex_unlock (&global_lock);
+ FAIL (err, 17, 0,
+ "cannot remove old default gateway");
+ }
+ err = 0;
}
- 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);
@@ -466,12 +577,76 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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
+#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)
+ {
+ pthread_mutex_unlock (&global_lock);
+ FAIL (ENODEV, 17, 0, "unknown device");
+ }
+ dev = dev_get (in->device->name);
+ if (!dev)
+ {
+ pthread_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)
+ {
+ pthread_mutex_unlock (&global_lock);
+ FAIL (err, 17, 0, "cannot add route");
+ }
+ }
pthread_mutex_unlock (&global_lock);
@@ -525,8 +700,9 @@ trivfs_append_args (struct trivfs_control *fsys, char
**argz, size_t *argz_len)
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
--
Alioth's /usr/local/bin/git-commit-notice on
/srv/git.debian.org/git/pkg-hurd/hurd.git
- [hurd] 27/37: startup: give the tasks we create a name, (continued)
- [hurd] 27/37: startup: give the tasks we create a name, Samuel Thibault, 2015/02/09
- [hurd] 33/37: Remove unimplemented -s option, Samuel Thibault, 2015/02/09
- [hurd] 19/37: misc: Fix typos in comments (found by codespell), Samuel Thibault, 2015/02/09
- [hurd] 36/37: startup: add more error handling, Samuel Thibault, 2015/02/09
- [hurd] 32/37: utils/rpctrace: fix notification port handling, Samuel Thibault, 2015/02/09
- [hurd] 16/37: aclocal.m4, configure.ac: Fix typos and grammar in comment (found by codespell), Samuel Thibault, 2015/02/09
- [hurd] 37/37: Merge remote-tracking branch 'upstream/master' into upstream, Samuel Thibault, 2015/02/09
- [hurd] 24/37: libfshelp: improve error handling, Samuel Thibault, 2015/02/09
- [hurd] 18/37: console: Fix typos in comments, Samuel Thibault, 2015/02/09
- [hurd] 30/37: proc: call `startup_essential_task' earlier, Samuel Thibault, 2015/02/09
- [hurd] 34/37: Allow dhcp trafic and configuration,
Samuel Thibault <=
- [hurd] 01/37: Makeconf: handle the task_notify protocol, Samuel Thibault, 2015/02/09
- [hurd] 02/37: proc: register for new task notifications, Samuel Thibault, 2015/02/09
- [hurd] 07/37: ext2fs: tune the size of the inode cache, Samuel Thibault, 2015/02/09
- [hurd] 26/37: libports: silence pointless error message, Samuel Thibault, 2015/02/09
- [hurd] 12/37: Avoid ./ components in mtab output, Samuel Thibault, 2015/02/09
- [hurd] 10/37: Fix inclusion loop between hurd_types.defs and hurd/signal.h>, Samuel Thibault, 2015/02/09
- [hurd] 35/37: Explicit the keymap compatibility flags, Samuel Thibault, 2015/02/09
- [hurd] 03/37: proc: implement `proc_make_task_namespace', Samuel Thibault, 2015/02/09
- [hurd] 28/37: auth: simplify expression, Samuel Thibault, 2015/02/09
- [hurd] 29/37: auth: remove implicit assumption about the bootstrap process, Samuel Thibault, 2015/02/09