summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Siegl <stesie@brokenpipe.de>2007-10-08 21:59:10 +0000
committerStefan Siegl <stesie@brokenpipe.de>2007-10-08 21:59:10 +0000
commit1145e4da1321f80b8f1fe9184bdd8e596f2dcd2a (patch)
treeebdd0cc6a174d8a585fa93fadfbde01c5f4a96ac
parent9ef3092f3172c049beb847d1dca602e2b4b755c5 (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.
-rw-r--r--pfinet/ChangeLog72
-rw-r--r--pfinet/Makefile22
-rw-r--r--pfinet/config.h4
-rw-r--r--pfinet/ethernet.c2
-rw-r--r--pfinet/glue-include/linux/in6.h109
-rw-r--r--pfinet/glue-include/linux/ipv6.h116
-rw-r--r--pfinet/glue-include/linux/socket.h2
-rw-r--r--pfinet/linux-src/net/ipv6/addrconf.c23
-rw-r--r--pfinet/linux-src/net/ipv6/af_inet6.c10
-rw-r--r--pfinet/linux-src/net/ipv6/icmpv6.c5
-rw-r--r--pfinet/linux-src/net/ipv6/ip6_fib.c6
-rw-r--r--pfinet/linux-src/net/ipv6/ip6_flowlabel.c7
-rw-r--r--pfinet/linux-src/net/ipv6/mcast.c4
-rw-r--r--pfinet/linux-src/net/ipv6/ndisc.c2
-rw-r--r--pfinet/linux-src/net/ipv6/route_ipv6.c4
-rw-r--r--pfinet/linux-src/net/ipv6/tcp_ipv6.c6
-rw-r--r--pfinet/linux-src/net/ipv6/udp_ipv6.c8
-rw-r--r--pfinet/main.c174
-rw-r--r--pfinet/options.c210
-rw-r--r--pfinet/pfinet.h18
-rw-r--r--pfinet/socket-ops.c10
21 files changed, 742 insertions, 72 deletions
diff --git a/pfinet/ChangeLog b/pfinet/ChangeLog
index 6868d270..b1aff756 100644
--- a/pfinet/ChangeLog
+++ b/pfinet/ChangeLog
@@ -1,5 +1,77 @@
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.
+
+2007-10-08 Stefan Siegl <stesie@brokenpipe.de>
+
Import a number of files from Linux 2.2.14. Renamed some of them,
to have unique filenames as required by the make system.
diff --git a/pfinet/Makefile b/pfinet/Makefile
index 75440d5b..9bc97e80 100644
--- a/pfinet/Makefile
+++ b/pfinet/Makefile
@@ -58,7 +58,25 @@ ipv4-srcs := af_inet.c \
timer.c \
udp.c \
utils.c
-LINUXSRCS = $(core-srcs) $(ethernet-srcs) $(ipv4-srcs) \
+ipv6-srcs := addrconf.c \
+ af_inet6.c \
+ datagram_ipv6.c \
+ exthdrs.c \
+ icmpv6.c \
+ ip6_fib.c \
+ ip6_flowlabel.c \
+ ip6_input.c \
+ ip6_output.c \
+ ipv6_sockglue.c \
+ mcast.c \
+ ndisc.c \
+ protocol_ipv6.c \
+ raw_ipv6.c \
+ reassembly.c \
+ route_ipv6.c \
+ tcp_ipv6.c \
+ udp_ipv6.c
+LINUXSRCS = $(core-srcs) $(ethernet-srcs) $(ipv4-srcs) $(ipv6-srcs) \
$(notdir $(wildcard $(addprefix \
$(srcdir)/linux-src/arch/$(asm_syntax)/lib/,\
$(arch-lib-srcs) $(arch-lib-srcs:.c=.S))))
@@ -87,7 +105,7 @@ target = pfinet
include ../Makeconf
-vpath %.c $(addprefix $(srcdir)/linux-src/net/,core ethernet ipv4)
+vpath %.c $(addprefix $(srcdir)/linux-src/net/,core ethernet ipv4 ipv6)
vpath %.c $(srcdir)/linux-src/arch/$(asm_syntax)/lib
vpath %.S $(srcdir)/linux-src/arch/$(asm_syntax)/lib
diff --git a/pfinet/config.h b/pfinet/config.h
index ce079620..95ac0f43 100644
--- a/pfinet/config.h
+++ b/pfinet/config.h
@@ -7,6 +7,7 @@
#define CONFIG_NET 1
#define CONFIG_INET 1
+#define CONFIG_IPV6 1
#undef CONFIG_IPX
#undef CONFIG_ATALK
@@ -34,3 +35,6 @@
#define CONFIG_SKB_LARGE 1
#define CONFIG_IP_NOSIOCRT 1 /* How convenient. */
+
+#define CONFIG_IPV6_EUI64 1
+#undef CONFIG_IPV6_NO_PB
diff --git a/pfinet/ethernet.c b/pfinet/ethernet.c
index 940b78c2..07dc4d59 100644
--- a/pfinet/ethernet.c
+++ b/pfinet/ethernet.c
@@ -119,7 +119,7 @@ ethernet_demuxer (mach_msg_header_t *inp,
__mutex_lock (&net_bh_lock);
skb = alloc_skb (datalen, GFP_ATOMIC);
- skb->len = datalen;
+ skb_put (skb, datalen);
skb->dev = dev;
/* Copy the two parts of the frame into the buffer. */
diff --git a/pfinet/glue-include/linux/in6.h b/pfinet/glue-include/linux/in6.h
index 260020a6..c3e5dfc4 100644
--- a/pfinet/glue-include/linux/in6.h
+++ b/pfinet/glue-include/linux/in6.h
@@ -1 +1,110 @@
+#ifndef GLUE_LINUX_IN6_H
+#define GLUE_LINUX_IN6_H 1
+
#include <netinet/in.h>
+
+#if 0
+struct ipv6_mreq {
+ /* IPv6 multicast address of group */
+ struct in6_addr ipv6mr_multiaddr;
+
+ /* local IPv6 address of interface */
+ int ipv6mr_ifindex;
+};
+#endif
+
+/* In Linux's struct ipv6_mreq the second member is called ipv6mr_ifindex,
+ * however it's called ipv6mr_interface in ours.
+ */
+#define ipv6mr_ifindex ipv6mr_interface
+
+struct in6_flowlabel_req
+{
+ struct in6_addr flr_dst;
+ __u32 flr_label;
+ __u8 flr_action;
+ __u8 flr_share;
+ __u16 flr_flags;
+ __u16 flr_expires;
+ __u16 flr_linger;
+ __u32 __flr_pad;
+ /* Options in format of IPV6_PKTOPTIONS */
+};
+
+#define IPV6_FL_A_GET 0
+#define IPV6_FL_A_PUT 1
+#define IPV6_FL_A_RENEW 2
+
+#define IPV6_FL_F_CREATE 1
+#define IPV6_FL_F_EXCL 2
+
+#define IPV6_FL_S_NONE 0
+#define IPV6_FL_S_EXCL 1
+#define IPV6_FL_S_PROCESS 2
+#define IPV6_FL_S_USER 3
+#define IPV6_FL_S_ANY 255
+
+
+/*
+ * Bitmask constant declarations to help applications select out the
+ * flow label and priority fields.
+ *
+ * Note that this are in host byte order while the flowinfo field of
+ * sockaddr_in6 is in network byte order.
+ */
+
+#define IPV6_FLOWINFO_FLOWLABEL 0x000fffff
+#define IPV6_FLOWINFO_PRIORITY 0x0ff00000
+
+/* These defintions are obsolete */
+#define IPV6_PRIORITY_UNCHARACTERIZED 0x0000
+#define IPV6_PRIORITY_FILLER 0x0100
+#define IPV6_PRIORITY_UNATTENDED 0x0200
+#define IPV6_PRIORITY_RESERVED1 0x0300
+#define IPV6_PRIORITY_BULK 0x0400
+#define IPV6_PRIORITY_RESERVED2 0x0500
+#define IPV6_PRIORITY_INTERACTIVE 0x0600
+#define IPV6_PRIORITY_CONTROL 0x0700
+#define IPV6_PRIORITY_8 0x0800
+#define IPV6_PRIORITY_9 0x0900
+#define IPV6_PRIORITY_10 0x0a00
+#define IPV6_PRIORITY_11 0x0b00
+#define IPV6_PRIORITY_12 0x0c00
+#define IPV6_PRIORITY_13 0x0d00
+#define IPV6_PRIORITY_14 0x0e00
+#define IPV6_PRIORITY_15 0x0f00
+
+/*
+ * IPv6 TLV options.
+ */
+#define IPV6_TLV_PAD0 0
+#define IPV6_TLV_PADN 1
+#define IPV6_TLV_ROUTERALERT 20
+#define IPV6_TLV_JUMBO 194
+
+/*
+ * IPV6 socket options
+ */
+
+#define IPV6_ADDRFORM 1
+#define IPV6_PKTINFO 2
+#define IPV6_HOPOPTS 3
+#define IPV6_DSTOPTS 4
+#define IPV6_RTHDR 5
+#define IPV6_PKTOPTIONS 6
+#define IPV6_CHECKSUM 7
+#define IPV6_HOPLIMIT 8
+#define IPV6_NEXTHOP 9
+#define IPV6_AUTHHDR 10
+#define IPV6_FLOWINFO 11
+
+/* IPV6_MTU_DISCOVER values */
+#define IPV6_PMTUDISC_DONT 0
+#define IPV6_PMTUDISC_WANT 1
+#define IPV6_PMTUDISC_DO 2
+
+/* Flowlabel */
+#define IPV6_FLOWLABEL_MGR 32
+#define IPV6_FLOWINFO_SEND 33
+
+#endif /* not GLUE_LINUX_IN6_H */
diff --git a/pfinet/glue-include/linux/ipv6.h b/pfinet/glue-include/linux/ipv6.h
index 374f9b1e..5a1604a3 100644
--- a/pfinet/glue-include/linux/ipv6.h
+++ b/pfinet/glue-include/linux/ipv6.h
@@ -1 +1,117 @@
+#ifndef _IPV6_H
+#define _IPV6_H
+
#include <linux/in6.h>
+#include <asm/byteorder.h>
+
+/* The latest drafts declared increase in minimal mtu up to 1280. */
+
+#define IPV6_MIN_MTU 1280
+
+/*
+ * Advanced API
+ * source interface/address selection, source routing, etc...
+ * *under construction*
+ */
+
+
+struct in6_ifreq {
+ struct in6_addr ifr6_addr;
+ __u32 ifr6_prefixlen;
+ int ifr6_ifindex;
+};
+
+#define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */
+#define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */
+
+/*
+ * routing header
+ */
+struct ipv6_rt_hdr {
+ __u8 nexthdr;
+ __u8 hdrlen;
+ __u8 type;
+ __u8 segments_left;
+
+ /*
+ * type specific data
+ * variable length field
+ */
+};
+
+
+struct ipv6_opt_hdr {
+ __u8 nexthdr;
+ __u8 hdrlen;
+ /*
+ * TLV encoded option data follows.
+ */
+};
+
+#define ipv6_destopt_hdr ipv6_opt_hdr
+#define ipv6_hopopt_hdr ipv6_opt_hdr
+
+#ifdef __KERNEL__
+#define ipv6_optlen(p) (((p)->hdrlen+1) << 3)
+#endif
+
+/*
+ * routing header type 0 (used in cmsghdr struct)
+ */
+
+struct rt0_hdr {
+ struct ipv6_rt_hdr rt_hdr;
+ __u32 bitmap; /* strict/loose bit map */
+ struct in6_addr addr[0];
+
+#define rt0_type rt_hdr.type;
+};
+
+/*
+ * IPv6 fixed header
+ *
+ * BEWARE, it is incorrect. The first 4 bits of flow_lbl
+ * are glued to priority now, forming "class".
+ */
+
+struct ipv6hdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 priority:4,
+ version:4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 version:4,
+ priority:4;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __u8 flow_lbl[3];
+
+ __u16 payload_len;
+ __u8 nexthdr;
+ __u8 hop_limit;
+
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+};
+
+#ifdef __KERNEL__
+
+/*
+ This structure contains results of exthdrs parsing
+ as offsets from skb->nh.
+ */
+
+struct inet6_skb_parm
+{
+ int iif;
+ __u16 ra;
+ __u16 hop;
+ __u16 auth;
+ __u16 dst0;
+ __u16 srcrt;
+ __u16 dst1;
+};
+
+#endif
+
+#endif
diff --git a/pfinet/glue-include/linux/socket.h b/pfinet/glue-include/linux/socket.h
index bf37f490..82806d9d 100644
--- a/pfinet/glue-include/linux/socket.h
+++ b/pfinet/glue-include/linux/socket.h
@@ -22,6 +22,8 @@
#define SOL_IP IPPROTO_IP
#define SOL_TCP IPPROTO_TCP
+#define SOL_IPV6 IPPROTO_IPV6
+#define SOL_ICMPV6 IPPROTO_ICMPV6
#define SOL_RAW IPPROTO_RAW
/* IP options */
diff --git a/pfinet/linux-src/net/ipv6/addrconf.c b/pfinet/linux-src/net/ipv6/addrconf.c
index f8428bd8..7fbf4061 100644
--- a/pfinet/linux-src/net/ipv6/addrconf.c
+++ b/pfinet/linux-src/net/ipv6/addrconf.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: addrconf.c,v 1.1 2007/10/08 21:12:30 stesie Exp $
+ * $Id: addrconf.c,v 1.2 2007/10/08 21:59:10 stesie Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -247,7 +247,10 @@ static struct inet6_dev * ipv6_add_dev(struct device *dev)
return ndev;
}
-static struct inet6_dev * ipv6_find_idev(struct device *dev)
+#ifndef _HURD_
+static
+#endif
+struct inet6_dev * ipv6_find_idev(struct device *dev)
{
struct inet6_dev *idev;
@@ -808,6 +811,7 @@ ok:
}
}
+#ifndef _HURD_
/*
* Set destination address.
* Special case for SIT interfaces where we create a new "virtual"
@@ -865,11 +869,15 @@ err_exit:
rtnl_unlock();
return err;
}
+#endif /* not _HURD_ */
/*
* Manual configuration of address on an interface
*/
-static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
+#ifndef _HURD_
+static
+#endif
+int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
{
struct inet6_ifaddr *ifp;
struct inet6_dev *idev;
@@ -900,7 +908,10 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
return -ENOBUFS;
}
-static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
+#ifndef _HURD_
+static
+#endif
+int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
{
struct inet6_ifaddr *ifp;
struct inet6_dev *idev;
@@ -932,6 +943,7 @@ static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
}
+#ifndef _HURD_
int addrconf_add_ifaddr(void *arg)
{
struct in6_ifreq ireq;
@@ -948,7 +960,9 @@ int addrconf_add_ifaddr(void *arg)
rtnl_unlock();
return err;
}
+#endif /* not _HURD_ */
+#ifndef _HURD_
int addrconf_del_ifaddr(void *arg)
{
struct in6_ifreq ireq;
@@ -965,6 +979,7 @@ int addrconf_del_ifaddr(void *arg)
rtnl_unlock();
return err;
}
+#endif /* not _HURD_ */
static void sit_add_v4_addrs(struct inet6_dev *idev)
{
diff --git a/pfinet/linux-src/net/ipv6/af_inet6.c b/pfinet/linux-src/net/ipv6/af_inet6.c
index 4ad6403c..9077c0f1 100644
--- a/pfinet/linux-src/net/ipv6/af_inet6.c
+++ b/pfinet/linux-src/net/ipv6/af_inet6.c
@@ -7,7 +7,7 @@
*
* Adapted from linux/net/ipv4/af_inet.c
*
- * $Id: af_inet6.c,v 1.1 2007/10/08 21:12:30 stesie Exp $
+ * $Id: af_inet6.c,v 1.2 2007/10/08 21:59:10 stesie Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -337,6 +337,10 @@ static int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
return(0);
}
+#ifdef _HURD_
+#define inet6_ioctl 0
+#else
+
static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
@@ -396,6 +400,8 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return(0);
}
+#endif /* not _HURD_ */
+
struct proto_ops inet6_stream_ops = {
PF_INET6,
@@ -542,7 +548,9 @@ __initfunc(void inet6_proto_init(struct net_proto *pro))
ip6_route_init();
ip6_flowlabel_init();
addrconf_init();
+#ifndef _HURD_
sit_init();
+#endif
/* Init v6 transport protocols. */
udpv6_init();
diff --git a/pfinet/linux-src/net/ipv6/icmpv6.c b/pfinet/linux-src/net/ipv6/icmpv6.c
index de5e7780..62dd149f 100644
--- a/pfinet/linux-src/net/ipv6/icmpv6.c
+++ b/pfinet/linux-src/net/ipv6/icmpv6.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: icmpv6.c,v 1.1 2007/10/08 21:12:30 stesie Exp $
+ * $Id: icmpv6.c,v 1.2 2007/10/08 21:59:10 stesie Exp $
*
* Based on net/ipv4/icmp.c
*
@@ -499,6 +499,7 @@ int icmpv6_rcv(struct sk_buff *skb, unsigned long len)
}
default:
/* CHECKSUM_UNNECESSARY */
+ break;
};
/*
@@ -600,8 +601,10 @@ int __init icmpv6_init(struct net_proto_family *ops)
"Failed to create the ICMP6 control socket.\n");
return -1;
}
+#ifndef _HURD_
icmpv6_socket->inode->i_uid = 0;
icmpv6_socket->inode->i_gid = 0;
+#endif
icmpv6_socket->type = SOCK_RAW;
if ((err = ops->create(icmpv6_socket, IPPROTO_ICMPV6)) < 0) {
diff --git a/pfinet/linux-src/net/ipv6/ip6_fib.c b/pfinet/linux-src/net/ipv6/ip6_fib.c
index 69735248..18df5c38 100644
--- a/pfinet/linux-src/net/ipv6/ip6_fib.c
+++ b/pfinet/linux-src/net/ipv6/ip6_fib.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: ip6_fib.c,v 1.1 2007/10/08 21:12:30 stesie Exp $
+ * $Id: ip6_fib.c,v 1.2 2007/10/08 21:59:10 stesie Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -36,7 +36,7 @@
#undef CONFIG_IPV6_SUBTREES
#if RT6_DEBUG >= 1
-#define BUG_TRAP(x) ({ if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); } })
+#define BUG_TRAP(x) ({ if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):%s\n", __LINE__, __FUNCTION__); } })
#else
#define BUG_TRAP(x) do { ; } while (0)
#endif
@@ -94,7 +94,7 @@ static struct timer_list ip6_fib_timer = {
fib6_run_gc
};
-static struct fib6_walker_t fib6_walker_list = {
+struct fib6_walker_t fib6_walker_list = {
&fib6_walker_list, &fib6_walker_list,
};
diff --git a/pfinet/linux-src/net/ipv6/ip6_flowlabel.c b/pfinet/linux-src/net/ipv6/ip6_flowlabel.c
index 9aa60db4..4a34b878 100644
--- a/pfinet/linux-src/net/ipv6/ip6_flowlabel.c
+++ b/pfinet/linux-src/net/ipv6/ip6_flowlabel.c
@@ -340,8 +340,15 @@ fl_create(struct in6_flowlabel_req *freq, char *optval, int optlen, int *err_p)
fl->owner = current->pid;
break;
case IPV6_FL_S_USER:
+#ifdef _HURD_
+ /* FIXME
+ * Which euid shall be assigned? Where to get it,
+ * `struct task_struct' doesn't have a `euid'.
+ */
+#else
fl->owner = current->euid;
break;
+#endif
default:
err = -EINVAL;
goto done;
diff --git a/pfinet/linux-src/net/ipv6/mcast.c b/pfinet/linux-src/net/ipv6/mcast.c
index 27d1d316..87e9e909 100644
--- a/pfinet/linux-src/net/ipv6/mcast.c
+++ b/pfinet/linux-src/net/ipv6/mcast.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: mcast.c,v 1.1 2007/10/08 21:12:30 stesie Exp $
+ * $Id: mcast.c,v 1.2 2007/10/08 21:59:10 stesie Exp $
*
* Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c
*
@@ -671,8 +671,10 @@ __initfunc(int igmp6_init(struct net_proto_family *ops))
"Failed to create the IGMP6 control socket.\n");
return -1;
}
+#ifndef _HURD_
igmp6_socket->inode->i_uid = 0;
igmp6_socket->inode->i_gid = 0;
+#endif
igmp6_socket->type = SOCK_RAW;
if((err = ops->create(igmp6_socket, IPPROTO_ICMPV6)) < 0) {
diff --git a/pfinet/linux-src/net/ipv6/ndisc.c b/pfinet/linux-src/net/ipv6/ndisc.c
index bb5e0837..3b3d3f4e 100644
--- a/pfinet/linux-src/net/ipv6/ndisc.c
+++ b/pfinet/linux-src/net/ipv6/ndisc.c
@@ -1164,8 +1164,10 @@ __initfunc(int ndisc_init(struct net_proto_family *ops))
"Failed to create the NDISC control socket.\n");
return -1;
}
+#ifndef _HURD_
ndisc_socket->inode->i_uid = 0;
ndisc_socket->inode->i_gid = 0;
+#endif
ndisc_socket->type = SOCK_RAW;
if((err = ops->create(ndisc_socket, IPPROTO_ICMPV6)) < 0) {
diff --git a/pfinet/linux-src/net/ipv6/route_ipv6.c b/pfinet/linux-src/net/ipv6/route_ipv6.c
index c34a3b5d..5f79a226 100644
--- a/pfinet/linux-src/net/ipv6/route_ipv6.c
+++ b/pfinet/linux-src/net/ipv6/route_ipv6.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: route_ipv6.c,v 1.1 2007/10/08 21:12:31 stesie Exp $
+ * $Id: route_ipv6.c,v 1.2 2007/10/08 21:59:10 stesie Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -1156,6 +1156,7 @@ restart:
}
}
+#ifndef _HURD_
int ipv6_route_ioctl(unsigned int cmd, void *arg)
{
struct in6_rtmsg rtmsg;
@@ -1194,6 +1195,7 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg)
return -EINVAL;
}
+#endif /* not _HURD_ */
/*
* Drop the packet on the floor
diff --git a/pfinet/linux-src/net/ipv6/tcp_ipv6.c b/pfinet/linux-src/net/ipv6/tcp_ipv6.c
index e9d1d079..85a5ab27 100644
--- a/pfinet/linux-src/net/ipv6/tcp_ipv6.c
+++ b/pfinet/linux-src/net/ipv6/tcp_ipv6.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: tcp_ipv6.c,v 1.1 2007/10/08 21:12:31 stesie Exp $
+ * $Id: tcp_ipv6.c,v 1.2 2007/10/08 21:59:10 stesie Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
@@ -103,7 +103,10 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
if (tb->port == rover)
goto next;
break;
+
next:
+ (void) 0;
+
} while (--remaining > 0);
tcp_port_rover = rover;
@@ -1426,6 +1429,7 @@ int tcp_v6_rcv(struct sk_buff *skb, unsigned long len)
}
default:
/* CHECKSUM_UNNECESSARY */
+ break;
};
if((th->doff * 4) < sizeof(struct tcphdr) ||
diff --git a/pfinet/linux-src/net/ipv6/udp_ipv6.c b/pfinet/linux-src/net/ipv6/udp_ipv6.c
index 377f5751..57b5db1a 100644
--- a/pfinet/linux-src/net/ipv6/udp_ipv6.c
+++ b/pfinet/linux-src/net/ipv6/udp_ipv6.c
@@ -7,7 +7,7 @@
*
* Based on linux/ipv4/udp.c
*
- * $Id: udp_ipv6.c,v 1.1 2007/10/08 21:12:31 stesie Exp $
+ * $Id: udp_ipv6.c,v 1.2 2007/10/08 21:59:10 stesie Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -79,7 +79,9 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum)
} while ((sk = sk->next) != NULL);
best_size_so_far = size;
best = result;
+
next:
+ (void) 0;
}
result = best;
for(;; result += UDP_HTABLE_SIZE) {
@@ -890,6 +892,10 @@ static struct inet6_protocol udpv6_protocol =
"UDPv6" /* name */
};
+#ifdef _HURD_
+#define udp_ioctl 0
+#endif
+
struct proto udpv6_prot = {
(struct sock *)&udpv6_prot, /* sklist_next */
(struct sock *)&udpv6_prot, /* sklist_prev */
diff --git a/pfinet/main.c b/pfinet/main.c
index 9337b27a..c1e080a6 100644
--- a/pfinet/main.c
+++ b/pfinet/main.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1995,96,97,99,2000,02 Free Software Foundation, Inc.
+ Copyright (C) 1995,96,97,99,2000,02,07 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -29,24 +29,40 @@
#include <fcntl.h>
#include <version.h>
+/* Include Hurd's errno.h file, but don't include glue-include/hurd/errno.h,
+ since it #undef's the errno macro. */
+#define _HACK_ERRNO_H
+#include <errno.h>
+
#include <linux/netdevice.h>
#include <linux/inet.h>
+static void pfinet_activate_ipv6 (void);
+
/* devinet.c */
extern error_t configure_device (struct device *dev,
uint32_t addr, uint32_t netmask,
uint32_t peer, uint32_t broadcast);
+/* addrconf.c */
+extern int addrconf_notify(struct notifier_block *this, unsigned long event,
+ void * data);
+
int trivfs_fstype = FSTYPE_MISC;
int trivfs_fsid;
int trivfs_support_read = 1;
int trivfs_support_write = 1;
int trivfs_support_exec = 0;
int trivfs_allow_open = O_READ | O_WRITE;
-struct port_class *trivfs_protid_portclasses[1];
-int trivfs_protid_nportclasses = 1;
-struct port_class *trivfs_cntl_portclasses[1];
-int trivfs_cntl_nportclasses = 1;
+
+struct port_class *trivfs_protid_portclasses[2];
+int trivfs_protid_nportclasses = 2;
+
+struct port_class *trivfs_cntl_portclasses[2];
+int trivfs_cntl_nportclasses = 2;
+
+/* Which portclass to install on the bootstrap port, default to IPv4. */
+int pfinet_bootstrap_portclass = PORTCLASS_INET;
struct port_class *shutdown_notify_class;
@@ -224,6 +240,7 @@ enumerate_devices (error_t (*fun) (struct device *dev))
extern void sk_init (void), skb_init (void);
extern int net_dev_init (void);
+extern void inet6_proto_init (struct net_proto *pro);
int
main (int argc,
@@ -234,8 +251,6 @@ main (int argc,
struct stat st;
pfinet_bucket = ports_create_bucket ();
- trivfs_protid_portclasses[0] = ports_create_class (trivfs_clean_protid, 0);
- trivfs_cntl_portclasses[0] = ports_create_class (trivfs_clean_cntl, 0);
addrport_class = ports_create_class (clean_addrport, 0);
socketport_class = ports_create_class (clean_socketport, 0);
trivfs_fsid = getpid ();
@@ -276,36 +291,59 @@ main (int argc,
(And when not sucessful, it never returns.) */
argp_parse (&pfinet_argp, argc, argv, 0,0,0);
- /* Ask init to tell us when the system is going down,
- so we can try to be friendly to our correspondents on the network. */
- arrange_shutdown_notification ();
-
- /* Talk to parent and link us in. */
task_get_bootstrap_port (mach_task_self (), &bootstrap);
- if (bootstrap == MACH_PORT_NULL)
- error (1, 0, "Must be started as a translator");
- err = trivfs_startup (bootstrap, 0,
- trivfs_cntl_portclasses[0], pfinet_bucket,
- trivfs_protid_portclasses[0], pfinet_bucket,
- &pfinetctl);
+ pfinet_owner = pfinet_group = 0;
- if (err)
- error (1, err, "contacting parent");
+ if (bootstrap != MACH_PORT_NULL) {
+ /* Create portclass to install on the bootstrap port. */
+ if(trivfs_protid_portclasses[pfinet_bootstrap_portclass]
+ != MACH_PORT_NULL)
+ error(1, 0, "No portclass left to assign to bootstrap port");
- /* Initialize status from underlying node. */
- err = io_stat (pfinetctl->underlying, &st);
- if (err)
- {
- /* We cannot stat the underlying node. Fallback to the defaults. */
- pfinet_owner = pfinet_group = 0;
- err = 0;
- }
- else
- {
- pfinet_owner = st.st_uid;
- pfinet_group = st.st_gid;
- }
+#ifdef CONFIG_IPV6
+ if (pfinet_bootstrap_portclass == PORTCLASS_INET6)
+ pfinet_activate_ipv6 ();
+#endif
+
+ trivfs_protid_portclasses[pfinet_bootstrap_portclass] =
+ ports_create_class (trivfs_clean_protid, 0);
+ trivfs_cntl_portclasses[pfinet_bootstrap_portclass] =
+ ports_create_class (trivfs_clean_cntl, 0);
+
+ /* Talk to parent and link us in. */
+ err = trivfs_startup (bootstrap, 0,
+ trivfs_cntl_portclasses[pfinet_bootstrap_portclass],
+ pfinet_bucket, trivfs_protid_portclasses
+ [pfinet_bootstrap_portclass], pfinet_bucket,
+ &pfinetctl);
+
+ if (err)
+ error (1, err, "contacting parent");
+
+ /* Initialize status from underlying node. */
+ err = io_stat (pfinetctl->underlying, &st);
+ if (! err)
+ {
+ pfinet_owner = st.st_uid;
+ pfinet_group = st.st_gid;
+ }
+ }
+ else { /* no bootstrap port. */
+ int i;
+ /* Check that at least one portclass has been bound,
+ error out otherwise. */
+ for (i = 0; i < trivfs_protid_nportclasses; i ++)
+ if (trivfs_protid_portclasses[i] != MACH_PORT_NULL)
+ break;
+
+ if (i == trivfs_protid_nportclasses)
+ error (1, 0, "should be started as a translator.\n");
+ }
+
+ /* Ask init to tell us when the system is going down,
+ so we can try to be friendly to our correspondents on the network. */
+ arrange_shutdown_notification ();
/* Launch */
ports_manage_port_operations_multithread (pfinet_bucket,
@@ -314,6 +352,76 @@ main (int argc,
return 0;
}
+#ifdef CONFIG_IPV6
+static void
+pfinet_activate_ipv6 (void)
+{
+ inet6_proto_init (0);
+
+ /* Since we're registering the protocol after the devices have been
+ initialized, we need to care for the linking by ourselves. */
+ struct device *dev = dev_base;
+
+ if (dev)
+ do
+ {
+ if (!(dev->flags & IFF_UP))
+ continue;
+
+ addrconf_notify (NULL, NETDEV_REGISTER, dev);
+ addrconf_notify (NULL, NETDEV_UP, dev);
+ }
+ while ((dev = dev->next));
+}
+#endif /* CONFIG_IPV6 */
+
+void
+pfinet_bind (int portclass, const char *name)
+{
+ struct trivfs_control *cntl;
+ error_t err = 0;
+ mach_port_t right;
+ file_t file = file_name_lookup (name, O_CREAT|O_NOTRANS, 0666);
+
+ if (file == MACH_PORT_NULL)
+ err = errno;
+
+ if (! err) {
+ if (trivfs_protid_portclasses[portclass] != MACH_PORT_NULL)
+ error (1, 0, "Cannot bind one protocol to multiple nodes.\n");
+
+#ifdef CONFIG_IPV6
+ if (portclass == PORTCLASS_INET6)
+ pfinet_activate_ipv6 ();
+#endif
+
+ trivfs_protid_portclasses[portclass] =
+ ports_create_class (trivfs_clean_protid, 0);
+ trivfs_cntl_portclasses[portclass] =
+ ports_create_class (trivfs_clean_cntl, 0);
+
+ err = trivfs_create_control (file, trivfs_cntl_portclasses[portclass],
+ pfinet_bucket,
+ trivfs_protid_portclasses[portclass],
+ pfinet_bucket, &cntl);
+ }
+
+ if (! err)
+ {
+ right = ports_get_send_right (cntl);
+ err = file_set_translator (file, 0, FS_TRANS_EXCL | FS_TRANS_SET,
+ 0, 0, 0, right, MACH_MSG_TYPE_COPY_SEND);
+ mach_port_deallocate (mach_task_self (), right);
+ }
+
+ if (err)
+ error (1, err, name);
+
+ ports_port_deref (cntl);
+
+}
+
+
void
trivfs_modify_stat (struct trivfs_protid *cred,
struct stat *st)
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;
diff --git a/pfinet/pfinet.h b/pfinet/pfinet.h
index c5f53182..dbb8ed3a 100644
--- a/pfinet/pfinet.h
+++ b/pfinet/pfinet.h
@@ -92,4 +92,22 @@ void clean_socketport (void *);
typedef struct sock_user *sock_user_t;
typedef struct sock_addr *sock_addr_t;
+/* pfinet6 port classes. */
+enum {
+ PORTCLASS_INET,
+ PORTCLASS_INET6,
+};
+
+extern struct port_class *trivfs_protid_portclasses[];
+extern int trivfs_protid_nportclasses;
+
+extern struct port_class *trivfs_cntl_portclasses[2];
+extern int trivfs_cntl_nportclasses;
+
+/* Which portclass to install on the bootstrap port. */
+extern int pfinet_bootstrap_portclass;
+
+/* Install portclass on node NAME. */
+void pfinet_bind (int portclass, const char *name);
+
#endif
diff --git a/pfinet/socket-ops.c b/pfinet/socket-ops.c
index 77ae3599..baeaad30 100644
--- a/pfinet/socket-ops.c
+++ b/pfinet/socket-ops.c
@@ -1,5 +1,5 @@
/* Interface functions for the socket.defs interface.
- Copyright (C) 1995,96,97,99,2000,02 Free Software Foundation, Inc.
+ Copyright (C) 1995,96,97,99,2000,02,07 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -80,7 +80,11 @@ S_socket_create (struct trivfs_protid *master,
isroot = 1;
}
- err = - (*net_families[PF_INET]->create) (sock, protocol);
+ if (master->pi.class == trivfs_protid_portclasses[PORTCLASS_INET])
+ err = - (*net_families[PF_INET]->create) (sock, protocol);
+ else
+ err = - (*net_families[PF_INET6]->create) (sock, protocol);
+
if (err)
sock_release (sock);
else
@@ -295,7 +299,7 @@ S_socket_create_address (mach_port_t server,
struct sock_addr *addrstruct;
const struct sockaddr *const sa = (void *) data;
- if (sockaddr_type != AF_INET)
+ if (sockaddr_type != AF_INET && sockaddr_type != AF_INET6)
return EAFNOSUPPORT;
if (sa->sa_family != sockaddr_type
|| data_len < offsetof (struct sockaddr, sa_data))