summaryrefslogtreecommitdiff
path: root/eth-multiplexer/multiplexer.c~
diff options
context:
space:
mode:
authorroot <root@(null).(none)>2009-05-03 17:20:00 +0200
committerroot <root@(null).(none)>2009-05-03 17:20:00 +0200
commite0faf22f31c48fb27b43c1825897d26e58feafc4 (patch)
tree65a09372b31e08a3a865bd0a88cd2718bafcd643 /eth-multiplexer/multiplexer.c~
This is my initial working version.
There is a bug in boot in this version: subhurd sometimes cannot boot.
Diffstat (limited to 'eth-multiplexer/multiplexer.c~')
-rw-r--r--eth-multiplexer/multiplexer.c~190
1 files changed, 190 insertions, 0 deletions
diff --git a/eth-multiplexer/multiplexer.c~ b/eth-multiplexer/multiplexer.c~
new file mode 100644
index 00000000..d3724602
--- /dev/null
+++ b/eth-multiplexer/multiplexer.c~
@@ -0,0 +1,190 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ 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. */
+
+/*
+ * The multiplexer server provides the virtual network interface.
+ * When it gets a packet, it forwards it to every other network interface,
+ * the ones that are created by itself or that it connects to.
+ * BPF is ported to the multiplexer to help deliver packets
+ * to the right pfinet.
+ */
+
+#include <argp.h>
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <hurd.h>
+#include <mach.h>
+#include <version.h>
+#include <device/device.h>
+#include <hurd/ports.h>
+#include <hurd/netfs.h>
+
+#include "ethernet.h"
+#include "vdev.h"
+#include "ourdevice_S.h"
+#include "notify_S.h"
+#include "bpf_impl.h"
+#include "netfs_impl.h"
+#include "util.h"
+
+/* The device which the multiplexer connects to */
+static char *device_file;
+
+const char *argp_program_version = "eth-multiplexer 0.1";
+const char *argp_program_bug_address = "<bug-hurd@gnu.org>";
+static const char doc[] = "Hurd multiplexer server.";
+static const struct argp_option options[] =
+{
+ {"interface", 'i', "DEVICE", 0,
+ "Network interface to use", 2},
+ {0}
+};
+
+/* Port bucket we service requests on. */
+struct port_bucket *port_bucket;
+struct port_class *other_portclass;
+struct port_class *vdev_portclass;
+struct port_info *notify_pi;
+
+int netfs_maxsymlinks = 12;
+char *netfs_server_name = "multiplexer";
+char *netfs_server_version = HURD_VERSION;
+file_t root_file;
+struct lnode root;
+struct stat underlying_node_stat;
+
+static int
+multiplexer_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ int device_server (mach_msg_header_t *, mach_msg_header_t *);
+ int notify_server (mach_msg_header_t *, mach_msg_header_t *);
+
+ return (device_server (inp, outp)
+ || notify_server (inp, outp)
+ || ethernet_demuxer (inp, outp));
+}
+
+static any_t
+multiplexer_thread (any_t arg)
+{
+ ports_manage_port_operations_one_thread (port_bucket,
+ multiplexer_demuxer,
+ 0);
+ return 0;
+}
+
+static error_t
+parse_opt (int opt, char *arg, struct argp_state *state)
+{
+ switch (opt)
+ {
+ case 'i':
+ device_file = arg;
+ break;
+ case ARGP_KEY_ERROR:
+ case ARGP_KEY_SUCCESS:
+ case ARGP_KEY_INIT:
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ error_t err;
+ mach_port_t bootstrap;
+ mach_port_t master_device;
+ const struct argp argp = { options, parse_opt, 0, doc };
+
+ port_bucket = ports_create_bucket ();
+ other_portclass = ports_create_class (0, 0);
+ vdev_portclass = ports_create_class (destroy_vdev, 0);
+
+ argp_parse (&argp, argc, argv, 0, 0, 0);
+
+ /* Open the network interface. */
+ if (device_file)
+ {
+ master_device = file_name_lookup (device_file, 0, 0);
+ if (master_device == MACH_PORT_NULL)
+ error (1, errno, "file_name_lookup");
+
+ ethernet_open (device_file, master_device, port_bucket,
+ other_portclass);
+ }
+
+ /* Prepare for the notification. */
+ err = ports_create_port (other_portclass, port_bucket,
+ sizeof (struct port_info), &notify_pi);
+ if (err)
+ error (1, err, "ports_create_port for notification");
+
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap == MACH_PORT_NULL)
+ error (1, 0, "must be started as a translator");
+
+ /* Run the multiplexer server in another thread. */
+ cthread_detach (cthread_fork (multiplexer_thread, 0));
+
+ err = maptime_map (0, 0, &multiplexer_maptime);
+ if (err)
+ error (4, err, "Cannot map time");
+
+ /* Initialize netfs and start the translator. */
+ netfs_init ();
+
+ root_file = netfs_startup (bootstrap, O_READ);
+ err = new_node (&root, &netfs_root_node);
+ if (err)
+ error (5, err, "Cannot create root node");
+
+ err = io_stat (root_file, &underlying_node_stat);
+ if (err)
+ error (6, err, "Cannot stat underlying node");
+
+ struct stat stat = underlying_node_stat;
+ /* If the underlying node is not a directory, increase its permissions */
+ if(!S_ISDIR(stat.st_mode))
+ {
+ if(stat.st_mode & S_IRUSR)
+ stat.st_mode |= S_IXUSR;
+ if(stat.st_mode & S_IRGRP)
+ stat.st_mode |= S_IXGRP;
+ if(stat.st_mode & S_IROTH)
+ stat.st_mode |= S_IXOTH;
+ }
+
+ stat.st_mode &= ~(S_ITRANS | S_IFMT);
+ stat.st_mode |= S_IFDIR;
+ fprintf (stderr, "set it as a dir\n");
+ netfs_root_node->nn->ln->st = stat;
+ fshelp_touch (&netfs_root_node->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME,
+ multiplexer_maptime);
+
+ netfs_server_loop (); /* Never returns. */
+ return 0;
+}