summaryrefslogtreecommitdiff
path: root/pfinet
diff options
context:
space:
mode:
Diffstat (limited to 'pfinet')
-rw-r--r--pfinet/ChangeLog640
-rw-r--r--pfinet/Makefile116
-rw-r--r--pfinet/README49
-rw-r--r--pfinet/config.h36
-rw-r--r--pfinet/ethernet.c247
-rw-r--r--pfinet/glue-include/asm/atomic.h27
-rw-r--r--pfinet/glue-include/asm/bitops.h37
-rw-r--r--pfinet/glue-include/asm/byteorder.h154
-rw-r--r--pfinet/glue-include/asm/checksum.h5
-rw-r--r--pfinet/glue-include/asm/errno.h3
-rw-r--r--pfinet/glue-include/asm/hardirq.h1
-rw-r--r--pfinet/glue-include/asm/init.h3
-rw-r--r--pfinet/glue-include/asm/segment.h0
-rw-r--r--pfinet/glue-include/asm/spinlock.h75
-rw-r--r--pfinet/glue-include/asm/system.h20
-rw-r--r--pfinet/glue-include/asm/types.h1
-rw-r--r--pfinet/glue-include/asm/uaccess.h47
-rw-r--r--pfinet/glue-include/linux/autoconf.h0
-rw-r--r--pfinet/glue-include/linux/binfmts.h1
-rw-r--r--pfinet/glue-include/linux/config.h1
-rw-r--r--pfinet/glue-include/linux/errno.h13
-rw-r--r--pfinet/glue-include/linux/fcntl.h1
-rw-r--r--pfinet/glue-include/linux/fs.h21
-rw-r--r--pfinet/glue-include/linux/in.h44
-rw-r--r--pfinet/glue-include/linux/in6.h1
-rw-r--r--pfinet/glue-include/linux/interrupt.h44
-rw-r--r--pfinet/glue-include/linux/ioctl.h1
-rw-r--r--pfinet/glue-include/linux/ipv6.h1
-rw-r--r--pfinet/glue-include/linux/kernel.h78
-rw-r--r--pfinet/glue-include/linux/limits.h8
-rw-r--r--pfinet/glue-include/linux/major.h0
-rw-r--r--pfinet/glue-include/linux/malloc.h27
-rw-r--r--pfinet/glue-include/linux/mm.h18
-rw-r--r--pfinet/glue-include/linux/param.h1
-rw-r--r--pfinet/glue-include/linux/personality.h1
-rw-r--r--pfinet/glue-include/linux/poll.h24
-rw-r--r--pfinet/glue-include/linux/proc_fs.h0
-rw-r--r--pfinet/glue-include/linux/sched.h176
-rw-r--r--pfinet/glue-include/linux/slab.h0
-rw-r--r--pfinet/glue-include/linux/socket.h138
-rw-r--r--pfinet/glue-include/linux/sockios.h0
-rw-r--r--pfinet/glue-include/linux/stat.h1
-rw-r--r--pfinet/glue-include/linux/string.h1
-rw-r--r--pfinet/glue-include/linux/termios.h1
-rw-r--r--pfinet/glue-include/linux/time.h10
-rw-r--r--pfinet/glue-include/linux/timer.h36
-rw-r--r--pfinet/glue-include/linux/timex.h0
-rw-r--r--pfinet/glue-include/linux/types.h31
-rw-r--r--pfinet/glue-include/linux/un.h0
-rw-r--r--pfinet/glue-include/linux/version.h3
-rw-r--r--pfinet/glue-include/linux/wait.h32
-rw-r--r--pfinet/io-ops.c598
-rw-r--r--pfinet/kmem_cache.c88
-rw-r--r--pfinet/linux-src/include/linux/net.h12
-rw-r--r--pfinet/linux-src/include/linux/rtnetlink.h8
-rw-r--r--pfinet/linux-src/net/core/dev.c202
-rw-r--r--pfinet/linux-src/net/ipv4/af_inet.c116
-rw-r--r--pfinet/linux-src/net/ipv4/arp.c73
-rw-r--r--pfinet/linux-src/net/ipv4/devinet.c86
-rw-r--r--pfinet/linux-src/net/ipv4/tcp.c159
-rw-r--r--pfinet/linux-src/net/ipv4/udp.c104
-rw-r--r--pfinet/loopback.c130
-rw-r--r--pfinet/main.c273
-rw-r--r--pfinet/mapped-time.h30
-rw-r--r--pfinet/misc.c95
-rw-r--r--pfinet/mutations.h38
-rw-r--r--pfinet/options.c360
-rw-r--r--pfinet/pfinet.h85
-rw-r--r--pfinet/sched.c69
-rw-r--r--pfinet/socket-ops.c513
-rw-r--r--pfinet/socket.c119
-rw-r--r--pfinet/stubs.c70
-rw-r--r--pfinet/time.c27
-rw-r--r--pfinet/timer-emul.c171
74 files changed, 5276 insertions, 325 deletions
diff --git a/pfinet/ChangeLog b/pfinet/ChangeLog
new file mode 100644
index 00000000..4bf8d70d
--- /dev/null
+++ b/pfinet/ChangeLog
@@ -0,0 +1,640 @@
+2000-02-04 Roland McGrath <roland@baalperazim.frob.com>
+
+ * options.c (parse_opt): New code to set the default gateway using
+ fib_new_table and the tb_insert/tb_delete callbacks.
+
+ * options.c (parse_opt): Take global_lock while applying changes.
+ * main.c (main): Unlock global_lock before calling argp_parse.
+
+ * options.c (struct parse_interface): Use uint32_t for the IP
+ address members.
+
+ * linux-src/net/ipv4/devinet.c [_HURD_] (inquire_device): New function.
+ * options.c: Declare it.
+ (trivfs_append_args): Use inquire_device for --address and --netmask.
+ (ADD_ADDR_OPT): #undef it after uses.
+
+2000-02-03 Roland McGrath <roland@baalperazim.frob.com>
+
+ Complete overhaul of pfinet based on the IPv4 networking code from the
+ Linux 2.2.12 kernel sources. This page describes a single unified set
+ of interdependent changes, but there are so many changes that I have
+ broken up the log entry into paragraphs based on rough topical
+ divisions of the work involved.
+
+ Subset of verbatim Linux 2.2.12 sources imported on a vendor branch.
+ * linux-src: New directory, see README for details.
+ * README: New file, describes linux-src layout and procedures for
+ tracking Linux source updates.
+
+ Light modifications to linux-src files to avoid really bending over
+ backwards with the glue macros. All modifications to files in
+ linux-src are conditionalized by #ifdef _HURD_.
+ * linux-src/include/linux/net.h [_HURD_] (struct socket): New members
+ refcnt and identity; elide members fasync_list, file.
+ * linux-src/include/linux/rtnetlink.h [! CONFIG_RTNETLINK]
+ (rtnl_shlock, rtnl_shunlock) [! _HURD_]: Conditionalize contents on
+ this, making these no-ops #ifdef _HURD_.
+ * linux-src/net/core/dev.c [_HURD_] (dev_ioctl): Don't define the
+ function, instead #define it to 0.
+ * linux-src/net/ipv4/af_inet.c [_HURD_] (inet_ioctl): Likewise.
+ * linux-src/net/ipv4/arp.c [_HURD_] (arp_ioctl): Likewise.
+ * linux-src/net/ipv4/udp.c [_HURD_] (udp_ioctl): Likewise.
+ * linux-src/net/ipv4/tcp.c [_HURD_] (tcp_ioctl): Likewise.
+ [_HURD_] (tcp_tiocinq): New function, TIOCINQ code from tcp_ioctl.
+ * linux-src/net/ipv4/devinet.c [_HURD_] (devinet_ioctl): Don't define
+ the function, instead #define it to 0.
+ [_HURD_] (configure_device): New function, cobbled from SIOCSIFADDR
+ and SIOCSIFNETMASK code from devinet_ioctl.
+
+ * glue-include/asm, glue-include/linux: New directories.
+ These contain glue kludge headers that replace all of the
+ Linux <asm/*.h> headers except checksum.h, and several of
+ the Linux <linux/*.h> headers (the remainder come from
+ linux-src/include/linux and are mostly unmodified).
+ * glue-include/asm/atomic.h: New file, glue replacement header.
+ * glue-include/asm/bitops.h: New file, glue replacement header.
+ * glue-include/asm/byteorder.h: New file, glue replacement header.
+ * glue-include/asm/checksum.h: New file, glue replacement header.
+ * glue-include/asm/errno.h: New file, glue replacement header.
+ * glue-include/asm/hardirq.h: New file, glue replacement header.
+ * glue-include/asm/init.h: New file, glue replacement header.
+ * glue-include/asm/segment.h: New file, glue replacement header.
+ * glue-include/asm/spinlock.h: New file, glue replacement header.
+ * glue-include/asm/system.h: New file, glue replacement header.
+ * glue-include/asm/types.h: New file, glue replacement header.
+ * glue-include/asm/uaccess.h: New file, glue replacement header.
+ * glue-include/linux/autoconf.h: New file, glue replacement header.
+ * glue-include/linux/binfmts.h: New file, glue replacement header.
+ * glue-include/linux/config.h: New file, glue replacement header.
+ * glue-include/linux/errno.h: New file, glue replacement header.
+ * glue-include/linux/fcntl.h: New file, glue replacement header.
+ * glue-include/linux/fs.h: New file, glue replacement header.
+ * glue-include/linux/in.h: New file, glue replacement header.
+ * glue-include/linux/in6.h: New file, glue replacement header.
+ * glue-include/linux/interrupt.h: New file, glue replacement header.
+ * glue-include/linux/ioctl.h: New file, glue replacement header.
+ * glue-include/linux/ipv6.h: New file, glue replacement header.
+ * glue-include/linux/kernel.h: New file, glue replacement header.
+ * glue-include/linux/limits.h: New file, glue replacement header.
+ * glue-include/linux/major.h: New file, glue replacement header.
+ * glue-include/linux/malloc.h: New file, glue replacement header.
+ * glue-include/linux/mm.h: New file, glue replacement header.
+ * glue-include/linux/param.h: New file, glue replacement header.
+ * glue-include/linux/personality.h: New file, glue replacement header.
+ * glue-include/linux/poll.h: New file, glue replacement header.
+ * glue-include/linux/proc_fs.h: New file, glue replacement header.
+ * glue-include/linux/sched.h: New file, glue replacement header.
+ * glue-include/linux/slab.h: New file, glue replacement header.
+ * glue-include/linux/socket.h: New file, glue replacement header.
+ * glue-include/linux/sockios.h: New file, glue replacement header.
+ * glue-include/linux/stat.h: New file, glue replacement header.
+ * glue-include/linux/string.h: New file, glue replacement header.
+ * glue-include/linux/termios.h: New file, glue replacement header.
+ * glue-include/linux/time.h: New file, glue replacement header.
+ * glue-include/linux/timer.h: New file, glue replacement header.
+ * glue-include/linux/timex.h: New file, glue replacement header.
+ * glue-include/linux/types.h: New file, glue replacement header.
+ * glue-include/linux/un.h: New file, glue replacement header.
+ * glue-include/linux/version.h: New file, glue replacement header.
+ * glue-include/linux/wait.h: New file, glue replacement header.
+
+ * kmem_cache.c: New file. Glue code replaces Linux kmem_cache_t et al.
+ * stubs.c: New file. No-op functions and stub variables for a few
+ things the Linux networking code needs to link.
+
+ * Makefile (core-srcs, arch-lib-srcs, ethernet-srcs, ipv4-srcs): New
+ variables, listing sources used from linux-src subdirectories.
+ (LINUXSRCS): Define using those.
+ (SRCS): Remove devices.c; add kmem_cache.c, stubs.c.
+ (UNUSEDSRC): Variable removed.
+ (vpath %.c): Remove vpath for $(srcdir)/linux-inet directory.
+ Add vpaths for $(srcdir)/linux-src subdirectories.
+ (CPPFLAGS): Add -D_HURD_SYSTYPE defining it to $(asm_syntax) as a
+ double-quoted string. Add -I's for glue-include and linux-src/include.
+
+ * pfinet.h: Include <sys/socket.h>, and not <linux/netdevice.h>.
+ (master_device): Remove decl.
+ (global_lock, packet_queue_lock): Remove common defns.
+ (global_lock, net_bh_lock): Declare them as externs.
+ (struct sockaddr): Remove len member, make address member just a
+ struct sockaddr rather than a 0-length array.
+ (setup_loopback_device, become_task_protid, become_task): Remove decls.
+ (ethernet_initialize): Declare it.
+ (input_work_thread): Remove decl.
+ (net_bh_thread): Declare it.
+ (tcp_readable): Remove decl.
+ (tcp_tiocinq): Declare it.
+
+ * config.h: Rewritten based on Linux 2.2.12 set of CONFIG_* options.
+ (CONFIG_NET, CONFIG_INET, CONFIG_SKB_LARGE): These are the only
+ Linux config options we set.
+ (CONFIG_IP_NOSIOCRT): New macro (not a proper config option, but
+ used conveniently in the code).
+ * ethernet.c (ethernet_set_multi): Take only one parameter.
+ Remove assert, since we always get passed IGMP_ALL_HOSTS.
+ (ethernet_thread): Make static.
+ (ethernet_demuxer): Use __mutex_lock in place of mutex_lock, so as to
+ get cthreads instead of linux/spinlock.h glue macros. Lock
+ net_bh_lock instead of global_lock. Set SKB->protocol with
+ eth_type_trans before calling netif_rx.
+ (ethernet_initialize): New function, one-time initialization broken
+ out of ethernet_open.
+ (ethernet_open): Ports setup moved to ethernet_initialize.
+ Don't use `errno' to avoid glue conflicts.
+ Use get_privileged_ports here to get the master device port, and
+ deallocate it after calling device_open.
+ (ethernet_xmit): Use assert_perror. Only one arg to dev_kfree_skb now.
+ (setup_ethernet_device): Change initializations for structure changes.
+ Call dev_init_buffers and register_netdevice on the device.
+ * timer-emul.c (all functions): Use __mutex_lock instead of mutex_lock.
+ Adjust for renaming of `prevp' member to `prev' in struct timer_list.
+ (mod_timer): New function.
+ * socket.c (proto_ops): Variable removed.
+ (net_families): New variable replaces it.
+ (sock_register): Rewritten for new calling convention, set
+ net_families rather than proto_ops.
+ (make_sock_user, clean_socketport, sock_alloc, sock_release):
+ Functions moved here from misc.c.
+ * sched.c (packet_queue_lock): Variable removed.
+ (net_bh_lock, net_bh_wakeup): New variables.
+ (current): Variable removed (now a macro in the glue headers).
+ (interruptible_sleep_on, wake_up_interruptible): Functions removed.
+ They are replaced by inlines in the glue headers.
+ (become_task, become_task_protid): Functions removed; they are
+ replaced by macros in glue-include/linux/sched.h.
+ (net_bh_worker): New function.
+ * loopback.c: Completely rewritten, mostly copied from linux-2.2.12's
+ drivers/net/loopback.c source file.
+
+ * io-ops.c (all functions): Use __mutex_lock in place of mutex_lock.
+ (S_io_write): Call ops->sendmsg instead of ops->write,
+ which no longer exists. If O_NONBLOCK is set, set MSG_DONTWAIT in
+ msg_flags.
+ (S_io_read): Call ops->recvmsg instead of ops->read,
+ which no longer exists If O_NONBLOCK is set, pass MSG_DONTWAIT.
+ (S_io_readable): Use USER->sock->data in place of USER->sock->sk.
+ For SOCK_STREAM and SOCK_SEQPACKET types, call tcp_tiocinq.
+ (S_io_set_all_openmodes, S_io_get_openmodes, S_io_set_some_openmodes,
+ S_io_clear_some_openmodes): Member USER->sock->userflags is now
+ renamed USER->sock->flags.
+ (S_io_select): Completely rewritten using ops->poll.
+ (select_wait): Function removed.
+ (S_io_stat): Set st_mode to reflect S_IFSOCK.
+ * socket-ops.c (all functions): Use __mutex_lock instead of mutex_lock.
+ (S_socket_create): Don't set SOCK->ops or call SOCK->ops->create.
+ Instead, call net_families[PF_INET]->create.
+ (S_socket_listen): Remove extra checks; just call ops->listen.
+ (S_socket_accept): Remove extra checks before ops->accept call.
+ Avoid use of goto.
+ (S_socket_connect): Remove extra checks; just call ops->connect.
+ (S_socket_bind): Adjust for struct sock_addr changes.
+ (S_socket_create_address): Likewise.
+ (S_socket_whatis_address): Likewise.
+ (S_socket_connect2): Don't diddle data structures after
+ ops->socketpair call.
+ (S_socket_getopt): Use sock_getsockopt if LEVEL is SOL_SOCKET.
+ Accept any data size, not just sizeof (int).
+ (S_socket_setopt): Use sock_setsockopt if LEVEL is SOL_SOCKET.
+ (S_socket_send): Always use ops->sendmsg instead of ops->send or
+ ops->sendto, which no longer exist. If O_NONBLOCK is set, set
+ MSG_DONTWAIT in msg_flags.
+ (S_socket_recv): Always use ops->recvmsg instead of ops->recv, which
+ no longer exists. If O_NONBLOCK is set, set MSG_DONTWAIT in flags.
+ Check for error from S_socket_create_address.
+
+ * main.c (find_device): Don't try to set ether_dev.pa_mask (it's gone).
+ (main): Don't call init_devices. Call ethernet_initialize.
+ Start net_bh_worker instead of input_work_thread. Don't call
+ setup_loopback_device. Instead, take global_lock, do prepare_current,
+ and then call sk_init, skb_init, inet_proto_init, and net_dev_init.
+ Keep global_lock held while calling argp_parse.
+ Call arrange_shutdown_notification only after all that.
+ Fix error call for "contacting parent" to pass ERR instead of errno.
+ * options.c (ADDR): #undef before defining macro.
+ (parse_opt): #if 0 out EDESTADDRREQ check (I don't understand it).
+ To apply settings, call configure_devices.
+ (ADD_ADDR_OPT): #if 0 --address and --netmask options. Needs fixed.
+ * misc.c (make_sock_user, clean_socketport, sock_alloc, sock_release):
+ Functions moved to socket.c.
+ (sock_release_peer): Function removed.
+ (make_sockaddr_port): Use struct sockaddr_storage to size buffer.
+ Fix size calculation for new struct sock_addr layout.
+ Initialize sa_family and sa_len of new struct sock_addr.
+
+ Remove the old Linux (2.0.??) network stack and the glue code for it.
+ * linux-inet, asm, linux: Directories and all files removed.
+ Some of the new files in glue-include came from the old glue headers
+ in the asm and linux directories, but most were substantially modified.
+ * devices.c: File removed. The equivalent glue is now elsewhere.
+
+2000-01-27 Roland McGrath <roland@baalperazim.frob.com>
+
+ * mapped-time.h: Include <maptime.h>.
+ (fill_timeval): Function removed.
+ (fetch_jiffies): Use maptime_read.
+ * timer-emul.c (init_time): Use maptime_map and maptime_read.
+ * linux/sched.h (fetch_xtime): Use maptime_read.
+ * linux/time.h (do_gettimeofday): Likewise.
+
+1999-10-22 Roland McGrath <roland@baalperazim.frob.com>
+
+ * socket-ops.c (S_socket_getopt): Implement the call.
+ All options supported by the code in linux-inet are in
+ fact of type int, so we can support just that one size.
+ (This is still a bogus untyped interface!)
+
+1999-09-13 Roland McGrath <roland@baalperazim.frob.com>
+
+ * io-ops.c: Reverted changes related to io_map_segment.
+
+1999-09-09 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * ethernet.c (ethernet_open): Don't start the input work thread
+ here.
+ (more_packets, mark_bh, input_work_thread): Move
+ these to ...
+ * devices.c: ... here.
+ Also include "pfinet.h" instead of list of <> includes.
+ * main.c (main): Launch input work thread here.
+ * pfinet.h (input_work_thread): Declare function.
+
+ * devices.c (add_device): Remove unused function.
+ * pfinet.h (incoming_net_packet): Remove unused declaration.
+
+1999-09-07 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-ops.c (S_io_map_segment): New function.
+
+1999-07-11 Roland McGrath <roland@baalperazim.frob.com>
+
+ * pfinet.h: Add #include <sys/mman.h> for munmap decl.
+
+1999-07-10 Roland McGrath <roland@baalperazim.frob.com>
+
+ * io-ops.c: Add #include <sys/mman.h> for munmap decl.
+
+1999-07-09 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-ops.c (S_io_read): Use mmap instead of vm_allocate.
+ * socket-ops.c (S_socket_whatis_address): Likewise.
+
+1999-07-03 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-ops.c (S_io_read): Use munmap instead of vm_deallocate.
+ (S_io_reauthenticate): Likewise.
+
+1999-06-13 Roland McGrath <roland@baalperazim.frob.com>
+
+ * main.c (trivfs_goaway): Exit if there are no socket ports.
+
+Sun Mar 14 18:33:54 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * ethernet.c (ether_filter): Use a shorter filter program.
+ (ether_filter_len): Compute more safely.
+
+1999-02-28 Roland McGrath <roland@baalperazim.frob.com>
+
+ * main.c (S_startup_dosync): Use ports_class_iterate.
+ (sigterm_handler): Likewise.
+
+Tue Feb 16 05:50:27 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-ops.c (S_io_revoke): New function. Don't attempt to
+ implement. (Other systems don't even permit non-file revokes.)
+
+1998-10-24 Roland McGrath <roland@baalperazim.frob.com>
+
+ * ethernet.c (ethernet_open): Check error return from device_open and
+ device_set_filter.
+ (setup_ethernet_device): Check error return from device_get_status.
+
+ * ethernet.c (ethername): Remove static variable.
+ (setup_ethernet_device): Don't set it.
+ (ethernet_open): Don't use it; use DEV->name instead.
+
+1998-09-04 Roland McGrath <roland@baalperazim.frob.com>
+
+ * loopback.c (loopback_type_trans): Return u_int16_t.
+
+Fri Apr 24 15:43:07 1998 Thomas Bushnell, n/BSG <tb@mit.edu>
+
+ * io-ops.c (S_io_select): When returning EINTR after cancellation,
+ deallocate REPLY because the stub won't do it for us. Reported by
+ UCHIYAMA Yasushi (uch@nop.or.jp).
+
+1997-08-25 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * io-ops.c (S_io_write): Negate linux error codes before returning.
+
+1997-08-19 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * linux-inet/tcp.c (tcp_conn_request): SK->err holds errno values,
+ not linux negative errno return vals.
+
+Wed Aug 20 14:05:52 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * main.c (main): New args for
+ ports_manage_port_operations_multithread.
+
+Fri Aug 8 11:47:08 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * linux-inet/tcp.c (tcp_check): Move to end of file so it isn't
+ inlined and can be profiled easily.
+ * linux-inet/udp.c (udp_check): Likewise.
+
+Mon Jul 21 14:58:13 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile (HURDLIBS): Add iohelp.
+
+ * main.c (trivfs_goaway): If FSYS_GOAWAY_FORCE is set, then go
+ away, otherwise, continue to return EBUSY.
+
+Fri Apr 25 10:46:49 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * options.c (trivfs_append_args): Renamed from trivfs_get_options.
+ Don't initialize ARGZ/ARGZ_LEN.
+
+Tue Feb 4 16:53:19 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * socket-ops.c (S_socket_send): Don't deref ADDR if it's 0.
+ (S_socket_bind): Return EADDRNOTAVAIL if ADDR is 0.
+
+Fri Oct 25 20:02:17 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * loopback.c (loopback_type_trans): New function.
+ (setup_loopback_device): Bother to mark interface up
+ too. Set LOOPBACK_DEV.type_trans.
+
+Thu Oct 24 22:38:55 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * main.c (main): Call setup_loopback_device before parsing args
+ (and thus before the ethernet device shows up).
+ * loopback.c: New file.
+ * Makefile (SRCS): Add loopback.c.
+ * pfinet.h (loopback_dev): New variable.
+
+ * pfinet.h (ip_rt_del): New prototype.
+
+Thu Sep 12 16:47:24 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile (HURDLIBS): New variable.
+ (pfinet): Omit special dependency.
+
+ * Makefile (vpath %.c): Put this after Makeconf inclusion so it
+ catches setting of $(srcdir) there.
+
+Fri Sep 6 16:46:43 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * socket-ops.c (S_socket_recv): Bother to pass
+ USER->sock->userflags through to the recvfrom routine.
+
+Sat Jul 20 15:48:29 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * Makefile (lndist-asm-files): Look for files in $(srcdir).
+ (lndist-linux-files): Likewise.
+ (lndist-linux-inet-files): Likewise.
+
+Fri Jul 19 09:39:08 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * pfinet.h (make_sock_user): Declaration updated.
+
+Thu Jul 18 23:19:07 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * misc.c (make_sock_user): New parm `noinstall'; if it's set use
+ non-installing version of ports_create_port. All callers
+ changed.
+ * io-ops.c (S_io_reauthenticate): Install NEWUSER port right into
+ portset after it's fully initialized.
+
+Sat Jul 13 20:18:18 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * io-ops.c (S_io_reauthenticate): Repeat auth_server_authenticate
+ for as long as we get EINTR. Deal with other errors without
+ crashing.
+
+Sun Jul 7 21:29:42 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * io-ops.c (S_io_reauthenticate): Don't use unsafe MOVE_SEND in
+ call to auth_server_authenticate.
+
+Fri Jul 5 19:42:54 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * ethernet.c (setup_ethernet_device): Linux's device `mtu' member
+ does not include the hardware header size; subtract that off the
+ value the kernel specifies as maximum packet size in setting
+ ETHER_DEV.mtu.
+
+Thu Jun 27 10:14:10 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * Makefile (lndist): Add lndist-asm-files.
+ (lndist-asm-files): New rule.
+ (ASMHEADERS): New variable.
+ ($(top_srcdir)/hurd-snap/$(dir)/asm): New rule.
+
+Tue Jun 25 14:00:07 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * linux-inet/route.c (ip_rt_del): New function.
+ * linux-inet/route.h (ip_rt_del): New declaration.
+
+ * options.c (trivfs_get_options): Initialize *ARGZ & *ARGZ_LEN.
+ (parse_opt): Fix test for address-less netmask.
+ Fix byte order when using IN_* macros.
+ Base default netmask on dev->pa_addr, not in->address.
+ Don't clear dev->pa_addr.
+ Delete old routing entries before adding new ones.
+ (trivfs_get_options): Add & use ADD_ADDR_OPT macro.
+ (parse_hook_add_interface): Initialize H->curint->device.
+
+Mon Jun 24 16:48:51 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * main.c (sigterm_handler): Renamed from sighup_handle. Make void.
+ Deal with SIGTERM instead of SIGHUP.
+ (main): Use SIGTERM & sigterm_handler instead of SIGHUP &c.
+
+ * options.c (parse_hook_add_interface): Realloc the correct number
+ of bytes.
+
+Mon Jun 24 16:33:55 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * main.c (sighup_handle): New function.
+ (arrange_shutdown_notification): Register SIGHUP handler.
+
+Mon Jun 24 12:44:17 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * options.c (parse_opt): Don't fail if there were no options.
+ (RETURN): New macro.
+ (PERR, FAIL): Use RETURN instead of return to free memory if nec.
+
+Fri Jun 21 16:42:29 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * main.c (main): Pass ARGC & ARGV to argp_parse in the correct order.
+
+Thu Jun 20 22:39:17 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * options.c: Renamed from opts.c.
+ (parse_opt): Fix lots of typos.
+ (trivfs_get_options): New function.
+ (get_opts, trivfs_S_fsys_get_options, trivfs_S_file_get_fs_options):
+ Functions removed.
+ <netinet/in.h>, <arpa/inet.h>: New includes.
+ * Makefile (pfinet): Depend on ../libfshelp/libfshelp.a &
+ ../libshouldbeinlibc/libshouldbeinlibc.a.
+ (SRCS): Add options.c.
+
+Thu Jun 20 19:47:40 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * main.c: Include <hurd/startup.h> and <string.h>.
+ (shutdown_notify_class): Declare variable.
+ (S_startup_dosync): Give enough args to ports_lookup_port.
+ (S_startup_dosync/do1): Return a value.
+ (arrange_shutdown_notification): Correct spelling of
+ ports_create_port. Initialize shutdown_notify_class.
+ (find_device): Construct arg to strcmp correctly. Correct
+ spelling of ENXIO.
+
+Wed Jun 19 18:46:35 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts.c (trivfs_S_fsys_set_options): Function removed.
+ (trivfs_runtime_argp): New variable.
+
+Sun Jun 16 22:45:54 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts.c (parse_opt): Rename ERR macro to FAIL. Use argp_failure.
+
+Sat Jun 15 19:47:06 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * main.c (main): Rearrange for arg parsing some more.
+ (enumerate_devices): New function.
+ (pfinet_argp): New declaration.
+ (already_open): Make global.
+ <error.h>, <argp.h>: New includes.
+
+Fri Jun 14 15:41:57 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * main.c (find_device): New function.
+ (main): Rearrange to use new argument parsing.
+
+Thu Jun 13 16:55:42 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * Makefile (MIGSRCS): Add startup_notifyServer.c.
+ * main.c (S_startup_dosync, arrange_shutdown_notification): New
+ functions.
+ (pfinet_demuxer): Call startup_notify_server.
+ (main): Call arrange_shutdown_notification).
+
+Tue May 14 14:12:25 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * main.c (main): Initialize fsys_identity.
+ * misc.c (sock_alloc): Initialize SOCK->identity.
+ (sock_release): Destroy SOCK->identity if it's been set.
+ * io-ops.c (S_io_identity): New function.
+ * pfinet.h (fsys_identity): New variable.
+ * linux/net.h (struct socket) [_HURD_]: New member `identity'.
+
+ * ethernet.c (ethernet_open): Delete superfluous arg to
+ assert_perror.
+
+Fri May 10 16:56:52 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * misc.c (make_sock_user): Pass correct args to ports_create_port.
+
+ * ethernet.c (ethernet_open): Pass in ERRNO to assert_perror.
+
+Thu May 9 20:27:28 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * io-ops.c (S_io_reauthenticate): Use new auth_server_authenticate
+ interface.
+
+ * io-ops.c (S_io_select): Drop ID_TAG arg.
+
+ * ethernet.c (ethernet_thread): Return any_t.
+ (input_work_thread): Likewise.
+
+ * ethernet.c (ethernet_open): Use new ports_create_port call.
+ * socket-ops.c (S_socket_create_address): Likewise.
+ * misc.c (make_sock_user): Likewise.
+ (make_sockaddr_port): Likewise.
+
+Wed Apr 24 18:35:50 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * main.c (main): Take third cmdline arg and add gateway route.
+
+Mon Apr 15 12:53:24 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * Makefile (CPPFLAGS): Look for config.h in $(srcdir).
+ (io-MIGSFLAGS, socket-MIGSFLAGS): Look for mutations.h in
+ $(srcdir).
+ (vpath %.c): Find linux-inet dir under #(srcdir)>
+ (SRCS): Add time.c.
+ (LCLHDRS, LINUXHDRS, FROBBEDLINUXHEADERS): New variables.
+ (lndist, lndist-linux-inet-files, lndist-linux-files,
+ $(top-srcdir)/hurd-snap/$(dir)/linux-inet,
+ $(top-srcdir)/hurd-snap/$(dir)/linux): New targets.
+
+Mon Feb 26 13:36:14 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * misc.c (end_using_sockaddr_port): Only call ports_port_deref if
+ arg is valid.
+ (end_using_socket_port): Likewise.
+
+ * linux/interrupt.h (mark_bh): Remove stubby inline, replace
+ with real declaration.
+ * pfinet.h (packet_queue_lock): New variable.
+ * sched.c (packet_queue_lock): Provide initialization.
+ * ethernet.c (ethernet_open): Put READPT in etherport_bucket
+ instead of pfinet_bucket. Fork ethernet_thread and
+ input_work_thread before returning.
+ (more_packets, etherport_bucket): New variables.
+ (input_work_thread, ethernet_thread, mark_bh): New functions.
+
+ * main.c (pfinet_demuxer): Don't use call ethernet_demuxer.
+
+Thu Feb 22 17:54:25 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * ethernet.c (ethernet_open): Request maximum queue limit
+ on our read port.
+
+Thu Feb 8 18:32:33 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * socket-ops.c (S_socket_connect): Don't return EINVAL for
+ SS_CONNECTED state.
+
+Mon Jan 22 13:47:47 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * timer-emul.c (init_time): There are *still* a million microseconds to
+ the second.
+
+Thu Jan 18 12:37:57 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * mapped-time.h (fetch_jiffies): Uh, duh, there are a million
+ microseconds in a second, not just a thousand.
+
+Tue Dec 26 19:29:16 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * io-ops.c (S_io_select): Add REPLY parameter, and request
+ notification if it dies.
+ * mutations.h (IO_SELECT_REPLY_PORT): New def.
+
+Thu Dec 14 18:50:07 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * ethernet.c (ethernet_open): Don't set filter priority high.
+
+Mon Dec 11 13:23:49 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * socket-ops.c (S_socket_recv): Whoops, incorrectly negated this
+ particular return value. Rename the variable `recvd' to make
+ things more clear.
+ (S_socket_send): Ditto (`sent'), plus correctly check the return
+ value when deciding whether to deallocate ADDR's send right.
+
+Thu Dec 7 18:24:37 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * socket-ops.c (S_socket_recv, S_socket_bind, S_socket_send):
+ Negate error return values from linux code.
+ (S_socket_setopt): Implement.
+
+Wed Aug 23 14:20:48 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * Makefile (pfinet): Put all dependencies here.
+ (HURDLIBS): Removed.
diff --git a/pfinet/Makefile b/pfinet/Makefile
new file mode 100644
index 00000000..81e76480
--- /dev/null
+++ b/pfinet/Makefile
@@ -0,0 +1,116 @@
+#
+# Copyright (C) 1995,96,97,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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+
+dir := pfinet
+makemode := server
+
+core-srcs := datagram.c \
+ dev.c \
+ dev_mcast.c \
+ dst.c \
+ iovec.c \
+ neighbour.c \
+ skbuff.c \
+ sock.c \
+ utils.c
+arch-lib-srcs := checksum.c old-checksum.c
+ethernet-srcs := eth.c
+ipv4-srcs := af_inet.c \
+ arp.c \
+ devinet.c \
+ fib_frontend.c \
+ fib_hash.c \
+ fib_semantics.c \
+ icmp.c \
+ igmp.c \
+ ip_forward.c \
+ ip_fragment.c \
+ ip_input.c \
+ ip_options.c \
+ ip_output.c \
+ ip_sockglue.c \
+ protocol.c \
+ raw.c \
+ route.c \
+ syncookies.c \
+ sysctl_net_ipv4.c \
+ tcp.c \
+ tcp_input.c \
+ tcp_ipv4.c \
+ tcp_output.c \
+ tcp_timer.c \
+ timer.c \
+ udp.c \
+ utils.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
+MIGSRCS = ioServer.c socketServer.c startup_notifyServer.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 \
+ p8022call.h protocol.h psnap.h psnapcall.h \
+ rarp.h raw.h route.h snmp.h sock.h tcp.h udp.h
+FROBBEDLINUXHEADERS = autoconf.h config.h errno.h etherdevice.h fcntl.h \
+ icmp.h if.h if_arp.h if_ether.h igmp.h in.h inet.h interrupt.h \
+ ip.h ip_fw.h ipx.h kernel.h major.h malloc.h mm.h net.h netdevice.h \
+ notifier.h param.h route.h sched.h skbuff.h socket.h sockios.h stat.h \
+ string.h tcp.h termios.h time.h timer.h types.h udp.h un.h wait.h
+ASMHEADERS=bitops.h segment.h system.h
+
+HURDLIBS=trivfs fshelp threads ports ihash shouldbeinlibc iohelp
+
+target = pfinet
+
+include ../Makeconf
+
+vpath %.c $(addprefix $(srcdir)/linux-src/net/,core ethernet ipv4)
+vpath %.c $(srcdir)/linux-src/arch/$(asm_syntax)/lib
+vpath %.S $(srcdir)/linux-src/arch/$(asm_syntax)/lib
+
+CPPFLAGS += '-D_HURD_SYSTYPE="$(asm_syntax)"' \
+ -imacros $(srcdir)/config.h \
+ -I$(srcdir)/glue-include \
+ -I$(srcdir)/linux-src/include
+
+io-MIGSFLAGS = -imacros $(srcdir)/mutations.h
+socket-MIGSFLAGS = -imacros $(srcdir)/mutations.h
+
+# cpp doesn't automatically make dependencies for -imacros dependencies. argh.
+io_S.h ioServer.c socket_S.h socketServer.c: mutations.h
+$(OBJS): config.h
+
+lndist: lndist-linux-inet-files lndist-linux-files lndist-asm-files
+
+lndist-linux-inet-files: $(top_srcdir)/hurd-snap/$(dir)/linux-inet
+ ln $(addprefix $(srcdir)/linux-inet/,$(LINUXSRCS) $(UNUSEDSRC) $(LINUXHDRS)) $<
+
+lndist-linux-files: $(top_srcdir)/hurd-snap/$(dir)/linux
+ ln $(addprefix $(srcdir)/linux/,$(FROBBEDLINUXHEADERS)) $<
+
+lndist-asm-files: $(top_srcdir)/hurd-snap/$(dir)/asm
+ ln $(addprefix $(srcdir)/asm/,$(ASMHEADERS)) $<
+
+$(top_srcdir)/hurd-snap/$(dir)/linux-inet:
+ mkdir $@
+$(top_srcdir)/hurd-snap/$(dir)/linux:
+ mkdir $@
+$(top_srcdir)/hurd-snap/$(dir)/asm:
+ mkdir $@
diff --git a/pfinet/README b/pfinet/README
new file mode 100644
index 00000000..decbb307
--- /dev/null
+++ b/pfinet/README
@@ -0,0 +1,49 @@
+The Hurd's pfinet server is based on networking code taken from
+the Linux kernel sources, initially version 2.2.12 of Linux.
+The subset of the Linux kernel sources used for pfinet is kept
+in the linux-src subdirectory.
+
+This file describes the procedures for tracking new Linux kernel versions
+and updating the Linux networking code in the Hurd CVS repository.
+
+The verbatim Linux kernel sources are kept on a vendor branch in CVS. To
+simplify the process of importing and merging new versions, I have mostly
+imported whole subdirectories of the linux source tree rather than just the
+precise subset of files we are actually using. However, for the arch/*/lib
+and include/asm-* subdirectories I have taken just the checksum files (the
+only thing we use from the machine-dependent Linux code); and I have
+removed the extraneous whole subdirectories within the include/linux and
+include/net directories. It is my intention to leave the remaining
+extraneous files in the CVS repository, but to include in the distributions
+only the files we are actually using (they will be listed in the Makefile).
+They could also be left on the vendor branch and removed from the trunk, but
+I think that would have more disadvantages than advantages.
+
+The initial import was done with the following commands. It is crucial to
+use `-I !' in the `cvs import' command because of the directory
+linux-src/net/core/ ("core" is in CVS's default list of names to ignore).
+
+mkdir import-tmp
+cd import-tmp
+bunzip2 < linux-2.2.12.tar.bz2 | tar xf - linux/{'arch/*/lib/*checksum*','include/asm-*/checksum.h',include/{linux,net},net/{core,ipv4,ethernet}}
+cd linux
+rm -rf include/{net,linux}/*/
+cvs -d `cat ../../CVS/Root` import -I ! -ko -m "Import of Linux 2.2.12 subset (ipv4 stack and related)" hurd/pfinet/linux-src Linux Linux_2_2_12
+
+It should work to repeat the same procedure with later versions to upgrade
+the `Linux' vendor branch. Please import only verbatim official Linux
+kernel sources, and stick to the tag name schema. If you don't already
+know how to merge the new vendor release into the trunk and finish the
+upgrade, then you probably should not be doing this anyway.
+
+On the main branch, only a few files within the linux-src tree are
+modified, and those only lightly (the changes are described in ChangeLog).
+Linux header files that are heavily modified or wholly replaced for use in
+pfinet go into the glue-include/ subdirectory instead of modifying
+linux-src files in place. Whole C source files can just be replaced with
+new files in the top-level pfinet source directory. When modifications to
+a file in linux-src are justified, the modifications should always be
+conditionalized by #ifdef _HURD_.
+
+
+ -- Roland McGrath <roland@gnu.org> 2000-02-03
diff --git a/pfinet/config.h b/pfinet/config.h
new file mode 100644
index 00000000..ce079620
--- /dev/null
+++ b/pfinet/config.h
@@ -0,0 +1,36 @@
+#define __KERNEL__ 1
+#undef __SMP__
+
+#define _HURD_ 1
+#define ENONET ENETUNREACH
+
+
+#define CONFIG_NET 1
+#define CONFIG_INET 1
+
+#undef CONFIG_IPX
+#undef CONFIG_ATALK
+#undef CONFIG_PACKET
+#undef CONFIG_UNIX
+#undef CONFIG_NETLINK
+#undef CONFIG_RTNETLINK
+
+#undef CONFIG_FIREWALL
+#undef CONFIG_FILTER
+
+#undef CONFIG_IP_MULTICAST
+#undef CONFIG_IP_ROUTER
+#undef CONFIG_IP_ADVANCED_ROUTER
+#undef CONFIG_IP_PNP
+#undef CONFIG_IP_ALIAS
+
+#undef CONFIG_NET_IPIP
+#undef CONFIG_NET_IPGRE
+
+#undef CONFIG_SYN_COOKIES
+
+#undef CONFIG_INET_RARP
+
+#define CONFIG_SKB_LARGE 1
+
+#define CONFIG_IP_NOSIOCRT 1 /* How convenient. */
diff --git a/pfinet/ethernet.c b/pfinet/ethernet.c
new file mode 100644
index 00000000..1b81e1aa
--- /dev/null
+++ b/pfinet/ethernet.c
@@ -0,0 +1,247 @@
+/*
+ Copyright (C) 1995,96,98,99,2000 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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 <device/device.h>
+#include <device/net_status.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <error.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+
+device_t ether_port;
+
+struct port_class *etherreadclass;
+struct port_info *readpt;
+mach_port_t readptname;
+
+struct device ether_dev;
+
+struct enet_statistics retbuf;
+
+
+/* Mach doesn't provide this. DAMN. */
+struct enet_statistics *
+ethernet_get_stats (struct device *dev)
+{
+ return &retbuf;
+}
+
+int
+ethernet_stop (struct device *dev)
+{
+ return 0;
+}
+
+void
+ethernet_set_multi (struct device *dev)
+{
+}
+
+static short ether_filter[] =
+{
+ NETF_PUSHLIT | NETF_NOP,
+ 1
+};
+static int ether_filter_len = sizeof (ether_filter) / sizeof (short);
+
+static struct port_bucket *etherport_bucket;
+
+
+static any_t
+ethernet_thread (any_t arg)
+{
+ ports_manage_port_operations_one_thread (etherport_bucket,
+ ethernet_demuxer,
+ 0);
+ return 0;
+}
+
+int
+ethernet_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ struct net_rcv_msg *msg = (struct net_rcv_msg *) inp;
+ struct sk_buff *skb;
+ int datalen;
+
+ if (inp->msgh_id != NET_RCV_MSG_ID)
+ return 0;
+
+ if (inp->msgh_local_port != readptname)
+ {
+ if (inp->msgh_remote_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), inp->msgh_remote_port);
+ return 1;
+ }
+
+ datalen = ETH_HLEN
+ + msg->packet_type.msgt_number - sizeof (struct packet_header);
+
+ __mutex_lock (&net_bh_lock);
+ skb = alloc_skb (datalen, GFP_ATOMIC);
+ skb->len = datalen;
+ skb->dev = &ether_dev;
+
+ /* Copy the two parts of the frame into the buffer. */
+ bcopy (msg->header, skb->data, ETH_HLEN);
+ bcopy (msg->packet + sizeof (struct packet_header),
+ skb->data + ETH_HLEN,
+ datalen - ETH_HLEN);
+
+ /* Drop it on the queue. */
+ skb->protocol = eth_type_trans (skb, &ether_dev);
+ netif_rx (skb);
+ __mutex_unlock (&net_bh_lock);
+
+ return 1;
+}
+
+
+void
+ethernet_initialize (void)
+{
+ etherport_bucket = ports_create_bucket ();
+ etherreadclass = ports_create_class (0, 0);
+
+ cthread_detach (cthread_fork (ethernet_thread, 0));
+}
+
+int
+ethernet_open (struct device *dev)
+{
+ error_t err;
+ device_t master_device;
+
+ assert (ether_port == MACH_PORT_NULL);
+
+ err = ports_create_port (etherreadclass, etherport_bucket,
+ sizeof (struct port_info), &readpt);
+ assert_perror (err);
+ readptname = ports_get_right (readpt);
+ mach_port_insert_right (mach_task_self (), readptname, readptname,
+ MACH_MSG_TYPE_MAKE_SEND);
+
+ mach_port_set_qlimit (mach_task_self (), readptname, MACH_PORT_QLIMIT_MAX);
+
+ err = get_privileged_ports (0, &master_device);
+ if (err)
+ error (2, err, "cannot get device master port");
+
+ err = device_open (master_device, D_WRITE | D_READ, dev->name, &ether_port);
+ mach_port_deallocate (mach_task_self (), master_device);
+ if (err)
+ error (2, err, "%s", dev->name);
+
+ err = device_set_filter (ether_port, ports_get_right (readpt),
+ MACH_MSG_TYPE_MAKE_SEND, 0,
+ ether_filter, ether_filter_len);
+ if (err)
+ error (2, err, "%s", dev->name);
+ return 0;
+}
+
+
+/* Transmit an ethernet frame */
+int
+ethernet_xmit (struct sk_buff *skb, struct device *dev)
+{
+ u_int count;
+ error_t err;
+
+ err = device_write (ether_port, D_NOWAIT, 0, skb->data, skb->len, &count);
+ assert_perror (err);
+ assert (count == skb->len);
+ dev_kfree_skb (skb);
+ return 0;
+}
+
+void
+setup_ethernet_device (char *name)
+{
+ struct net_status netstat;
+ u_int count;
+ int net_address[2];
+ error_t err;
+
+ bzero (&ether_dev, sizeof ether_dev);
+
+ ether_dev.name = strdup (name);
+
+ /* Functions. These ones are the true "hardware layer" in Linux. */
+ ether_dev.open = 0; /* We set up before calling dev_open. */
+ ether_dev.stop = ethernet_stop;
+ ether_dev.hard_start_xmit = ethernet_xmit;
+ ether_dev.get_stats = ethernet_get_stats;
+ ether_dev.set_multicast_list = ethernet_set_multi;
+
+ /* These are the ones set by drivers/net/net_init.c::ether_setup. */
+ ether_dev.hard_header = eth_header;
+ ether_dev.rebuild_header = eth_rebuild_header;
+ ether_dev.hard_header_cache = eth_header_cache;
+ ether_dev.header_cache_update = eth_header_cache_update;
+ ether_dev.hard_header_parse = eth_header_parse;
+ /* We can't do these two (and we never try anyway). */
+ /* ether_dev.change_mtu = eth_change_mtu; */
+ /* ether_dev.set_mac_address = eth_mac_addr; */
+
+ /* Some more fields */
+ ether_dev.type = ARPHRD_ETHER;
+ ether_dev.hard_header_len = ETH_HLEN;
+ ether_dev.addr_len = ETH_ALEN;
+ memset (ether_dev.broadcast, 0xff, ETH_ALEN);
+ ether_dev.flags = IFF_BROADCAST | IFF_MULTICAST;
+ dev_init_buffers (&ether_dev);
+
+ ethernet_open (&ether_dev);
+
+ /* Fetch hardware information */
+ count = NET_STATUS_COUNT;
+ err = device_get_status (ether_port, NET_STATUS,
+ (dev_status_t) &netstat, &count);
+ if (err)
+ error (2, err, "%s: Cannot get device status", name);
+ ether_dev.mtu = netstat.max_packet_size - ether_dev.hard_header_len;
+ assert (netstat.header_format == HDR_ETHERNET);
+ assert (netstat.header_size == ETH_HLEN);
+ assert (netstat.address_size == ETH_ALEN);
+
+ count = 2;
+ assert (count * sizeof (int) >= ETH_ALEN);
+ err = device_get_status (ether_port, NET_ADDRESS, net_address, &count);
+ if (err)
+ error (2, err, "%s: Cannot get hardware Ethernet address", name);
+ net_address[0] = ntohl (net_address[0]);
+ net_address[1] = ntohl (net_address[1]);
+ bcopy (net_address, ether_dev.dev_addr, ETH_ALEN);
+
+ /* That should be enough. */
+
+ /* This call adds the device to the `dev_base' chain,
+ initializes its `ifindex' member (which matters!),
+ and tells the protocol stacks about the device. */
+ err = - register_netdevice (&ether_dev);
+ assert_perror (err);
+}
diff --git a/pfinet/glue-include/asm/atomic.h b/pfinet/glue-include/asm/atomic.h
new file mode 100644
index 00000000..d053854e
--- /dev/null
+++ b/pfinet/glue-include/asm/atomic.h
@@ -0,0 +1,27 @@
+#ifndef _HACK_ASM_ATOMIC_H
+#define _HACK_ASM_ATOMIC_H
+
+/* We don't need atomicity in the Linux code because we serialize all
+ entries to it. */
+
+typedef struct { int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+static __inline__ void atomic_add(int i, atomic_t *v) { v->counter += i; }
+static __inline__ void atomic_sub(int i, atomic_t *v) { v->counter -= i; }
+static __inline__ void atomic_inc(atomic_t *v) { ++v->counter; }
+static __inline__ void atomic_dec(atomic_t *v) { --v->counter; }
+static __inline__ int atomic_dec_and_test(atomic_t *v)
+{ return --v->counter == 0; }
+static __inline__ int atomic_inc_and_test_greater_zero(atomic_t *v)
+{ return ++v->counter > 0; }
+
+#define atomic_clear_mask(mask, addr) (*(addr) &= ~(mask))
+#define atomic_set_mask(mask, addr) (*(addr) |= (mask))
+
+
+#endif
diff --git a/pfinet/glue-include/asm/bitops.h b/pfinet/glue-include/asm/bitops.h
new file mode 100644
index 00000000..8c5a835d
--- /dev/null
+++ b/pfinet/glue-include/asm/bitops.h
@@ -0,0 +1,37 @@
+#ifndef _HACK_ASM_BITOPS_H
+#define _HACK_ASM_BITOPS_H
+
+/* We don't need atomicity in the Linux code because we serialize all
+ entries to it. */
+
+#include <stdint.h>
+
+#define BITOPS_WORD(nr, addr) (((uint32_t *) (addr))[(nr) / 32])
+#define BITOPS_MASK(nr) (1 << ((nr) & 31))
+
+static __inline__ void set_bit (int nr, void *addr)
+{ BITOPS_WORD (nr, addr) |= BITOPS_MASK (nr); }
+
+static __inline__ void clear_bit (int nr, void *addr)
+{ BITOPS_WORD (nr, addr) &= ~BITOPS_MASK (nr); }
+
+static __inline__ void change_bit (int nr, void *addr)
+{ BITOPS_WORD (nr, addr) ^= BITOPS_MASK (nr); }
+
+static __inline__ int test_bit (int nr, void *addr)
+{ return BITOPS_WORD (nr, addr) & BITOPS_MASK (nr); }
+
+static __inline__ int test_and_set_bit (int nr, void *addr)
+{
+ int res = BITOPS_WORD (nr, addr) & BITOPS_MASK (nr);
+ BITOPS_WORD (nr, addr) |= BITOPS_MASK (nr);
+ return res;
+}
+
+#define find_first_zero_bit #error loser
+#define find_next_zero_bit #error loser
+
+#define ffz(word) (ffs (~(unsigned int) (word)) - 1)
+
+
+#endif
diff --git a/pfinet/glue-include/asm/byteorder.h b/pfinet/glue-include/asm/byteorder.h
new file mode 100644
index 00000000..ee1da1f4
--- /dev/null
+++ b/pfinet/glue-include/asm/byteorder.h
@@ -0,0 +1,154 @@
+/* Provide the specified-byte-order access functions used in the Linux
+ kernel, implemented as macros in terms of the GNU libc facilities. */
+
+#ifndef _HACK_ASM_BYTEORDER_H
+#define _HACK_ASM_BYTEORDER_H 1
+
+#include <endian.h>
+#include <byteswap.h>
+
+#define BO_cvt(bits, from, to, x) \
+ ((from) == (to) ? (u_int##bits##_t) (x) : bswap_##bits (x))
+#define BO_cvtp(bits, from, to, p) \
+ BO_cvt (bits, from, to, *(const u_int##bits##_t *) (p))
+#define BO_cvts(bits, from, to, p) \
+ ({ const u_int##bits##_t *_p = (p); *_p = BO_cvt (bits, from, to, *_p); })
+
+#define __cpu_to_le64(x) BO_cvt (64, BYTE_ORDER, LITTLE_ENDIAN, (x))
+#define __le64_to_cpu(x) BO_cvt (64, LITTLE_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_le32(x) BO_cvt (32, BYTE_ORDER, LITTLE_ENDIAN, (x))
+#define __le32_to_cpu(x) BO_cvt (32, LITTLE_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_le16(x) BO_cvt (16, BYTE_ORDER, LITTLE_ENDIAN, (x))
+#define __le16_to_cpu(x) BO_cvt (16, LITTLE_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_be64(x) BO_cvt (64, BYTE_ORDER, BIG_ENDIAN, (x))
+#define __be64_to_cpu(x) BO_cvt (64, BIG_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_be32(x) BO_cvt (32, BYTE_ORDER, BIG_ENDIAN, (x))
+#define __be32_to_cpu(x) BO_cvt (32, BIG_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_be16(x) BO_cvt (16, BYTE_ORDER, BIG_ENDIAN, (x))
+#define __be16_to_cpu(x) BO_cvt (16, BIG_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_le64p(p) BO_cvtp (64, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le64_to_cpup(p) BO_cvtp (64, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le32p(p) BO_cvtp (32, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le32_to_cpup(p) BO_cvtp (32, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le16p(p) BO_cvtp (16, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le16_to_cpup(p) BO_cvtp (16, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be64p(p) BO_cvtp (64, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be64_to_cpup(p) BO_cvtp (64, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be32p(p) BO_cvtp (32, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be32_to_cpup(p) BO_cvtp (32, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be16p(p) BO_cvtp (16, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be16_to_cpup(p) BO_cvtp (16, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le64s(p) BO_cvts (64, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le64_to_cpus(p) BO_cvts (64, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le32s(p) BO_cvts (32, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le32_to_cpus(p) BO_cvts (32, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le16s(p) BO_cvts (16, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le16_to_cpus(p) BO_cvts (16, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be64s(p) BO_cvts (64, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be64_to_cpus(p) BO_cvts (64, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be32s(p) BO_cvts (32, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be32_to_cpus(p) BO_cvts (32, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be16s(p) BO_cvts (16, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be16_to_cpus(p) BO_cvts (16, BIG_ENDIAN, BYTE_ORDER, (p))
+
+#define cpu_to_le64 __cpu_to_le64
+#define le64_to_cpu __le64_to_cpu
+#define cpu_to_le32 __cpu_to_le32
+#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le16 __cpu_to_le16
+#define le16_to_cpu __le16_to_cpu
+#define cpu_to_be64 __cpu_to_be64
+#define be64_to_cpu __be64_to_cpu
+#define cpu_to_be32 __cpu_to_be32
+#define be32_to_cpu __be32_to_cpu
+#define cpu_to_be16 __cpu_to_be16
+#define be16_to_cpu __be16_to_cpu
+#define cpu_to_le64p __cpu_to_le64p
+#define le64_to_cpup __le64_to_cpup
+#define cpu_to_le32p __cpu_to_le32p
+#define le32_to_cpup __le32_to_cpup
+#define cpu_to_le16p __cpu_to_le16p
+#define le16_to_cpup __le16_to_cpup
+#define cpu_to_be64p __cpu_to_be64p
+#define be64_to_cpup __be64_to_cpup
+#define cpu_to_be32p __cpu_to_be32p
+#define be32_to_cpup __be32_to_cpup
+#define cpu_to_be16p __cpu_to_be16p
+#define be16_to_cpup __be16_to_cpup
+#define cpu_to_le64s __cpu_to_le64s
+#define le64_to_cpus __le64_to_cpus
+#define cpu_to_le32s __cpu_to_le32s
+#define le32_to_cpus __le32_to_cpus
+#define cpu_to_le16s __cpu_to_le16s
+#define le16_to_cpus __le16_to_cpus
+#define cpu_to_be64s __cpu_to_be64s
+#define be64_to_cpus __be64_to_cpus
+#define cpu_to_be32s __cpu_to_be32s
+#define be32_to_cpus __be32_to_cpus
+#define cpu_to_be16s __cpu_to_be16s
+#define be16_to_cpus __be16_to_cpus
+
+
+#if BYTE_ORDER == BIG_ENDIAN
+# define __BIG_ENDIAN_BITFIELD
+#elif BYTE_ORDER == LITTLE_ENDIAN
+# define __LITTLE_ENDIAN_BITFIELD
+#else
+# error __FOO_ENDIAN_BITFIELD
+#endif
+
+
+#include <netinet/in.h> /* for htonl et al */
+
+/* Though the optimized macros defined by glibc do the constant magic,
+ there are places in the Linux code that use these in constant-only
+ places like initializers, and the ({...}) expressions the macros use are
+ not valid in those contexts. */
+#if BYTE_ORDER == BIG_ENDIAN
+# if !defined(__constant_htonl)
+# define __constant_htonl(x) (x)
+# endif
+# if !defined(__constant_htons)
+# define __constant_htons(x) (x)
+# endif
+#elif BYTE_ORDER == LITTLE_ENDIAN
+# if !defined(__constant_htonl)
+# define __constant_htonl(x) \
+ ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
+ (((unsigned long int)(x) & 0x0000ff00U) << 8) | \
+ (((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
+ (((unsigned long int)(x) & 0xff000000U) >> 24)))
+# endif
+# if !defined(__constant_htons)
+# define __constant_htons(x) \
+ ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
+ (((unsigned short int)(x) & 0xff00) >> 8)))
+# endif
+#else
+# error "Don't know if bytes are big- or little-endian!"
+#endif
+
+/* The transformation is the same in both directions. */
+#define __constant_ntohl __constant_htonl
+#define __constant_ntohs __constant_htons
+
+
+/* Some Linux code (e.g. <net/tcp.h>) uses #ifdef __BIG_ENDIAN et al.
+ This is not real wonderful with the glibc definitions, where
+ __BIG_ENDIAN et al are always defined (as values for __BYTE_ORDER). */
+#if BYTE_ORDER == BIG_ENDIAN
+#undef __LITTLE_ENDIAN
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#undef __BIG_ENDIAN
+#endif
+#undef __PDP_ENDIAN
+
+/* Since we've now broken anything that does glibc-style tests,
+ make sure they break loudly rather than silently. Any headers
+ that need __BYTE_ORDER will just have to be included before
+ we diddle with __BIG_ENDIAN or __LITTLE_ENDIAN above. */
+#undef __BYTE_ORDER
+#define __BYTE_ORDER ?????crash?????
+
+
+#endif /* asm/byteorder.h */
diff --git a/pfinet/glue-include/asm/checksum.h b/pfinet/glue-include/asm/checksum.h
new file mode 100644
index 00000000..5bcf7551
--- /dev/null
+++ b/pfinet/glue-include/asm/checksum.h
@@ -0,0 +1,5 @@
+/* This is the only file from the Linux include/asm-* directory
+ that we use, so we use this magic file here rather than making a
+ symlink asm -> .../linux-src/include/asm-SYSTYPE somewhere. */
+
+#include "../../linux-src/include/asm-" _HURD_SYSTYPE "/checksum.h"
diff --git a/pfinet/glue-include/asm/errno.h b/pfinet/glue-include/asm/errno.h
new file mode 100644
index 00000000..7afb6fdc
--- /dev/null
+++ b/pfinet/glue-include/asm/errno.h
@@ -0,0 +1,3 @@
+/* This is used only by checksum.S; the C code uses <linux/errno.h>. */
+
+#define EFAULT 42 /* only used in unreached code */
diff --git a/pfinet/glue-include/asm/hardirq.h b/pfinet/glue-include/asm/hardirq.h
new file mode 100644
index 00000000..c73d7dcb
--- /dev/null
+++ b/pfinet/glue-include/asm/hardirq.h
@@ -0,0 +1 @@
+#include <linux/interrupt.h>
diff --git a/pfinet/glue-include/asm/init.h b/pfinet/glue-include/asm/init.h
new file mode 100644
index 00000000..2331be7c
--- /dev/null
+++ b/pfinet/glue-include/asm/init.h
@@ -0,0 +1,3 @@
+#define __init
+#define __initdata
+#define __initfunc(x) x
diff --git a/pfinet/glue-include/asm/segment.h b/pfinet/glue-include/asm/segment.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pfinet/glue-include/asm/segment.h
diff --git a/pfinet/glue-include/asm/spinlock.h b/pfinet/glue-include/asm/spinlock.h
new file mode 100644
index 00000000..937c5d05
--- /dev/null
+++ b/pfinet/glue-include/asm/spinlock.h
@@ -0,0 +1,75 @@
+#ifndef _HACK_ASM_SPINLOCK_H_
+#define _HACK_ASM_SPINLOCK_H_
+
+#include <cthreads.h>
+
+typedef struct { } spinlock_t;
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { }
+
+#undef spin_lock_init
+#undef spin_lock
+#undef spin_unlock
+
+#define spin_lock_init(lock) ((void) (lock))
+#define spin_lock(lock) ((void) (lock))
+#define spin_trylock(lock) ((void) (lock), 1)
+#define spin_unlock_wait(lock) ((void) (lock))
+#define spin_unlock(lock) ((void) (lock))
+#define spin_lock_irq(lock) ((void) (lock))
+#define spin_unlock_irq(lock) ((void) (lock))
+#define spin_lock_irqsave(lock, flags) ((void) (lock), (void) (flags))
+#define spin_unlock_irqrestore(lock, flags) ((void) (lock), (void) (flags))
+
+typedef struct { } rwlock_t;
+#define read_lock(rw) do { } while(0)
+#define write_lock(rw) do { } while(0)
+#define write_unlock(rw) do { } while(0)
+#define read_unlock(rw) do { } while(0)
+
+#if 0
+#include <rwlock.h>
+
+typedef struct mutex spinlock_t;
+
+#undef spin_lock_init
+#undef spin_lock
+#undef spin_unlock
+
+#define SPIN_LOCK_UNLOCKED MUTEX_INITIALIZER
+#define spin_lock_init(lock) ({ __mutex_init (lock); })
+#define spin_lock(lock) ({ __mutex_lock (lock); })
+#define spin_trylock(lock) ({ __mutex_trylock (lock); })
+#define spin_unlock_wait(lock) ({ __mutex_unlock (lock); })
+#define spin_unlock(lock) ({ __mutex_unlock (lock); })
+#define spin_lock_irq(lock) ({ __mutex_lock (lock); })
+#define spin_unlock_irq(lock) ({ __mutex_unlock (lock); })
+
+#define spin_lock_irqsave(lock, flags) \
+ do { flags = 0; __mutex_lock (lock); } while (0)
+#define spin_unlock_irqrestore(lock, flags) ({ __mutex_unlock (lock); })
+
+
+typedef struct rwlock rwlock_t;
+
+#define read_lock(rw) rwlock_reader_lock(rw)
+#define write_lock(rw) rwlock_writer_lock(rw)
+#define write_unlock(rw) rwlock_writer_unlock(rw)
+#define read_unlock(rw) rwlock_reader_unlock(rw)
+
+#endif
+
+
+#define read_lock_irq(lock) read_lock(lock)
+#define read_unlock_irq(lock) read_unlock(lock)
+#define write_lock_irq(lock) write_lock(lock)
+#define write_unlock_irq(lock) write_unlock(lock)
+
+#define read_lock_irqsave(lock, flags) \
+ do { (flags) = 0; read_lock(lock); } while (0)
+#define read_unlock_irqrestore(lock, flags) read_unlock(lock)
+#define write_lock_irqsave(lock, flags) \
+ do { (flags) = 0; write_lock(lock); } while (0)
+#define write_unlock_irqrestore(lock, flags) write_unlock(lock)
+
+
+#endif
diff --git a/pfinet/glue-include/asm/system.h b/pfinet/glue-include/asm/system.h
new file mode 100644
index 00000000..1a5d61cd
--- /dev/null
+++ b/pfinet/glue-include/asm/system.h
@@ -0,0 +1,20 @@
+#ifndef _HACK_ASM_SYSTEM_H
+#define _HACK_ASM_SYSTEM_H
+
+/* We don't need atomicity in the Linux code because we serialize all
+ entries to it. */
+
+#include <stdint.h>
+
+#define xchg(ptr, x) \
+ ({ \
+ __typeof__ (*(ptr)) *_ptr = (ptr), _x = *_ptr; \
+ (uintptr_t) *_ptr = (x); _x; \
+ })
+
+#define mb() ((void) 0) /* memory barrier */
+#define rmb() mb()
+#define wmb() mb()
+
+
+#endif
diff --git a/pfinet/glue-include/asm/types.h b/pfinet/glue-include/asm/types.h
new file mode 100644
index 00000000..ee9b980a
--- /dev/null
+++ b/pfinet/glue-include/asm/types.h
@@ -0,0 +1 @@
+#include <linux/types.h>
diff --git a/pfinet/glue-include/asm/uaccess.h b/pfinet/glue-include/asm/uaccess.h
new file mode 100644
index 00000000..d8373797
--- /dev/null
+++ b/pfinet/glue-include/asm/uaccess.h
@@ -0,0 +1,47 @@
+#ifndef _HACK_ASM_UACCESS_H_
+#define _HACK_ASM_UACCESS_H_
+
+#include <linux/mm.h>
+
+
+#define MAKE_MM_SEG(s) XXX
+#define KERNEL_DS XXX
+#define USER_DS XXX
+
+#define get_ds() XXX
+#define get_fs() XXX
+#define set_fs(x) XXX
+
+#define segment_eq(a,b) XXX
+
+extern int __verify_write(const void *, unsigned long);
+#define __verify_write XXX
+
+#define __addr_ok(addr) (1)
+#define __range_ok(addr,size) (1)
+#define access_ok(type,addr,size) (1)
+
+#define put_user(x,ptr) (*(ptr) = (x), 0)
+#define get_user(x,ptr) ((x) = *(ptr), 0)
+
+/*
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
+ */
+
+#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
+
+#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
+
+
+#define copy_to_user(to,from,n) (memcpy ((to), (from), (n)), 0)
+#define copy_from_user(to,from,n) (memcpy ((to), (from), (n)), 0)
+#define clear_user(mem, len) (bzero ((mem), (len)), 0)
+
+#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
+
+#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
+
+
+#endif
diff --git a/pfinet/glue-include/linux/autoconf.h b/pfinet/glue-include/linux/autoconf.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pfinet/glue-include/linux/autoconf.h
diff --git a/pfinet/glue-include/linux/binfmts.h b/pfinet/glue-include/linux/binfmts.h
new file mode 100644
index 00000000..c8229dad
--- /dev/null
+++ b/pfinet/glue-include/linux/binfmts.h
@@ -0,0 +1 @@
+#include <linux/capability.h>
diff --git a/pfinet/glue-include/linux/config.h b/pfinet/glue-include/linux/config.h
new file mode 100644
index 00000000..be1e4d3f
--- /dev/null
+++ b/pfinet/glue-include/linux/config.h
@@ -0,0 +1 @@
+#include <linux/errno.h>
diff --git a/pfinet/glue-include/linux/errno.h b/pfinet/glue-include/linux/errno.h
new file mode 100644
index 00000000..7afcd9fd
--- /dev/null
+++ b/pfinet/glue-include/linux/errno.h
@@ -0,0 +1,13 @@
+#ifndef _HACK_ERRNO_H
+#define _HACK_ERRNO_H
+
+#include <errno.h>
+#include <hurd.h>
+
+#define ERESTARTSYS EINTR
+#define ENOPKG ENOSYS
+#define ENOIOCTLCMD ENOTTY
+
+#undef errno
+
+#endif
diff --git a/pfinet/glue-include/linux/fcntl.h b/pfinet/glue-include/linux/fcntl.h
new file mode 100644
index 00000000..cd304557
--- /dev/null
+++ b/pfinet/glue-include/linux/fcntl.h
@@ -0,0 +1 @@
+#include <fcntl.h>
diff --git a/pfinet/glue-include/linux/fs.h b/pfinet/glue-include/linux/fs.h
new file mode 100644
index 00000000..45dbb19f
--- /dev/null
+++ b/pfinet/glue-include/linux/fs.h
@@ -0,0 +1,21 @@
+#ifndef _HACK_FS_H
+#define _HACK_FS_H
+
+#include <linux/net.h>
+
+/* Hackery */
+struct inode
+{
+ union
+ {
+ int i_garbage;
+ struct socket socket_i; /* icmp.c actually needs this!! */
+ } u;
+};
+#define i_uid u.i_garbage
+#define i_gid u.i_garbage
+#define i_sock u.i_garbage
+#define i_ino u.i_garbage
+#define i_mode u.i_garbage
+
+#endif
diff --git a/pfinet/glue-include/linux/in.h b/pfinet/glue-include/linux/in.h
new file mode 100644
index 00000000..074c70e3
--- /dev/null
+++ b/pfinet/glue-include/linux/in.h
@@ -0,0 +1,44 @@
+#ifndef _HACK_IN_H_
+#define _HACK_IN_H_
+
+#include <netinet/in.h>
+
+/* IP_MTU_DISCOVER values */
+#define IP_PMTUDISC_DONT 0 /* Never send DF frames */
+#define IP_PMTUDISC_WANT 1 /* Use per route hints */
+#define IP_PMTUDISC_DO 2 /* Always DF */
+
+/* These need to appear somewhere around here */
+#define IP_DEFAULT_MULTICAST_TTL 1
+#define IP_DEFAULT_MULTICAST_LOOP 1
+
+struct ip_mreqn
+{
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_address; /* local IP address of interface */
+ int imr_ifindex; /* Interface index */
+};
+
+struct in_pktinfo
+{
+ int ipi_ifindex;
+ struct in_addr ipi_spec_dst;
+ struct in_addr ipi_addr;
+};
+
+
+/* <asm/byteorder.h> contains the htonl type stuff.. */
+#include <asm/byteorder.h>
+
+#ifdef __KERNEL__
+/* Some random defines to make it easier in the kernel.. */
+#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
+#define MULTICAST(x) (((x) & htonl(0xf0000000)) == htonl(0xe0000000))
+#define BADCLASS(x) (((x) & htonl(0xf0000000)) == htonl(0xf0000000))
+#define ZERONET(x) (((x) & htonl(0xff000000)) == htonl(0x00000000))
+#define LOCAL_MCAST(x) (((x) & htonl(0xFFFFFF00)) == htonl(0xE0000000))
+
+#endif
+
+
+#endif
diff --git a/pfinet/glue-include/linux/in6.h b/pfinet/glue-include/linux/in6.h
new file mode 100644
index 00000000..260020a6
--- /dev/null
+++ b/pfinet/glue-include/linux/in6.h
@@ -0,0 +1 @@
+#include <netinet/in.h>
diff --git a/pfinet/glue-include/linux/interrupt.h b/pfinet/glue-include/linux/interrupt.h
new file mode 100644
index 00000000..5f485e32
--- /dev/null
+++ b/pfinet/glue-include/linux/interrupt.h
@@ -0,0 +1,44 @@
+#ifndef _HACK_INTERRUPT_H_
+#define _HACK_INTERRUPT_H_
+
+#include <linux/netdevice.h>
+#include "pfinet.h"
+
+#define in_interrupt() (0)
+#define synchronize_irq() ((void) 0)
+
+#define synchronize_bh() ((void) 0) /* XXX ? */
+
+/* The code that can call these are already entered holding
+ global_lock, which locks out the net_bh worker thread. */
+#define start_bh_atomic() ((void) 0)
+#define end_bh_atomic() ((void) 0)
+/*
+extern struct mutex net_bh_lock;
+#define start_bh_atomic() __mutex_lock (&net_bh_lock)
+#define end_bh_atomic() __mutex_unlock (&net_bh_lock)
+*/
+
+/* See sched.c::net_bh_worker comments. */
+extern struct condition net_bh_wakeup;
+
+#define NET_BH 0xb00bee51
+
+/* The only call to this ever reached is in net/core/dev.c::netif_rx,
+ to announce having enqueued a packet on `backlog'. */
+static inline void
+mark_bh (int bh)
+{
+ assert (bh == NET_BH);
+ condition_broadcast (&net_bh_wakeup);
+}
+
+void net_bh (void);
+static inline void
+init_bh (int bh, void (*fn) (void))
+{
+ assert (bh == NET_BH);
+ assert (fn == &net_bh);
+}
+
+#endif
diff --git a/pfinet/glue-include/linux/ioctl.h b/pfinet/glue-include/linux/ioctl.h
new file mode 100644
index 00000000..6ec92cf7
--- /dev/null
+++ b/pfinet/glue-include/linux/ioctl.h
@@ -0,0 +1 @@
+#include <sys/ioctl.h>
diff --git a/pfinet/glue-include/linux/ipv6.h b/pfinet/glue-include/linux/ipv6.h
new file mode 100644
index 00000000..374f9b1e
--- /dev/null
+++ b/pfinet/glue-include/linux/ipv6.h
@@ -0,0 +1 @@
+#include <linux/in6.h>
diff --git a/pfinet/glue-include/linux/kernel.h b/pfinet/glue-include/linux/kernel.h
new file mode 100644
index 00000000..a0e101b9
--- /dev/null
+++ b/pfinet/glue-include/linux/kernel.h
@@ -0,0 +1,78 @@
+#ifndef _HACK_KERNEL_H
+#define _HACK_KERNEL_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+
+/* These don't actually matter since our locking protocols are different. */
+#define barrier() ((void)0) /*__asm__ __volatile__("": : :"memory") */
+
+#define NORET_TYPE /**/
+#define ATTRIB_NORET __attribute__((noreturn))
+#define NORET_AND noreturn,
+#define FASTCALL(x) x
+
+/* XXX do something syslogy */
+#define KERN_EMERG
+#define KERN_ALERT
+#define KERN_CRIT
+#define KERN_ERR
+#define KERN_WARNING
+#define KERN_NOTICE
+#define KERN_INFO
+#define KERN_DEBUG
+
+#define panic(str...) (printk (str), assert (!"panic"))
+
+/*
+ * Display an IP address in readable format.
+ */
+
+#define NIPQUAD(addr) \
+ ((unsigned char *)&addr)[0], \
+ ((unsigned char *)&addr)[1], \
+ ((unsigned char *)&addr)[2], \
+ ((unsigned char *)&addr)[3]
+
+
+#include <linux/sched.h>
+#include <linux/bitops.h>
+
+#define printk printf
+
+extern inline int
+getname (const char *name, char **newp)
+{
+ *newp = malloc (strlen (name) + 1);
+ strcpy (*newp, name);
+ return 0;
+}
+
+extern inline void
+putname (char *p)
+{
+ free (p);
+}
+
+/* These two functions are used only to send SIGURG. But I can't
+ find any SIGIO code at all. So we'll just punt on that; clearly
+ Linux is missing the point. SIGURG should only be sent for
+ sockets that have explicitly requested it. */
+extern inline int
+kill_proc (int pid, int signo, int priv)
+{
+ assert (signo == SIGURG);
+ return 0;
+}
+
+extern inline int
+kill_pg (int pgrp, int signo, int priv)
+{
+ assert (signo == SIGURG);
+ return 0;
+}
+
+
+#endif
diff --git a/pfinet/glue-include/linux/limits.h b/pfinet/glue-include/linux/limits.h
new file mode 100644
index 00000000..856c3bde
--- /dev/null
+++ b/pfinet/glue-include/linux/limits.h
@@ -0,0 +1,8 @@
+#ifndef _HACK_LIMITS_H
+#define _HACK_LIMITS_H
+
+#include <limits.h>
+
+#define UIO_MAXIOV 1024 /* probably 1 would do */
+
+#endif
diff --git a/pfinet/glue-include/linux/major.h b/pfinet/glue-include/linux/major.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pfinet/glue-include/linux/major.h
diff --git a/pfinet/glue-include/linux/malloc.h b/pfinet/glue-include/linux/malloc.h
new file mode 100644
index 00000000..46ae1051
--- /dev/null
+++ b/pfinet/glue-include/linux/malloc.h
@@ -0,0 +1,27 @@
+#ifndef _HACK_MALLOC_H_
+#define _HACK_MALLOC_H_
+
+#include <linux/mm.h>
+
+#include <stdlib.h>
+
+static inline void *kmalloc (size_t sz, int ignored) { return malloc (sz); }
+static inline void kfree (void *ptr) { free (ptr); }
+static inline void kfree_s (void *ptr, size_t sz) { free (ptr); }
+#define free(x) kfree(x) /* just don't ask */
+
+
+typedef struct kmem_cache_s kmem_cache_t;
+
+#define SLAB_HWCACHE_ALIGN 0 /* flag everybody uses */
+#define SLAB_ATOMIC 0
+
+
+extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
+ void (*)(void *, kmem_cache_t *, unsigned long),
+ void (*)(void *, kmem_cache_t *, unsigned long));
+extern void *kmem_cache_alloc(kmem_cache_t *, int);
+extern void kmem_cache_free(kmem_cache_t *, void *);
+
+
+#endif
diff --git a/pfinet/glue-include/linux/mm.h b/pfinet/glue-include/linux/mm.h
new file mode 100644
index 00000000..a6f28e00
--- /dev/null
+++ b/pfinet/glue-include/linux/mm.h
@@ -0,0 +1,18 @@
+#ifndef _HACK_MM_H_
+#define _HACK_MM_H_
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+/* All memory addresses are presumptively valid, because they are
+ all internal. */
+#define verify_area(a,b,c) 0
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 0
+#define GFP_ATOMIC 0
+#define GFP_KERNEL 0
+#define GFP_BUFFER 0
+#define __GFP_WAIT 0
+
+#endif
diff --git a/pfinet/glue-include/linux/param.h b/pfinet/glue-include/linux/param.h
new file mode 100644
index 00000000..39efaf0d
--- /dev/null
+++ b/pfinet/glue-include/linux/param.h
@@ -0,0 +1 @@
+#include <sys/param.h>
diff --git a/pfinet/glue-include/linux/personality.h b/pfinet/glue-include/linux/personality.h
new file mode 100644
index 00000000..9e218435
--- /dev/null
+++ b/pfinet/glue-include/linux/personality.h
@@ -0,0 +1 @@
+#include <linux/linkage.h>
diff --git a/pfinet/glue-include/linux/poll.h b/pfinet/glue-include/linux/poll.h
new file mode 100644
index 00000000..d608abf2
--- /dev/null
+++ b/pfinet/glue-include/linux/poll.h
@@ -0,0 +1,24 @@
+#ifndef _HACK_POLL_H_
+#define _HACK_POLL_H_
+
+#include <hurd/hurd_types.h>
+
+#define POLLIN SELECT_READ
+#define POLLRDNORM SELECT_READ
+#define POLLOUT SELECT_WRITE
+#define POLLWRNORM SELECT_WRITE
+#define POLLWRBAND SELECT_WRITE
+#define POLLPRI SELECT_URG
+#define POLLERR 0
+#define POLLHUP 0
+
+typedef struct poll_table_struct { } poll_table;
+
+#include <linux/sched.h>
+
+static inline void
+poll_wait(struct file * filp, struct wait_queue ** wait_address, poll_table *p)
+{
+}
+
+#endif
diff --git a/pfinet/glue-include/linux/proc_fs.h b/pfinet/glue-include/linux/proc_fs.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pfinet/glue-include/linux/proc_fs.h
diff --git a/pfinet/glue-include/linux/sched.h b/pfinet/glue-include/linux/sched.h
new file mode 100644
index 00000000..897a2df0
--- /dev/null
+++ b/pfinet/glue-include/linux/sched.h
@@ -0,0 +1,176 @@
+#ifndef _HACK_SCHED_H
+#define _HACK_SCHED_H
+
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <mach.h>
+#include <hurd/hurd_types.h>
+#include <limits.h>
+#include <assert.h>
+#include <cthreads.h>
+
+#include "mapped-time.h"
+
+#include <linux/binfmts.h>
+#include <linux/personality.h>
+#include <linux/tasks.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/times.h>
+#include <linux/timex.h>
+
+#include <asm/system.h>
+#if 0
+#include <asm/semaphore.h>
+#include <asm/page.h>
+
+#include <linux/smp.h>
+#include <linux/tty.h>
+#include <linux/sem.h>
+#include <linux/signal.h>
+#include <linux/securebits.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/net.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+
+
+#define jiffies (fetch_jiffies ())
+
+#define current (&current_contents)
+extern struct task_struct current_contents;
+struct task_struct
+{
+ uid_t pgrp, pid;
+ int flags;
+ int timeout;
+ int signal;
+ int blocked;
+ int state, policy;
+ int isroot;
+ char *comm;
+ struct wait_queue **next_wait;
+};
+
+static inline void
+prepare_current (int isroot)
+{
+ current->signal = 0;
+ current->isroot = isroot;
+ /* All other members are constant zero and ignored. */
+}
+#define become_task(user) prepare_current ((user)->isroot)
+#define become_task_protid(protid) prepare_current ((protid)->isroot)
+
+#define signal_pending(current) ((current)->signal)
+
+/* FLAGS in task_struct's. */
+#define PF_EXITING 1
+/* STATE in task_struct's. */
+#define TASK_INTERRUPTIBLE 0
+#define TASK_RUNNING 0
+/* policy in task_struct's. */
+#define SCHED_YIELD 0
+
+struct semaphore { };
+
+
+extern inline int
+suser ()
+{
+ return current->isroot;
+};
+
+extern inline int
+capable(int cap)
+{
+ return current->isroot;
+}
+
+
+extern struct mutex global_lock;
+
+static inline void
+interruptible_sleep_on (struct wait_queue **p)
+{
+ struct condition **condp = (void *) p, *c;
+ int isroot;
+ struct wait_queue **next_wait;
+
+ c = *condp;
+ if (c == 0)
+ {
+ c = malloc (sizeof **condp);
+ assert (c);
+ condition_init (c);
+ *condp = c;
+ }
+
+ isroot = current->isroot; /* This is our context that needs switched. */
+ next_wait = current->next_wait; /* This too, for multiple schedule calls. */
+ current->next_wait = 0;
+ if (hurd_condition_wait (c, &global_lock))
+ current->signal = 1; /* We got cancelled, mark it for later. */
+ current->isroot = isroot; /* Switch back to our context. */
+ current->next_wait = next_wait;
+}
+#define sleep_on interruptible_sleep_on
+
+static inline void
+wake_up_interruptible (struct wait_queue **p)
+{
+ struct condition **condp = (void *) p, *c = *condp;
+ if (c)
+ condition_broadcast (c);
+}
+#define wake_up wake_up_interruptible
+
+
+static inline void
+add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+{
+ assert (current->next_wait == 0);
+ current->next_wait = p;
+}
+
+static inline void
+remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+{
+ assert (current->next_wait == p);
+ current->next_wait = 0;
+}
+
+static inline void
+schedule (void)
+{
+ assert (current->next_wait);
+ interruptible_sleep_on (current->next_wait);
+}
+
+static inline long
+schedule_timeout (long timeout)
+{
+ /* XXX this is only ever called to do SO_LINGER, which we don't support */
+ assert (!"schedule_timeout");
+ return 0;
+}
+
+#define MAX_SCHEDULE_TIMEOUT LONG_MAX
+
+/* This function is used only to send SIGPIPE to the current
+ task. In all such cases, EPIPE is returned anyhow. In the
+ Hurd, servers are not responsible for SIGPIPE; the library
+ does that itself upon receiving EPIPE. So we can just
+ NOP such calls. */
+extern inline int
+send_sig (u_long signo, struct task_struct *task, int priv)
+{
+ assert (signo == SIGPIPE);
+ assert (task == current);
+ return 0;
+}
+
+
+#endif
diff --git a/pfinet/glue-include/linux/slab.h b/pfinet/glue-include/linux/slab.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pfinet/glue-include/linux/slab.h
diff --git a/pfinet/glue-include/linux/socket.h b/pfinet/glue-include/linux/socket.h
new file mode 100644
index 00000000..12c73bfa
--- /dev/null
+++ b/pfinet/glue-include/linux/socket.h
@@ -0,0 +1,138 @@
+#ifndef _HACK_SOCKET_H_
+#define _HACK_SOCKET_H_
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+
+
+/* #define IP_MAX_MEMBERSHIPS 10 */
+
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_RELIABILITY 0x04
+
+#define SOPRI_INTERACTIVE 0
+#define SOPRI_NORMAL 1
+#define SOPRI_BACKGROUND 2
+
+#define SOL_IP IPPROTO_IP
+#define SOL_TCP IPPROTO_TCP
+#define SOL_RAW IPPROTO_RAW
+
+/* IP options */
+#define IP_PKTINFO 190
+#define IP_PKTOPTIONS 191
+#define IP_MTU_DISCOVER 192
+#define IP_RECVERR 193
+#define IP_RECVTTL 194
+#define IP_RECVTOS 195
+#define IP_MTU 196
+#define IP_ROUTER_ALERT 197
+
+
+/* TCP options */
+#define TCP_NODELAY 1
+#define TCP_MAXSEG 2
+#define TCP_CORK 3
+
+#define SO_NO_CHECK 11
+#define SO_PRIORITY 12
+
+#define SO_PASSCRED 190
+#define SO_PEERCRED 191
+#define SO_BSDCOMPAT 192
+
+/* Maximum queue length specifiable by listen. */
+#define SOMAXCONN 128
+
+/* XXX */
+#define msg_control msg_accrights
+#define msg_controllen msg_accrightslen
+struct cmsghdr { int cmsg_garbage; };
+#define cmsg_len cmsg_garbage
+#define cmsg_type cmsg_garbage
+#define cmsg_level cmsg_garbage
+static inline int
+put_cmsg(struct msghdr *msg, int level, int type, int len, void *data)
+{ return 0; }
+#define CMSG_FIRSTHDR(msg) (0)
+#define CMSG_NXTHDR(msg, cmsg) (0)
+#define CMSG_DATA(cmsg) (0)
+#define CMSG_ALIGN(size) (0)
+#define CMSG_LEN(size) (0)
+
+
+#define MSG_NOSIGNAL 0
+#define MSG_ERRQUEUE 0
+
+/* There is no SOCK_PACKET, it is a bad bad thing. This chicanery is
+ because the one use of it is a comparison against a `short int' value;
+ using a value outside the range of that type ensures that the comparison
+ will always fail, and in fact it and the dead code will get optimized
+ out entirely at compile time. */
+#define SOCK_PACKET ((int)((uint32_t)USHRT_MAX) * 2)
+#define PF_PACKET 0
+
+#ifndef UIO_MAXIOV
+#define UIO_MAXIOV 4 /* 1 would do */
+#endif
+
+
+struct ucred {
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+};
+
+
+extern inline int
+memcpy_fromiovecend (unsigned char *kdata, struct iovec *iov,
+ int offset, int len)
+{
+ assert (offset + len <= iov->iov_len);
+ memcpy (kdata, iov->iov_base + offset, len);
+ return 0;
+}
+extern inline int
+memcpy_fromiovec (unsigned char *kdata, struct iovec *iov, int len)
+{
+ assert (len <= iov->iov_len);
+ memcpy (kdata, iov->iov_base, len);
+ return 0;
+}
+extern inline int
+memcpy_toiovec (struct iovec *iov, unsigned char *kdata, int len)
+{
+ assert (len <= iov->iov_len);
+ memcpy (iov->iov_base, kdata, len);
+ return 0;
+}
+extern inline void
+memcpy_tokerneliovec (struct iovec *iov, unsigned char *kdata, int len)
+{
+ assert (len <= iov->iov_len);
+ memcpy (iov->iov_base, kdata, len);
+}
+
+extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
+ struct iovec *iov,
+ int offset,
+ unsigned int len, int *csump);
+
+static inline int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr)
+{
+ abort ();
+ return 0;
+}
+#if 0
+extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
+extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
+#endif
+
+
+#endif
diff --git a/pfinet/glue-include/linux/sockios.h b/pfinet/glue-include/linux/sockios.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pfinet/glue-include/linux/sockios.h
diff --git a/pfinet/glue-include/linux/stat.h b/pfinet/glue-include/linux/stat.h
new file mode 100644
index 00000000..5165069b
--- /dev/null
+++ b/pfinet/glue-include/linux/stat.h
@@ -0,0 +1 @@
+#include <sys/stat.h>
diff --git a/pfinet/glue-include/linux/string.h b/pfinet/glue-include/linux/string.h
new file mode 100644
index 00000000..3b2f5900
--- /dev/null
+++ b/pfinet/glue-include/linux/string.h
@@ -0,0 +1 @@
+#include <string.h>
diff --git a/pfinet/glue-include/linux/termios.h b/pfinet/glue-include/linux/termios.h
new file mode 100644
index 00000000..9e269565
--- /dev/null
+++ b/pfinet/glue-include/linux/termios.h
@@ -0,0 +1 @@
+#include <termios.h>
diff --git a/pfinet/glue-include/linux/time.h b/pfinet/glue-include/linux/time.h
new file mode 100644
index 00000000..4973c4ab
--- /dev/null
+++ b/pfinet/glue-include/linux/time.h
@@ -0,0 +1,10 @@
+#ifndef _HACK_TIME_H_
+#define _HACK_TIME_H_
+
+#include <sys/time.h>
+#include "mapped-time.h"
+
+#define do_gettimeofday(tp) maptime_read (mapped_time, (tp))
+#define get_fast_time(tp) maptime_read (mapped_time, (tp))
+
+#endif
diff --git a/pfinet/glue-include/linux/timer.h b/pfinet/glue-include/linux/timer.h
new file mode 100644
index 00000000..cc8dec80
--- /dev/null
+++ b/pfinet/glue-include/linux/timer.h
@@ -0,0 +1,36 @@
+#ifndef _HACK_TIMER_H_
+#define _HACK_TIMER_H_
+
+#include <cthreads.h>
+
+enum tstate
+{
+ TIMER_INACTIVE,
+ TIMER_STARTING,
+ TIMER_STARTED,
+ TIMER_EXPIRED,
+ TIMER_FUNCTION_RUNNING,
+};
+
+struct timer_list
+{
+ struct timer_list *next, **prev; /* things like to test "T->prev != NULL" */
+ unsigned long expires;
+ unsigned long data;
+ void (*function)(unsigned long);
+};
+
+void add_timer (struct timer_list *);
+int del_timer (struct timer_list *);
+void mod_timer (struct timer_list *, unsigned long);
+void init_timer (struct timer_list *);
+
+
+#define time_after(a,b) ((long)(b) - (long)(a) < 0)
+#define time_before(a,b) time_after(b,a)
+
+#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
+#define time_before_eq(a,b) time_after_eq(b,a)
+
+
+#endif
diff --git a/pfinet/glue-include/linux/timex.h b/pfinet/glue-include/linux/timex.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pfinet/glue-include/linux/timex.h
diff --git a/pfinet/glue-include/linux/types.h b/pfinet/glue-include/linux/types.h
new file mode 100644
index 00000000..604b8b14
--- /dev/null
+++ b/pfinet/glue-include/linux/types.h
@@ -0,0 +1,31 @@
+#ifndef _HACK_TYPES_H
+#define _HACK_TYPES_H
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+
+#define __u8 uint8_t
+#define __u16 uint16_t
+#define __u32 uint32_t
+#define __u64 uint64_t
+#define __s8 int8_t
+#define __s16 int16_t
+#define __s32 int32_t
+#define __s64 int64_t
+#define u8 uint8_t
+#define u16 uint16_t
+#define u32 uint32_t
+#define u64 uint64_t
+#define s8 int8_t
+#define s16 int16_t
+#define s32 int32_t
+#define s64 int64_t
+
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <linux/errno.h>
+
+#endif
diff --git a/pfinet/glue-include/linux/un.h b/pfinet/glue-include/linux/un.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pfinet/glue-include/linux/un.h
diff --git a/pfinet/glue-include/linux/version.h b/pfinet/glue-include/linux/version.h
new file mode 100644
index 00000000..3a49a481
--- /dev/null
+++ b/pfinet/glue-include/linux/version.h
@@ -0,0 +1,3 @@
+#define UTS_RELEASE "2.1.12"
+#define LINUX_VERSION_CODE KERNEL_VERSION(2,1,12)
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
diff --git a/pfinet/glue-include/linux/wait.h b/pfinet/glue-include/linux/wait.h
new file mode 100644
index 00000000..7ee962dc
--- /dev/null
+++ b/pfinet/glue-include/linux/wait.h
@@ -0,0 +1,32 @@
+#ifndef _HACK_WAIT_H_
+#define _HACK_WAIT_H_
+
+#include <cthreads.h>
+
+/* This data structure actually represents one waiter on a wait queue,
+ and waiters always expect to initialize it with { current, NULL }.
+ The actual wait queue is a `struct wait_queue *' stored somewhere.
+ We ignore these structures provided by the waiters entirely.
+ In the `struct wait_queue *' that is the "head of the wait queue" slot,
+ we actually store a `struct condition *' pointing to malloc'd storage. */
+
+struct wait_queue
+{
+ struct task_struct *task; /* current */
+ struct wait_queue *next; /* NULL */
+};
+
+
+struct select_table_elt
+{
+ struct condition *dependent_condition;
+ struct select_table_elt *next;
+};
+
+typedef struct select_table_struct
+{
+ struct condition master_condition;
+ struct select_table_elt *head;
+} select_table;
+
+#endif
diff --git a/pfinet/io-ops.c b/pfinet/io-ops.c
new file mode 100644
index 00000000..c4cfc253
--- /dev/null
+++ b/pfinet/io-ops.c
@@ -0,0 +1,598 @@
+/*
+ Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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/wait.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <net/sock.h>
+
+#include "io_S.h"
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <mach/notify.h>
+#include <sys/mman.h>
+
+error_t
+S_io_write (struct sock_user *user,
+ char *data,
+ u_int datalen,
+ off_t offset,
+ mach_msg_type_number_t *amount)
+{
+ error_t err;
+ struct iovec iov = { data, datalen };
+ struct msghdr m = { msg_name: 0, msg_namelen: 0, msg_flags: 0,
+ msg_controllen: 0, msg_iov: &iov, msg_iovlen: 1 };
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ if (user->sock->flags & O_NONBLOCK)
+ m.msg_flags |= MSG_DONTWAIT;
+ err = (*user->sock->ops->sendmsg) (user->sock, &m, datalen, 0);
+ __mutex_unlock (&global_lock);
+
+ if (err < 0)
+ err = -err;
+ else
+ {
+ *amount = err;
+ err = 0;
+ }
+
+ return err;
+}
+
+error_t
+S_io_read (struct sock_user *user,
+ char **data,
+ u_int *datalen,
+ off_t offset,
+ mach_msg_type_number_t amount)
+{
+ error_t err;
+ int alloced = 0;
+ struct iovec iov;
+ struct msghdr m = { msg_name: 0, msg_namelen: 0, msg_flags: 0,
+ msg_controllen: 0, msg_iov: &iov, msg_iovlen: 1 };
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ /* Instead of this, we should peek and the socket and only
+ allocate as much as necessary. */
+ if (amount > *datalen)
+ {
+ *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ alloced = 1;
+ }
+
+ iov.iov_base = *data;
+ iov.iov_len = amount;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ err = (*user->sock->ops->recvmsg) (user->sock, &m, amount,
+ ((user->sock->flags & O_NONBLOCK)
+ ? MSG_DONTWAIT : 0),
+ 0);
+ __mutex_unlock (&global_lock);
+
+ if (err < 0)
+ err = -err;
+ else
+ {
+ *datalen = err;
+ if (alloced && round_page (*datalen) < round_page (amount))
+ munmap (*data + round_page (*datalen),
+ round_page (amount) - round_page (*datalen));
+ err = 0;
+ }
+ return err;
+}
+
+error_t
+S_io_seek (struct sock_user *user,
+ off_t offset,
+ int whence,
+ off_t *newp)
+{
+ return user ? ESPIPE : EOPNOTSUPP;
+}
+
+error_t
+S_io_readable (struct sock_user *user,
+ mach_msg_type_number_t *amount)
+{
+ struct sock *sk;
+ error_t err;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+
+ /* We need to avoid calling the Linux ioctl routines,
+ so here is a rather ugly break of modularity. */
+
+ sk = user->sock->sk;
+ err = 0;
+
+ /* Linux's af_inet.c ioctl routine just calls the protocol-specific
+ ioctl routine; it's those routines that we need to simulate. So
+ this switch corresponds to the initialization of SK->prot in
+ af_inet.c:inet_create. */
+ switch (user->sock->type)
+ {
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ err = tcp_tiocinq (sk, amount);
+ break;
+
+ case SOCK_DGRAM:
+ /* These guts are copied from udp.c:udp_ioctl (TIOCINQ). */
+ if (sk->state == TCP_LISTEN)
+ err = EINVAL;
+ else
+ /* Boy, I really love the C language. */
+ *amount = (skb_peek (&sk->receive_queue)
+ ? : &((struct sk_buff){}))->len;
+ break;
+
+ case SOCK_RAW:
+ default:
+ err = EOPNOTSUPP;
+ break;
+ }
+
+ __mutex_unlock (&global_lock);
+ return err;
+}
+
+error_t
+S_io_set_all_openmodes (struct sock_user *user,
+ int bits)
+{
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ if (bits & O_NONBLOCK)
+ user->sock->flags |= O_NONBLOCK;
+ else
+ user->sock->flags &= ~O_NONBLOCK;
+ __mutex_unlock (&global_lock);
+ return 0;
+}
+
+error_t
+S_io_get_openmodes (struct sock_user *user,
+ int *bits)
+{
+ struct sock *sk;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ sk = user->sock->sk;
+
+ *bits = 0;
+ if (!(sk->shutdown & SEND_SHUTDOWN))
+ *bits |= O_WRITE;
+ if (!(sk->shutdown & RCV_SHUTDOWN))
+ *bits |= O_READ;
+ if (user->sock->flags & O_NONBLOCK)
+ *bits |= O_NONBLOCK;
+
+ __mutex_unlock (&global_lock);
+ return 0;
+}
+
+error_t
+S_io_set_some_openmodes (struct sock_user *user,
+ int bits)
+{
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ if (bits & O_NONBLOCK)
+ user->sock->flags |= O_NONBLOCK;
+ __mutex_unlock (&global_lock);
+ return 0;
+}
+
+error_t
+S_io_clear_some_openmodes (struct sock_user *user,
+ int bits)
+{
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ if (bits & O_NONBLOCK)
+ user->sock->flags &= ~O_NONBLOCK;
+ __mutex_unlock (&global_lock);
+ return 0;
+}
+
+error_t
+S_io_select (struct sock_user *user,
+ mach_port_t reply,
+ mach_msg_type_name_t reply_type,
+ int *select_type)
+{
+ const int want = *select_type;
+ int avail;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+
+ /* In Linux, this means (supposedly) that I/O will never be possible.
+ That's a lose, so prevent it from happening. */
+ assert (user->sock->ops->poll);
+
+ avail = (*user->sock->ops->poll) ((void *) 0xdeadbeef,
+ user->sock,
+ (void *) 0xdeadbead);
+ if ((avail & want) == 0)
+ {
+ ports_interrupt_self_on_notification (user, reply,
+ MACH_NOTIFY_DEAD_NAME);
+
+ do
+ {
+ /* Block until we are woken or cancelled. */
+ interruptible_sleep_on (user->sock->sk->sleep);
+ if (signal_pending (current)) /* This means we were cancelled. */
+ {
+ __mutex_unlock (&global_lock);
+ return EINTR;
+ }
+ avail = (*user->sock->ops->poll) ((void *) 0xdeadbeef,
+ user->sock,
+ (void *) 0xdeadbead);
+ }
+ while ((avail & want) == 0);
+ }
+
+ /* We got something. */
+ *select_type = avail;
+
+ __mutex_unlock (&global_lock);
+
+ return 0;
+}
+
+error_t
+S_io_stat (struct sock_user *user,
+ struct stat *st)
+{
+ if (!user)
+ return EOPNOTSUPP;
+
+ bzero (st, sizeof (struct stat));
+
+ st->st_fstype = FSTYPE_SOCKET;
+ st->st_fsid = getpid ();
+ st->st_ino = (ino_t) user->sock; /* why not? */
+
+ st->st_mode = S_IFSOCK | ACCESSPERMS;
+ st->st_blksize = 512; /* ???? */
+
+ return 0;
+}
+
+error_t
+S_io_reauthenticate (struct sock_user *user,
+ mach_port_t rend)
+{
+ struct sock_user *newuser;
+ uid_t gubuf[20], ggbuf[20], aubuf[20], agbuf[20];
+ uid_t *gen_uids, *gen_gids, *aux_uids, *aux_gids;
+ u_int genuidlen, gengidlen, auxuidlen, auxgidlen;
+ error_t err;
+ int i;
+ auth_t auth;
+ mach_port_t newright;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ genuidlen = gengidlen = auxuidlen = auxgidlen = 20;
+ gen_uids = gubuf;
+ gen_gids = ggbuf;
+ aux_uids = aubuf;
+ aux_gids = agbuf;
+
+ __mutex_lock (&global_lock);
+ newuser = make_sock_user (user->sock, 0, 1);
+
+ auth = getauth ();
+ newright = ports_get_right (newuser);
+ err = mach_port_insert_right (mach_task_self (), newright, newright,
+ MACH_MSG_TYPE_MAKE_SEND);
+ assert_perror (err);
+ do
+ err = auth_server_authenticate (auth,
+ rend,
+ MACH_MSG_TYPE_COPY_SEND,
+ newright,
+ MACH_MSG_TYPE_COPY_SEND,
+ &gen_uids, &genuidlen,
+ &aux_uids, &auxuidlen,
+ &gen_gids, &gengidlen,
+ &aux_gids, &auxgidlen);
+ while (err == EINTR);
+ mach_port_deallocate (mach_task_self (), rend);
+ mach_port_deallocate (mach_task_self (), newright);
+ mach_port_deallocate (mach_task_self (), auth);
+
+ if (err)
+ newuser->isroot = 0;
+ else
+ for (i = 0; i < genuidlen; i++)
+ if (gen_uids[i] == 0)
+ newuser->isroot = 1;
+
+ mach_port_move_member (mach_task_self (), newuser->pi.port_right,
+ pfinet_bucket->portset);
+
+ __mutex_unlock (&global_lock);
+
+ ports_port_deref (newuser);
+
+ if (gubuf != gen_uids)
+ munmap (gen_uids, genuidlen * sizeof (uid_t));
+ if (ggbuf != gen_gids)
+ munmap (gen_gids, gengidlen * sizeof (uid_t));
+ if (aubuf != aux_uids)
+ munmap (aux_uids, auxuidlen * sizeof (uid_t));
+ if (agbuf != aux_gids)
+ munmap (aux_gids, auxgidlen * sizeof (uid_t));
+
+ return 0;
+}
+
+error_t
+S_io_restrict_auth (struct sock_user *user,
+ mach_port_t *newobject,
+ mach_msg_type_name_t *newobject_type,
+ uid_t *uids,
+ u_int uidslen,
+ uid_t *gids,
+ u_int gidslen)
+{
+ struct sock_user *newuser;
+ int i = 0;
+ int isroot;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+
+ isroot = 0;
+ if (user->isroot)
+ for (i = 0; i < uidslen && !isroot; i++)
+ if (uids[i] == 0)
+ isroot = 1;
+
+ newuser = make_sock_user (user->sock, isroot, 0);
+ *newobject = ports_get_right (newuser);
+ *newobject_type = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newuser);
+ __mutex_unlock (&global_lock);
+ return 0;
+}
+
+error_t
+S_io_duplicate (struct sock_user *user,
+ mach_port_t *newobject,
+ mach_msg_type_name_t *newobject_type)
+{
+ struct sock_user *newuser;
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ newuser = make_sock_user (user->sock, user->isroot, 0);
+ *newobject = ports_get_right (newuser);
+ *newobject_type = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newuser);
+ __mutex_unlock (&global_lock);
+ return 0;
+}
+
+error_t
+S_io_identity (struct sock_user *user,
+ mach_port_t *id,
+ mach_msg_type_name_t *idtype,
+ mach_port_t *fsys,
+ mach_msg_type_name_t *fsystype,
+ int *fileno)
+{
+ error_t err;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ if (user->sock->identity == MACH_PORT_NULL)
+ {
+ err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &user->sock->identity);
+ if (err)
+ {
+ __mutex_unlock (&global_lock);
+ return err;
+ }
+ }
+
+ *id = user->sock->identity;
+ *idtype = MACH_MSG_TYPE_MAKE_SEND;
+ *fsys = fsys_identity;
+ *fsystype = MACH_MSG_TYPE_MAKE_SEND;
+ *fileno = (ino_t) user->sock; /* matches S_io_stat above */
+
+ __mutex_unlock (&global_lock);
+ return 0;
+}
+
+error_t
+S_io_revoke (struct sock_user *user)
+{
+ /* XXX maybe we should try */
+ return EOPNOTSUPP;
+}
+
+
+
+error_t
+S_io_async (struct sock_user *user,
+ mach_port_t notify,
+ mach_port_t *id,
+ mach_msg_type_name_t *idtype)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_mod_owner (struct sock_user *user,
+ pid_t owner)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_get_owner (struct sock_user *user,
+ pid_t *owner)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_get_icky_async_id (struct sock_user *user,
+ mach_port_t *id,
+ mach_msg_type_name_t *idtype)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_server_version (struct sock_user *user,
+ char *name,
+ int *major,
+ int *minor,
+ int *edit)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_pathconf (struct sock_user *user,
+ int name,
+ int *value)
+{
+ return EOPNOTSUPP;
+}
+
+
+
+error_t
+S_io_map (struct sock_user *user,
+ mach_port_t *rdobj,
+ mach_msg_type_name_t *rdobj_type,
+ mach_port_t *wrobj,
+ mach_msg_type_name_t *wrobj_type)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_map_cntl (struct sock_user *user,
+ mach_port_t *obj,
+ mach_msg_type_name_t *obj_type)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_get_conch (struct sock_user *user)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_release_conch (struct sock_user *user)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_eofnotify (struct sock_user *user)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_prenotify (struct sock_user *user,
+ vm_offset_t start,
+ vm_offset_t end)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_postnotify (struct sock_user *user,
+ vm_offset_t start,
+ vm_offset_t end)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_readnotify (struct sock_user *user)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_readsleep (struct sock_user *user)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_io_sigio (struct sock_user *user)
+{
+ return EOPNOTSUPP;
+}
diff --git a/pfinet/kmem_cache.c b/pfinet/kmem_cache.c
new file mode 100644
index 00000000..8c73c9bf
--- /dev/null
+++ b/pfinet/kmem_cache.c
@@ -0,0 +1,88 @@
+/* Hack replacement for Linux's kmem_cache_t allocator
+ 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+/* Hack replacement for Linux's kmem_cache_t allocator, using plain malloc
+ and cthreads locking. The locking here is probably unnecessary. */
+
+#include <cthreads.h>
+#include <linux/malloc.h>
+
+struct kmem_cache_s
+{
+ struct mutex lock;
+
+ void *freelist;
+ size_t item_size;
+
+ void (*ctor) (void *, kmem_cache_t *, unsigned long);
+ void (*dtor) (void *, kmem_cache_t *, unsigned long);
+};
+
+kmem_cache_t *
+kmem_cache_create (const char *name, size_t item_size,
+ size_t something, unsigned long flags,
+ void (*ctor) (void *, kmem_cache_t *, unsigned long),
+ void (*dtor) (void *, kmem_cache_t *, unsigned long))
+{
+ kmem_cache_t *new = malloc (sizeof *new);
+ if (!new)
+ return 0;
+ mutex_init (&new->lock);
+ new->freelist = 0;
+ new->item_size = item_size;
+ new->ctor = ctor;
+ new->dtor = dtor;
+
+ return new;
+}
+
+
+void *
+kmem_cache_alloc (kmem_cache_t *cache, int flags)
+{
+ void *p;
+
+ __mutex_lock (&cache->lock);
+ p = cache->freelist;
+ if (p != 0) {
+ cache->freelist = *(void **)(p + cache->item_size);
+ __mutex_unlock (&cache->lock);
+ return p;
+ }
+ __mutex_unlock (&cache->lock);
+
+ p = malloc (cache->item_size + sizeof (void *));
+ if (p && cache->ctor)
+ (*cache->ctor) (p, cache, flags);
+ return p;
+}
+
+
+void
+kmem_cache_free (kmem_cache_t *cache, void *p)
+{
+ void **const nextp = (void **) (p + cache->item_size);
+
+ __mutex_lock (&cache->lock);
+ *nextp = cache->freelist;
+ cache->freelist = p;
+ __mutex_unlock (&cache->lock);
+
+ /* XXX eventually destroy some... */
+}
diff --git a/pfinet/linux-src/include/linux/net.h b/pfinet/linux-src/include/linux/net.h
index 63e996f9..da193dcc 100644
--- a/pfinet/linux-src/include/linux/net.h
+++ b/pfinet/linux-src/include/linux/net.h
@@ -65,8 +65,14 @@ struct socket
unsigned long flags;
struct proto_ops *ops;
struct inode *inode;
+#ifdef _HURD_
+ uint_fast32_t refcnt; /* # of sock_user's pointing to this */
+ mach_port_t identity; /* for io_identity */
+ struct file; /* forward decl magic */
+#else
struct fasync_struct *fasync_list; /* Asynchronous wake up list */
struct file *file; /* File back pointer for gc */
+#endif
struct sock *sk;
struct wait_queue *wait;
@@ -103,12 +109,12 @@ struct proto_ops {
int (*getsockopt) (struct socket *sock, int level, int optname,
char *optval, int *optlen);
int (*fcntl) (struct socket *sock, unsigned int cmd,
- unsigned long arg);
+ unsigned long arg);
int (*sendmsg) (struct socket *sock, struct msghdr *m, int total_len, struct scm_cookie *scm);
int (*recvmsg) (struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm);
};
-struct net_proto_family
+struct net_proto_family
{
int family;
int (*create)(struct socket *sock, int protocol);
@@ -119,7 +125,7 @@ struct net_proto_family
short encrypt_net;
};
-struct net_proto
+struct net_proto
{
const char *name; /* Protocol name */
void (*init_func)(struct net_proto *); /* Bootstrap */
diff --git a/pfinet/linux-src/include/linux/rtnetlink.h b/pfinet/linux-src/include/linux/rtnetlink.h
index b339f652..2b5d6efa 100644
--- a/pfinet/linux-src/include/linux/rtnetlink.h
+++ b/pfinet/linux-src/include/linux/rtnetlink.h
@@ -49,7 +49,7 @@
#define RTM_MAX (RTM_BASE+31)
-/*
+/*
Generic structure for encapsulation optional route information.
It is reminiscent of sockaddr, but with sa_family replaced
with attribute type.
@@ -90,7 +90,7 @@ struct rtmsg
unsigned char rtm_table; /* Routing table id */
unsigned char rtm_protocol; /* Routing protocol; see below */
- unsigned char rtm_scope; /* See below */
+ unsigned char rtm_scope; /* See below */
unsigned char rtm_type; /* See below */
unsigned rtm_flags;
@@ -636,15 +636,19 @@ extern __inline__ void rtnl_exunlock(void)
extern __inline__ void rtnl_shlock(void)
{
+#ifndef _HURD_
while (atomic_read(&rtnl_rlockct))
sleep_on(&rtnl_wait);
atomic_inc(&rtnl_rlockct);
+#endif
}
extern __inline__ void rtnl_shunlock(void)
{
+#ifndef _HURD_
if (atomic_dec_and_test(&rtnl_rlockct))
wake_up(&rtnl_wait);
+#endif
}
extern __inline__ void rtnl_exlock(void)
diff --git a/pfinet/linux-src/net/core/dev.c b/pfinet/linux-src/net/core/dev.c
index 75fae54a..1dba3926 100644
--- a/pfinet/linux-src/net/core/dev.c
+++ b/pfinet/linux-src/net/core/dev.c
@@ -115,7 +115,7 @@ const char *if_port_text[] = {
* and the routines to invoke.
*
* Why 16. Because with 16 the only overlap we get on a hash of the
- * low nibble of the protocol value is RARP/SNAP/X.25.
+ * low nibble of the protocol value is RARP/SNAP/X.25.
*
* 0800 IP
* 0001 802.3
@@ -137,13 +137,13 @@ struct packet_type *ptype_all = NULL; /* Taps */
* Device list lock. Setting it provides that interface
* will not disappear unexpectedly while kernel sleeps.
*/
-
+
atomic_t dev_lockct = ATOMIC_INIT(0);
/*
* Our notifier list
*/
-
+
static struct notifier_block *netdev_chain=NULL;
/*
@@ -189,7 +189,7 @@ int netdev_nit=0;
* change it and subsequent readers will get broken packet.
* --ANK (980803)
*/
-
+
void dev_add_pack(struct packet_type *pt)
{
int hash;
@@ -207,7 +207,7 @@ void dev_add_pack(struct packet_type *pt)
ptype_all=pt;
}
else
- {
+ {
hash=ntohs(pt->type)&15;
pt->next = ptype_base[hash];
ptype_base[hash] = pt;
@@ -218,7 +218,7 @@ void dev_add_pack(struct packet_type *pt)
/*
* Remove a protocol ID from the list.
*/
-
+
void dev_remove_pack(struct packet_type *pt)
{
struct packet_type **pt1;
@@ -251,15 +251,15 @@ void dev_remove_pack(struct packet_type *pt)
******************************************************************************************/
-/*
+/*
* Find an interface by name.
*/
-
+
struct device *dev_get(const char *name)
{
struct device *dev;
- for (dev = dev_base; dev != NULL; dev = dev->next)
+ for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (strcmp(dev->name, name) == 0)
return(dev);
@@ -271,7 +271,7 @@ struct device * dev_get_by_index(int ifindex)
{
struct device *dev;
- for (dev = dev_base; dev != NULL; dev = dev->next)
+ for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (dev->ifindex == ifindex)
return(dev);
@@ -283,7 +283,7 @@ struct device *dev_getbyhwaddr(unsigned short type, char *ha)
{
struct device *dev;
- for (dev = dev_base; dev != NULL; dev = dev->next)
+ for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (dev->type == type &&
memcmp(dev->dev_addr, ha, dev->addr_len) == 0)
@@ -311,7 +311,7 @@ int dev_alloc_name(struct device *dev, const char *name)
}
return -ENFILE; /* Over 100 of the things .. bail out! */
}
-
+
struct device *dev_alloc(const char *name, int *err)
{
struct device *dev=kmalloc(sizeof(struct device)+16, GFP_KERNEL);
@@ -340,7 +340,7 @@ void netdev_state_change(struct device *dev)
/*
* Find and possibly load an interface.
*/
-
+
#ifdef CONFIG_KMOD
void dev_load(const char *name)
@@ -363,9 +363,9 @@ static int default_rebuild_header(struct sk_buff *skb)
}
/*
- * Prepare an interface for use.
+ * Prepare an interface for use.
*/
-
+
int dev_open(struct device *dev)
{
int ret = 0;
@@ -380,15 +380,15 @@ int dev_open(struct device *dev)
/*
* Call device private open method
*/
-
- if (dev->open)
+
+ if (dev->open)
ret = dev->open(dev);
/*
* If it went open OK then:
*/
-
- if (ret == 0)
+
+ if (ret == 0)
{
/*
* nil rebuild_header routine,
@@ -404,7 +404,7 @@ int dev_open(struct device *dev)
dev->flags |= (IFF_UP | IFF_RUNNING);
/*
- * Initialize multicasting status
+ * Initialize multicasting status
*/
dev_mc_upload(dev);
@@ -448,7 +448,7 @@ void dev_clear_fastroute(struct device *dev)
/*
* Completely shutdown an interface.
*/
-
+
int dev_close(struct device *dev)
{
if (!(dev->flags&IFF_UP))
@@ -462,7 +462,7 @@ int dev_close(struct device *dev)
* Call the device specific close. This cannot fail.
* Only if device is UP
*/
-
+
if (dev->stop)
dev->stop(dev);
@@ -513,7 +513,7 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct device *dev)
struct packet_type *ptype;
get_fast_time(&skb->stamp);
- for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next)
+ for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next)
{
/* Never send packets back to the socket
* they originated from - MvS (miquels@drinkel.ow.org)
@@ -558,7 +558,7 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct device *dev)
/*
* Fast path for loopback frames.
*/
-
+
void dev_loopback_xmit(struct sk_buff *skb)
{
struct sk_buff *newskb=skb_clone(skb, GFP_ATOMIC);
@@ -608,7 +608,7 @@ int dev_queue_xmit(struct sk_buff *skb)
made by us here.
*/
if (dev->flags&IFF_UP) {
- if (netdev_nit)
+ if (netdev_nit)
dev_queue_xmit_nit(skb,dev);
if (dev->hard_start_xmit(skb, dev) == 0) {
end_bh_atomic();
@@ -723,7 +723,7 @@ static void dev_clear_backlog(struct device *dev)
*
* It looks better to use net_bh trick, at least
* to be sure, that we keep interrupt latency really low. --ANK (980727)
- */
+ */
if (backlog.qlen) {
start_bh_atomic();
@@ -751,7 +751,7 @@ static void dev_clear_backlog(struct device *dev)
/*
* Receive a packet from a device driver and queue it for the upper
- * (protocol) levels. It always succeeds.
+ * (protocol) levels. It always succeeds.
*/
void netif_rx(struct sk_buff *skb)
@@ -802,13 +802,13 @@ static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
* We pass the bridge a complete frame. This means
* recovering the MAC header first.
*/
-
+
int offset;
skb=skb_clone(skb, GFP_ATOMIC);
- if(skb==NULL)
+ if(skb==NULL)
return;
-
+
offset=skb->data-skb->mac.raw;
skb_push(skb,offset); /* Put header back on for bridge */
@@ -828,7 +828,7 @@ static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
* This is run as a bottom half after an interrupt handler that does
* mark_bh(NET_BH);
*/
-
+
void net_bh(void)
{
struct packet_type *ptype;
@@ -854,7 +854,7 @@ void net_bh(void)
if (qdisc_head.forw != &qdisc_head)
qdisc_run_queues();
-
+
/*
* Any data left to process. This may occur because a
* mark_bh() is done after we empty the queue including
@@ -869,7 +869,7 @@ void net_bh(void)
* disabling interrupts.
*/
- while (!skb_queue_empty(&backlog))
+ while (!skb_queue_empty(&backlog))
{
struct sk_buff * skb;
@@ -904,7 +904,7 @@ void net_bh(void)
/*
* Bump the pointer to the next structure.
- *
+ *
* On entry to the protocol layer. skb->data and
* skb->nh.raw point to the MAC and encapsulated data
*/
@@ -919,7 +919,7 @@ void net_bh(void)
}
/*
- * Fetch the packet protocol ID.
+ * Fetch the packet protocol ID.
*/
type = skb->protocol;
@@ -930,7 +930,7 @@ void net_bh(void)
* bridging code (if this protocol is to be bridged).
* If it is bridged then move on
*/
- handle_bridge(skb, type);
+ handle_bridge(skb, type);
#endif
/*
@@ -953,7 +953,7 @@ void net_bh(void)
}
}
- for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)
+ for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)
{
if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
{
@@ -989,16 +989,16 @@ void net_bh(void)
/*
* Has an unknown packet has been received ?
*/
-
+
else {
kfree_skb(skb);
}
} /* End of queue loop */
-
+
/*
* We have emptied the queue
*/
-
+
/*
* One last output flush.
*/
@@ -1067,9 +1067,9 @@ static int dev_ifname(struct ifreq *arg)
int err;
/*
- * Fetch the caller's info block.
+ * Fetch the caller's info block.
*/
-
+
err = copy_from_user(&ifr, arg, sizeof(struct ifreq));
if (err)
return -EFAULT;
@@ -1100,9 +1100,9 @@ static int dev_ifconf(char *arg)
int i;
/*
- * Fetch the caller's info block.
+ * Fetch the caller's info block.
*/
-
+
if (copy_from_user(&ifc, arg, sizeof(struct ifconf)))
return -EFAULT;
@@ -1110,7 +1110,7 @@ static int dev_ifconf(char *arg)
len = ifc.ifc_len;
/*
- * Loop over the interfaces, and write an info block for each.
+ * Loop over the interfaces, and write an info block for each.
*/
total = 0;
@@ -1131,14 +1131,14 @@ static int dev_ifconf(char *arg)
}
/*
- * All done. Write the updated control block back to the caller.
+ * All done. Write the updated control block back to the caller.
*/
ifc.ifc_len = total;
if (copy_to_user(arg, &ifc, sizeof(struct ifconf)))
- return -EFAULT;
+ return -EFAULT;
- /*
+ /*
* Both BSD and Solaris return 0 here, so we do too.
*/
return 0;
@@ -1154,7 +1154,7 @@ static int sprintf_stats(char *buffer, struct device *dev)
{
struct net_device_stats *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
int size;
-
+
if (stats)
size = sprintf(buffer, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu %8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
dev->name,
@@ -1181,31 +1181,31 @@ static int sprintf_stats(char *buffer, struct device *dev)
* Called from the PROCfs module. This now uses the new arbitrary sized /proc/net interface
* to create /proc/net/dev
*/
-
+
int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
int len=0;
off_t begin=0;
off_t pos=0;
int size;
-
+
struct device *dev;
- size = sprintf(buffer,
+ size = sprintf(buffer,
"Inter-| Receive | Transmit\n"
" face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n");
-
+
pos+=size;
len+=size;
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
+
+ for (dev = dev_base; dev != NULL; dev = dev->next)
{
size = sprintf_stats(buffer+len, dev);
len+=size;
pos=begin+len;
-
+
if(pos<offset)
{
len=0;
@@ -1214,7 +1214,7 @@ int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy
if(pos>offset+length)
break;
}
-
+
*start=buffer+(offset-begin); /* Start of wanted data */
len-=(offset-begin); /* Start slop */
if(len>length)
@@ -1284,7 +1284,7 @@ static int sprintf_wireless_stats(char *buffer, struct device *dev)
stats->qual.level,
stats->qual.updated & 2 ? '.' : ' ',
stats->qual.noise,
- stats->qual.updated & 4 ? '.' : ' ',
+ stats->qual.updated & 3 ? '.' : ' ',
stats->discard.nwid,
stats->discard.code,
stats->discard.misc);
@@ -1305,17 +1305,17 @@ int dev_get_wireless_info(char * buffer, char **start, off_t offset,
off_t begin = 0;
off_t pos = 0;
int size;
-
+
struct device * dev;
size = sprintf(buffer,
"Inter-|sta| Quality | Discarded packets\n"
" face |tus|link level noise| nwid crypt misc\n");
-
+
pos+=size;
len+=size;
- for(dev = dev_base; dev != NULL; dev = dev->next)
+ for(dev = dev_base; dev != NULL; dev = dev->next)
{
size = sprintf_wireless_stats(buffer+len, dev);
len+=size;
@@ -1388,7 +1388,7 @@ int dev_change_flags(struct device *dev, unsigned flags)
/*
* Load in the correct multicast list now the flags have changed.
- */
+ */
dev_mc_upload(dev);
@@ -1403,7 +1403,7 @@ int dev_change_flags(struct device *dev, unsigned flags)
{
ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
- if (ret == 0)
+ if (ret == 0)
dev_mc_upload(dev);
}
@@ -1430,10 +1430,16 @@ int dev_change_flags(struct device *dev, unsigned flags)
return ret;
}
+#ifdef _HURD_
+
+#define dev_ioctl 0
+
+#else
+
/*
- * Perform the SIOCxIFxxx calls.
+ * Perform the SIOCxIFxxx calls.
*/
-
+
static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
{
struct device *dev;
@@ -1442,7 +1448,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
if ((dev = dev_get(ifr->ifr_name)) == NULL)
return -ENODEV;
- switch(cmd)
+ switch(cmd)
{
case SIOCGIFFLAGS: /* Get interface flags */
ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
@@ -1451,18 +1457,18 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
case SIOCSIFFLAGS: /* Set interface flags */
return dev_change_flags(dev, ifr->ifr_flags);
-
+
case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */
ifr->ifr_metric = 0;
return 0;
-
+
case SIOCSIFMETRIC: /* Set the metric on the interface (currently unused) */
return -EOPNOTSUPP;
-
+
case SIOCGIFMTU: /* Get the MTU of a device */
ifr->ifr_mtu = dev->mtu;
return 0;
-
+
case SIOCSIFMTU: /* Set the MTU of a device */
if (ifr->ifr_mtu == dev->mtu)
return 0;
@@ -1470,7 +1476,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
/*
* MTU must be positive.
*/
-
+
if (ifr->ifr_mtu<=0)
return -EINVAL;
@@ -1488,7 +1494,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
memcpy(ifr->ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN);
ifr->ifr_hwaddr.sa_family=dev->type;
return 0;
-
+
case SIOCSIFHWADDR:
if(dev->set_mac_address==NULL)
return -EOPNOTSUPP;
@@ -1498,7 +1504,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
if (!err)
notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
return err;
-
+
case SIOCSIFHWBROADCAST:
if(ifr->ifr_hwaddr.sa_family!=dev->type)
return -EINVAL;
@@ -1514,12 +1520,12 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
ifr->ifr_map.dma=dev->dma;
ifr->ifr_map.port=dev->if_port;
return 0;
-
+
case SIOCSIFMAP:
if (dev->set_config)
return dev->set_config(dev,&ifr->ifr_map);
return -EOPNOTSUPP;
-
+
case SIOCADDMULTI:
if(dev->set_multicast_list==NULL ||
ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
@@ -1598,7 +1604,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
and requires shared lock, because it sleeps writing
to user space.
*/
-
+
if (cmd == SIOCGIFCONF) {
rtnl_shlock();
ret = dev_ifconf((char *) arg);
@@ -1619,10 +1625,10 @@ int dev_ioctl(unsigned int cmd, void *arg)
*colon = 0;
/*
- * See which interface the caller is talking about.
+ * See which interface the caller is talking about.
*/
-
- switch(cmd)
+
+ switch(cmd)
{
/*
* These ioctl calls:
@@ -1630,7 +1636,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
* - atomic and do not require locking.
* - return a value
*/
-
+
case SIOCGIFFLAGS:
case SIOCGIFMETRIC:
case SIOCGIFMTU:
@@ -1655,7 +1661,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
* - require strict serialization.
* - do not return a value
*/
-
+
case SIOCSIFFLAGS:
case SIOCSIFMETRIC:
case SIOCSIFMTU:
@@ -1674,7 +1680,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock();
return ret;
-
+
case SIOCGIFMEM:
/* Get the per device memory space. We can add this but currently
do not support it */
@@ -1685,8 +1691,8 @@ int dev_ioctl(unsigned int cmd, void *arg)
/*
* Unknown or private ioctl.
- */
-
+ */
+
default:
if (cmd >= SIOCDEVPRIVATE &&
cmd <= SIOCDEVPRIVATE + 15) {
@@ -1719,6 +1725,8 @@ int dev_ioctl(unsigned int cmd, void *arg)
}
}
+#endif
+
int dev_new_index(void)
{
static int ifindex;
@@ -1740,7 +1748,7 @@ int register_netdevice(struct device *dev)
if (dev_boot_phase) {
/* This is NOT bug, but I am not sure, that all the
devices, initialized before netdev module is started
- are sane.
+ are sane.
Now they are chained to device boot list
and probed later. If a module is initialized
@@ -1838,7 +1846,7 @@ int unregister_netdevice(struct device *dev)
/*
* Initialize the DEV module. At boot time this walks the device list and
- * unhooks any devices that fail to initialise (normally hardware not
+ * unhooks any devices that fail to initialise (normally hardware not
* present) and leaves us with a valid list of present and active devices.
*
*/
@@ -1892,17 +1900,17 @@ __initfunc(int net_dev_init(void))
/*
* Initialise the packet receive queue.
*/
-
+
skb_queue_head_init(&backlog);
-
+
/*
* The bridge has to be up before the devices
*/
-#ifdef CONFIG_BRIDGE
+#ifdef CONFIG_BRIDGE
br_init();
-#endif
-
+#endif
+
/*
* This is Very Ugly(tm).
*
@@ -1914,7 +1922,7 @@ __initfunc(int net_dev_init(void))
#endif
#if defined(CONFIG_DMASCC)
dmascc_init();
-#endif
+#endif
#if defined(CONFIG_BPQETHER)
bpq_init();
#endif
@@ -1952,13 +1960,13 @@ __initfunc(int net_dev_init(void))
* SLHC if present needs attaching so other people see it
* even if not opened.
*/
-
-#ifdef CONFIG_INET
+
+#ifdef CONFIG_INET
#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
|| defined(CONFIG_PPP) \
|| (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
slhc_install();
-#endif
+#endif
#endif
#ifdef CONFIG_NET_PROFILE
@@ -1980,14 +1988,14 @@ __initfunc(int net_dev_init(void))
while ((dev = *dp) != NULL)
{
dev->iflink = -1;
- if (dev->init && dev->init(dev))
+ if (dev->init && dev->init(dev))
{
/*
* It failed to come up. Unhook it.
*/
*dp = dev->next;
synchronize_bh();
- }
+ }
else
{
dp = &dev->next;
diff --git a/pfinet/linux-src/net/ipv4/af_inet.c b/pfinet/linux-src/net/ipv4/af_inet.c
index e37eb6bd..04e05107 100644
--- a/pfinet/linux-src/net/ipv4/af_inet.c
+++ b/pfinet/linux-src/net/ipv4/af_inet.c
@@ -23,10 +23,10 @@
* when accept() ed
* Alan Cox : Semantics of SO_LINGER aren't state moved
* to close when you look carefully. With
- * this fixed and the accept bug fixed
+ * this fixed and the accept bug fixed
* some RPC stuff seems happier.
* Niibe Yutaka : 4.4BSD style write async I/O
- * Alan Cox,
+ * Alan Cox,
* Tony Gale : Fixed reuse semantics.
* Alan Cox : bind() shouldn't abort existing but dead
* sockets. Stops FTP netin:.. I hope.
@@ -141,7 +141,7 @@ int (*rarp_ioctl_hook)(unsigned int,void*) = NULL;
/*
* Destroy an AF_INET socket
*/
-
+
static __inline__ void kill_sk_queues(struct sock *sk)
{
struct sk_buff *skb;
@@ -177,12 +177,12 @@ static __inline__ void kill_sk_later(struct sock *sk)
{
/* this should never happen. */
/* actually it can if an ack has just been sent. */
- /*
+ /*
* It's more normal than that...
* It can happen because a skb is still in the device queues
* [PR]
*/
-
+
NETDEBUG(printk(KERN_DEBUG "Socket destroy delayed (r=%d w=%d)\n",
atomic_read(&sk->rmem_alloc),
atomic_read(&sk->wmem_alloc)));
@@ -223,12 +223,12 @@ void destroy_sock(struct sock *sk)
* socket object. Mostly it punts to the subprotocols of IP to do
* the work.
*/
-
+
/*
* Set socket options on an inet socket.
*/
-
+
int inet_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
@@ -275,7 +275,7 @@ static int inet_autobind(struct sock *sk)
/*
* Move a socket into listening state.
*/
-
+
int inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
@@ -330,7 +330,7 @@ static int inet_create(struct socket *sock, int protocol)
/* Compatibility */
if (sock->type == SOCK_PACKET) {
- static int warned;
+ static int warned;
if (net_families[PF_PACKET]==NULL)
{
#if defined(CONFIG_KMOD) && defined(CONFIG_PACKET_MODULE)
@@ -348,7 +348,7 @@ static int inet_create(struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
sk = sk_alloc(PF_INET, GFP_KERNEL, 1);
- if (sk == NULL)
+ if (sk == NULL)
goto do_oom;
switch (sock->type) {
@@ -392,13 +392,13 @@ static int inet_create(struct socket *sock, int protocol)
}
sock_init_data(sock,sk);
-
+
sk->destruct = NULL;
sk->zapped=0;
#ifdef CONFIG_TCP_NAGLE_OFF
sk->nonagle = 1;
-#endif
+#endif
sk->family = PF_INET;
sk->protocol = protocol;
@@ -414,7 +414,7 @@ static int inet_create(struct socket *sock, int protocol)
sk->ip_mc_ttl=1;
sk->ip_mc_index=0;
sk->ip_mc_list=NULL;
-
+
if (sk->num) {
/* It assumes that any protocol which allows
* the user to assign a number at socket
@@ -459,7 +459,7 @@ do_oom:
* function we are destroying the object and from then on nobody
* should refer to it.
*/
-
+
int inet_release(struct socket *sock, struct socket *peersock)
{
struct sock *sk = sock->sk;
@@ -505,13 +505,13 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
/* If the socket has its own bind function then use it. (RAW) */
if(sk->prot->bind)
return sk->prot->bind(sk, uaddr, addr_len);
-
+
/* Check these errors (active socket, bad address length, double bind). */
if ((sk->state != TCP_CLOSE) ||
(addr_len < sizeof(struct sockaddr_in)) ||
(sk->num != 0))
return -EINVAL;
-
+
chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
if (addr->sin_addr.s_addr != 0 && chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) {
@@ -538,10 +538,10 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
/* The kernel masquerader needs some ports. */
if((snum >= PORT_MASQ_BEGIN) && (snum <= PORT_MASQ_END))
return -EADDRINUSE;
-#endif
+#endif
if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
return(-EACCES);
-
+
/* Make sure we are allowed to bind here. */
if (sk->prot->get_port(sk, snum) != 0)
return -EADDRINUSE;
@@ -564,10 +564,10 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,
if (inet_autobind(sk) != 0)
return(-EAGAIN);
- if (sk->prot->connect == NULL)
+ if (sk->prot->connect == NULL)
return(-EOPNOTSUPP);
err = sk->prot->connect(sk, (struct sockaddr *)uaddr, addr_len);
- if (err < 0)
+ if (err < 0)
return(err);
return(0);
}
@@ -594,7 +594,7 @@ static void inet_wait_for_connect(struct sock *sk)
* Connect to a remote host. There is regrettably still a little
* TCP 'magic' in here.
*/
-
+
int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
int addr_len, int flags)
{
@@ -609,7 +609,7 @@ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
if(sock->state == SS_CONNECTING) {
/* Note: tcp_connected contains SYN_RECV, which may cause
- bogus results here. -AK */
+ bogus results here. -AK */
if(tcp_connected(sk->state)) {
sock->state = SS_CONNECTED;
return 0;
@@ -619,7 +619,7 @@ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
if (flags & O_NONBLOCK)
return -EALREADY;
} else {
- if (sk->prot->connect == NULL)
+ if (sk->prot->connect == NULL)
return(-EOPNOTSUPP);
/* We may need to bind the socket. */
@@ -635,11 +635,11 @@ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
return(err);
sock->state = SS_CONNECTING;
}
-
+
if (sk->state > TCP_FIN_WAIT2 && sock->state == SS_CONNECTING)
goto sock_error;
- if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
+ if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
return (-EINPROGRESS);
if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {
@@ -650,15 +650,15 @@ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
sock->state = SS_CONNECTED;
if ((sk->state != TCP_ESTABLISHED) && sk->err)
- goto sock_error;
+ goto sock_error;
return(0);
-sock_error:
+sock_error:
/* This is ugly but needed to fix a race in the ICMP error handler */
- if (sk->zapped && sk->state != TCP_CLOSE) {
- lock_sock(sk);
+ if (sk->zapped && sk->state != TCP_CLOSE) {
+ lock_sock(sk);
tcp_set_state(sk, TCP_CLOSE);
- release_sock(sk);
+ release_sock(sk);
sk->zapped = 0;
}
sock->state = SS_UNCONNECTED;
@@ -735,16 +735,16 @@ do_err:
/*
* This does both peername and sockname.
*/
-
+
static int inet_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
struct sock *sk = sock->sk;
struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
-
+
sin->sin_family = AF_INET;
if (peer) {
- if (!tcp_connected(sk->state))
+ if (!tcp_connected(sk->state))
return(-ENOTCONN);
sin->sin_port = sk->dport;
sin->sin_addr.s_addr = sk->daddr;
@@ -767,10 +767,10 @@ int inet_recvmsg(struct socket *sock, struct msghdr *msg, int size,
struct sock *sk = sock->sk;
int addr_len = 0;
int err;
-
+
if (sock->flags & SO_ACCEPTCON)
return(-EINVAL);
- if (sk->prot->recvmsg == NULL)
+ if (sk->prot->recvmsg == NULL)
return(-EOPNOTSUPP);
/* We may need to bind the socket. */
if (inet_autobind(sk) != 0)
@@ -793,7 +793,7 @@ int inet_sendmsg(struct socket *sock, struct msghdr *msg, int size,
send_sig(SIGPIPE, current, 1);
return(-EPIPE);
}
- if (sk->prot->sendmsg == NULL)
+ if (sk->prot->sendmsg == NULL)
return(-EOPNOTSUPP);
if(sk->err)
return sock_error(sk);
@@ -822,7 +822,7 @@ int inet_shutdown(struct socket *sock, int how)
return(-ENOTCONN);
if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)
sock->state = SS_CONNECTED;
- if (!tcp_connected(sk->state))
+ if (!tcp_connected(sk->state))
return(-ENOTCONN);
sk->shutdown |= how;
if (sk->prot->shutdown)
@@ -842,6 +842,10 @@ unsigned int inet_poll(struct file * file, struct socket *sock, poll_table *wait
return sk->prot->poll(file, sock, wait);
}
+#ifdef _HURD_
+#define inet_ioctl 0
+#else
+
/*
* ioctl() calls you can issue on an INET socket. Most of these are
* device configuration and stuff and very rarely used. Some ioctls
@@ -858,14 +862,14 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
int err;
int pid;
- switch(cmd)
+ switch(cmd)
{
case FIOSETOWN:
case SIOCSPGRP:
err = get_user(pid, (int *) arg);
if (err)
- return err;
- if (current->pid != pid && current->pgrp != -pid &&
+ return err;
+ if (current->pid != pid && current->pgrp != -pid &&
!capable(CAP_NET_ADMIN))
return -EPERM;
sk->proc = pid;
@@ -905,18 +909,18 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFNETMASK:
case SIOCGIFDSTADDR:
case SIOCSIFDSTADDR:
- case SIOCSIFPFLAGS:
- case SIOCGIFPFLAGS:
+ case SIOCSIFPFLAGS:
+ case SIOCGIFPFLAGS:
case SIOCSIFFLAGS:
return(devinet_ioctl(cmd,(void *) arg));
case SIOCGIFBR:
case SIOCSIFBR:
-#ifdef CONFIG_BRIDGE
+#ifdef CONFIG_BRIDGE
return(br_ioctl(cmd,(void *) arg));
#else
return -ENOPKG;
-#endif
-
+#endif
+
case SIOCADDDLCI:
case SIOCDELDLCI:
#ifdef CONFIG_DLCI
@@ -946,13 +950,15 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
#endif
if (sk->prot->ioctl==NULL || (err=sk->prot->ioctl(sk, cmd, arg))==-ENOIOCTLCMD)
- return(dev_ioctl(cmd,(void *) arg));
+ return(dev_ioctl(cmd,(void *) arg));
return err;
}
/*NOTREACHED*/
return(0);
}
+#endif
+
struct proto_ops inet_stream_ops = {
PF_INET,
@@ -962,7 +968,7 @@ struct proto_ops inet_stream_ops = {
inet_stream_connect,
sock_no_socketpair,
inet_accept,
- inet_getname,
+ inet_getname,
inet_poll,
inet_ioctl,
inet_listen,
@@ -983,7 +989,7 @@ struct proto_ops inet_dgram_ops = {
inet_dgram_connect,
sock_no_socketpair,
sock_no_accept,
- inet_getname,
+ inet_getname,
datagram_poll,
inet_ioctl,
sock_no_listen,
@@ -1053,9 +1059,9 @@ extern void tcp_v4_init(struct net_proto_family *);
/*
- * Called by socket.c on kernel startup.
+ * Called by socket.c on kernel startup.
*/
-
+
__initfunc(void inet_proto_init(struct net_proto *pro))
{
struct sk_buff *dummy_skb;
@@ -1070,17 +1076,17 @@ __initfunc(void inet_proto_init(struct net_proto *pro))
}
/*
- * Tell SOCKET that we are alive...
+ * Tell SOCKET that we are alive...
*/
-
+
(void) sock_register(&inet_family_ops);
/*
- * Add all the protocols.
+ * Add all the protocols.
*/
printk(KERN_INFO "IP Protocols: ");
- for(p = inet_protocol_base; p != NULL;)
+ for(p = inet_protocol_base; p != NULL;)
{
struct inet_protocol *tmp = (struct inet_protocol *) p->next;
inet_add_protocol(p);
@@ -1132,7 +1138,7 @@ __initfunc(void inet_proto_init(struct net_proto *pro))
#ifdef CONFIG_IP_MASQUERADE
ip_masq_init();
#endif
-
+
/*
* Initialise the multicast router
*/
diff --git a/pfinet/linux-src/net/ipv4/arp.c b/pfinet/linux-src/net/ipv4/arp.c
index 1e5cf1b1..045513a8 100644
--- a/pfinet/linux-src/net/ipv4/arp.c
+++ b/pfinet/linux-src/net/ipv4/arp.c
@@ -15,9 +15,9 @@
* 2 of the License, or (at your option) any later version.
*
* Fixes:
- * Alan Cox : Removed the Ethernet assumptions in
+ * Alan Cox : Removed the Ethernet assumptions in
* Florian's code
- * Alan Cox : Fixed some small errors in the ARP
+ * Alan Cox : Fixed some small errors in the ARP
* logic
* Alan Cox : Allow >4K in /proc
* Alan Cox : Make ARP add its own protocol entry
@@ -39,18 +39,18 @@
* Jonathan Naylor : Only lookup the hardware address for
* the correct hardware type.
* Germano Caronni : Assorted subtle races.
- * Craig Schlenter : Don't modify permanent entry
+ * Craig Schlenter : Don't modify permanent entry
* during arp_rcv.
* Russ Nelson : Tidied up a few bits.
* Alexey Kuznetsov: Major changes to caching and behaviour,
- * eg intelligent arp probing and
+ * eg intelligent arp probing and
* generation
* of host down events.
* Alan Cox : Missing unlock in device events.
* Eckes : ARP ioctl control errors.
* Alexey Kuznetsov: Arp free fix.
* Manuel Rodriguez: Gratuitous ARP.
- * Jonathan Layes : Added arpd support through kerneld
+ * Jonathan Layes : Added arpd support through kerneld
* message queue (960314)
* Mike Shaver : /proc/sys/net/ipv4/arp_* support
* Mike McLagan : Routing by source
@@ -77,7 +77,7 @@
unresolved IP address. (OK)
950727 -- MS
*/
-
+
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
@@ -194,14 +194,9 @@ int arp_mc_map(u32 addr, u8 *haddr, struct device *dev, int dir)
{
switch (dev->type) {
case ARPHRD_ETHER:
- case ARPHRD_FDDI:
- ip_eth_mc_map(addr, haddr) ;
- return 0 ;
case ARPHRD_IEEE802:
- if ( (dev->name[0] == 't') && (dev->name[1] == 'r')) /* Token Ring */
- ip_tr_mc_map(addr,haddr) ;
- else
- ip_eth_mc_map(addr, haddr);
+ case ARPHRD_FDDI:
+ ip_eth_mc_map(addr, haddr);
return 0;
default:
if (dir) {
@@ -262,7 +257,7 @@ static int arp_constructor(struct neighbour *neigh)
switch (dev->type) {
default:
break;
- case ARPHRD_ROSE:
+ case ARPHRD_ROSE:
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
case ARPHRD_AX25:
#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
@@ -424,8 +419,8 @@ int arp_bind_neighbour(struct dst_entry *dst)
* message.
*/
-void arp_send(int type, int ptype, u32 dest_ip,
- struct device *dev, u32 src_ip,
+void arp_send(int type, int ptype, u32 dest_ip,
+ struct device *dev, u32 src_ip,
unsigned char *dest_hw, unsigned char *src_hw,
unsigned char *target_hw)
{
@@ -436,14 +431,14 @@ void arp_send(int type, int ptype, u32 dest_ip,
/*
* No arp on this interface.
*/
-
+
if (dev->flags&IFF_NOARP)
return;
/*
* Allocate a buffer
*/
-
+
skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
+ dev->hard_header_len + 15, GFP_ATOMIC);
if (skb == NULL)
@@ -549,10 +544,10 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
* of the device. Similarly, the hardware types should match. The
* device should be ARP-able. Also, if pln is not 4, then the lookup
* is not from an IP number. We can't currently handle this, so toss
- * it.
- */
+ * it.
+ */
if (in_dev == NULL ||
- arp->ar_hln != dev->addr_len ||
+ arp->ar_hln != dev->addr_len ||
dev->flags & IFF_NOARP ||
skb->pkt_type == PACKET_OTHERHOST ||
skb->pkt_type == PACKET_LOOPBACK ||
@@ -560,7 +555,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
goto out;
switch (dev_type) {
- default:
+ default:
if (arp->ar_pro != __constant_htons(ETH_P_IP))
goto out;
if (htons(dev_type) != arp->ar_hrd)
@@ -627,7 +622,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
tha=arp_ptr;
arp_ptr += dev->addr_len;
memcpy(&tip, arp_ptr, 4);
-/*
+/*
* Check for bad requests for 127.x.x.x and requests for multicast
* addresses. If this is one such, delete it.
*/
@@ -638,16 +633,16 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
* Process entry. The idea here is we want to send a reply if it is a
* request for us or if it is a request for someone else that we hold
* a proxy for. We want to add an entry to our cache if it is a reply
- * to us or if it is a request for our address.
- * (The assumption for this last is that if someone is requesting our
- * address, they are probably intending to talk to us, so it saves time
- * if we cache their address. Their address is also probably not in
+ * to us or if it is a request for our address.
+ * (The assumption for this last is that if someone is requesting our
+ * address, they are probably intending to talk to us, so it saves time
+ * if we cache their address. Their address is also probably not in
* our cache, since ours is not in their cache.)
- *
+ *
* Putting this another way, we only care about replies if they are to
* us, in which case we add them to the cache. For requests, we care
* about those for us and those for our proxies. We reply to both,
- * and in the case of requests for us we add the requester to the arp
+ * and in the case of requests for us we add the requester to the arp
* cache.
*/
@@ -786,7 +781,7 @@ int arp_req_set(struct arpreq *r, struct device * dev)
if (!dev)
return -EINVAL;
}
- if (r->arp_ha.sa_family != dev->type)
+ if (r->arp_ha.sa_family != dev->type)
return -EINVAL;
err = -ENOBUFS;
@@ -883,6 +878,9 @@ int arp_req_delete(struct arpreq *r, struct device * dev)
return err;
}
+#ifdef _HURD_
+#define arp_ioctl 0
+#else
/*
* Handle an ARP layer I/O control request.
*/
@@ -950,6 +948,7 @@ out:
rtnl_unlock();
return err;
}
+#endif
/*
* Write the contents of the ARP cache to a PROCfs file.
@@ -1003,7 +1002,7 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy
hbuffer[k++]=':';
}
hbuffer[--k]=0;
-
+
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
}
#endif
@@ -1020,7 +1019,7 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy
"%-17s0x%-10x0x%-10x%s",
in_ntoa(*(u32*)n->primary_key),
hatype,
- arp_state_to_flags(n),
+ arp_state_to_flags(n),
hbuffer);
size += sprintf(buffer+len+size,
" %-17s %s\n",
@@ -1028,7 +1027,7 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy
len += size;
pos += size;
-
+
if (pos <= offset)
len=0;
if (pos >= offset+length)
@@ -1054,7 +1053,7 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy
len += size;
pos += size;
-
+
if (pos <= offset)
len=0;
if (pos >= offset+length)
@@ -1064,7 +1063,7 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy
done:
neigh_table_unlock(&arp_tbl);
-
+
*start = buffer+len-(pos-offset); /* Start of wanted data */
len = pos-offset; /* Start slop */
if (len>length)
@@ -1138,14 +1137,14 @@ char *ax2asc(ax25_address *a)
if (c != ' ') *s++ = c;
}
-
+
*s++ = '-';
if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
*s++ = '1';
n -= 10;
}
-
+
*s++ = n + '0';
*s++ = '\0';
diff --git a/pfinet/linux-src/net/ipv4/devinet.c b/pfinet/linux-src/net/ipv4/devinet.c
index a50ee3bd..d980631b 100644
--- a/pfinet/linux-src/net/ipv4/devinet.c
+++ b/pfinet/linux-src/net/ipv4/devinet.c
@@ -23,7 +23,7 @@
*/
#include <linux/config.h>
-
+
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
@@ -370,8 +370,8 @@ inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
#endif
-/*
- * Determine a default network mask, based on the IP address.
+/*
+ * Determine a default network mask, based on the IP address.
*/
static __inline__ int inet_abc_len(u32 addr)
@@ -380,21 +380,79 @@ static __inline__ int inet_abc_len(u32 addr)
return 0;
addr = ntohl(addr);
- if (IN_CLASSA(addr))
+ if (IN_CLASSA(addr))
return 8;
- if (IN_CLASSB(addr))
+ if (IN_CLASSB(addr))
return 16;
- if (IN_CLASSC(addr))
+ if (IN_CLASSC(addr))
return 24;
/*
- * Something else, probably a multicast.
+ * Something else, probably a multicast.
*/
-
+
return -1;
}
+#ifdef _HURD_
+
+#define devinet_ioctl 0
+
+error_t
+configure_device (struct device *dev,
+ uint32_t addr, uint32_t netmask)
+{
+ struct in_device *in_dev = dev->ip_ptr;
+ struct in_ifaddr *ifa = in_dev ? in_dev->ifa_list : 0;
+
+ if (ifa)
+ {
+ inet_del_ifa (in_dev, &in_dev->ifa_list, 0);
+ ifa->ifa_broadcast = 0;
+ ifa->ifa_anycast = 0;
+ }
+ else
+ {
+ ifa = inet_alloc_ifa ();
+ if (!ifa)
+ return ENOBUFS;
+ memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
+ }
+
+ if (addr != INADDR_NONE)
+ ifa->ifa_address = ifa->ifa_local = addr;
+ if (netmask != INADDR_NONE)
+ {
+ ifa->ifa_mask = netmask;
+ ifa->ifa_prefixlen = inet_mask_len (ifa->ifa_mask);
+ if ((dev->flags&IFF_BROADCAST) && ifa->ifa_prefixlen < 31)
+ ifa->ifa_broadcast = ifa->ifa_address|~ifa->ifa_mask;
+ else
+ ifa->ifa_broadcast = 0;
+ }
+
+ return - inet_set_ifa (dev, ifa);
+}
+
+void
+inquire_device (struct device *dev,
+ uint32_t *addr, uint32_t *netmask)
+{
+ struct in_device *in_dev = dev->ip_ptr;
+ struct in_ifaddr *ifa = in_dev ? in_dev->ifa_list : 0;
+
+ if (ifa)
+ {
+ *addr = ifa->ifa_local;
+ *netmask = ifa->ifa_mask;
+ }
+ else
+ *addr = *netmask = INADDR_NONE;
+}
+
+#else
+
int devinet_ioctl(unsigned int cmd, void *arg)
{
struct ifreq ifr;
@@ -514,7 +572,7 @@ int devinet_ioctl(unsigned int cmd, void *arg)
#endif
ret = dev_change_flags(dev, ifr.ifr_flags);
break;
-
+
case SIOCSIFADDR: /* Set interface address (and family) */
if (inet_abc_len(sin->sin_addr.s_addr) < 0) {
ret = -EINVAL;
@@ -563,7 +621,7 @@ int devinet_ioctl(unsigned int cmd, void *arg)
inet_insert_ifa(in_dev, ifa);
}
break;
-
+
case SIOCSIFDSTADDR: /* Set the destination address */
if (ifa->ifa_address != sin->sin_addr.s_addr) {
if (inet_abc_len(sin->sin_addr.s_addr) < 0) {
@@ -605,6 +663,8 @@ rarok:
return 0;
}
+#endif
+
static int
inet_gifconf(struct device *dev, char *buf, int len)
{
@@ -657,7 +717,7 @@ u32 inet_select_addr(struct device *dev, u32 dst, int scope)
if (!addr)
addr = ifa->ifa_local;
} endfor_ifa(in_dev);
-
+
if (addr || scope >= RT_SCOPE_LINK)
return addr;
@@ -691,7 +751,7 @@ int unregister_inetaddr_notifier(struct notifier_block *nb)
{
return notifier_chain_unregister(&inetaddr_chain,nb);
}
-
+
static int inetdev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct device *dev = ptr;
@@ -725,7 +785,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, void
case NETDEV_DOWN:
ip_mc_down(in_dev);
break;
- case NETDEV_CHANGEMTU:
+ case NETDEV_CHANGEMTU:
if (dev->mtu >= 68)
break;
/* MTU falled under minimal IP mtu. Disable IP. */
diff --git a/pfinet/linux-src/net/ipv4/tcp.c b/pfinet/linux-src/net/ipv4/tcp.c
index 65763215..89e1bbbf 100644
--- a/pfinet/linux-src/net/ipv4/tcp.c
+++ b/pfinet/linux-src/net/ipv4/tcp.c
@@ -202,7 +202,7 @@
* Eric Schenk : Fix fast close down bug with
* shutdown() followed by close().
* Andi Kleen : Make poll agree with SIGIO
- *
+ *
* This program 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
@@ -249,8 +249,8 @@
* for violations and the like. tcp.c is just too big... If I say something
* "does?" or "doesn't?", it means I'm not sure, and will have to hash it out
* with Alan. -- MS 950903
- * [Note: Most of the TCP code has been rewriten/redesigned since this
- * RFC1122 check. It is probably not correct anymore. It should be redone
+ * [Note: Most of the TCP code has been rewriten/redesigned since this
+ * RFC1122 check. It is probably not correct anymore. It should be redone
* before 2.2. -AK]
*
* Use of PSH (4.2.2.2)
@@ -384,14 +384,14 @@
*
* ICMP messages (4.2.3.9)
* MUST act on ICMP errors. (does)
- * MUST slow transmission upon receipt of a Source Quench. (doesn't anymore
+ * MUST slow transmission upon receipt of a Source Quench. (doesn't anymore
* because that is deprecated now by the IETF, can be turned on)
* MUST NOT abort connection upon receipt of soft Destination
* Unreachables (0, 1, 5), Time Exceededs and Parameter
* Problems. (doesn't)
* SHOULD report soft Destination Unreachables etc. to the
* application. (does, except during SYN_RECV and may drop messages
- * in some rare cases before accept() - ICMP is unreliable)
+ * in some rare cases before accept() - ICMP is unreliable)
* SHOULD abort connection upon receipt of hard Destination Unreachable
* messages (2, 3, 4). (does, but see above)
*
@@ -435,20 +435,20 @@ kmem_cache_t *tcp_timewait_cachep;
* the socket locked or with interrupts disabled
*/
-static struct open_request *tcp_find_established(struct tcp_opt *tp,
+static struct open_request *tcp_find_established(struct tcp_opt *tp,
struct open_request **prevp)
{
struct open_request *req = tp->syn_wait_queue;
- struct open_request *prev = (struct open_request *)&tp->syn_wait_queue;
+ struct open_request *prev = (struct open_request *)&tp->syn_wait_queue;
while(req) {
- if (req->sk &&
+ if (req->sk &&
((1 << req->sk->state) &
~(TCPF_SYN_SENT|TCPF_SYN_RECV)))
break;
- prev = req;
+ prev = req;
req = req->dl_next;
}
- *prevp = prev;
+ *prevp = prev;
return req;
}
@@ -539,7 +539,7 @@ static unsigned int tcp_listen_poll(struct sock *sk, poll_table *wait)
}
/*
- * Compute minimal free write space needed to queue new packets.
+ * Compute minimal free write space needed to queue new packets.
*/
#define tcp_min_write_space(__sk) \
(atomic_read(&(__sk)->wmem_alloc) / 2)
@@ -605,12 +605,12 @@ unsigned int tcp_poll(struct file * file, struct socket *sock, poll_table *wait)
/*
* Socket write_space callback.
- * This (or rather the sock_wake_async) should agree with poll.
+ * This (or rather the sock_wake_async) should agree with poll.
*/
void tcp_write_space(struct sock *sk)
{
if (sk->dead)
- return;
+ return;
wake_up_interruptible(sk->sleep);
if (sock_wspace(sk) >=
@@ -619,6 +619,23 @@ void tcp_write_space(struct sock *sk)
}
+#ifdef _HURD_
+
+#define tcp_ioctl 0
+
+error_t
+tcp_tiocinq(struct sock *sk, mach_msg_type_number_t *amount)
+{
+ if (sk->state == TCP_LISTEN)
+ return EINVAL;
+ lock_sock(sk);
+ *amount = tcp_readable(sk);
+ release_sock(sk);
+ return 0;
+}
+
+#else
+
int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
int answ;
@@ -652,6 +669,8 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
return put_user(answ, (int *)arg);
}
+#endif
+
/*
* Wait for a socket to get into the connected state
*
@@ -727,20 +746,20 @@ static void wait_for_tcp_memory(struct sock * sk)
/*
* Wait for a buffer.
- */
-static int wait_for_buffer(struct sock *sk)
-{
- struct wait_queue wait = { current, NULL };
-
- release_sock(sk);
- add_wait_queue(sk->sleep, &wait);
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- current->state = TASK_RUNNING;
+ */
+static int wait_for_buffer(struct sock *sk)
+{
+ struct wait_queue wait = { current, NULL };
+
+ release_sock(sk);
+ add_wait_queue(sk->sleep, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ current->state = TASK_RUNNING;
remove_wait_queue(sk->sleep, &wait);
- lock_sock(sk);
- return 0;
-}
+ lock_sock(sk);
+ return 0;
+}
/* When all user supplied data has been queued set the PSH bit */
#define PSH_NEEDED (seglen == 0 && iovlen == 0)
@@ -781,7 +800,7 @@ int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg)
iovlen = msg->msg_iovlen;
iov = msg->msg_iov;
copied = 0;
-
+
while(--iovlen >= 0) {
int seglen=iov->iov_len;
unsigned char * from=iov->iov_base;
@@ -801,7 +820,7 @@ int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg)
/* Make sure that we are established. */
if (sk->shutdown & SEND_SHUTDOWN)
goto do_shutdown;
-
+
/* Now we need to check if we have a half
* built packet we can tack some data onto.
*/
@@ -809,7 +828,7 @@ int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg)
skb = sk->write_queue.prev;
copy = skb->len;
/* If the remote does SWS avoidance we should
- * queue the best we can if not we should in
+ * queue the best we can if not we should in
* fact send multiple packets...
* A method for detecting this would be most
* welcome.
@@ -819,21 +838,21 @@ int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg)
tp->snd_nxt < TCP_SKB_CB(skb)->end_seq) {
int last_byte_was_odd = (copy % 4);
- /*
+ /*
* Check for parallel writers sleeping in user access.
- */
- if (tp->partial_writers++ > 0) {
+ */
+ if (tp->partial_writers++ > 0) {
wait_for_buffer(sk);
tp->partial_writers--;
- continue;
+ continue;
}
-
+
copy = mss_now - copy;
if(copy > skb_tailroom(skb))
copy = skb_tailroom(skb);
if(copy > seglen)
copy = seglen;
-
+
if(last_byte_was_odd) {
if(copy_from_user(skb_put(skb, copy),
from, copy))
@@ -846,7 +865,7 @@ int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg)
from, skb_put(skb, copy),
copy, skb->csum, &err);
}
-
+
/*
* FIXME: the *_user functions should
* return how much data was
@@ -867,8 +886,8 @@ int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg)
if (PSH_NEEDED)
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
- if (--tp->partial_writers > 0)
- wake_up_interruptible(sk->sleep);
+ if (--tp->partial_writers > 0)
+ wake_up_interruptible(sk->sleep);
continue;
}
@@ -1012,7 +1031,7 @@ out:
* this with tcp_send_ack().
* This is called for delayed acks also.
*/
-
+
void tcp_read_wakeup(struct sock *sk)
{
/* If we're closed, don't send an ack, or we'll get a RST
@@ -1028,7 +1047,7 @@ void tcp_read_wakeup(struct sock *sk)
*/
static int tcp_recv_urg(struct sock * sk, int nonblock,
- struct msghdr *msg, int len, int flags,
+ struct msghdr *msg, int len, int flags,
int *addr_len)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
@@ -1050,15 +1069,15 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
lock_sock(sk);
if (tp->urg_data & URG_VALID) {
- int err = 0;
+ int err = 0;
char c = tp->urg_data;
if (!(flags & MSG_PEEK))
tp->urg_data = URG_READ;
-
+
if(msg->msg_name)
tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
- msg->msg_name);
+ msg->msg_name);
if(addr_len)
*addr_len = tp->af_specific->sockaddr_len;
@@ -1075,8 +1094,8 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
}
else
msg->msg_flags|=MSG_TRUNC;
-
- /* N.B. Is this right?? If len == 0 we didn't read any data */
+
+ /* N.B. Is this right?? If len == 0 we didn't read any data */
return err ? -EFAULT : 1;
}
release_sock(sk);
@@ -1111,7 +1130,7 @@ static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
static void cleanup_rbuf(struct sock *sk, int copied)
{
struct sk_buff *skb;
-
+
/* NOTE! The socket must be locked, so that we don't get
* a messed-up receive queue.
*/
@@ -1143,9 +1162,9 @@ static void cleanup_rbuf(struct sock *sk, int copied)
/*
- * This routine copies from a sock struct into the user buffer.
+ * This routine copies from a sock struct into the user buffer.
*/
-
+
int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
int len, int nonblock, int flags, int *addr_len)
{
@@ -1155,7 +1174,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
u32 peek_seq;
volatile u32 *seq; /* So gcc doesn't overoptimise */
unsigned long used;
- int err = 0;
+ int err = 0;
int target = 1; /* Read at least this many bytes */
if (sk->err)
@@ -1176,20 +1195,20 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
seq = &tp->copied_seq;
if (flags & MSG_PEEK)
seq = &peek_seq;
-
+
/* Handle the POSIX bogosity MSG_WAITALL. */
if (flags & MSG_WAITALL)
target=len;
add_wait_queue(sk->sleep, &wait);
lock_sock(sk);
-
+
/*
* BUG BUG BUG
- * This violates 1003.1g compliance. We must wait for
+ * This violates 1003.1g compliance. We must wait for
* data to exist even if we read none!
*/
-
+
while (len > 0) {
struct sk_buff * skb;
u32 offset;
@@ -1219,7 +1238,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
if (!skb)
break;
- /* Now that we have two receive queues this
+ /* Now that we have two receive queues this
* shouldn't happen.
*/
if (before(*seq, TCP_SKB_CB(skb)->seq)) {
@@ -1366,7 +1385,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
if(copied >= 0 && msg->msg_name) {
tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
- msg->msg_name);
+ msg->msg_name);
if(addr_len)
*addr_len = tp->af_specific->sockaddr_len;
}
@@ -1483,13 +1502,13 @@ static void tcp_close_pending (struct sock *sk)
while(req) {
struct open_request *iter;
-
+
if (req->sk)
tcp_close(req->sk, 0);
iter = req;
req = req->dl_next;
-
+
(*iter->class->destructor)(iter);
tcp_dec_slow_timer(TCP_SLT_SYNACK);
sk->ack_backlog--;
@@ -1583,7 +1602,7 @@ void tcp_close(struct sock *sk, long timeout)
tsk->state = TASK_RUNNING;
remove_wait_queue(sk->sleep, &wait);
-
+
lock_sock(sk);
}
@@ -1613,7 +1632,7 @@ static struct open_request * wait_for_connect(struct sock * sk,
schedule();
lock_sock(sk);
req = tcp_find_established(&(sk->tp_pinfo.af_tcp), pprev);
- if (req)
+ if (req)
break;
if (signal_pending(current))
break;
@@ -1636,7 +1655,7 @@ struct sock *tcp_accept(struct sock *sk, int flags)
struct sock *newsk = NULL;
int error;
- lock_sock(sk);
+ lock_sock(sk);
/* We need to make sure that this socket is listening,
* and that it has something pending.
@@ -1652,10 +1671,10 @@ struct sock *tcp_accept(struct sock *sk, int flags)
error = EAGAIN;
if (flags & O_NONBLOCK)
goto out;
-
+
error = ERESTARTSYS;
req = wait_for_connect(sk, &prev);
- if (!req)
+ if (!req)
goto out;
}
@@ -1663,7 +1682,7 @@ struct sock *tcp_accept(struct sock *sk, int flags)
newsk = req->sk;
req->class->destructor(req);
tcp_openreq_free(req);
- sk->ack_backlog--;
+ sk->ack_backlog--;
if(sk->keepopen)
tcp_inc_slow_timer(TCP_SLT_KEEPALIVE);
@@ -1673,26 +1692,26 @@ struct sock *tcp_accept(struct sock *sk, int flags)
out:
/* sk should be in LISTEN state, thus accept can use sk->err for
* internal purposes without stomping one anyone's feed.
- */
- sk->err = error;
+ */
+ sk->err = error;
release_sock(sk);
return newsk;
}
/*
- * Socket option code for TCP.
+ * Socket option code for TCP.
*/
-
-int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval,
+
+int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval,
int optlen)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
int val;
if (level != SOL_TCP)
- return tp->af_specific->setsockopt(sk, level, optname,
+ return tp->af_specific->setsockopt(sk, level, optname,
optval, optlen);
-
+
if(optlen<sizeof(int))
return -EINVAL;
diff --git a/pfinet/linux-src/net/ipv4/udp.c b/pfinet/linux-src/net/ipv4/udp.c
index 909e858f..87ff84ce 100644
--- a/pfinet/linux-src/net/ipv4/udp.c
+++ b/pfinet/linux-src/net/ipv4/udp.c
@@ -19,8 +19,8 @@
* for udp at least is 'valid'.
* Alan Cox : Fixed icmp handling properly
* Alan Cox : Correct error for oversized datagrams
- * Alan Cox : Tidied select() semantics.
- * Alan Cox : udp_err() fixed properly, also now
+ * Alan Cox : Tidied select() semantics.
+ * Alan Cox : udp_err() fixed properly, also now
* select and read wake correctly on errors
* Alan Cox : udp_send verify_area moved to avoid mem leak
* Alan Cox : UDP can count its memory
@@ -55,7 +55,7 @@
* does have a high hit rate.
* Olaf Kirch : Don't linearise iovec on sendmsg.
* Andi Kleen : Some cleanups, cache destination entry
- * for connect.
+ * for connect.
* Vitaly E. Lavrov : Transparent proxy revived after year coma.
* Melvin Smith : Check msg_name not msg_namelen in sendto(),
* return ENOTCONN for unconnected sockets (POSIX)
@@ -68,10 +68,10 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
+
/* RFC1122 Status:
4.1.3.1 (Ports):
- SHOULD send ICMP_PORT_UNREACHABLE in response to datagrams to
+ SHOULD send ICMP_PORT_UNREACHABLE in response to datagrams to
an un-listened port. (OK)
4.1.3.2 (IP Options)
MUST pass IP options from IP -> application (OK)
@@ -399,7 +399,7 @@ static inline struct sock *udp_v4_mcast_next(struct sock *sk,
* This routine is called by the ICMP module when it gets some
* sort of error condition. If err < 0 then the socket should
* be closed and the error returned to the user. If err > 0
- * it's just the icmp type << 8 | icmp code.
+ * it's just the icmp type << 8 | icmp code.
* Header points to the ip header of the error packet. We move
* on past this. Then (as it used to claim before adjustment)
* header points to the first 8 bytes of the udp header. We need
@@ -463,16 +463,16 @@ void udp_err(struct sk_buff *skb, unsigned char *dp, int len)
}
/*
- * Various people wanted BSD UDP semantics. Well they've come
+ * Various people wanted BSD UDP semantics. Well they've come
* back out because they slow down response to stuff like dead
* or unreachable name servers and they screw term users something
- * chronic. Oh and it violates RFC1122. So basically fix your
+ * chronic. Oh and it violates RFC1122. So basically fix your
* client code people.
*/
-
+
/*
- * RFC1122: OK. Passes ICMP errors back to application, as per
- * 4.1.3.3. After the comment above, that should be no surprise.
+ * RFC1122: OK. Passes ICMP errors back to application, as per
+ * 4.1.3.3. After the comment above, that should be no surprise.
*/
if (!harderr && !sk->ip_recverr)
@@ -497,7 +497,7 @@ static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr,
return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
}
-struct udpfakehdr
+struct udpfakehdr
{
struct udphdr uh;
u32 saddr;
@@ -512,8 +512,8 @@ struct udpfakehdr
* card and provide an additional callback mode for direct user->board I/O
* transfers. That one will be fun.
*/
-
-static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned int fraglen)
+
+static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned int fraglen)
{
struct udpfakehdr *ufh = (struct udpfakehdr *)p;
if (offset==0) {
@@ -522,7 +522,7 @@ static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned i
return -EFAULT;
ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
ufh->wcheck);
- ufh->uh.check = csum_tcpudp_magic(ufh->saddr, ufh->daddr,
+ ufh->uh.check = csum_tcpudp_magic(ufh->saddr, ufh->daddr,
ntohs(ufh->uh.len),
IPPROTO_UDP, ufh->wcheck);
if (ufh->uh.check == 0)
@@ -542,8 +542,8 @@ static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned i
* CONFIG_FAST_NET set for >10Mb/second boards to activate this sort of coding.
* Timing needed to verify if this is a valid decision.
*/
-
-static int udp_getfrag_nosum(const void *p, char * to, unsigned int offset, unsigned int fraglen)
+
+static int udp_getfrag_nosum(const void *p, char * to, unsigned int offset, unsigned int fraglen)
{
struct udpfakehdr *ufh = (struct udpfakehdr *)p;
@@ -582,7 +582,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
if (len < 0 || len > 0xFFFF)
return -EMSGSIZE;
- /*
+ /*
* Check the flags.
*/
@@ -600,9 +600,9 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
#endif
/*
- * Get and verify the address.
+ * Get and verify the address.
*/
-
+
if (msg->msg_name) {
struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;
if (msg->msg_namelen < sizeof(*usin))
@@ -673,7 +673,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
connected = 0;
}
tos = RT_TOS(sk->ip_tos);
- if (sk->localroute || (msg->msg_flags&MSG_DONTROUTE) ||
+ if (sk->localroute || (msg->msg_flags&MSG_DONTROUTE) ||
(ipc.opt && ipc.opt->is_strictroute)) {
tos |= RTO_ONLINK;
connected = 0;
@@ -703,11 +703,11 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
(msg->msg_flags&MSG_PROXY ? RTO_TPROXY : 0) |
#endif
tos, ipc.oif);
- if (err)
+ if (err)
goto out;
err = -EACCES;
- if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast)
+ if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast)
goto out;
if (connected && sk->dst_cache == NULL)
sk->dst_cache = dst_clone(&rt->u.dst);
@@ -739,13 +739,19 @@ out:
return err;
}
+#ifdef _HURD_
+
+#define udp_ioctl 0
+
+#else
+
/*
* IOCTL requests applicable to the UDP protocol
*/
-
+
int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
- switch(cmd)
+ switch(cmd)
{
case TIOCOUTQ:
{
@@ -782,6 +788,8 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
return(0);
}
+#endif
+
#ifndef HAVE_CSUM_COPY_USER
#undef CONFIG_UDP_DELAY_CSUM
#endif
@@ -809,7 +817,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb)
goto out;
-
+
copied = skb->len - sizeof(struct udphdr);
if (copied > len) {
copied = len;
@@ -824,7 +832,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
copied);
} else if (copied > msg->msg_iov[0].iov_len || (msg->msg_flags&MSG_TRUNC)) {
- if ((unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum)))
+ if ((unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum)))
goto csum_copy_err;
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
copied);
@@ -833,11 +841,11 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
err = 0;
csum = csum_partial(skb->h.raw, sizeof(struct udphdr), skb->csum);
- csum = csum_and_copy_to_user((char*)&skb->h.uh[1], msg->msg_iov[0].iov_base,
+ csum = csum_and_copy_to_user((char*)&skb->h.uh[1], msg->msg_iov[0].iov_base,
copied, csum, &err);
if (err)
goto out_free;
- if ((unsigned short)csum_fold(csum))
+ if ((unsigned short)csum_fold(csum))
goto csum_copy_err;
}
#endif
@@ -851,7 +859,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
/*
* Check any passed addresses
*/
- if (addr_len)
+ if (addr_len)
*addr_len=sizeof(*sin);
sin->sin_family = AF_INET;
@@ -878,7 +886,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
if (sk->ip_cmsg_flags)
ip_cmsg_recv(msg, skb);
err = copied;
-
+
out_free:
skb_free_datagram(sk, skb);
out:
@@ -889,11 +897,11 @@ csum_copy_err:
udp_statistics.UdpInErrors++;
skb_free_datagram(sk, skb);
- /*
+ /*
* Error for blocking case is chosen to masquerade
* as some normal condition.
*/
- return (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
+ return (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
#endif
}
@@ -903,14 +911,14 @@ int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
struct rtable *rt;
int err;
-
- if (addr_len < sizeof(*usin))
+
+ if (addr_len < sizeof(*usin))
return(-EINVAL);
/*
* 1003.1g - break association.
*/
-
+
if (usin->sin_family==AF_UNSPEC)
{
sk->saddr=INADDR_ANY;
@@ -922,7 +930,7 @@ int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
return 0;
}
- if (usin->sin_family && usin->sin_family != AF_INET)
+ if (usin->sin_family && usin->sin_family != AF_INET)
return(-EAFNOSUPPORT);
dst_release(xchg(&sk->dst_cache, NULL));
@@ -1056,9 +1064,9 @@ int udp_chkaddr(struct sk_buff *skb)
#endif
/*
- * All we need to do is get the socket, and then do a checksum.
+ * All we need to do is get the socket, and then do a checksum.
*/
-
+
int udp_rcv(struct sk_buff *skb, unsigned short len)
{
struct sock *sk;
@@ -1076,7 +1084,7 @@ int udp_rcv(struct sk_buff *skb, unsigned short len)
/*
* Get the header.
*/
-
+
uh = skb->h.uh;
__skb_pull(skb, skb->h.raw - skb->data);
@@ -1085,7 +1093,7 @@ int udp_rcv(struct sk_buff *skb, unsigned short len)
/*
* Validate the packet and the UDP length.
*/
-
+
ulen = ntohs(uh->len);
if (ulen > len || ulen < sizeof(*uh)) {
@@ -1100,13 +1108,13 @@ int udp_rcv(struct sk_buff *skb, unsigned short len)
if (uh->check &&
(((skb->ip_summed==CHECKSUM_HW)&&udp_check(uh,ulen,saddr,daddr,skb->csum)) ||
((skb->ip_summed==CHECKSUM_NONE) &&
- (udp_check(uh,ulen,saddr,daddr, csum_partial((char*)uh, ulen, 0))))))
+ (udp_check(uh,ulen,saddr,daddr, csum_partial((char*)uh, ulen, 0))))))
goto csum_error;
#else
if (uh->check==0)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else if (skb->ip_summed==CHECKSUM_HW) {
- if (udp_check(uh,ulen,saddr,daddr,skb->csum))
+ if (udp_check(uh,ulen,saddr,daddr,skb->csum))
goto csum_error;
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else if (skb->ip_summed != CHECKSUM_UNNECESSARY)
@@ -1124,11 +1132,11 @@ int udp_rcv(struct sk_buff *skb, unsigned short len)
else
#endif
sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex);
-
+
if (sk == NULL) {
#ifdef CONFIG_UDP_DELAY_CSUM
if (skb->ip_summed != CHECKSUM_UNNECESSARY &&
- (unsigned short)csum_fold(csum_partial((char*)uh, ulen, skb->csum)))
+ (unsigned short)csum_fold(csum_partial((char*)uh, ulen, skb->csum)))
goto csum_error;
#endif
udp_statistics.UdpNoPorts++;
@@ -1145,9 +1153,9 @@ int udp_rcv(struct sk_buff *skb, unsigned short len)
return 0;
csum_error:
- /*
- * RFC1122: OK. Discards the bad packet silently (as far as
- * the network is concerned, anyway) as per 4.1.3.4 (MUST).
+ /*
+ * RFC1122: OK. Discards the bad packet silently (as far as
+ * the network is concerned, anyway) as per 4.1.3.4 (MUST).
*/
NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
NIPQUAD(saddr),
diff --git a/pfinet/loopback.c b/pfinet/loopback.c
new file mode 100644
index 00000000..068cf3c8
--- /dev/null
+++ b/pfinet/loopback.c
@@ -0,0 +1,130 @@
+/* Loopback "device" for pfinet
+ Copyright (C) 1996,98,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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "pfinet.h"
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/if_ether.h> /* For the statistics structure. */
+#include <linux/if_arp.h> /* For ARPHRD_ETHER */
+
+#define LOOPBACK_MTU (vm_page_size - 172)
+
+/*
+ * The higher levels take care of making this non-reentrant (it's
+ * called with bh's disabled).
+ */
+static int loopback_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
+
+ /*
+ * Take this out if the debug says its ok
+ */
+
+ if (skb == NULL || dev == NULL)
+ printk(KERN_DEBUG "loopback fed NULL data - splat\n");
+
+ /*
+ * Optimise so buffers with skb->free=1 are not copied but
+ * instead are lobbed from tx queue to rx queue
+ */
+
+ if(atomic_read(&skb->users) != 1)
+ {
+ struct sk_buff *skb2=skb;
+ skb=skb_clone(skb, GFP_ATOMIC); /* Clone the buffer */
+ if(skb==NULL) {
+ kfree_skb(skb2);
+ return 0;
+ }
+ kfree_skb(skb2);
+ }
+ else
+ skb_orphan(skb);
+
+ skb->protocol=eth_type_trans(skb,dev);
+ skb->dev=dev;
+#ifndef LOOPBACK_MUST_CHECKSUM
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+#endif
+ netif_rx(skb);
+
+ stats->rx_bytes+=skb->len;
+ stats->tx_bytes+=skb->len;
+ stats->rx_packets++;
+ stats->tx_packets++;
+
+ return(0);
+}
+
+static struct net_device_stats *get_stats(struct device *dev)
+{
+ return (struct net_device_stats *)dev->priv;
+}
+
+static int loopback_open(struct device *dev)
+{
+ dev->flags|=IFF_LOOPBACK;
+ return 0;
+}
+
+/* Initialize the rest of the LOOPBACK device. */
+static int loopback_init(struct device *dev)
+{
+ dev->mtu = LOOPBACK_MTU;
+ dev->tbusy = 0;
+ dev->hard_start_xmit = loopback_xmit;
+ dev->hard_header = eth_header;
+ dev->hard_header_cache = eth_header_cache;
+ dev->header_cache_update= eth_header_cache_update;
+ dev->hard_header_len = ETH_HLEN; /* 14 */
+ dev->addr_len = ETH_ALEN; /* 6 */
+ dev->tx_queue_len = 0;
+ dev->type = ARPHRD_LOOPBACK; /* 0x0001 */
+ dev->rebuild_header = eth_rebuild_header;
+ dev->open = loopback_open;
+ dev->flags = IFF_LOOPBACK;
+ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
+ if (dev->priv == NULL)
+ return -ENOMEM;
+ memset(dev->priv, 0, sizeof(struct net_device_stats));
+ dev->get_stats = get_stats;
+
+ /*
+ * Fill in the generic fields of the device structure.
+ */
+
+ dev_init_buffers(dev);
+
+ return(0);
+}
+
+
+struct device loopback_dev = { name: "lo", init: &loopback_init, };
+
+/* It is important magic that this is the first thing on the list. */
+struct device *dev_base = &loopback_dev;
diff --git a/pfinet/main.c b/pfinet/main.c
new file mode 100644
index 00000000..01dc24be
--- /dev/null
+++ b/pfinet/main.c
@@ -0,0 +1,273 @@
+/*
+ Copyright (C) 1995,96,97,99,2000 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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 <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <error.h>
+#include <argp.h>
+#include <hurd/startup.h>
+#include <string.h>
+
+#include <linux/netdevice.h>
+#include <linux/inet.h>
+
+int trivfs_fstype = FSTYPE_MISC;
+int trivfs_fsid;
+int trivfs_support_read = 0;
+int trivfs_support_write = 0;
+int trivfs_support_exec = 0;
+int trivfs_allow_open = 0;
+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 *shutdown_notify_class;
+
+/* Option parser. */
+extern struct argp pfinet_argp;
+
+int
+pfinet_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ 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 *);
+
+ return (io_server (inp, outp)
+ || socket_server (inp, outp)
+ || trivfs_demuxer (inp, outp)
+ || startup_notify_server (inp, outp));
+}
+
+/* The system is going down; destroy all the extant port rights. That
+ will cause net channels and such to close promptly. */
+error_t
+S_startup_dosync (mach_port_t handle)
+{
+ struct port_info *inpi = ports_lookup_port (pfinet_bucket, handle,
+ shutdown_notify_class);
+
+ if (!inpi)
+ return EOPNOTSUPP;
+
+ ports_class_iterate (socketport_class, ports_destroy_right);
+ return 0;
+}
+
+void
+sigterm_handler (int signo)
+{
+ ports_class_iterate (socketport_class, ports_destroy_right);
+ sleep (10);
+ signal (SIGTERM, SIG_DFL);
+ raise (SIGTERM);
+}
+
+void
+arrange_shutdown_notification ()
+{
+ error_t err;
+ mach_port_t initport, notify;
+ process_t procserver;
+ struct port_info *pi;
+
+ shutdown_notify_class = ports_create_class (0, 0);
+
+ signal (SIGTERM, sigterm_handler);
+
+ /* Arrange to get notified when the system goes down,
+ but if we fail for some reason, just silently give up. No big deal. */
+
+ err = ports_create_port (shutdown_notify_class, pfinet_bucket,
+ sizeof (struct port_info), &pi);
+ if (err)
+ return;
+
+ procserver = getproc ();
+ if (!procserver)
+ return;
+
+ err = proc_getmsgport (procserver, 1, &initport);
+ mach_port_deallocate (mach_task_self (), procserver);
+ if (err)
+ return;
+
+ notify = ports_get_right (pi);
+ ports_port_deref (pi);
+ startup_request_notification (initport, notify,
+ MACH_MSG_TYPE_MAKE_SEND,
+ program_invocation_short_name);
+ mach_port_deallocate (mach_task_self (), initport);
+}
+
+static char *already_open = 0;
+
+/* Return an open device called NAME. If NMAE is 0, and there is a single
+ active device, it is returned, otherwise an error.
+ XXX hacky single-interface version. */
+error_t
+find_device (char *name, struct device **device)
+{
+ if (already_open)
+ if (!name || strcmp (already_open, (*device)->name) == 0)
+ {
+ *device = &ether_dev;
+ return 0;
+ }
+ else
+ return EBUSY; /* XXXACK */
+ else if (! name)
+ return ENXIO; /* XXX */
+
+ name = already_open = strdup (name);
+
+ setup_ethernet_device (name);
+
+ /* Turn on device. */
+ dev_open (&ether_dev);
+
+ *device = &ether_dev;
+
+ return 0;
+}
+
+/* Call FUN with each active device. If a call to FUN returns a
+ non-zero value, this function will return immediately. Otherwise 0 is
+ returned.
+ XXX hacky single-interface version. */
+error_t
+enumerate_devices (error_t (*fun) (struct device *dev))
+{
+ if (already_open)
+ return (*fun) (&ether_dev);
+ else
+ return 0;
+}
+
+extern void sk_init (void), skb_init (void);
+extern int net_dev_init (void);
+
+int
+main (int argc,
+ char **argv)
+{
+ error_t err;
+ mach_port_t bootstrap;
+
+ 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 ();
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &fsys_identity);
+
+ /* Generic initialization */
+
+ init_time ();
+ ethernet_initialize ();
+ cthread_detach (cthread_fork (net_bh_worker, 0));
+
+ __mutex_lock (&global_lock);
+
+ prepare_current (1); /* Set up to call into Linux initialization. */
+
+ sk_init ();
+#ifdef SLAB_SKB
+ skb_init ();
+#endif
+ inet_proto_init (0);
+
+ /* This initializes the Linux network device layer, including
+ initializing each device on the `dev_base' list. For us,
+ that means just loopback_dev, which will get fully initialized now.
+ After this, we can use `register_netdevice' for new interfaces. */
+ net_dev_init ();
+
+ __mutex_unlock (&global_lock);
+
+ /* Parse options. When successful, this configures the interfaces
+ before returning; to do so, it will acquire the global_lock.
+ (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, 0);
+ if (err)
+ error (1, err, "contacting parent");
+
+ /* Launch */
+ ports_manage_port_operations_multithread (pfinet_bucket,
+ pfinet_demuxer,
+ 0, 0, 0);
+ return 0;
+}
+
+void
+trivfs_modify_stat (struct trivfs_protid *cred,
+ struct stat *st)
+{
+}
+
+error_t
+trivfs_goaway (struct trivfs_control *cntl, int flags)
+{
+ if (flags & FSYS_GOAWAY_FORCE)
+ exit (0);
+ else
+ {
+ /* Stop new requests. */
+ ports_inhibit_class_rpcs (trivfs_cntl_portclasses[0]);
+ ports_inhibit_class_rpcs (trivfs_protid_portclasses[0]);
+ ports_inhibit_class_rpcs (socketport_class);
+
+ if (ports_count_class (socketport_class) != 0)
+ {
+ /* We won't go away, so start things going again... */
+ ports_enable_class (socketport_class);
+ ports_resume_class_rpcs (trivfs_cntl_portclasses[0]);
+ ports_resume_class_rpcs (trivfs_protid_portclasses[0]);
+
+ return EBUSY;
+ }
+
+ /* There are no sockets, so we can die without breaking anybody
+ too badly. We don't let user ports on the /servers/socket/2
+ file keep us alive because those get cached in every process
+ that ever makes a PF_INET socket, libc copes with getting
+ MACH_SEND_INVALID_DEST and looking up the new translator. */
+ exit (0);
+ }
+}
diff --git a/pfinet/mapped-time.h b/pfinet/mapped-time.h
new file mode 100644
index 00000000..bcbfc6d4
--- /dev/null
+++ b/pfinet/mapped-time.h
@@ -0,0 +1,30 @@
+#ifndef _MAPPED_TIME_H_
+#define _MAPPED_TIME_H_
+
+#include <maptime.h>
+
+#define HZ 100
+
+extern volatile struct mapped_time_value *mapped_time;
+extern long long root_jiffies;
+
+extern inline int
+read_mapped_secs ()
+{
+ return mapped_time->seconds;
+}
+
+extern inline int
+fetch_jiffies ()
+{
+ struct timeval tv;
+ long long j;
+
+ maptime_read (mapped_time, &tv);
+
+ j = (long long) tv.tv_sec * HZ + ((long long) tv.tv_usec * HZ) / 1000000;
+ return j - root_jiffies;
+}
+
+
+#endif
diff --git a/pfinet/misc.c b/pfinet/misc.c
new file mode 100644
index 00000000..56611daf
--- /dev/null
+++ b/pfinet/misc.c
@@ -0,0 +1,95 @@
+/*
+ Copyright (C) 1995,96,2000 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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 <string.h>
+#include <stddef.h>
+
+#include <linux/socket.h>
+#include <linux/net.h>
+
+
+/* Create a sockaddr port. Fill in *ADDR and *ADDRTYPE accordingly.
+ The address should come from SOCK; PEER is 0 if we want this socket's
+ name and 1 if we want the peer's name. */
+error_t
+make_sockaddr_port (struct socket *sock,
+ int peer,
+ mach_port_t *addr,
+ mach_msg_type_name_t *addrtype)
+{
+ union { struct sockaddr_storage storage; struct sockaddr sa; } buf;
+ int buflen = sizeof buf;
+ error_t err;
+ struct sock_addr *addrstruct;
+
+ err = (*sock->ops->getname) (sock, &buf.sa, &buflen, peer);
+ if (err)
+ return err;
+
+ err = ports_create_port (addrport_class, pfinet_bucket,
+ (offsetof (struct sock_addr, address)
+ + buflen), &addrstruct);
+ if (!err)
+ {
+ addrstruct->address.sa_family = buf.sa.sa_family;
+ addrstruct->address.sa_len = buflen;
+ memcpy (addrstruct->address.sa_data, buf.sa.sa_data,
+ buflen - offsetof (struct sockaddr, sa_data));
+ *addr = ports_get_right (addrstruct);
+ *addrtype = MACH_MSG_TYPE_MAKE_SEND;
+ }
+
+ ports_port_deref (addrstruct);
+
+ return 0;
+}
+
+struct sock_user *
+begin_using_socket_port (mach_port_t port)
+{
+ return ports_lookup_port (pfinet_bucket, port, socketport_class);
+}
+
+void
+end_using_socket_port (struct sock_user *user)
+{
+ if (user)
+ ports_port_deref (user);
+}
+
+struct sock_addr *
+begin_using_sockaddr_port (mach_port_t port)
+{
+ return ports_lookup_port (pfinet_bucket, port, addrport_class);
+}
+
+void
+end_using_sockaddr_port (struct sock_addr *addr)
+{
+ if (addr)
+ ports_port_deref (addr);
+}
+
+/* Nothing need be done here. */
+void
+clean_addrport (void *arg)
+{
+}
diff --git a/pfinet/mutations.h b/pfinet/mutations.h
new file mode 100644
index 00000000..f63ad9b9
--- /dev/null
+++ b/pfinet/mutations.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 1995 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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. */
+
+/* Only CPP macro definitions should go in this file. */
+
+#define IO_SELECT_REPLY_PORT
+
+#define IO_INTRAN sock_user_t begin_using_socket_port (io_t)
+#define IO_DESTRUCTOR end_using_socket_port (sock_user_t)
+
+#define SOCKET_INTRAN sock_user_t begin_using_socket_port (socket_t)
+#define SOCKET_DESTRUCTOR end_using_socket_port (sock_user_t)
+
+#define ADDRPORT_INTRAN sock_addr_t begin_using_sockaddr_port (addr_port_t)
+#define ADDRPORT_DESTRUCTOR end_using_sockaddr_port (sock_addr_t)
+
+#define PF_INTRAN trivfs_protid_t trivfs_begin_using_protid (pf_t)
+#define PF_DESTRUCTOR trivfs_end_using_protid (trivfs_protid_t)
+
+#define IO_IMPORTS import "pfinet.h";
+#define SOCKET_IMPORTS import "pfinet.h";
diff --git a/pfinet/options.c b/pfinet/options.c
new file mode 100644
index 00000000..0a00ea9d
--- /dev/null
+++ b/pfinet/options.c
@@ -0,0 +1,360 @@
+/* Pfinet option parsing
+
+ Copyright (C) 1996,97,2000 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.org>
+
+ 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.,
+ 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <hurd.h>
+#include <argp.h>
+#include <argz.h>
+#include <error.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "pfinet.h"
+
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/ip.h>
+#include <linux/route.h>
+#include <linux/rtnetlink.h>
+#include <net/route.h>
+#include <net/ip_fib.h>
+
+/* Our interface to the set of devices. */
+extern error_t find_device (char *name, struct device **device);
+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);
+extern void inquire_device (struct device *dev,
+ uint32_t *addr, uint32_t *netmask);
+
+/* Pfinet options. Used for both startup and runtime. */
+static const struct argp_option options[] =
+{
+ {"interface", 'i', "DEVICE", 0, "Network interface to use", 1},
+ {0,0,0,0,"These apply to a given interface:", 2},
+ {"address", 'a', "ADDRESS", 0, "Set the network address"},
+ {"netmask", 'm', "MASK", 0, "Set the netmask"},
+ {"gateway", 'g', "ADDRESS", 0, "Set the default gateway"},
+ {"shutdown", 's', 0, 0, "Shut it down"},
+ {0}
+};
+
+static const char doc[] = "Interface-specific options before the first \
+interface specification apply to the first following interface; otherwise \
+they apply to the previously specified interface.";
+
+/* Used to describe a particular interface during argument parsing. */
+struct parse_interface
+{
+ /* The network interface in question. */
+ struct device *device;
+
+ /* New values to apply to it. */
+ uint32_t address, netmask, gateway;
+};
+
+/* Used to hold data during argument parsing. */
+struct parse_hook
+{
+ /* A list of specified interfaces and their corresponding options. */
+ struct parse_interface *interfaces;
+ size_t num_interfaces;
+
+ /* Interface to which options apply. If the device field isn't filled in
+ then it should be by the next --interface option. */
+ struct parse_interface *curint;
+};
+
+/* Adds an empty interface slot to H, and sets H's current interface to it, or
+ returns an error. */
+static error_t
+parse_hook_add_interface (struct parse_hook *h)
+{
+ struct parse_interface *new =
+ realloc (h->interfaces,
+ (h->num_interfaces + 1) * sizeof (struct parse_interface));
+ if (! new)
+ return ENOMEM;
+ h->interfaces = new;
+ h->num_interfaces++;
+ h->curint = new + h->num_interfaces - 1;
+ h->curint->device = 0;
+ h->curint->address = INADDR_NONE;
+ h->curint->netmask = INADDR_NONE;
+ h->curint->gateway = INADDR_NONE;
+ return 0;
+}
+
+static error_t
+parse_opt (int opt, char *arg, struct argp_state *state)
+{
+ error_t err = 0;
+ struct parse_hook *h = state->hook;
+
+ /* Return _ERR from this routine, and in the special case of OPT being
+ ARGP_KEY_SUCCESS, remember to free H first. */
+#define RETURN(_err) \
+ do { if (opt == ARGP_KEY_SUCCESS) \
+ { err = (_err); goto free_hook; } \
+ else \
+ return _err; } while (0)
+
+ /* Print a parsing error message and (if exiting is turned off) return the
+ error code ERR. */
+#define PERR(err, fmt, args...) \
+ do { argp_error (state, fmt , ##args); RETURN (err); } while (0)
+
+ /* Like PERR but for non-parsing errors. */
+#define FAIL(rerr, status, perr, fmt, args...) \
+ do{ argp_failure (state, status, perr, fmt , ##args); RETURN (rerr); } while(0)
+
+ /* Parse STR and return the corresponding internet address. If STR is not
+ a valid internet address, signal an error mentioned TYPE. */
+#undef ADDR
+#define ADDR(str, type) \
+ ({ unsigned long addr = inet_addr (str); \
+ if (addr == INADDR_NONE) PERR (EINVAL, "Malformed %s", type); \
+ addr; })
+
+ switch (opt)
+ {
+ struct parse_interface *in;
+ uint32_t gateway;
+
+ case 'i':
+ /* An interface. */
+ err = 0;
+ if (h->curint->device)
+ /* The current interface slot is not available. */
+ {
+ /* First see if a previously specified one is being re-specified. */
+ for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
+ if (strcmp (in->device->name, arg) == 0)
+ /* Re-use an old slot. */
+ {
+ h->curint = in;
+ return 0;
+ }
+
+ /* Add a new interface entry. */
+ err = parse_hook_add_interface (h);
+ }
+ in = h->curint;
+
+ if (! err)
+ err = find_device (arg, &in->device);
+ if (err)
+ FAIL (err, 10, err, "%s", arg);
+
+ break;
+
+ case 'a':
+ h->curint->address = ADDR (arg, "address");
+ if (!IN_CLASSA (ntohl (h->curint->address))
+ && !IN_CLASSB (ntohl (h->curint->address))
+ && !IN_CLASSC (ntohl (h->curint->address)))
+ {
+ if (IN_MULTICAST (ntohl (h->curint->address)))
+ FAIL (EINVAL, 1, 0,
+ "%s: Cannot set interface address to multicast address",
+ arg);
+ else
+ FAIL (EINVAL, 1, 0,
+ "%s: Illegal or undefined network address", arg);
+ }
+ break;
+ case 'm':
+ h->curint->netmask = ADDR (arg, "netmask"); break;
+ case 'g':
+ h->curint->gateway = ADDR (arg, "gateway"); break;
+
+ case ARGP_KEY_INIT:
+ /* Initialize our parsing state. */
+ h = malloc (sizeof (struct parse_hook));
+ if (! h)
+ FAIL (ENOMEM, 11, ENOMEM, "option parsing");
+
+ h->interfaces = 0;
+ h->num_interfaces = 0;
+ err = parse_hook_add_interface (h);
+ if (err)
+ FAIL (err, 12, err, "option parsing");
+
+ state->hook = h;
+ break;
+
+ case ARGP_KEY_SUCCESS:
+ in = h->curint;
+ if (! in->device)
+ /* No specific interface specified; is that ok? */
+ if (in->address != INADDR_NONE || in->netmask != INADDR_NONE
+ || in->gateway != INADDR_NONE)
+ /* Some options were specified, so we need an interface. See if
+ there's a single extant interface to use as a default. */
+ {
+ err = find_device (0, &in->device);
+ if (err)
+ FAIL (err, 13, 0, "No default interface");
+ }
+#if 0 /* XXX what does this mean??? */
+ /* Check for bogus option combinations. */
+ for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
+ if (in->netmask != INADDR_NONE
+ && in->address == INADDR_NONE && in->device->pa_addr == 0)
+ /* Specifying a netmask for an address-less interface is a no-no. */
+ FAIL (EDESTADDRREQ, 14, 0, "Cannot set netmask");
+#endif
+
+ gateway = INADDR_NONE;
+ 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;
+ }
+
+ /* 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);
+ if (err)
+ FAIL (err, 16, 0, "cannot configure interface");
+ }
+
+ /* Set the default gateway. This code is cobbled together from what
+ the SIOCADDRT ioctl code does, and from the apparent functionality
+ of the "netlink" layer from perusing a little. */
+ {
+ struct kern_rta rta;
+ struct
+ {
+ struct nlmsghdr nlh;
+ struct rtmsg rtm;
+ } req;
+ struct fib_table *tb;
+
+ req.nlh.nlmsg_pid = 0;
+ req.nlh.nlmsg_seq = 0;
+ req.nlh.nlmsg_len = NLMSG_LENGTH (sizeof req.rtm);
+
+ bzero (&req.rtm, sizeof req.rtm);
+ bzero (&rta, sizeof rta);
+ req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
+ req.rtm.rtm_type = RTN_UNICAST;
+ req.rtm.rtm_protocol = RTPROT_STATIC;
+ rta.rta_gw = &gateway;
+
+ if (gateway == INADDR_NONE)
+ {
+ /* Delete any existing default route. */
+ req.nlh.nlmsg_type = RTM_DELROUTE;
+ req.nlh.nlmsg_flags = 0;
+ tb = fib_get_table (req.rtm.rtm_table);
+ if (tb)
+ {
+ err = - (*tb->tb_delete) (tb, &req.rtm, &rta, &req.nlh, 0);
+ if (err && err != ESRCH)
+ FAIL (err, 17, 0, "cannot remove old default gateway");
+ }
+ }
+ else
+ {
+ /* Add a default route, replacing any existing one. */
+ req.nlh.nlmsg_type = RTM_NEWROUTE;
+ req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
+ tb = fib_new_table (req.rtm.rtm_table);
+ err = (!tb ? ENOBUFS
+ : - (*tb->tb_insert) (tb, &req.rtm, &rta, &req.nlh, 0));
+ if (err)
+ FAIL (err, 17, 0, "cannot set default gateway");
+ }
+ }
+
+ __mutex_unlock (&global_lock);
+
+
+ /* Fall through to free hook. */
+
+ case ARGP_KEY_ERROR:
+ /* Parsing error occured, free everything. */
+ free_hook:
+ free (h->interfaces);
+ free (h);
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return err;
+}
+
+struct argp
+pfinet_argp = { options, parse_opt, 0, doc };
+
+struct argp *trivfs_runtime_argp = &pfinet_argp;
+
+error_t
+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;
+
+ inquire_device (dev, &addr, &mask);
+
+#define ADD_OPT(fmt, args...) \
+ do { char buf[100]; \
+ if (! err) { \
+ snprintf (buf, sizeof buf, fmt , ##args); \
+ err = argz_add (argz, argz_len, buf); } } while (0)
+#define ADD_ADDR_OPT(name, addr) \
+ do { struct in_addr i; \
+ i.s_addr = (addr); \
+ ADD_OPT ("--%s=%s", name, inet_ntoa (i)); } while (0)
+
+ ADD_OPT ("--interface=%s", dev->name);
+ if (addr != INADDR_NONE)
+ ADD_ADDR_OPT ("address", addr);
+ if (mask != INADDR_NONE)
+ ADD_ADDR_OPT ("netmask", mask);
+
+ /* XXX how do we figure out the default gateway? */
+
+#undef ADD_ADDR_OPT
+#undef ADD_OPT
+
+ return err;
+ }
+
+ return enumerate_devices (add_dev_opts);
+}
diff --git a/pfinet/pfinet.h b/pfinet/pfinet.h
new file mode 100644
index 00000000..b5c551d8
--- /dev/null
+++ b/pfinet/pfinet.h
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 1995, 1996, 1999, 2000 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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. */
+
+#ifndef PFINET_H_
+#define PFINET_H_
+
+#include <device/device.h>
+#include <hurd/ports.h>
+#include <hurd/trivfs.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+
+extern struct mutex global_lock;
+extern struct mutex net_bh_lock;
+
+struct port_bucket *pfinet_bucket;
+struct port_class *addrport_class;
+struct port_class *socketport_class;
+
+mach_port_t fsys_identity;
+
+extern struct device ether_dev;
+extern struct device loopback_dev;
+
+/* A port on SOCK. Multiple sock_user's can point to the same socket. */
+struct sock_user
+{
+ struct port_info pi;
+ int isroot;
+ struct socket *sock;
+};
+
+/* Socket address ports. */
+struct sock_addr
+{
+ struct port_info pi;
+ struct sockaddr address;
+};
+
+void ethernet_initialize (void);
+int ethernet_demuxer (mach_msg_header_t *, mach_msg_header_t *);
+void setup_ethernet_device (char *);
+struct sock_user *make_sock_user (struct socket *, int, int);
+error_t make_sockaddr_port (struct socket *, int,
+ mach_port_t *, mach_msg_type_name_t *);
+void init_devices (void);
+any_t net_bh_worker (any_t);
+void init_time (void);
+void ip_rt_add (short, u_long, u_long, u_long, struct device *,
+ u_short, u_long);
+void ip_rt_del (u_long, struct device *);
+struct sock;
+error_t tcp_tiocinq (struct sock *sk, mach_msg_type_number_t *amount);
+
+
+struct sock_user *begin_using_socket_port (socket_t);
+struct sock_addr *begin_using_sockaddr_port (socket_t);
+void end_using_socket_port (struct sock_user *);
+void end_using_sockaddr_port (struct sock_addr *);
+void clean_addrport (void *);
+void clean_socketport (void *);
+
+/* MiG bogosity */
+typedef struct sock_user *sock_user_t;
+typedef struct sock_addr *sock_addr_t;
+typedef struct trivfs_protid *trivfs_protid_t;
+
+#endif
diff --git a/pfinet/sched.c b/pfinet/sched.c
new file mode 100644
index 00000000..53f0cb09
--- /dev/null
+++ b/pfinet/sched.c
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 1995, 1996, 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "pfinet.h"
+
+#include <asm/system.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+struct mutex global_lock = MUTEX_INITIALIZER;
+struct mutex net_bh_lock = MUTEX_INITIALIZER;
+struct condition net_bh_wakeup = CONDITION_INITIALIZER;
+
+struct task_struct current_contents; /* zeros are right default values */
+
+
+/* Wake up the owner of the SOCK. If HOW is zero, then just
+ send SIGIO. If HOW is one, then send SIGIO only if the
+ SO_WAITDATA flag is off. If HOW is two, then send SIGIO
+ only if the SO_NOSPACE flag is on, and also clear it. */
+int
+sock_wake_async (struct socket *sock, int how)
+{
+ /* For now, do nothing. XXX */
+ return 0;
+}
+
+
+/* This function is the "net_bh worker thread".
+ The packet receiver thread calls net/core/dev.c::netif_rx with a packet;
+ netif_rx either drops the packet, or enqueues it and wakes us up
+ via mark_bh which is really condition_broadcast on net_bh_wakeup.
+ The packet receiver thread holds net_bh_lock while calling netif_rx.
+ We wake up and take global_lock, which locks out RPC service threads.
+ We then also take net_bh_lock running net_bh.
+ Thus, only this thread running net_bh locks out the packet receiver
+ thread (which takes only net_bh_lock while calling netif_rx), so packets
+ are quickly moved from the Mach port's message queue to the `backlog'
+ queue, or dropped, without synchronizing with RPC service threads.
+ (The RPC service threads lock out the running of net_bh, but not
+ the queuing/dropping of packets in netif_rx.) */
+any_t
+net_bh_worker (any_t arg)
+{
+ __mutex_lock (&global_lock);
+ while (1)
+ {
+ condition_wait (&net_bh_wakeup, &global_lock);
+ __mutex_lock (&net_bh_lock);
+ net_bh ();
+ __mutex_unlock (&net_bh_lock);
+ }
+}
diff --git a/pfinet/socket-ops.c b/pfinet/socket-ops.c
new file mode 100644
index 00000000..bcfa7f45
--- /dev/null
+++ b/pfinet/socket-ops.c
@@ -0,0 +1,513 @@
+/* Interface functions for the socket.defs interface.
+ Copyright (C) 1995,96,97,99,2000 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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 <hurd/trivfs.h>
+#include <string.h>
+#include <stddef.h>
+#include <fcntl.h>
+
+#include "pfinet.h"
+#include "socket_S.h"
+
+#include <linux/sched.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <net/sock.h>
+
+
+error_t
+S_socket_create (struct trivfs_protid *master,
+ int sock_type,
+ int protocol,
+ mach_port_t *port,
+ mach_msg_type_name_t *porttype)
+{
+ struct sock_user *user;
+ struct socket *sock;
+ error_t err;
+
+ if (!master)
+ return EOPNOTSUPP;
+
+ /* Don't allow bogus SOCK_PACKET here. */
+
+ if ((sock_type != SOCK_STREAM
+ && sock_type != SOCK_DGRAM
+ && sock_type != SOCK_SEQPACKET
+ && sock_type != SOCK_RAW)
+ || protocol < 0)
+ return EINVAL;
+
+ __mutex_lock (&global_lock);
+
+ become_task_protid (master);
+
+ sock = sock_alloc ();
+
+ sock->type = sock_type;
+
+ err = - (*net_families[PF_INET]->create) (sock, protocol);
+ if (err)
+ sock_release (sock);
+ else
+ {
+ user = make_sock_user (sock, master->isroot, 0);
+ *port = ports_get_right (user);
+ *porttype = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (user);
+ }
+
+ __mutex_unlock (&global_lock);
+
+ return err;
+}
+
+
+/* Listen on a socket. */
+error_t
+S_socket_listen (struct sock_user *user, int queue_limit)
+{
+ error_t err;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ err = - (*user->sock->ops->listen) (user->sock, queue_limit);
+ __mutex_unlock (&global_lock);
+
+ return err;
+}
+
+error_t
+S_socket_accept (struct sock_user *user,
+ mach_port_t *new_port,
+ mach_msg_type_name_t *new_port_type,
+ mach_port_t *addr_port,
+ mach_msg_type_name_t *addr_port_type)
+{
+ struct sock_user *newuser;
+ struct socket *sock, *newsock;
+ error_t err;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ sock = user->sock;
+
+ __mutex_lock (&global_lock);
+
+ become_task (user);
+
+ newsock = sock_alloc ();
+ if (!newsock)
+ err = ENOMEM;
+ else
+ {
+ newsock->type = sock->type;
+
+ err = - (*sock->ops->dup) (newsock, sock);
+ if (!err)
+ err = - (*sock->ops->accept) (sock, newsock, sock->flags);
+
+ if (!err)
+ /* In Linux there is a race here with the socket closing before the
+ ops->getname call we do in make_sockaddr_port. Since we still
+ have the world locked, this shouldn't be an issue for us. */
+ err = make_sockaddr_port (newsock, 1, addr_port, addr_port_type);
+
+ if (!err)
+ {
+ newuser = make_sock_user (newsock, user->isroot, 0);
+ *new_port = ports_get_right (newuser);
+ *new_port_type = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newuser);
+ }
+
+ if (err)
+ sock_release (newsock);
+ }
+
+ __mutex_unlock (&global_lock);
+
+ return err;
+}
+
+error_t
+S_socket_connect (struct sock_user *user,
+ struct sock_addr *addr)
+{
+ struct socket *sock;
+ error_t err;
+
+ if (!user || !addr)
+ return EOPNOTSUPP;
+
+ sock = user->sock;
+
+ __mutex_lock (&global_lock);
+
+ become_task (user);
+
+ err = - (*sock->ops->connect) (sock, &addr->address, addr->address.sa_len,
+ sock->flags);
+
+ __mutex_unlock (&global_lock);
+
+ /* MiG should do this for us, but it doesn't. */
+ if (!err)
+ mach_port_deallocate (mach_task_self (), addr->pi.port_right);
+
+ return err;
+}
+
+error_t
+S_socket_bind (struct sock_user *user,
+ struct sock_addr *addr)
+{
+ error_t err;
+
+ if (!user)
+ return EOPNOTSUPP;
+ if (! addr)
+ return EADDRNOTAVAIL;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ err = - (*user->sock->ops->bind) (user->sock,
+ &addr->address, addr->address.sa_len);
+ __mutex_unlock (&global_lock);
+
+ /* MiG should do this for us, but it doesn't. */
+ if (!err)
+ mach_port_deallocate (mach_task_self (), addr->pi.port_right);
+
+ return err;
+}
+
+error_t
+S_socket_name (struct sock_user *user,
+ mach_port_t *addr_port,
+ mach_msg_type_name_t *addr_port_name)
+{
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ make_sockaddr_port (user->sock, 0, addr_port, addr_port_name);
+ __mutex_unlock (&global_lock);
+ return 0;
+}
+
+error_t
+S_socket_peername (struct sock_user *user,
+ mach_port_t *addr_port,
+ mach_msg_type_name_t *addr_port_name)
+{
+ error_t err;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ err = make_sockaddr_port (user->sock, 1, addr_port, addr_port_name);
+ __mutex_unlock (&global_lock);
+
+ return err;
+}
+
+error_t
+S_socket_connect2 (struct sock_user *user1,
+ struct sock_user *user2)
+{
+ error_t err;
+
+ if (!user1 || !user2)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+
+ become_task (user1);
+
+ if (user1->sock->type != user2->sock->type)
+ err = EINVAL;
+ else if (user1->sock->state != SS_UNCONNECTED
+ && user2->sock->state != SS_UNCONNECTED)
+ err = EISCONN;
+ else
+ err = - (*user1->sock->ops->socketpair) (user1->sock, user2->sock);
+
+ __mutex_unlock (&global_lock);
+
+ /* MiG should do this for us, but it doesn't. */
+ if (!err)
+ mach_port_deallocate (mach_task_self (), user2->pi.port_right);
+
+ return err;
+}
+
+error_t
+S_socket_create_address (mach_port_t server,
+ int sockaddr_type,
+ char *data,
+ mach_msg_type_number_t data_len,
+ mach_port_t *addr_port,
+ mach_msg_type_name_t *addr_port_type)
+{
+ error_t err;
+ struct sock_addr *addrstruct;
+ const struct sockaddr *const sa = (void *) data;
+
+ if (sockaddr_type != AF_INET)
+ return EAFNOSUPPORT;
+ if (sa->sa_family != sockaddr_type
+ || data_len < offsetof (struct sockaddr, sa_data))
+ return EINVAL;
+
+ err = ports_create_port (addrport_class, pfinet_bucket,
+ (offsetof (struct sock_addr, address)
+ + data_len), &addrstruct);
+ if (err)
+ return err;
+
+ memcpy (&addrstruct->address, data, data_len);
+
+ /* BSD does not require incoming sa_len to be set, so we don't either. */
+ addrstruct->address.sa_len = data_len;
+
+ *addr_port = ports_get_right (addrstruct);
+ *addr_port_type = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (addrstruct);
+ return 0;
+}
+
+error_t
+S_socket_fabricate_address (mach_port_t server,
+ int sockaddr_type,
+ mach_port_t *addr_port,
+ mach_msg_type_name_t *addr_port_type)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_socket_whatis_address (struct sock_addr *addr,
+ int *type,
+ char **data,
+ mach_msg_type_number_t *datalen)
+{
+ if (!addr)
+ return EOPNOTSUPP;
+
+ *type = addr->address.sa_family;
+ if (*datalen < addr->address.sa_len)
+ *data = mmap (0, addr->address.sa_len,
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ *datalen = addr->address.sa_len;
+ memcpy (*data, &addr->address, addr->address.sa_len);
+
+ return 0;
+}
+
+error_t
+S_socket_shutdown (struct sock_user *user,
+ int direction)
+{
+ error_t err;
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ err = - (*user->sock->ops->shutdown) (user->sock, direction);
+ __mutex_unlock (&global_lock);
+
+ return err;
+}
+
+error_t
+S_socket_getopt (struct sock_user *user,
+ int level,
+ int option,
+ char **data,
+ u_int *datalen)
+{
+ error_t err;
+
+ if (! user)
+ return EOPNOTSUPP;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+
+ err = - (level == SOL_SOCKET ? sock_getsockopt
+ : *user->sock->ops->getsockopt)
+ (user->sock, level, option, *data, datalen);
+
+ __mutex_unlock (&global_lock);
+
+ /* XXX option data not properly typed, needs byte-swapping for netmsgserver.
+ Most options are ints, some like IP_OPTIONS are bytesex-neutral. */
+
+ return err;
+}
+
+error_t
+S_socket_setopt (struct sock_user *user,
+ int level,
+ int option,
+ char *data,
+ u_int datalen)
+{
+ error_t err;
+
+ if (! user)
+ return EOPNOTSUPP;
+
+ /* XXX option data not properly typed, needs byte-swapping for netmsgserver.
+ Most options are ints, some like IP_OPTIONS are bytesex-neutral. */
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+
+ err = - (level == SOL_SOCKET ? sock_setsockopt
+ : *user->sock->ops->setsockopt)
+ (user->sock, level, option, data, datalen);
+
+ __mutex_unlock (&global_lock);
+
+ return err;
+}
+
+error_t
+S_socket_send (struct sock_user *user,
+ struct sock_addr *addr,
+ int flags,
+ char *data,
+ u_int datalen,
+ mach_port_t *ports,
+ u_int nports,
+ char *control,
+ u_int controllen,
+ mach_msg_type_number_t *amount)
+{
+ int sent;
+ struct iovec iov = { data, datalen };
+ struct msghdr m = { msg_name: addr ? &addr->address : 0,
+ msg_namelen: addr ? addr->address.sa_len : 0,
+ msg_flags: flags,
+ msg_controllen: 0, msg_iov: &iov, msg_iovlen: 1 };
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ /* Don't do this yet, it's too bizarre to think about right now. */
+ if (nports != 0 || controllen != 0)
+ return EINVAL;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ if (user->sock->flags & O_NONBLOCK)
+ m.msg_flags |= MSG_DONTWAIT;
+ sent = (*user->sock->ops->sendmsg) (user->sock, &m, datalen, 0);
+ __mutex_unlock (&global_lock);
+
+ /* MiG should do this for us, but it doesn't. */
+ if (addr && sent >= 0)
+ mach_port_deallocate (mach_task_self (), addr->pi.port_right);
+
+ if (sent >= 0)
+ {
+ *amount = sent;
+ return 0;
+ }
+ else
+ return (error_t)-sent;
+}
+
+error_t
+S_socket_recv (struct sock_user *user,
+ mach_port_t *addrport,
+ mach_msg_type_name_t *addrporttype,
+ int flags,
+ char **data,
+ u_int *datalen,
+ mach_port_t **ports,
+ mach_msg_type_name_t *portstype,
+ u_int *nports,
+ char **control,
+ u_int *controllen,
+ int *outflags,
+ mach_msg_type_number_t amount)
+{
+ error_t err;
+ union { struct sockaddr_storage storage; struct sockaddr sa; } addr;
+ int alloced = 0;
+ struct iovec iov;
+ struct msghdr m = { msg_name: &addr.sa, msg_namelen: sizeof addr,
+ msg_controllen: 0, msg_iov: &iov, msg_iovlen: 1 };
+
+ if (!user)
+ return EOPNOTSUPP;
+
+ /* Instead of this, we should peek and the socket and only
+ allocate as much as necessary. */
+ if (amount > *datalen)
+ {
+ *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ alloced = 1;
+ }
+
+ iov.iov_base = *data;
+ iov.iov_len = amount;
+
+ __mutex_lock (&global_lock);
+ become_task (user);
+ if (user->sock->flags & O_NONBLOCK)
+ flags |= MSG_DONTWAIT;
+ err = (*user->sock->ops->recvmsg) (user->sock, &m, amount, flags, 0);
+ __mutex_unlock (&global_lock);
+
+ if (err < 0)
+ err = -err;
+ else
+ {
+ *datalen = err;
+ if (alloced && round_page (*datalen) < round_page (amount))
+ munmap (*data + round_page (*datalen),
+ round_page (amount) - round_page (*datalen));
+ err = S_socket_create_address (0, addr.sa.sa_family,
+ (void *) &addr.sa, m.msg_namelen,
+ addrport, addrporttype);
+ if (err && alloced)
+ munmap (*data, *datalen);
+
+ *outflags = m.msg_flags;
+ *nports = 0;
+ *portstype = MACH_MSG_TYPE_COPY_SEND;
+ *controllen = 0;
+ }
+
+ return err;
+}
diff --git a/pfinet/socket.c b/pfinet/socket.c
new file mode 100644
index 00000000..52bd37ff
--- /dev/null
+++ b/pfinet/socket.c
@@ -0,0 +1,119 @@
+/*
+ Copyright (C) 1995,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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <assert.h>
+#include "pfinet.h"
+
+#include <linux/socket.h>
+#include <linux/net.h>
+
+#ifndef NPROTO
+#define NPROTO (PF_INET + 1)
+#endif
+struct net_proto_family *net_families[NPROTO];
+
+/* Notice that a protocol family is live; this only works for inet here. */
+int
+sock_register (struct net_proto_family *fam)
+{
+ assert (fam->family < NPROTO);
+ net_families[fam->family] = fam;
+ return 0;
+}
+
+
+struct socket *
+sock_alloc (void)
+{
+ struct socket *sock;
+ struct condition *c;
+
+ sock = malloc (sizeof *sock + sizeof (struct condition));
+ if (!sock)
+ return 0;
+ c = (void *) &sock[1];
+ condition_init (c);
+ bzero (sock, sizeof *sock);
+ sock->state = SS_UNCONNECTED;
+ sock->identity = MACH_PORT_NULL;
+ sock->refcnt = 1;
+ sock->wait = (void *) c;
+
+ return sock;
+}
+
+/* Create a sock_user structure, initialized from SOCK and ISROOT.
+ If NOINSTALL is set, don't put it in the portset. */
+struct sock_user *
+make_sock_user (struct socket *sock, int isroot, int noinstall)
+{
+ error_t err;
+ struct sock_user *user;
+
+ assert (sock->refcnt != 0);
+
+ if (noinstall)
+ err = ports_create_port_noinstall (socketport_class, pfinet_bucket,
+ sizeof (struct sock_user), &user);
+ else
+ err = ports_create_port (socketport_class, pfinet_bucket,
+ sizeof (struct sock_user), &user);
+ if (err)
+ return 0;
+
+ /* We maintain a reference count in `struct socket' (a member not
+ in the original Linux structure), because there can be multiple
+ ports (struct sock_user, aka protids) pointing to the same socket.
+ The socket lives until all the ports die. */
+ ++sock->refcnt;
+ user->isroot = isroot;
+ user->sock = sock;
+ return user;
+}
+
+/* This is called from the port cleanup function below, and on
+ a newly allocated socket when something went wrong in its creation. */
+void
+sock_release (struct socket *sock)
+{
+ if (--sock->refcnt != 0)
+ return;
+
+ if (sock->state != SS_UNCONNECTED)
+ sock->state = SS_DISCONNECTING;
+
+ if (sock->ops)
+ sock->ops->release(sock, NULL);
+
+ if (sock->identity != MACH_PORT_NULL)
+ mach_port_destroy (mach_task_self (), sock->identity);
+
+ free (sock);
+}
+
+/* Release the reference on the referenced socket. */
+void
+clean_socketport (void *arg)
+{
+ struct sock_user *const user = arg;
+
+ __mutex_lock (&global_lock);
+ sock_release (user->sock);
+ __mutex_unlock (&global_lock);
+}
diff --git a/pfinet/stubs.c b/pfinet/stubs.c
new file mode 100644
index 00000000..e610cbc9
--- /dev/null
+++ b/pfinet/stubs.c
@@ -0,0 +1,70 @@
+/* Stub functions replacing things called from the Linux code
+ 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include "pfinet.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+int qdisc_restart(struct device *dev)
+{
+ return 0;
+}
+
+void qdisc_run_queues(void)
+{
+}
+
+struct Qdisc_head qdisc_head;
+struct Qdisc qdisc_stub;
+
+void
+dev_init_scheduler (struct device *dev)
+{
+ dev->qdisc = &qdisc_stub;
+}
+#pragma weak dev_shutdown = dev_init_scheduler
+#pragma weak dev_activate = dev_init_scheduler
+#pragma weak dev_deactivate = dev_init_scheduler
+#pragma weak tcp_ioctl = dev_init_scheduler
+
+/* This isn't quite a stub, but it's not quite right either. */
+__u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
+ __u16 sport, __u16 dport)
+{
+ static u32 tcp_iss;
+ static time_t last;
+ struct timeval now;
+
+ do_gettimeofday (&now);
+
+ if (now.tv_sec - last > 300)
+ {
+ last = now.tv_sec;
+ srandom (getpid () ^ now.tv_sec ^ now.tv_usec);
+ tcp_iss = random ();
+ }
+
+ return tcp_iss + (now.tv_sec * 1000000) + now.tv_usec;
+}
diff --git a/pfinet/time.c b/pfinet/time.c
new file mode 100644
index 00000000..13f53cb7
--- /dev/null
+++ b/pfinet/time.c
@@ -0,0 +1,27 @@
+/* Time management functions
+ Copyright (C) 1995 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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 <sys/time.h>
+
+void
+do_gettimeofday (struct timeval *tp)
+{
+ gettimeofday (tp, 0);
+}
diff --git a/pfinet/timer-emul.c b/pfinet/timer-emul.c
new file mode 100644
index 00000000..c305486e
--- /dev/null
+++ b/pfinet/timer-emul.c
@@ -0,0 +1,171 @@
+/*
+ Copyright (C) 1995,96,2000 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ 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 <linux/timer.h>
+#include <asm/system.h>
+#include <linux/sched.h>
+#include <error.h>
+#include <string.h>
+#include "pfinet.h"
+
+long long root_jiffies;
+volatile struct mapped_time_value *mapped_time;
+
+struct timer_list *timers;
+thread_t timer_thread = 0;
+
+static int
+timer_function (int this_is_a_pointless_variable_with_a_rather_long_name)
+{
+ mach_port_t recv;
+ int wait = 0;
+
+ recv = mach_reply_port ();
+
+ timer_thread = mach_thread_self ();
+
+ __mutex_lock (&global_lock);
+ while (1)
+ {
+ int jiff = jiffies;
+
+ if (!timers)
+ wait = -1;
+ else if (timers->expires < jiff)
+ wait = 0;
+ else
+ wait = ((timers->expires - jiff) * 1000) / HZ;
+
+ __mutex_unlock (&global_lock);
+
+ mach_msg (NULL, (MACH_RCV_MSG | MACH_RCV_INTERRUPT
+ | (wait == -1 ? 0 : MACH_RCV_TIMEOUT)),
+ 0, 0, recv, wait, MACH_PORT_NULL);
+
+ __mutex_lock (&global_lock);
+
+ while (timers->expires < jiffies)
+ {
+ struct timer_list *tp;
+
+ tp = timers;
+
+ timers = timers->next;
+ if (timers)
+ timers->prev = &timers;
+
+ tp->next = 0;
+ tp->prev = 0;
+
+ (*tp->function) (tp->data);
+ }
+ }
+}
+
+
+void
+add_timer (struct timer_list *timer)
+{
+ struct timer_list **tp;
+
+ timer->expires += jiffies;
+
+ for (tp = &timers; *tp; tp = &(*tp)->next)
+ if ((*tp)->expires > timer->expires)
+ {
+ timer->next = *tp;
+ timer->next->prev = &timer->next;
+ timer->prev = tp;
+ *tp = timer;
+ break;
+ }
+ if (!*tp)
+ {
+ timer->next = 0;
+ timer->prev = tp;
+ *tp = timer;
+ }
+
+ if (timers == timer)
+ {
+ /* We have change the first one, so tweak the timer thread
+ to push things up. */
+ while (timer_thread == 0)
+ swtch_pri (0);
+
+ if (timer_thread != mach_thread_self ())
+ {
+ thread_suspend (timer_thread);
+ thread_abort (timer_thread);
+ thread_resume (timer_thread);
+ }
+ }
+}
+
+int
+del_timer (struct timer_list *timer)
+{
+ if (timer->prev)
+ {
+ *timer->prev = timer->next;
+ if (timer->next)
+ timer->next->prev = timer->prev;
+
+ timer->next = 0;
+ timer->prev = 0;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void
+mod_timer (struct timer_list *timer, unsigned long expires)
+{
+ /* Should optimize this. */
+ del_timer (timer);
+ timer->expires = expires;
+ add_timer (timer);
+}
+
+
+void
+init_timer (struct timer_list *timer)
+{
+ bzero (timer, sizeof (struct timer_list));
+}
+
+void
+init_time ()
+{
+ error_t err;
+ struct timeval tp;
+
+ err = maptime_map (0, 0, &mapped_time);
+ if (err)
+ error (2, err, "cannot map time device");
+
+ maptime_read (mapped_time, &tp);
+
+ root_jiffies = (long long) tp.tv_sec * HZ
+ + ((long long) tp.tv_usec * HZ) / 1000000;
+
+ cthread_detach (cthread_fork ((cthread_fn_t) timer_function, 0));
+}