diff options
-rw-r--r-- | pfinet/ChangeLog | 72 | ||||
-rw-r--r-- | pfinet/Makefile | 22 | ||||
-rw-r--r-- | pfinet/config.h | 4 | ||||
-rw-r--r-- | pfinet/ethernet.c | 2 | ||||
-rw-r--r-- | pfinet/glue-include/linux/in6.h | 109 | ||||
-rw-r--r-- | pfinet/glue-include/linux/ipv6.h | 116 | ||||
-rw-r--r-- | pfinet/glue-include/linux/socket.h | 2 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/addrconf.c | 23 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/af_inet6.c | 10 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/icmpv6.c | 5 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/ip6_fib.c | 6 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/ip6_flowlabel.c | 7 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/mcast.c | 4 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/ndisc.c | 2 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/route_ipv6.c | 4 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/tcp_ipv6.c | 6 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv6/udp_ipv6.c | 8 | ||||
-rw-r--r-- | pfinet/main.c | 174 | ||||
-rw-r--r-- | pfinet/options.c | 210 | ||||
-rw-r--r-- | pfinet/pfinet.h | 18 | ||||
-rw-r--r-- | pfinet/socket-ops.c | 10 |
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)) |