diff options
-rw-r--r-- | hurd/ChangeLog | 8 | ||||
-rw-r--r-- | hurd/iioctl.defs | 172 | ||||
-rw-r--r-- | hurd/ioctl_types.h | 4 | ||||
-rw-r--r-- | hurd/pfinet.defs | 46 | ||||
-rw-r--r-- | pfinet/ChangeLog | 46 | ||||
-rw-r--r-- | pfinet/Makefile | 6 | ||||
-rw-r--r-- | pfinet/glue-include/linux/if.h | 4 | ||||
-rw-r--r-- | pfinet/iioctl-ops.c | 369 | ||||
-rw-r--r-- | pfinet/io-ops.c | 28 | ||||
-rw-r--r-- | pfinet/linux-src/net/core/dev.c | 8 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/devinet.c | 15 | ||||
-rw-r--r-- | pfinet/main.c | 31 | ||||
-rw-r--r-- | pfinet/options.c | 13 | ||||
-rw-r--r-- | pfinet/pfinet-ops.c | 93 | ||||
-rw-r--r-- | pfinet/pfinet.h | 9 | ||||
-rw-r--r-- | pfinet/socket-ops.c | 19 |
16 files changed, 816 insertions, 55 deletions
diff --git a/hurd/ChangeLog b/hurd/ChangeLog index 301a80a8..4d621354 100644 --- a/hurd/ChangeLog +++ b/hurd/ChangeLog @@ -1,3 +1,11 @@ +2001-01-07 Marcus Brinkmann <marcus@gnu.org> + + * ioctl_types.h: Include <net/if.h>, define types sockaddr_t and + ifname_t for iioctl.defs. + * iioctl.defs: New file for network interface ioctls. + * pfinet.defs: Remove old RPCs, fix subsystem number, add RPC for + SIOCGIFCONF. + 2000-11-15 Marcus Brinkmann <marcus@gnu.org> * hurd_types.h: Doc fix reported by Neal H Walfield diff --git a/hurd/iioctl.defs b/hurd/iioctl.defs new file mode 100644 index 00000000..42c1ecaa --- /dev/null +++ b/hurd/iioctl.defs @@ -0,0 +1,172 @@ +/* Definitions for interface ioctls + Copyright (C) 2000 Free Software Foundation, Inc. + +This file is part of the GNU Hurd. + +The GNU Hurd is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +The GNU Hurd is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the GNU Hurd; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include <hurd/hurd_types.defs> + +INTR_INTERFACE + +/* Ioctl class `i'; the subsystem is derived from calculations in + <ioctls.h>. */ +subsystem iioctl 112000; /* XXX */ + +import <hurd/ioctl_types.h>; /* XXX */ + +/* This is the first arg for a struct ifreq_something as specified by the + definition of _IOT_ifreq_something in <net/if.h>. */ +type ifname_t = array[16] of char; /* IFNAMSIZ is 16. */ + +/* This is the second arg of struct ifreq as specified by the + definition of _IOT_ifreq in <net/if.h>. */ +type sockaddr_t = struct[16] of char; /* sizeof(struct sockaddr) is 16. */ + +skip; skip; skip; skip; /* 0 1 2 3 unused */ +skip; skip; skip; skip; /* 4 5 6 7 unused */ +skip; skip; skip; skip; /* 8 9 10 11 unused */ + +/* 12 SIOCSIFADDR */ +routine iioctl_siocsifaddr ( + reqport: io_t; + ifnam: ifname_t; + addr: sockaddr_t); + +skip; /* 13 unused */ + +/* 14 SIOCSIFDSTADDR */ +routine iioctl_siocsifdstaddr ( + reqport: io_t; + ifnam: ifname_t; + dstaddr: sockaddr_t); + +skip; /* 15 unused */ + +/* 16 SIOCSIFFLAGS */ +routine iioctl_siocsifflags ( + reqport: io_t; + ifnam: ifname_t; + flags: short); + +/* 17 SIOCGIFFLAGS */ +routine iioctl_siocgifflags ( + reqport: io_t; + inout ifnam: ifname_t; + inout flags: short); + +skip; /* 18 unused */ + +/* 19 SIOCSIFBRDADDR */ +routine iioctl_siocsifbrdaddr ( + reqport: io_t; + ifnam: ifname_t; + brdaddr: sockaddr_t); + +skip; skip; /* 20 21 unused */ + +/* 22 SIOCSIFNETMASK */ +routine iioctl_siocsifnetmask ( + reqport: io_t; + ifnam: ifname_t; + netmask: sockaddr_t); + +/* 23 SIOCGIFMETRIC */ +routine iioctl_siocgifmetric ( + reqport: io_t; + inout ifnam: ifname_t; + inout metric: int); + +/* 24 SIOCSIFMETRIC */ +routine iioctl_siocsifmetric ( + reqport: io_t; + ifnam: ifname_t; + metric: int); + +/* 25 SIOCDIFADDR */ +routine iioctl_siocdifaddr ( + reqport: io_t; + ifnam: ifname_t; + addr: sockaddr_t); + +skip; skip; skip; skip; /* 26 27 28 29 unused */ +skip; skip; skip; /* 30 31 32 unused */ + +/* 33 SIOCGIFADDR */ +routine iioctl_siocgifaddr ( + reqport: io_t; + inout ifnam: ifname_t; + inout addr: sockaddr_t); + +/* 34 SIOCGIFDSTADDR */ +routine iioctl_siocgifdstaddr ( + reqport: io_t; + inout ifnam: ifname_t; + inout dstaddr: sockaddr_t); + +/* 35 SIOCGIFBRDADDR */ +routine iioctl_siocgifbrdaddr ( + reqport: io_t; + inout ifnam: ifname_t; + inout brdaddr: sockaddr_t); + +skip; /* 36 SIOCGIFCONF -- implemented in C library */ + +/* 37 SIOCGIFNETMASK */ +routine iioctl_siocgifnetmask ( + reqport: io_t; + inout ifnam: ifname_t; + inout netmask: sockaddr_t); + +skip; skip; skip; skip; /* 38, 39, 40, 41 unused */ +skip; skip; skip; skip; /* 42, 43, 44, 45 unused */ +skip; skip; skip; skip; /* 46, 47, 48, 49 unused */ +skip; /* 50 unused */ + +/* 51 SIOCGIFMTU */ +routine iioctl_siocgifmtu ( + reqport: io_t; + inout ifnam: ifname_t; + inout mtu: int); + +/* 52 SIOCSIFMTU */ +routine iioctl_siocsifmtu ( + reqport: io_t; + ifnam: ifname_t; + mtu: int); + +skip; skip; skip; skip; /* 53, 54, 55, 56 unused */ +skip; skip; skip; skip; /* 57, 58, 59, 60 unused */ +skip; skip; skip; skip; /* 61, 62, 63, 64 unused */ +skip; skip; skip; skip; /* 65, 66, 67, 68 unused */ +skip; skip; skip; skip; /* 69, 70, 71, 72 unused */ +skip; skip; skip; skip; /* 73, 74, 75, 76 unused */ +skip; skip; skip; skip; /* 77, 78, 79, 80 unused */ +skip; skip; skip; skip; /* 81, 82, 83, 84 unused */ +skip; skip; skip; skip; /* 85, 86, 87, 88 unused */ +skip; /* 89 unused */ + +/* 90 SIOCGIFINDEX */ +routine iioctl_siocgifindex ( + reqport: io_t; + inout ifnam: ifname_t; + inout index: int); + +/* 91 SIOCGIFNAME */ +routine iioctl_siocgifname ( + reqport: io_t; + inout ifnam: ifname_t; + inout index: int); diff --git a/hurd/ioctl_types.h b/hurd/ioctl_types.h index 01a1e2e6..8baa3604 100644 --- a/hurd/ioctl_types.h +++ b/hurd/ioctl_types.h @@ -26,4 +26,8 @@ typedef cc_t ccs_t[NCCS]; #include <sys/ioctl.h> typedef struct winsize winsize_t; +#include <net/if.h> +typedef struct sockaddr sockaddr_t; +typedef char ifname_t[16]; + #endif /* hurd/ioctl_types.h */ diff --git a/hurd/pfinet.defs b/hurd/pfinet.defs index abaf14d8..669e3f7a 100644 --- a/hurd/pfinet.defs +++ b/hurd/pfinet.defs @@ -1,5 +1,5 @@ /* Definitions for pfinet-specific calls - Copyright (C) 1999 Free Software Foundation + Copyright (C) 1999, 2000 Free Software Foundation This file is part of the GNU Hurd. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with the GNU Hurd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -subsystem pfinet 21000; +subsystem pfinet 37000; #include <hurd/hurd_types.defs> @@ -27,35 +27,13 @@ SOCKET_IMPORTS INTR_INTERFACE - -/* Register a new interface. This call is made on the main socket - rendezvous port (/servers/socket/pfinet). */ -routine pfinet_register_interface ( - server: pf_t; - name: string_t; - address: int; /* in net byte order */ - network: int; /* in net byte order */ - mask: int; /* in net byte order */ - broadcast: int; /* in net byte order */ - mac_hdr_len: int; - xmit: mach_port_send_t; - out recv: mach_port_send_t); - -/* Process an incoming packet. This is made on the RECVXMIT port returned - by a previous call to pfinet_register_interface. */ -simpleroutine pfinet_recv ( - rx: mach_port_t; - packet: data_t); - -/* Sent by pfinet TO an interface for each packet that needs to be sent. - The first mac_hdr_len bytes of the buffer are unfilled; the actual - IP packet begins that many bytes in. */ -simpleroutine pfinet_xmit ( - tx: mach_port_t; - is_broadcast: int; - packet: data_t); - - - - - +/* Return a list of interfaces as expected by the SIOCGIFCONF ioctl. + The maximum number of bytes returned can be given in AMOUNT, but if + AMOUNT is negative, all interfaces will be returned. Always + succeeds (and interface list will be truncated to fit into AMOUNT + space) for BSD compatibility. */ +routine pfinet_siocgifconf ( + port: io_t; + amount: int; + out buf: data_t, dealloc +); diff --git a/pfinet/ChangeLog b/pfinet/ChangeLog index 1f18a849..a848cf18 100644 --- a/pfinet/ChangeLog +++ b/pfinet/ChangeLog @@ -1,3 +1,49 @@ +2001-01-07 Marcus Brinkmann <marcus@gnu.org> + + * pfinet-ops.c: New file to implement hurd/pfinet.defs. + + * iioctl-ops.c: New file to implement iioctl.defs. + * linux-src/net/core/dev.c: If _HURD_, don't define netdev_chain as + static. + + * glue-include/linux/if.h: New file, to avoid conflict between + <net/if.h> (imported by iioctl.defs) and linux version of it. + + * main.c (pfinet_demuxer): Prototype pfinet_server and + iioctl_server, use them. + + * pfinet.h: New global variables pfinetctl, pfinet_owner + and pfinet_group. + * main.c (main): New variable ST. Request pfinetctl from + trivfs_startup. Use it to determine the owner and group + of the underlying node. + * io-ops.c (S_io_reauthenticate): New index variable j. Set + newuser->isroot also for owners of the underlying file and + group owners. + (S_io_restrict_auth): Likewise. + * socket-ops.c: Include <sys/stat.h> and <hurd/fshelp.h>. + (S_socket_create): New variable isroot. If master->isroot is + not set, use fshelp_isowner to check ownership and if to set it. + Pass isroot to make_sock_user instead master->isroot. + + * linux-src/net/ipv4/devinet.c (configure_device): Accept new parameter + BROADCAST, set ifa_broadcast if this is not INADDR_NONE. + (inquire_device): Accept new parameter broadcast, set it. + * main.c: Add new paramter to prototype of configure_device. + (main): Add new parameter to call to configure_device. + * options.c: Add new parameters to prototypes of configure_device + and inquire_device. + (trivfs_append_args): Define new variable BROAD, use its address + as the new parameter for inquire_device. + + * linux-src/net/core/dev.c (dev_ifconf): Don't declare static + if _HURD_. + * linux-src/net/ipv4/devinet.c (inet_gifconf): If _HURD_, set + sin_len member. + + * Makefile (MIGSRCS): Add pfinetServer.c and iioctlServer.c. + (SRCS): Add pfinet-ops.c, iioctl-ops.c. + 2001-01-03 Marcus Brinkmann <marcus@gnu.org> * options.c (parse_opt): Set err to 0 if it was ESRCH. diff --git a/pfinet/Makefile b/pfinet/Makefile index 5f086559..3343b050 100644 --- a/pfinet/Makefile +++ b/pfinet/Makefile @@ -61,8 +61,10 @@ ipv4-srcs := af_inet.c \ LINUXSRCS = $(core-srcs) $(ethernet-srcs) $(ipv4-srcs) $(arch-lib-srcs) SRCS = sched.c timer-emul.c socket.c main.c ethernet.c \ io-ops.c socket-ops.c misc.c time.c options.c loopback.c \ - kmem_cache.c stubs.c dummy.c tunnel.c -MIGSRCS = ioServer.c socketServer.c startup_notifyServer.c + kmem_cache.c stubs.c dummy.c tunnel.c pfinet-ops.c \ + iioctl-ops.c +MIGSRCS = ioServer.c socketServer.c startup_notifyServer.c \ + pfinetServer.c iioctlServer.c OBJS := $(patsubst %.c,%.o,$(LINUXSRCS) $(SRCS) $(MIGSRCS)) LCLHDRS = config.h mapped-time.h mutations.h pfinet.h LINUXHDRS = arp.h datalink.h eth.h icmp.h ip.h ipx.h ipxcall.h p8022.h \ diff --git a/pfinet/glue-include/linux/if.h b/pfinet/glue-include/linux/if.h new file mode 100644 index 00000000..86ee83b2 --- /dev/null +++ b/pfinet/glue-include/linux/if.h @@ -0,0 +1,4 @@ +#include <net/if.h> + +#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ALLMULTI) +#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ diff --git a/pfinet/iioctl-ops.c b/pfinet/iioctl-ops.c new file mode 100644 index 00000000..0f82f622 --- /dev/null +++ b/pfinet/iioctl-ops.c @@ -0,0 +1,369 @@ +/* + Copyright (C) 2000 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "pfinet.h" + +#include <linux/netdevice.h> +#include <linux/notifier.h> + +#include "iioctl_S.h" +#include <netinet/in.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <mach/notify.h> +#include <sys/mman.h> +#include <hurd/fshelp.h> + +#include <sys/ioctl.h> +#include <net/if.h> + +extern struct notifier_block *netdev_chain; + +/* devinet.c */ +extern error_t configure_device (struct device *dev, uint32_t addr, + uint32_t netmask, uint32_t peer, + uint32_t broadcast); +extern void inquire_device (struct device *dev, uint32_t *addr, + uint32_t *netmask, uint32_t *peer, + uint32_t *broadcast); + +/* Truncate name, take the global lock and find device with this name. */ +struct device *get_dev (char *name) +{ + char ifname[16]; + struct device *dev; + + memcpy (ifname, name, IFNAMSIZ-1); + ifname[IFNAMSIZ-1] = 0; + + __mutex_lock (&global_lock); + + for (dev = dev_base; dev; dev = dev->next) + if (strcmp (dev->name, ifname) == 0) + break; + + return dev; +} + +enum siocgif_type +{ + ADDR, + NETMASK, + DSTADDR, + BRDADDR +}; + +#define SIOCGIF(name, type) \ + kern_return_t \ + S_iioctl_siocgif##name (io_t port, \ + ifname_t ifnam, \ + sockaddr_t *addr) \ + { \ + return siocgifXaddr (port, ifnam, addr, type); \ + } + +/* Get some sockaddr type of info. */ +static kern_return_t +siocgifXaddr (io_t port, + ifname_t ifnam, + sockaddr_t *addr, + enum siocgif_type type) +{ + error_t err = 0; + struct device *dev; + struct sockaddr_in *sin = (struct sockaddr_in *) addr; + uint32_t addrs[4]; + + if (!port) + return EOPNOTSUPP; + + dev = get_dev (ifnam); + if (!dev) + err = ENODEV; + else + { + sin->sin_family = AF_INET; + + inquire_device (dev, &addrs[0], &addrs[1], &addrs[2], &addrs[3]); + sin->sin_addr.s_addr = addrs[type]; + } + __mutex_unlock (&global_lock); + return err; +} + +#define SIOCSIF(name, type) \ + kern_return_t \ + S_iioctl_siocsif##name (io_t port, \ + ifname_t ifnam, \ + sockaddr_t addr) \ + { \ + return siocsifXaddr (port, ifnam, &addr, type); \ + } + +/* Set some sockaddr type of info. */ +static kern_return_t +siocsifXaddr (io_t port, + ifname_t ifnam, + sockaddr_t *addr, + enum siocgif_type type) +{ + struct sock_user *user = begin_using_socket_port(port); + error_t err = 0; + struct device *dev; + struct sockaddr_in *sin = (struct sockaddr_in *) addr; + uint32_t addrs[4]; + + if (!user) + return EOPNOTSUPP; + + dev = get_dev (ifnam); + + /* Only root is allowed to change the interface configuration. + XXX Check the underlying node as well. */ + if (!user->isroot) + err = EPERM; + else if (!dev) + err = ENODEV; + else if (sin->sin_family != AF_INET) + err = EINVAL; + else + { + inquire_device (dev, &addrs[0], &addrs[1], &addrs[2], &addrs[3]); + addrs[type] = sin->sin_addr.s_addr; + err = configure_device (dev, addrs[0], addrs[1], addrs[2], addrs[3]); + } + + __mutex_unlock (&global_lock); + end_using_socket_port (user); + return err; +} + +/* 12 SIOCSIFADDR -- Set address of a network interface. */ +SIOCSIF (addr, ADDR); + +/* 14 SIOCSIFDSTADDR -- Set point-to-point (peer) address of a network interface. */ +SIOCSIF (dstaddr, DSTADDR); + +/* 16 SIOCSIFFLAGS -- Set flags of a network interface. */ +kern_return_t +S_iioctl_siocsifflags (io_t port, + ifname_t ifnam, + short flags) +{ + struct sock_user *user = begin_using_socket_port (port); + error_t err = 0; + struct device *dev; + + if (!user) + return EOPNOTSUPP; + + dev = get_dev (ifnam); + + /* Only root is allowed to change the interface configuration. + XXX Check the underlying node as well. */ + if (!user->isroot) + err = EPERM; + else if (!dev) + err = ENODEV; + else + err = dev_change_flags(dev, flags); + + __mutex_unlock (&global_lock); + end_using_socket_port (user); + return err; +} + +/* 17 SIOCGIFFLAGS -- Get flags of a network interface. */ +kern_return_t +S_iioctl_siocgifflags (io_t port, + char *name, + short *flags) +{ + error_t err = 0; + struct device *dev; + + dev = get_dev (name); + if (!dev) + err = ENODEV; + else + { + *flags = dev->flags; + } + __mutex_unlock (&global_lock); + return err; +} + +/* 19 SIOCSIFBRDADDR -- Set broadcast address of a network interface. */ +SIOCSIF (brdaddr, BRDADDR); + +/* 22 SIOCSIFNETMASK -- Set netmask of a network interface. */ +SIOCSIF (netmask, NETMASK); + +/* 23 SIOCGIFMETRIC -- Get metric of a network interface. */ +kern_return_t +S_iioctl_siocgifmetric (io_t port, + ifname_t ifnam, + int *metric) +{ + error_t err = 0; + struct device *dev; + + dev = get_dev (ifnam); + if (!dev) + err = ENODEV; + else + { + *metric = 0; /* Not supported. */ + } + __mutex_unlock (&global_lock); + return err; +} + +/* 24 SIOCSIFMETRIC -- Set metric of a network interface. */ +kern_return_t +S_iioctl_siocsifmetric (io_t port, + ifname_t ifnam, + int metric) +{ + return EOPNOTSUPP; +} + +/* 25 SIOCDIFADDR -- Delete interface address. */ +kern_return_t +S_iioctl_siocdifaddr (io_t port, + ifname_t ifnam, + sockaddr_t addr) +{ + return EOPNOTSUPP; +} + +/* 33 SIOCGIFADDR -- Get address of a network interface. */ +SIOCGIF (addr, ADDR); + +/* 34 SIOCGIFDSTADDR -- Get point-to-point address of a network interface. */ +SIOCGIF (dstaddr, DSTADDR); + +/* 35 SIOCGIFBRDADDR -- Get broadcast address of a network interface. */ +SIOCGIF (brdaddr, BRDADDR); + +/* 37 SIOCGIFNETMASK -- Get netmask of a network interface. */ +SIOCGIF (netmask, NETMASK); + +/* 51 SIOCGIFMTU -- Get mtu of a network interface. */ +error_t +S_iioctl_siocgifmtu (io_t port, + ifname_t ifnam, + int *mtu) +{ + error_t err = 0; + struct device *dev; + + dev = get_dev (ifnam); + if (!dev) + err = ENODEV; + else + { + *mtu = dev->mtu; + } + __mutex_unlock (&global_lock); + return err; +} + +/* 51 SIOCSIFMTU -- Set mtu of a network interface. */ +error_t +S_iioctl_siocsifmtu (io_t port, + ifname_t ifnam, + int mtu) +{ + struct sock_user *user = begin_using_socket_port (port); + error_t err = 0; + struct device *dev; + + if (!user) + return EOPNOTSUPP; + + dev = get_dev (ifnam); + + /* Only root is allowed to change the interface configuration. + XXX Check the underlying node as well. */ + if (!user->isroot) + err = EPERM; + if (!dev) + err = ENODEV; + else if (mtu <= 0) + err = EINVAL; + else + { + if (dev->change_mtu) + dev->change_mtu (dev, mtu); + else + dev->mtu = mtu; + + notifier_call_chain (&netdev_chain, NETDEV_CHANGEMTU, dev); + } + + __mutex_unlock (&global_lock); + end_using_socket_port (user); + return err; +} + +/* 100 SIOCGIFINDEX -- Get index number of a network interface. */ +error_t +S_iioctl_siocgifindex (io_t port, + ifname_t ifnam, + int *index) +{ + error_t err = 0; + struct device *dev; + + dev = get_dev (ifnam); + if (!dev) + err = ENODEV; + else + { + *index = dev->ifindex; + } + __mutex_unlock (&global_lock); + return err; +} + +/* 101 SIOCGIFNAME -- Get name of a network interface from index number. */ +error_t +S_iioctl_siocgifname (io_t port, + ifname_t ifnam, + int *index) +{ + error_t err = 0; + struct device *dev; + + __mutex_lock (&global_lock); + dev = dev_get_by_index (*index); + if (!dev) + err = ENODEV; + else + { + strncpy (ifnam, dev->name, IFNAMSIZ); + ifnam[IFNAMSIZ-1] = '\0'; + } + __mutex_unlock (&global_lock); + + return err; +} diff --git a/pfinet/io-ops.c b/pfinet/io-ops.c index ebb1c172..bd4f590c 100644 --- a/pfinet/io-ops.c +++ b/pfinet/io-ops.c @@ -320,7 +320,7 @@ S_io_reauthenticate (struct sock_user *user, uid_t *gen_uids, *gen_gids, *aux_uids, *aux_gids; u_int genuidlen, gengidlen, auxuidlen, auxgidlen; error_t err; - int i; + int i, j; auth_t auth; mach_port_t newright; @@ -357,9 +357,16 @@ S_io_reauthenticate (struct sock_user *user, if (err) newuser->isroot = 0; else + /* Check permission as fshelp_isowner would do. */ for (i = 0; i < genuidlen; i++) - if (gen_uids[i] == 0) - newuser->isroot = 1; + { + if (gen_uids[i] == 0 || gen_uids[i] == pfinet_owner) + newuser->isroot = 1; + if (gen_uids[i] == pfinet_group) + for (j = 0; j < gengidlen; j++) + if (gen_gids[j] == pfinet_group) + newuser->isroot = 1; + } mach_port_move_member (mach_task_self (), newuser->pi.port_right, pfinet_bucket->portset); @@ -390,7 +397,7 @@ S_io_restrict_auth (struct sock_user *user, u_int gidslen) { struct sock_user *newuser; - int i = 0; + int i, j; int isroot; if (!user) @@ -400,9 +407,16 @@ S_io_restrict_auth (struct sock_user *user, isroot = 0; if (user->isroot) - for (i = 0; i < uidslen && !isroot; i++) - if (uids[i] == 0) - isroot = 1; + /* Check permission as fshelp_isowner would do. */ + for (i = 0; i < uidslen; i++) + { + if (uids[i] == 0 || uids[i] == pfinet_owner) + isroot = 1; + if (uids[i] == pfinet_group) + for (j = 0; j < gidslen; j++) + if (gids[j] == pfinet_group) + isroot = 1; + } newuser = make_sock_user (user->sock, isroot, 0, 0); *newobject = ports_get_right (newuser); diff --git a/pfinet/linux-src/net/core/dev.c b/pfinet/linux-src/net/core/dev.c index aaee35a2..5b4c6255 100644 --- a/pfinet/linux-src/net/core/dev.c +++ b/pfinet/linux-src/net/core/dev.c @@ -146,7 +146,11 @@ atomic_t dev_lockct = ATOMIC_INIT(0); * Our notifier list */ +#ifdef _HURD_ +struct notifier_block *netdev_chain=NULL; +#else static struct notifier_block *netdev_chain=NULL; +#endif /* * Device drivers call our routines to queue packets here. We empty the @@ -1103,7 +1107,11 @@ static int dev_ifname(struct ifreq *arg) * Thus we will need a 'compatibility mode'. */ +#ifdef _HURD_ +int dev_ifconf(char *arg) +#else static int dev_ifconf(char *arg) +#endif { struct ifconf ifc; struct device *dev; diff --git a/pfinet/linux-src/net/ipv4/devinet.c b/pfinet/linux-src/net/ipv4/devinet.c index 71beaf18..d107f335 100644 --- a/pfinet/linux-src/net/ipv4/devinet.c +++ b/pfinet/linux-src/net/ipv4/devinet.c @@ -401,7 +401,8 @@ static __inline__ int inet_abc_len(u32 addr) error_t configure_device (struct device *dev, - uint32_t addr, uint32_t netmask, uint32_t peer) + uint32_t addr, uint32_t netmask, uint32_t peer, + uint32_t broadcast) { struct in_device *in_dev = dev->ip_ptr; struct in_ifaddr *ifa = in_dev ? in_dev->ifa_list : 0; @@ -441,13 +442,17 @@ configure_device (struct device *dev, ifa->ifa_address = peer; } + if (broadcast != INADDR_NONE) + ifa->ifa_broadcast = broadcast; + return - (inet_set_ifa (dev, ifa) ?: dev_change_flags (dev, dev->flags | IFF_UP)); } void inquire_device (struct device *dev, - uint32_t *addr, uint32_t *netmask, uint32_t *peer) + uint32_t *addr, uint32_t *netmask, uint32_t *peer, + uint32_t *broadcast) { struct in_device *in_dev = dev->ip_ptr; struct in_ifaddr *ifa = in_dev ? in_dev->ifa_list : 0; @@ -457,9 +462,10 @@ inquire_device (struct device *dev, *addr = ifa->ifa_local; *netmask = ifa->ifa_mask; *peer = ifa->ifa_address; + *broadcast = ifa->ifa_broadcast; } else - *addr = *netmask = *peer = INADDR_NONE; + *addr = *netmask = *peer = *broadcast = INADDR_NONE; } #else @@ -700,6 +706,9 @@ inet_gifconf(struct device *dev, char *buf, int len) else strcpy(ifr.ifr_name, dev->name); +#ifdef _HURD_ + (*(struct sockaddr_in *) &ifr.ifr_addr).sin_len = sizeof (struct sockaddr_in); +#endif (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET; (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local; diff --git a/pfinet/main.c b/pfinet/main.c index 713eddc7..e5cac55f 100644 --- a/pfinet/main.c +++ b/pfinet/main.c @@ -33,7 +33,8 @@ /* devinet.c */ extern error_t configure_device (struct device *dev, - uint32_t addr, uint32_t netmask, uint32_t peer); + uint32_t addr, uint32_t netmask, + uint32_t peer, uint32_t broadcast); int trivfs_fstype = FSTYPE_MISC; int trivfs_fsid; @@ -59,6 +60,8 @@ pfinet_demuxer (mach_msg_header_t *inp, extern int io_server (mach_msg_header_t *, mach_msg_header_t *); extern int socket_server (mach_msg_header_t *, mach_msg_header_t *); extern int startup_notify_server (mach_msg_header_t *, mach_msg_header_t *); + extern int pfinet_server (mach_msg_header_t *, mach_msg_header_t *); + extern int iioctl_server (mach_msg_header_t *, mach_msg_header_t *); /* We have several classes in one bucket, which need to be demuxed differently. */ @@ -70,11 +73,15 @@ pfinet_demuxer (mach_msg_header_t *inp, return (io_server (inp, outp) || socket_server (inp, outp) + || pfinet_server (inp, outp) + || iioctl_server (inp, outp) || trivfs_demuxer (inp, outp) || startup_notify_server (inp, outp)); } else return (socket_server (inp, outp) + || pfinet_server (inp, outp) + || iioctl_server (inp, outp) || trivfs_demuxer (inp, outp) || startup_notify_server (inp, outp)); } @@ -221,6 +228,7 @@ main (int argc, { error_t err; mach_port_t bootstrap; + struct stat st; pfinet_bucket = ports_create_bucket (); trivfs_protid_portclasses[0] = ports_create_class (trivfs_clean_protid, 0); @@ -255,7 +263,8 @@ main (int argc, /* ifconfig lo up 127.0.0.1 netmask 0xff000000 */ configure_device (&loopback_dev, - htonl (INADDR_LOOPBACK), htonl (IN_CLASSA_NET), htonl (INADDR_NONE)); + htonl (INADDR_LOOPBACK), htonl (IN_CLASSA_NET), + htonl (INADDR_NONE), htonl (INADDR_NONE)); __mutex_unlock (&global_lock); @@ -275,10 +284,26 @@ main (int argc, err = trivfs_startup (bootstrap, 0, trivfs_cntl_portclasses[0], pfinet_bucket, - trivfs_protid_portclasses[0], pfinet_bucket, 0); + trivfs_protid_portclasses[0], pfinet_bucket, + &pfinetctl); + if (err) error (1, err, "contacting parent"); + /* 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; + } + /* Launch */ ports_manage_port_operations_multithread (pfinet_bucket, pfinet_demuxer, diff --git a/pfinet/options.c b/pfinet/options.c index 3de98c35..31d9e075 100644 --- a/pfinet/options.c +++ b/pfinet/options.c @@ -45,9 +45,11 @@ extern error_t enumerate_devices (error_t (*fun) (struct device *dev)); /* devinet.c */ extern error_t configure_device (struct device *dev, uint32_t addr, - uint32_t netmask, uint32_t peer); + uint32_t netmask, uint32_t peer, + uint32_t broadcast); extern void inquire_device (struct device *dev, uint32_t *addr, - uint32_t *netmask, uint32_t *peer); + uint32_t *netmask, uint32_t *peer, + uint32_t *broadcast); /* Pfinet options. Used for both startup and runtime. */ static const struct argp_option options[] = @@ -248,7 +250,8 @@ parse_opt (int opt, char *arg, struct argp_state *state) 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); + err = configure_device (in->device, in->address, in->netmask, + in->peer, INADDR_NONE); if (err) FAIL (err, 16, 0, "cannot configure interface"); } @@ -333,9 +336,9 @@ trivfs_append_args (struct trivfs_control *fsys, char **argz, size_t *argz_len) error_t add_dev_opts (struct device *dev) { error_t err = 0; - uint32_t addr, mask, peer; + uint32_t addr, mask, peer, broad; - inquire_device (dev, &addr, &mask, &peer); + inquire_device (dev, &addr, &mask, &peer, &broad); #define ADD_OPT(fmt, args...) \ do { char buf[100]; \ diff --git a/pfinet/pfinet-ops.c b/pfinet/pfinet-ops.c new file mode 100644 index 00000000..594b5ac7 --- /dev/null +++ b/pfinet/pfinet-ops.c @@ -0,0 +1,93 @@ +/* + Copyright (C) 2000 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "pfinet.h" + +#include <linux/netdevice.h> +#include <linux/notifier.h> + +#include "pfinet_S.h" +#include <netinet/in.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <mach/notify.h> +#include <sys/mman.h> + +#include <sys/ioctl.h> +#include <net/if.h> + +extern int dev_ifconf(char *arg); + +/* Return the list of devices in the format provided by SIOCGIFCONF + in IFR, but don't return more then AMOUNT bytes. If AMOUNT is + negative, there is no limit. */ +error_t +S_pfinet_siocgifconf (io_t port, + int amount, + char **ifr, + mach_msg_type_number_t *len) +{ + error_t err = 0; + struct ifconf ifc; + + __mutex_lock (&global_lock); + if (amount < 0) + { + /* Get the needed buffer length. */ + ifc.ifc_buf = NULL; + ifc.ifc_len = 0; + err = dev_ifconf ((char *) &ifc); + if (err) + { + __mutex_unlock (&global_lock); + return -err; + } + amount = ifc.ifc_len; + } + else + ifc.ifc_len = amount; + + if (amount > 0) + { + /* Possibly allocate a new buffer. */ + if (*len < amount) + ifc.ifc_buf = (char *) mmap (0, amount, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + else + ifc.ifc_buf = *ifr; + err = dev_ifconf ((char *) &ifc); + } + + if (err) + { + *len = 0; + if (ifc.ifc_buf != *ifr) + munmap (ifc.ifc_buf, amount); + } + else + { + *len = ifc.ifc_len; + *ifr = ifc.ifc_buf; + } + + __mutex_unlock (&global_lock); + return err; +} diff --git a/pfinet/pfinet.h b/pfinet/pfinet.h index 57e678c0..6b248722 100644 --- a/pfinet/pfinet.h +++ b/pfinet/pfinet.h @@ -54,6 +54,15 @@ struct sock_addr struct sockaddr address; }; +/* Trivfs control structure for pfinet. */ +struct trivfs_control *pfinetctl; + +/* Owner of the underlying node. */ +uid_t pfinet_owner; + +/* Group of the underlying node. */ +uid_t pfinet_group; + void ethernet_initialize (void); int ethernet_demuxer (mach_msg_header_t *, mach_msg_header_t *); void setup_ethernet_device (char *, struct device **); diff --git a/pfinet/socket-ops.c b/pfinet/socket-ops.c index d6edce7e..5cbc74b3 100644 --- a/pfinet/socket-ops.c +++ b/pfinet/socket-ops.c @@ -18,10 +18,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ +#include <sys/stat.h> #include <hurd/trivfs.h> #include <string.h> #include <stddef.h> #include <fcntl.h> +#include <hurd/fshelp.h> #include "pfinet.h" #include "socket_S.h" @@ -42,6 +44,7 @@ S_socket_create (struct trivfs_protid *master, struct sock_user *user; struct socket *sock; error_t err; + int isroot; if (!master) return EOPNOTSUPP; @@ -63,12 +66,26 @@ S_socket_create (struct trivfs_protid *master, sock->type = sock_type; + isroot = master->isroot; + if (!isroot) + { + struct stat st; + + /* XXX */ + st.st_uid = pfinet_owner; + st.st_gid = pfinet_group; + + err = fshelp_isowner (&st, master->user); + if (! err) + isroot = 1; + } + err = - (*net_families[PF_INET]->create) (sock, protocol); if (err) sock_release (sock); else { - user = make_sock_user (sock, master->isroot, 0, 1); + user = make_sock_user (sock, isroot, 0, 1); *port = ports_get_right (user); *porttype = MACH_MSG_TYPE_MAKE_SEND; ports_port_deref (user); |