diff options
author | Stefan Siegl <stesie@brokenpipe.de> | 2007-10-08 21:59:10 +0000 |
---|---|---|
committer | Stefan Siegl <stesie@brokenpipe.de> | 2007-10-08 21:59:10 +0000 |
commit | 1145e4da1321f80b8f1fe9184bdd8e596f2dcd2a (patch) | |
tree | ebdd0cc6a174d8a585fa93fadfbde01c5f4a96ac /pfinet/options.c | |
parent | 9ef3092f3172c049beb847d1dca602e2b4b755c5 (diff) |
2007-10-08 Stefan Siegl <stesie@brokenpipe.de>
* config.h (CONFIG_IPV6, CONFIG_IPV6_EUI64): New defines,
set to 1.
* Makefile (ipv6-srcs): New variable.
(LINUXSRCS): Add ipv6-srcs.
* ethernet.c (ethernet_demuxer): Call skb_put instead of changing
skb->len directly, and thus now update skb->tail accordingly.
* pfinet.h (PORTCLASS_INET, PORTCLASS_INET6): New enums.
(trivfs_protid_portclasses, trivfs_protid_nportclasses)
(trivfs_cntl_portclasses, trivfs_cntl_nportclasses): Declare
these.
(pfinet_bootstrap_portclass): New variable.
(pfinet_bind): New function.
* main.c: Define _HACK_ERRNO_H. Include <errno.h>.
(trivfs_protid_portclasses, trivfs_cntl_portclasses): New slots
for PORTCLASS_INET6.
(trivfs_protid_nportclasses, trivfs_cntl_nportclasses): Set to 2.
(pfinet_bootstrap_portclass): New variable.
(pfinet_bind): New function.
(pfinet_activate_ipv6) [CONFIG_IPV6]: New function.
(main) [CONFIG_IPV6]: Call inet6_proto_init.
(main): Reordered to allow pfinet to not be started as a
translator, if pfinet_bind is used. If started as a translator,
treat pfinet_bootstrap_portclass when calling trivfs_startup.
* options.c: Include <net/sock.h>, <net/ip6_fib.h>,
<net/ip6_route.h> and <net/addrconf.h>.
(options): New option `ipv4'.
(options) [CONFIG_IPV6]: New options `ipv6', `address6' and
`gateway6'.
(parse_interface) [CONFIG_IPV6]: Add address6 and gateway6.
(parse_hook_add_interface) [CONFIG_IPV6]: Initialize address6 and
gateway6.
(parse_opt): Parse new args.
* socket-ops.c (S_socket_create): Call either
net_families[PF_INET]->create or net_families[PF_INET6]->create,
depending on receiving master.
(S_socket_create_address): Allow creation of AF_INET6 addresses.
* glue-include/asm/delay.h: New stub file.
* glue-include/linux/ipv6.h: Merged many bits unmodified from Linux
header file.
* glue-include/linux/in6.h: Likewise.
(ipv6mr_ifindex): New define, glue to ipv6mr_interface.
* glue-include/linux/socket.h (SOL_IPV6, SOL_ICMPV6): New defines.
* linux-src/net/ipv6/addrconf.c (ipv6_find_idev, inet6_addr_add)
(inet6_addr_del) [_HURD_]: Make these non-static.
(addrconf_set_dstaddr, addrconf_add_ifaddr, addrconf_del_ifaddr)
[_HURD_]: Don't define these functions.
* linux-src/net/ipv6/route_ipv6.c (ipv6_route_ioctl) [_HURD_]:
Likewise.
* linux-src/net/ipv6/af_inet6.c (inet6_ioctl) [_HURD_]: Don't
define the function, instead #define it to 0.
(inet6_proto_init) [_HURD_]: Don't call sit_init.
* linux-src/net/ipv6/udp_ipv6.c (udp_ioctl) [_HURD_]: Define
to 0.
(udp_v6_get_port): Put empty statement after label to silence
compiler.
* linux-src/net/ipv6/tcp_ipv6.c (tcp_v6_get_port, tcp_v6_rcv):
Likewise.
* linux-src/net/ipv6/icmpv6.c (icmpv6_rcv): Likewise.
(icmpv6_init) [_HURD_]: Don't initialize i_uid and i_gid.
* linux-src/net/ipv6/mcast.c (igmp6_init): Likewise.
* linux-src/net/ipv6/ndisc.c (ndisc_init): Likewise.
* linux-src/net/ipv6/ip6_fib.c (BUG_TRAP): Don't use __FUNCTION__
as a string but a variable, to keep gcc happy.
(fib6_walker_list): Make it non-static, to keep gcc happy.
* linux-src/net/ipv6/ip6_flowlabel.c (fl_create) [_HURD_]: Drop
IPV6_FL_S_USER support, since current->euid is not available.
Diffstat (limited to 'pfinet/options.c')
-rw-r--r-- | pfinet/options.c | 210 |
1 files changed, 190 insertions, 20 deletions
diff --git a/pfinet/options.c b/pfinet/options.c index d05ac6d0..85738a5b 100644 --- a/pfinet/options.c +++ b/pfinet/options.c @@ -1,6 +1,6 @@ /* Pfinet option parsing - Copyright (C) 1996, 1997, 2000, 2001, 2006 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 2000, 2001, 2006, 2007 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.org> @@ -37,7 +37,11 @@ #include <linux/route.h> #include <linux/rtnetlink.h> #include <net/route.h> +#include <net/sock.h> #include <net/ip_fib.h> +#include <net/ip6_fib.h> +#include <net/ip6_route.h> +#include <net/addrconf.h> /* Our interface to the set of devices. */ extern error_t find_device (char *name, struct device **device); @@ -50,6 +54,12 @@ extern error_t configure_device (struct device *dev, uint32_t addr, extern void inquire_device (struct device *dev, uint32_t *addr, uint32_t *netmask, uint32_t *peer, uint32_t *broadcast); + +/* addrconf.c */ +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); + /* Pfinet options. Used for both startup and runtime. */ static const struct argp_option options[] = @@ -60,6 +70,12 @@ static const struct argp_option options[] = {"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"}, +#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"}, +#endif {"shutdown", 's', 0, 0, "Shut it down"}, {0} }; @@ -74,8 +90,14 @@ struct parse_interface /* The network interface in question. */ struct device *device; - /* New values to apply to it. */ + /* New values to apply to it. (IPv4) */ uint32_t address, netmask, peer, gateway; + +#ifdef CONFIG_IPV6 + /* New IPv6 configuration to apply. */ + struct inet6_ifaddr address6; + struct in6_addr gateway6; +#endif }; /* Used to hold data during argument parsing. */ @@ -108,6 +130,12 @@ parse_hook_add_interface (struct parse_hook *h) h->curint->netmask = INADDR_NONE; h->curint->peer = INADDR_NONE; h->curint->gateway = INADDR_NONE; + +#ifdef CONFIG_IPV6 + memset (&h->curint->address6, 0, sizeof (struct inet6_ifaddr)); + memset (&h->curint->gateway6, 0, sizeof (struct in6_addr)); +#endif + return 0; } @@ -146,6 +174,10 @@ parse_opt (int opt, char *arg, struct argp_state *state) { struct parse_interface *in; uint32_t gateway; +#ifdef CONFIG_IPV6 + struct parse_interface *gw6_in; + char *ptr; +#endif case 'i': /* An interface. */ @@ -196,6 +228,52 @@ parse_opt (int opt, char *arg, struct argp_state *state) case 'g': h->curint->gateway = ADDR (arg, "gateway"); break; + case '4': + pfinet_bind (PORTCLASS_INET, arg); + + /* Install IPv6 port class on bootstrap port. */ + pfinet_bootstrap_portclass = PORTCLASS_INET6; + break; + +#ifdef CONFIG_IPV6 + case '6': + pfinet_bind (PORTCLASS_INET6, arg); + 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); + break; + + case 'G': + 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); + break; +#endif /* CONFIG_IPV6 */ + case ARGP_KEY_INIT: /* Initialize our parsing state. */ h = malloc (sizeof (struct parse_hook)); @@ -234,30 +312,74 @@ parse_opt (int opt, char *arg, struct argp_state *state) #endif gateway = INADDR_NONE; +#ifdef CONFIG_IPV6 + gw6_in = NULL; +#endif for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++) - 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; - } - + { + 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; + } + +#ifdef CONFIG_IPV6 + if (!IN6_IS_ADDR_UNSPECIFIED (&in->gateway6)) + { + if (gw6_in != NULL) + FAIL (err, 15, 0, "Cannot have multiple IPv6 " + "default gateways"); + gw6_in = in; + } +#endif + } /* Successfully finished parsing, return a result. */ __mutex_lock (&global_lock); for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++) - if (in->address != INADDR_NONE || in->netmask != INADDR_NONE) - { - 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"); - } - } + { +#ifdef CONFIG_IPV6 + struct inet6_dev *idev = NULL; + if (trivfs_protid_portclasses[PORTCLASS_INET6] != MACH_PORT_NULL + && in->device) + idev = ipv6_find_idev(in->device); +#endif + + if (in->address != INADDR_NONE || in->netmask != INADDR_NONE) + { + 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"); + } + } + +#ifdef CONFIG_IPV6 + if (!idev) + continue; + + if (!IN6_IS_ADDR_UNSPECIFIED (&in->address6.addr)) + { + /* First let's remove all non-local addresses. */ + struct inet6_ifaddr *ifa = idev->addr_list; + do + if (!IN6_IS_ADDR_LINKLOCAL (&ifa->addr) + && !IN6_IS_ADDR_SITELOCAL (&ifa->addr)) + inet6_addr_del (in->device->ifindex, &ifa->addr, + ifa->prefix_len); + while ((ifa = ifa->if_next)); + + /* Now assign the new address */ + inet6_addr_add (in->device->ifindex, &in->address6.addr, + in->address6.prefix_len); + } +#endif /* CONFIG_IPV6 */ + } /* Set the default gateway. This code is cobbled together from what the SIOCADDRT ioctl code does, and from the apparent functionality @@ -315,6 +437,16 @@ parse_opt (int opt, char *arg, struct argp_state *state) } } + /* Set IPv6 default router. */ +#ifdef CONFIG_IPV6 + if (trivfs_protid_portclasses[PORTCLASS_INET6] != MACH_PORT_NULL) + { + rt6_purge_dflt_routers (0); + if (gw6_in) + rt6_add_dflt_router (&gw6_in->gateway6, gw6_in->device); + } +#endif + __mutex_unlock (&global_lock); /* Fall through to free hook. */ @@ -372,6 +504,44 @@ trivfs_append_args (struct trivfs_control *fsys, char **argz, size_t *argz_len) ADD_ADDR_OPT ("gateway", FIB_RES_GW (res)); #undef ADD_ADDR_OPT + +#ifdef CONFIG_IPV6 + struct inet6_dev *idev = NULL; + + if (trivfs_protid_portclasses[PORTCLASS_INET6] != MACH_PORT_NULL) + idev = ipv6_find_idev(dev); + + if (idev) + { + struct inet6_ifaddr *ifa = idev->addr_list; + struct in6_addr daddr; + static char addr_buf[INET6_ADDRSTRLEN]; + + /* Look for IPv6 default route (we use the first ifa->addr as + source address), but don't yet push it to the option stack. */ + memset (&daddr, 0, sizeof(daddr)); + struct fib6_node *fib = fib6_lookup + (&ip6_routing_table, &daddr, &ifa->addr); + struct rt6_info *rt6i = fib->leaf; + + /* Push all IPv6 addresses assigned to the interface. */ + do + { + inet_ntop (AF_INET6, &ifa->addr, addr_buf, INET6_ADDRSTRLEN); + ADD_OPT ("--address6=%s/%d", addr_buf, ifa->prefix_len); + } + while ((ifa = ifa->if_next)); + + /* Last not least push --gateway6 option. */ + if(rt6i->rt6i_dev == dev) + { + inet_ntop (AF_INET6, &rt6i->rt6i_gateway, addr_buf, + INET6_ADDRSTRLEN); + ADD_OPT ("--gateway6=%s", addr_buf); + } + } +#endif /* CONFIG_IPV6 */ + #undef ADD_OPT return err; |