summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hurd/ChangeLog8
-rw-r--r--hurd/iioctl.defs172
-rw-r--r--hurd/ioctl_types.h4
-rw-r--r--hurd/pfinet.defs46
-rw-r--r--pfinet/ChangeLog46
-rw-r--r--pfinet/Makefile6
-rw-r--r--pfinet/glue-include/linux/if.h4
-rw-r--r--pfinet/iioctl-ops.c369
-rw-r--r--pfinet/io-ops.c28
-rw-r--r--pfinet/linux-src/net/core/dev.c8
-rw-r--r--pfinet/linux-src/net/ipv4/devinet.c15
-rw-r--r--pfinet/main.c31
-rw-r--r--pfinet/options.c13
-rw-r--r--pfinet/pfinet-ops.c93
-rw-r--r--pfinet/pfinet.h9
-rw-r--r--pfinet/socket-ops.c19
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);