diff options
Diffstat (limited to 'pfinet')
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 = ðer_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, ðer_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, ðer_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 (ðer_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 (ðer_dev); + + ethernet_open (ðer_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 (ðer_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 (¤t_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 = ðer_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 (ðer_dev); + + *device = ðer_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) (ðer_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)); +} |