summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pfinet/ChangeLog214
-rw-r--r--pfinet/Makefile80
-rw-r--r--pfinet/README49
-rw-r--r--pfinet/asm/bitops.h135
-rw-r--r--pfinet/asm/segment.h21
-rw-r--r--pfinet/asm/system.h10
-rw-r--r--pfinet/config.h50
-rw-r--r--pfinet/devices.c60
-rw-r--r--pfinet/ethernet.c96
-rw-r--r--pfinet/glue-include/asm/atomic.h27
-rw-r--r--pfinet/glue-include/asm/bitops.h37
-rw-r--r--pfinet/glue-include/asm/byteorder.h154
-rw-r--r--pfinet/glue-include/asm/checksum.h5
-rw-r--r--pfinet/glue-include/asm/errno.h3
-rw-r--r--pfinet/glue-include/asm/hardirq.h1
-rw-r--r--pfinet/glue-include/asm/init.h3
-rw-r--r--pfinet/glue-include/asm/segment.h (renamed from pfinet/linux/autoconf.h)0
-rw-r--r--pfinet/glue-include/asm/spinlock.h75
-rw-r--r--pfinet/glue-include/asm/system.h20
-rw-r--r--pfinet/glue-include/asm/types.h1
-rw-r--r--pfinet/glue-include/asm/uaccess.h47
-rw-r--r--pfinet/glue-include/linux/autoconf.h (renamed from pfinet/linux/config.h)0
-rw-r--r--pfinet/glue-include/linux/binfmts.h1
-rw-r--r--pfinet/glue-include/linux/config.h1
-rw-r--r--pfinet/glue-include/linux/errno.h13
-rw-r--r--pfinet/glue-include/linux/fcntl.h (renamed from pfinet/linux/fcntl.h)0
-rw-r--r--pfinet/glue-include/linux/fs.h21
-rw-r--r--pfinet/glue-include/linux/in.h44
-rw-r--r--pfinet/glue-include/linux/in6.h (renamed from pfinet/linux/in.h)0
-rw-r--r--pfinet/glue-include/linux/interrupt.h44
-rw-r--r--pfinet/glue-include/linux/ioctl.h1
-rw-r--r--pfinet/glue-include/linux/ipv6.h1
-rw-r--r--pfinet/glue-include/linux/kernel.h78
-rw-r--r--pfinet/glue-include/linux/limits.h8
-rw-r--r--pfinet/glue-include/linux/major.h (renamed from pfinet/linux/major.h)0
-rw-r--r--pfinet/glue-include/linux/malloc.h27
-rw-r--r--pfinet/glue-include/linux/mm.h (renamed from pfinet/linux/mm.h)2
-rw-r--r--pfinet/glue-include/linux/param.h (renamed from pfinet/linux/param.h)0
-rw-r--r--pfinet/glue-include/linux/personality.h1
-rw-r--r--pfinet/glue-include/linux/poll.h24
-rw-r--r--pfinet/glue-include/linux/proc_fs.h (renamed from pfinet/linux/sockios.h)0
-rw-r--r--pfinet/glue-include/linux/sched.h176
-rw-r--r--pfinet/glue-include/linux/slab.h (renamed from pfinet/linux/un.h)0
-rw-r--r--pfinet/glue-include/linux/socket.h138
-rw-r--r--pfinet/glue-include/linux/sockios.h0
-rw-r--r--pfinet/glue-include/linux/stat.h (renamed from pfinet/linux/stat.h)0
-rw-r--r--pfinet/glue-include/linux/string.h (renamed from pfinet/linux/string.h)0
-rw-r--r--pfinet/glue-include/linux/termios.h (renamed from pfinet/linux/termios.h)0
-rw-r--r--pfinet/glue-include/linux/time.h10
-rw-r--r--pfinet/glue-include/linux/timer.h (renamed from pfinet/linux/timer.h)13
-rw-r--r--pfinet/glue-include/linux/timex.h0
-rw-r--r--pfinet/glue-include/linux/types.h31
-rw-r--r--pfinet/glue-include/linux/un.h0
-rw-r--r--pfinet/glue-include/linux/version.h3
-rw-r--r--pfinet/glue-include/linux/wait.h32
-rw-r--r--pfinet/io-ops.c208
-rw-r--r--pfinet/kmem_cache.c88
-rw-r--r--pfinet/linux-inet/af_inet.c1578
-rw-r--r--pfinet/linux-inet/arp.c1295
-rw-r--r--pfinet/linux-inet/arp.h18
-rw-r--r--pfinet/linux-inet/datagram.c210
-rw-r--r--pfinet/linux-inet/datalink.h17
-rw-r--r--pfinet/linux-inet/dev.c1449
-rw-r--r--pfinet/linux-inet/dev_mcast.c169
-rw-r--r--pfinet/linux-inet/devinet.c213
-rw-r--r--pfinet/linux-inet/eth.c196
-rw-r--r--pfinet/linux-inet/eth.h35
-rw-r--r--pfinet/linux-inet/icmp.c774
-rw-r--r--pfinet/linux-inet/icmp.h38
-rw-r--r--pfinet/linux-inet/igmp.c390
-rw-r--r--pfinet/linux-inet/ip.c2427
-rw-r--r--pfinet/linux-inet/ip.h130
-rw-r--r--pfinet/linux-inet/ip_fw.c1016
-rw-r--r--pfinet/linux-inet/ipx.c1947
-rw-r--r--pfinet/linux-inet/ipx.h84
-rw-r--r--pfinet/linux-inet/ipxcall.h2
-rw-r--r--pfinet/linux-inet/p8022.c98
-rw-r--r--pfinet/linux-inet/p8022.h2
-rw-r--r--pfinet/linux-inet/p8022call.h2
-rw-r--r--pfinet/linux-inet/p8023.c35
-rw-r--r--pfinet/linux-inet/packet.c410
-rw-r--r--pfinet/linux-inet/pe2.c35
-rw-r--r--pfinet/linux-inet/proc.c257
-rw-r--r--pfinet/linux-inet/protocol.c177
-rw-r--r--pfinet/linux-inet/protocol.h59
-rw-r--r--pfinet/linux-inet/psnap.c123
-rw-r--r--pfinet/linux-inet/psnap.h2
-rw-r--r--pfinet/linux-inet/psnapcall.h2
-rw-r--r--pfinet/linux-inet/rarp.c491
-rw-r--r--pfinet/linux-inet/rarp.h14
-rw-r--r--pfinet/linux-inet/raw.c319
-rw-r--r--pfinet/linux-inet/raw.h34
-rw-r--r--pfinet/linux-inet/route.c684
-rw-r--r--pfinet/linux-inet/route.h54
-rw-r--r--pfinet/linux-inet/skbuff.c573
-rw-r--r--pfinet/linux-inet/snmp.h107
-rw-r--r--pfinet/linux-inet/sock.c574
-rw-r--r--pfinet/linux-inet/sock.h316
-rw-r--r--pfinet/linux-inet/tcp.c5121
-rw-r--r--pfinet/linux-inet/tcp.h142
-rw-r--r--pfinet/linux-inet/timer.c264
-rw-r--r--pfinet/linux-inet/udp.c740
-rw-r--r--pfinet/linux-inet/udp.h50
-rw-r--r--pfinet/linux-inet/utils.c91
-rw-r--r--pfinet/linux-src/include/linux/net.h12
-rw-r--r--pfinet/linux-src/include/linux/rtnetlink.h8
-rw-r--r--pfinet/linux-src/net/core/dev.c200
-rw-r--r--pfinet/linux-src/net/ipv4/af_inet.c116
-rw-r--r--pfinet/linux-src/net/ipv4/arp.c64
-rw-r--r--pfinet/linux-src/net/ipv4/devinet.c70
-rw-r--r--pfinet/linux-src/net/ipv4/tcp.c159
-rw-r--r--pfinet/linux-src/net/ipv4/udp.c104
-rw-r--r--pfinet/linux/errno.h8
-rw-r--r--pfinet/linux/etherdevice.h41
-rw-r--r--pfinet/linux/icmp.h81
-rw-r--r--pfinet/linux/if.h156
-rw-r--r--pfinet/linux/if_arp.h91
-rw-r--r--pfinet/linux/if_ether.h80
-rw-r--r--pfinet/linux/igmp.h67
-rw-r--r--pfinet/linux/inet.h6
-rw-r--r--pfinet/linux/interrupt.h11
-rw-r--r--pfinet/linux/ip.h121
-rw-r--r--pfinet/linux/ip_fw.h147
-rw-r--r--pfinet/linux/ipx.h78
-rw-r--r--pfinet/linux/kernel.h44
-rw-r--r--pfinet/linux/malloc.h10
-rw-r--r--pfinet/linux/net.h146
-rw-r--r--pfinet/linux/netdevice.h235
-rw-r--r--pfinet/linux/notifier.h96
-rw-r--r--pfinet/linux/route.h69
-rw-r--r--pfinet/linux/sched.h81
-rw-r--r--pfinet/linux/skbuff.h286
-rw-r--r--pfinet/linux/socket.h27
-rw-r--r--pfinet/linux/tcp.h112
-rw-r--r--pfinet/linux/time.h13
-rw-r--r--pfinet/linux/types.h16
-rw-r--r--pfinet/linux/udp.h29
-rw-r--r--pfinet/linux/wait.h23
-rw-r--r--pfinet/loopback.c166
-rw-r--r--pfinet/main.c48
-rw-r--r--pfinet/misc.c144
-rw-r--r--pfinet/mutations.h2
-rw-r--r--pfinet/options.c67
-rw-r--r--pfinet/pfinet.h26
-rw-r--r--pfinet/sched.c82
-rw-r--r--pfinet/socket-ops.c309
-rw-r--r--pfinet/socket.c100
-rw-r--r--pfinet/stubs.c70
-rw-r--r--pfinet/timer-emul.c34
149 files changed, 2592 insertions, 26080 deletions
diff --git a/pfinet/ChangeLog b/pfinet/ChangeLog
index 255dd7b4..cd0acf7f 100644
--- a/pfinet/ChangeLog
+++ b/pfinet/ChangeLog
@@ -1,3 +1,217 @@
+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>.
diff --git a/pfinet/Makefile b/pfinet/Makefile
index e86512a9..81e76480 100644
--- a/pfinet/Makefile
+++ b/pfinet/Makefile
@@ -1,6 +1,5 @@
-#
-# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
-# Written by Michael I. Bushnell.
+#
+# Copyright (C) 1995,96,97,2000 Free Software Foundation, Inc.
#
# This file is part of the GNU Hurd.
#
@@ -18,21 +17,57 @@
# 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
-LINUXSRCS= af_inet.c arp.c datagram.c dev.c dev_mcast.c devinet.c eth.c \
- icmp.c igmp.c ip.c \
- proc.c protocol.c raw.c route.c skbuff.c sock.c \
- tcp.c timer.c udp.c utils.c
-UNUSEDSRC = packet.c ipx.c ip_fw.c p8022.c p8023.c pe2.c psnap.c rarp.c
-SRCS = sched.c timer-emul.c devices.c socket.c main.c ethernet.c \
- io-ops.c socket-ops.c misc.c time.c options.c loopback.c
-MIGSRCS = ioServer.c socketServer.c startup_notifyServer.c
-OBJS= $(subst .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
+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 \
@@ -46,9 +81,14 @@ target = pfinet
include ../Makeconf
-vpath %.c $(srcdir)/linux-inet
+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 += -imacros $(srcdir)/config.h
+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
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/asm/bitops.h b/pfinet/asm/bitops.h
deleted file mode 100644
index ee339bd6..00000000
--- a/pfinet/asm/bitops.h
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _I386_BITOPS_H
-#define _I386_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-/*
- * These have to be done with inline assembly: that way the bit-setting
- * is guaranteed to be atomic. All bit operations return 0 if the bit
- * was cleared before the operation and != 0 if it was not.
- *
- * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
- */
-
-/*
- * Some hacks to defeat gcc over-optimizations..
- */
-struct __dummy { unsigned long a[100]; };
-#define ADDR (*(struct __dummy *) addr)
-
-extern __inline__ int set_bit(int nr, void * addr)
-{
- int oldbit;
-
- __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
- :"r" (nr));
- return oldbit;
-}
-
-extern __inline__ int clear_bit(int nr, void * addr)
-{
- int oldbit;
-
- __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
- :"r" (nr));
- return oldbit;
-}
-
-extern __inline__ int change_bit(int nr, void * addr)
-{
- int oldbit;
-
- __asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
- :"r" (nr));
- return oldbit;
-}
-
-/*
- * This routine doesn't need to be atomic, but it's faster to code it
- * this way.
- */
-extern __inline__ int test_bit(int nr, void * addr)
-{
- int oldbit;
-
- __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit)
- :"m" (ADDR),"r" (nr));
- return oldbit;
-}
-
-/*
- * Find-bit routines..
- */
-extern inline int find_first_zero_bit(void * addr, unsigned size)
-{
- int res;
-
- if (!size)
- return 0;
- __asm__("
- cld
- movl $-1,%%eax
- repe; scasl
- je 1f
- subl $4,%%edi
- movl (%%edi),%%eax
- notl %%eax
- bsfl %%eax,%%edx
- jmp 2f
-1: xorl %%edx,%%edx
-2: subl %%ebx,%%edi
- shll $3,%%edi
- addl %%edi,%%edx"
- :"=d" (res)
- :"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
- :"ax", "bx", "cx", "di");
- return res;
-}
-
-extern inline int find_next_zero_bit (void * addr, int size, int offset)
-{
- unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
- int set = 0, bit = offset & 31, res;
-
- if (bit) {
- /*
- * Look for zero in first byte
- */
- __asm__("
- bsfl %1,%0
- jne 1f
- movl $32, %0
-1: "
- : "=r" (set)
- : "r" (~(*p >> bit)));
- if (set < (32 - bit))
- return set + offset;
- set = 32 - bit;
- p++;
- }
- /*
- * No zero yet, search remaining full bytes for a zero
- */
- res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
- return (offset + set + res);
-}
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-extern inline unsigned long ffz(unsigned long word)
-{
- __asm__("bsfl %1,%0"
- :"=r" (word)
- :"r" (~word));
- return word;
-}
-
-#endif /* _I386_BITOPS_H */
diff --git a/pfinet/asm/segment.h b/pfinet/asm/segment.h
deleted file mode 100644
index 34c35b96..00000000
--- a/pfinet/asm/segment.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef _HACK_ASM_SEGMENT_H_
-#define _HACK_ASM_SEGMENT_H_
-
-#include <sys/types.h>
-
-#define get_fs_long(addr) (*(long *)(addr))
-#define get_user_long(addr) (*(long *)(addr))
-
-#define get_fs_byte(addr) (*(char *)(addr))
-#define get_user_byte(addr) (*(char *)(addr))
-
-#define put_fs_long(x,addr) (*(long *)(addr) = (x))
-#define put_user_long(x,addr) (*(long *)(addr) = (x)
-
-#define put_fs_byte(x,addr) (*(char *)(addr) = (x))
-#define put_user_byte(x,addr) (*(char *)(addr) = (x))
-
-#define memcpy_fromfs(a,b,s) (memcpy (a, b, s))
-#define memcpy_tofs(a,b,s) (memcpy (a, b, s))
-
-#endif
diff --git a/pfinet/asm/system.h b/pfinet/asm/system.h
deleted file mode 100644
index f828c3bb..00000000
--- a/pfinet/asm/system.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _HACK_ASM_SYSTEM_H_
-#define _HACK_ASM_SYSTEM_H_
-
-#define intr_count 0
-#define save_flags(x) ((x) = 0)
-#define restore_flags(x)
-#define cli()
-#define sti()
-
-#endif
diff --git a/pfinet/config.h b/pfinet/config.h
index eb8314ef..ce079620 100644
--- a/pfinet/config.h
+++ b/pfinet/config.h
@@ -1,28 +1,36 @@
-#define __KERNEL__
-#define _HURD_
+#define __KERNEL__ 1
+#undef __SMP__
+
+#define _HURD_ 1
#define ENONET ENETUNREACH
-#define CONFIG_INET
-#define CONFIG_NET
-/* #undef CONFIG_INET_RARP */
-/* #undef CONFIG_IP_MULTICAST */
-/* #undef CONFIG_IP_FORWARD */
-/* #undef CONFIG_IP_FIREWALL */
-/* #undef CONFIG_IP_FIREWALL_DEBUG */
-/* #undef CONFIG_IP_FIREWALL_VERBOSE */
-/* #undef DEBUG_CONFIG_IP_FIREWALL */
-/* #undef CONFIG_IP_ACCT */
+#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_SKB_CHECK */
+#undef CONFIG_SYN_COOKIES
-/* #undef CONFIG_TCP_NAGLE_OFF */
-/* #undef CONFIG_AX25 */
-/* #undef CONFIG_IPX */
-/* #undef CONFIG_ATALK */
-/* #undef CONFIG_SLAVE_BALANCING */
+#undef CONFIG_INET_RARP
-/* #undef CONFIG_INET_PCTCP */
-/* #undef CONFIG_INET_SNARL */
+#define CONFIG_SKB_LARGE 1
-/* #undef CONFIG_I_AM_A_BROKEN_BSD_WEENIE */
+#define CONFIG_IP_NOSIOCRT 1 /* How convenient. */
diff --git a/pfinet/devices.c b/pfinet/devices.c
deleted file mode 100644
index 34d865a6..00000000
--- a/pfinet/devices.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- Copyright (C) 1995, 1996, 1999 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"
-
-struct device *dev_base;
-struct device loopback_dev;
-
-device_t master_device;
-
-static struct condition more_packets = CONDITION_INITIALIZER;
-
-void
-init_devices (void)
-{
- error_t err;
-
- err = get_privileged_ports (0, &master_device);
- if (err)
- {
- perror ("Cannot fetch master device port");
- exit (1);
- }
-
- dev_base = 0;
-}
-
-void
-mark_bh (int arg)
-{
- condition_broadcast (&more_packets);
-}
-
-any_t
-input_work_thread (any_t arg)
-{
- mutex_lock (&global_lock);
- for (;;)
- {
- condition_wait (&more_packets, &global_lock);
- net_bh (0);
- }
-}
diff --git a/pfinet/ethernet.c b/pfinet/ethernet.c
index 85162fd8..1b81e1aa 100644
--- a/pfinet/ethernet.c
+++ b/pfinet/ethernet.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
+ 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.
@@ -18,15 +18,18 @@
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 <linux/netdevice.h>
-#include <linux/etherdevice.h>
#include <netinet/in.h>
#include <string.h>
#include <error.h>
-#include "pfinet.h"
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
device_t ether_port;
@@ -53,9 +56,8 @@ ethernet_stop (struct device *dev)
}
void
-ethernet_set_multi (struct device *dev, int numaddrs, void *addrs)
+ethernet_set_multi (struct device *dev)
{
- assert (numaddrs == 0);
}
static short ether_filter[] =
@@ -68,7 +70,7 @@ static int ether_filter_len = sizeof (ether_filter) / sizeof (short);
static struct port_bucket *etherport_bucket;
-any_t
+static any_t
ethernet_thread (any_t arg)
{
ports_manage_port_operations_one_thread (etherport_bucket,
@@ -98,7 +100,7 @@ ethernet_demuxer (mach_msg_header_t *inp,
datalen = ETH_HLEN
+ msg->packet_type.msgt_number - sizeof (struct packet_header);
- mutex_lock (&global_lock);
+ __mutex_lock (&net_bh_lock);
skb = alloc_skb (datalen, GFP_ATOMIC);
skb->len = datalen;
skb->dev = &ether_dev;
@@ -110,32 +112,46 @@ ethernet_demuxer (mach_msg_header_t *inp,
datalen - ETH_HLEN);
/* Drop it on the queue. */
+ skb->protocol = eth_type_trans (skb, &ether_dev);
netif_rx (skb);
- mutex_unlock (&global_lock);
+ __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;
- if (ether_port != MACH_PORT_NULL)
- return 0;
+ assert (ether_port == MACH_PORT_NULL);
- etherreadclass = ports_create_class (0, 0);
- errno = ports_create_port (etherreadclass, etherport_bucket,
- sizeof (struct port_info), &readpt);
- assert_perror (errno);
+ err = ports_create_port (etherreadclass, etherport_bucket,
+ sizeof (struct port_info), &readpt);
+ assert_perror (err);
readptname = ports_get_right (readpt);
mach_port_insert_right (mach_task_self (), readptname, readptname,
MACH_MSG_TYPE_MAKE_SEND);
mach_port_set_qlimit (mach_task_self (), readptname, MACH_PORT_QLIMIT_MAX);
+ err = get_privileged_ports (0, &master_device);
+ if (err)
+ error (2, err, "cannot get device master port");
+
err = device_open (master_device, D_WRITE | D_READ, dev->name, &ether_port);
+ mach_port_deallocate (mach_task_self (), master_device);
if (err)
error (2, err, "%s", dev->name);
@@ -144,7 +160,6 @@ ethernet_open (struct device *dev)
ether_filter, ether_filter_len);
if (err)
error (2, err, "%s", dev->name);
- cthread_detach (cthread_fork (ethernet_thread, 0));
return 0;
}
@@ -154,12 +169,12 @@ int
ethernet_xmit (struct sk_buff *skb, struct device *dev)
{
u_int count;
- int err;
+ error_t err;
err = device_write (ether_port, D_NOWAIT, 0, skb->data, skb->len, &count);
- assert (err == 0);
+ assert_perror (err);
assert (count == skb->len);
- dev_kfree_skb (skb, FREE_WRITE);
+ dev_kfree_skb (skb);
return 0;
}
@@ -169,36 +184,36 @@ setup_ethernet_device (char *name)
struct net_status netstat;
u_int count;
int net_address[2];
- int i;
error_t err;
- etherport_bucket = ports_create_bucket ();
+ bzero (&ether_dev, sizeof ether_dev);
- /* Interface buffers. */
- ether_dev.name = name;
- for (i = 0; i < DEV_NUMBUFFS; i++)
- skb_queue_head_init (&ether_dev.buffs[i]);
+ ether_dev.name = strdup (name);
- /* Functions */
- ether_dev.open = ethernet_open;
+ /* 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.hard_header = eth_header;
- ether_dev.rebuild_header = eth_rebuild_header;
- ether_dev.type_trans = eth_type_trans;
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 = sizeof (struct ethhdr);
+ ether_dev.hard_header_len = ETH_HLEN;
ether_dev.addr_len = ETH_ALEN;
- for (i = 0; i < 6; i++)
- ether_dev.broadcast[i] = 0xff;
+ memset (ether_dev.broadcast, 0xff, ETH_ALEN);
ether_dev.flags = IFF_BROADCAST | IFF_MULTICAST;
- ether_dev.family = AF_INET; /* hmm. */
- ether_dev.pa_addr = ether_dev.pa_brdaddr = ether_dev.pa_mask = 0;
- ether_dev.pa_alen = sizeof (unsigned long);
+ dev_init_buffers (&ether_dev);
ethernet_open (&ether_dev);
@@ -222,8 +237,11 @@ setup_ethernet_device (char *name)
net_address[1] = ntohl (net_address[1]);
bcopy (net_address, ether_dev.dev_addr, ETH_ALEN);
- /* That should be enough. */
+ /* That should be enough. */
- ether_dev.next = dev_base;
- dev_base = &ether_dev;
+ /* This call adds the device to the `dev_base' chain,
+ initializes its `ifindex' member (which matters!),
+ and tells the protocol stacks about the device. */
+ err = - register_netdevice (&ether_dev);
+ assert_perror (err);
}
diff --git a/pfinet/glue-include/asm/atomic.h b/pfinet/glue-include/asm/atomic.h
new file mode 100644
index 00000000..d053854e
--- /dev/null
+++ b/pfinet/glue-include/asm/atomic.h
@@ -0,0 +1,27 @@
+#ifndef _HACK_ASM_ATOMIC_H
+#define _HACK_ASM_ATOMIC_H
+
+/* We don't need atomicity in the Linux code because we serialize all
+ entries to it. */
+
+typedef struct { int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+static __inline__ void atomic_add(int i, atomic_t *v) { v->counter += i; }
+static __inline__ void atomic_sub(int i, atomic_t *v) { v->counter -= i; }
+static __inline__ void atomic_inc(atomic_t *v) { ++v->counter; }
+static __inline__ void atomic_dec(atomic_t *v) { --v->counter; }
+static __inline__ int atomic_dec_and_test(atomic_t *v)
+{ return --v->counter == 0; }
+static __inline__ int atomic_inc_and_test_greater_zero(atomic_t *v)
+{ return ++v->counter > 0; }
+
+#define atomic_clear_mask(mask, addr) (*(addr) &= ~(mask))
+#define atomic_set_mask(mask, addr) (*(addr) |= (mask))
+
+
+#endif
diff --git a/pfinet/glue-include/asm/bitops.h b/pfinet/glue-include/asm/bitops.h
new file mode 100644
index 00000000..8c5a835d
--- /dev/null
+++ b/pfinet/glue-include/asm/bitops.h
@@ -0,0 +1,37 @@
+#ifndef _HACK_ASM_BITOPS_H
+#define _HACK_ASM_BITOPS_H
+
+/* We don't need atomicity in the Linux code because we serialize all
+ entries to it. */
+
+#include <stdint.h>
+
+#define BITOPS_WORD(nr, addr) (((uint32_t *) (addr))[(nr) / 32])
+#define BITOPS_MASK(nr) (1 << ((nr) & 31))
+
+static __inline__ void set_bit (int nr, void *addr)
+{ BITOPS_WORD (nr, addr) |= BITOPS_MASK (nr); }
+
+static __inline__ void clear_bit (int nr, void *addr)
+{ BITOPS_WORD (nr, addr) &= ~BITOPS_MASK (nr); }
+
+static __inline__ void change_bit (int nr, void *addr)
+{ BITOPS_WORD (nr, addr) ^= BITOPS_MASK (nr); }
+
+static __inline__ int test_bit (int nr, void *addr)
+{ return BITOPS_WORD (nr, addr) & BITOPS_MASK (nr); }
+
+static __inline__ int test_and_set_bit (int nr, void *addr)
+{
+ int res = BITOPS_WORD (nr, addr) & BITOPS_MASK (nr);
+ BITOPS_WORD (nr, addr) |= BITOPS_MASK (nr);
+ return res;
+}
+
+#define find_first_zero_bit #error loser
+#define find_next_zero_bit #error loser
+
+#define ffz(word) (ffs (~(unsigned int) (word)) - 1)
+
+
+#endif
diff --git a/pfinet/glue-include/asm/byteorder.h b/pfinet/glue-include/asm/byteorder.h
new file mode 100644
index 00000000..ee1da1f4
--- /dev/null
+++ b/pfinet/glue-include/asm/byteorder.h
@@ -0,0 +1,154 @@
+/* Provide the specified-byte-order access functions used in the Linux
+ kernel, implemented as macros in terms of the GNU libc facilities. */
+
+#ifndef _HACK_ASM_BYTEORDER_H
+#define _HACK_ASM_BYTEORDER_H 1
+
+#include <endian.h>
+#include <byteswap.h>
+
+#define BO_cvt(bits, from, to, x) \
+ ((from) == (to) ? (u_int##bits##_t) (x) : bswap_##bits (x))
+#define BO_cvtp(bits, from, to, p) \
+ BO_cvt (bits, from, to, *(const u_int##bits##_t *) (p))
+#define BO_cvts(bits, from, to, p) \
+ ({ const u_int##bits##_t *_p = (p); *_p = BO_cvt (bits, from, to, *_p); })
+
+#define __cpu_to_le64(x) BO_cvt (64, BYTE_ORDER, LITTLE_ENDIAN, (x))
+#define __le64_to_cpu(x) BO_cvt (64, LITTLE_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_le32(x) BO_cvt (32, BYTE_ORDER, LITTLE_ENDIAN, (x))
+#define __le32_to_cpu(x) BO_cvt (32, LITTLE_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_le16(x) BO_cvt (16, BYTE_ORDER, LITTLE_ENDIAN, (x))
+#define __le16_to_cpu(x) BO_cvt (16, LITTLE_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_be64(x) BO_cvt (64, BYTE_ORDER, BIG_ENDIAN, (x))
+#define __be64_to_cpu(x) BO_cvt (64, BIG_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_be32(x) BO_cvt (32, BYTE_ORDER, BIG_ENDIAN, (x))
+#define __be32_to_cpu(x) BO_cvt (32, BIG_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_be16(x) BO_cvt (16, BYTE_ORDER, BIG_ENDIAN, (x))
+#define __be16_to_cpu(x) BO_cvt (16, BIG_ENDIAN, BYTE_ORDER, (x))
+#define __cpu_to_le64p(p) BO_cvtp (64, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le64_to_cpup(p) BO_cvtp (64, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le32p(p) BO_cvtp (32, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le32_to_cpup(p) BO_cvtp (32, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le16p(p) BO_cvtp (16, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le16_to_cpup(p) BO_cvtp (16, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be64p(p) BO_cvtp (64, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be64_to_cpup(p) BO_cvtp (64, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be32p(p) BO_cvtp (32, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be32_to_cpup(p) BO_cvtp (32, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be16p(p) BO_cvtp (16, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be16_to_cpup(p) BO_cvtp (16, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le64s(p) BO_cvts (64, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le64_to_cpus(p) BO_cvts (64, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le32s(p) BO_cvts (32, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le32_to_cpus(p) BO_cvts (32, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_le16s(p) BO_cvts (16, BYTE_ORDER, LITTLE_ENDIAN, (p))
+#define __le16_to_cpus(p) BO_cvts (16, LITTLE_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be64s(p) BO_cvts (64, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be64_to_cpus(p) BO_cvts (64, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be32s(p) BO_cvts (32, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be32_to_cpus(p) BO_cvts (32, BIG_ENDIAN, BYTE_ORDER, (p))
+#define __cpu_to_be16s(p) BO_cvts (16, BYTE_ORDER, BIG_ENDIAN, (p))
+#define __be16_to_cpus(p) BO_cvts (16, BIG_ENDIAN, BYTE_ORDER, (p))
+
+#define cpu_to_le64 __cpu_to_le64
+#define le64_to_cpu __le64_to_cpu
+#define cpu_to_le32 __cpu_to_le32
+#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le16 __cpu_to_le16
+#define le16_to_cpu __le16_to_cpu
+#define cpu_to_be64 __cpu_to_be64
+#define be64_to_cpu __be64_to_cpu
+#define cpu_to_be32 __cpu_to_be32
+#define be32_to_cpu __be32_to_cpu
+#define cpu_to_be16 __cpu_to_be16
+#define be16_to_cpu __be16_to_cpu
+#define cpu_to_le64p __cpu_to_le64p
+#define le64_to_cpup __le64_to_cpup
+#define cpu_to_le32p __cpu_to_le32p
+#define le32_to_cpup __le32_to_cpup
+#define cpu_to_le16p __cpu_to_le16p
+#define le16_to_cpup __le16_to_cpup
+#define cpu_to_be64p __cpu_to_be64p
+#define be64_to_cpup __be64_to_cpup
+#define cpu_to_be32p __cpu_to_be32p
+#define be32_to_cpup __be32_to_cpup
+#define cpu_to_be16p __cpu_to_be16p
+#define be16_to_cpup __be16_to_cpup
+#define cpu_to_le64s __cpu_to_le64s
+#define le64_to_cpus __le64_to_cpus
+#define cpu_to_le32s __cpu_to_le32s
+#define le32_to_cpus __le32_to_cpus
+#define cpu_to_le16s __cpu_to_le16s
+#define le16_to_cpus __le16_to_cpus
+#define cpu_to_be64s __cpu_to_be64s
+#define be64_to_cpus __be64_to_cpus
+#define cpu_to_be32s __cpu_to_be32s
+#define be32_to_cpus __be32_to_cpus
+#define cpu_to_be16s __cpu_to_be16s
+#define be16_to_cpus __be16_to_cpus
+
+
+#if BYTE_ORDER == BIG_ENDIAN
+# define __BIG_ENDIAN_BITFIELD
+#elif BYTE_ORDER == LITTLE_ENDIAN
+# define __LITTLE_ENDIAN_BITFIELD
+#else
+# error __FOO_ENDIAN_BITFIELD
+#endif
+
+
+#include <netinet/in.h> /* for htonl et al */
+
+/* Though the optimized macros defined by glibc do the constant magic,
+ there are places in the Linux code that use these in constant-only
+ places like initializers, and the ({...}) expressions the macros use are
+ not valid in those contexts. */
+#if BYTE_ORDER == BIG_ENDIAN
+# if !defined(__constant_htonl)
+# define __constant_htonl(x) (x)
+# endif
+# if !defined(__constant_htons)
+# define __constant_htons(x) (x)
+# endif
+#elif BYTE_ORDER == LITTLE_ENDIAN
+# if !defined(__constant_htonl)
+# define __constant_htonl(x) \
+ ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
+ (((unsigned long int)(x) & 0x0000ff00U) << 8) | \
+ (((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
+ (((unsigned long int)(x) & 0xff000000U) >> 24)))
+# endif
+# if !defined(__constant_htons)
+# define __constant_htons(x) \
+ ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
+ (((unsigned short int)(x) & 0xff00) >> 8)))
+# endif
+#else
+# error "Don't know if bytes are big- or little-endian!"
+#endif
+
+/* The transformation is the same in both directions. */
+#define __constant_ntohl __constant_htonl
+#define __constant_ntohs __constant_htons
+
+
+/* Some Linux code (e.g. <net/tcp.h>) uses #ifdef __BIG_ENDIAN et al.
+ This is not real wonderful with the glibc definitions, where
+ __BIG_ENDIAN et al are always defined (as values for __BYTE_ORDER). */
+#if BYTE_ORDER == BIG_ENDIAN
+#undef __LITTLE_ENDIAN
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#undef __BIG_ENDIAN
+#endif
+#undef __PDP_ENDIAN
+
+/* Since we've now broken anything that does glibc-style tests,
+ make sure they break loudly rather than silently. Any headers
+ that need __BYTE_ORDER will just have to be included before
+ we diddle with __BIG_ENDIAN or __LITTLE_ENDIAN above. */
+#undef __BYTE_ORDER
+#define __BYTE_ORDER ?????crash?????
+
+
+#endif /* asm/byteorder.h */
diff --git a/pfinet/glue-include/asm/checksum.h b/pfinet/glue-include/asm/checksum.h
new file mode 100644
index 00000000..5bcf7551
--- /dev/null
+++ b/pfinet/glue-include/asm/checksum.h
@@ -0,0 +1,5 @@
+/* This is the only file from the Linux include/asm-* directory
+ that we use, so we use this magic file here rather than making a
+ symlink asm -> .../linux-src/include/asm-SYSTYPE somewhere. */
+
+#include "../../linux-src/include/asm-" _HURD_SYSTYPE "/checksum.h"
diff --git a/pfinet/glue-include/asm/errno.h b/pfinet/glue-include/asm/errno.h
new file mode 100644
index 00000000..7afb6fdc
--- /dev/null
+++ b/pfinet/glue-include/asm/errno.h
@@ -0,0 +1,3 @@
+/* This is used only by checksum.S; the C code uses <linux/errno.h>. */
+
+#define EFAULT 42 /* only used in unreached code */
diff --git a/pfinet/glue-include/asm/hardirq.h b/pfinet/glue-include/asm/hardirq.h
new file mode 100644
index 00000000..c73d7dcb
--- /dev/null
+++ b/pfinet/glue-include/asm/hardirq.h
@@ -0,0 +1 @@
+#include <linux/interrupt.h>
diff --git a/pfinet/glue-include/asm/init.h b/pfinet/glue-include/asm/init.h
new file mode 100644
index 00000000..2331be7c
--- /dev/null
+++ b/pfinet/glue-include/asm/init.h
@@ -0,0 +1,3 @@
+#define __init
+#define __initdata
+#define __initfunc(x) x
diff --git a/pfinet/linux/autoconf.h b/pfinet/glue-include/asm/segment.h
index e69de29b..e69de29b 100644
--- a/pfinet/linux/autoconf.h
+++ 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/linux/config.h b/pfinet/glue-include/linux/autoconf.h
index e69de29b..e69de29b 100644
--- a/pfinet/linux/config.h
+++ 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/linux/fcntl.h b/pfinet/glue-include/linux/fcntl.h
index cd304557..cd304557 100644
--- a/pfinet/linux/fcntl.h
+++ b/pfinet/glue-include/linux/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/linux/in.h b/pfinet/glue-include/linux/in6.h
index 260020a6..260020a6 100644
--- a/pfinet/linux/in.h
+++ b/pfinet/glue-include/linux/in6.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/linux/major.h b/pfinet/glue-include/linux/major.h
index e69de29b..e69de29b 100644
--- a/pfinet/linux/major.h
+++ 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/linux/mm.h b/pfinet/glue-include/linux/mm.h
index 0fb18a59..a6f28e00 100644
--- a/pfinet/linux/mm.h
+++ b/pfinet/glue-include/linux/mm.h
@@ -12,5 +12,7 @@
#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/linux/param.h b/pfinet/glue-include/linux/param.h
index 39efaf0d..39efaf0d 100644
--- a/pfinet/linux/param.h
+++ b/pfinet/glue-include/linux/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/linux/sockios.h b/pfinet/glue-include/linux/proc_fs.h
index e69de29b..e69de29b 100644
--- a/pfinet/linux/sockios.h
+++ b/pfinet/glue-include/linux/proc_fs.h
diff --git a/pfinet/glue-include/linux/sched.h b/pfinet/glue-include/linux/sched.h
new file mode 100644
index 00000000..897a2df0
--- /dev/null
+++ b/pfinet/glue-include/linux/sched.h
@@ -0,0 +1,176 @@
+#ifndef _HACK_SCHED_H
+#define _HACK_SCHED_H
+
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <mach.h>
+#include <hurd/hurd_types.h>
+#include <limits.h>
+#include <assert.h>
+#include <cthreads.h>
+
+#include "mapped-time.h"
+
+#include <linux/binfmts.h>
+#include <linux/personality.h>
+#include <linux/tasks.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/times.h>
+#include <linux/timex.h>
+
+#include <asm/system.h>
+#if 0
+#include <asm/semaphore.h>
+#include <asm/page.h>
+
+#include <linux/smp.h>
+#include <linux/tty.h>
+#include <linux/sem.h>
+#include <linux/signal.h>
+#include <linux/securebits.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/net.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+
+
+#define jiffies (fetch_jiffies ())
+
+#define current (&current_contents)
+extern struct task_struct current_contents;
+struct task_struct
+{
+ uid_t pgrp, pid;
+ int flags;
+ int timeout;
+ int signal;
+ int blocked;
+ int state, policy;
+ int isroot;
+ char *comm;
+ struct wait_queue **next_wait;
+};
+
+static inline void
+prepare_current (int isroot)
+{
+ current->signal = 0;
+ current->isroot = isroot;
+ /* All other members are constant zero and ignored. */
+}
+#define become_task(user) prepare_current ((user)->isroot)
+#define become_task_protid(protid) prepare_current ((protid)->isroot)
+
+#define signal_pending(current) ((current)->signal)
+
+/* FLAGS in task_struct's. */
+#define PF_EXITING 1
+/* STATE in task_struct's. */
+#define TASK_INTERRUPTIBLE 0
+#define TASK_RUNNING 0
+/* policy in task_struct's. */
+#define SCHED_YIELD 0
+
+struct semaphore { };
+
+
+extern inline int
+suser ()
+{
+ return current->isroot;
+};
+
+extern inline int
+capable(int cap)
+{
+ return current->isroot;
+}
+
+
+extern struct mutex global_lock;
+
+static inline void
+interruptible_sleep_on (struct wait_queue **p)
+{
+ struct condition **condp = (void *) p, *c;
+ int isroot;
+ struct wait_queue **next_wait;
+
+ c = *condp;
+ if (c == 0)
+ {
+ c = malloc (sizeof **condp);
+ assert (c);
+ condition_init (c);
+ *condp = c;
+ }
+
+ isroot = current->isroot; /* This is our context that needs switched. */
+ next_wait = current->next_wait; /* This too, for multiple schedule calls. */
+ current->next_wait = 0;
+ if (hurd_condition_wait (c, &global_lock))
+ current->signal = 1; /* We got cancelled, mark it for later. */
+ current->isroot = isroot; /* Switch back to our context. */
+ current->next_wait = next_wait;
+}
+#define sleep_on interruptible_sleep_on
+
+static inline void
+wake_up_interruptible (struct wait_queue **p)
+{
+ struct condition **condp = (void *) p, *c = *condp;
+ if (c)
+ condition_broadcast (c);
+}
+#define wake_up wake_up_interruptible
+
+
+static inline void
+add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+{
+ assert (current->next_wait == 0);
+ current->next_wait = p;
+}
+
+static inline void
+remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+{
+ assert (current->next_wait == p);
+ current->next_wait = 0;
+}
+
+static inline void
+schedule (void)
+{
+ assert (current->next_wait);
+ interruptible_sleep_on (current->next_wait);
+}
+
+static inline long
+schedule_timeout (long timeout)
+{
+ /* XXX this is only ever called to do SO_LINGER, which we don't support */
+ assert (!"schedule_timeout");
+ return 0;
+}
+
+#define MAX_SCHEDULE_TIMEOUT LONG_MAX
+
+/* This function is used only to send SIGPIPE to the current
+ task. In all such cases, EPIPE is returned anyhow. In the
+ Hurd, servers are not responsible for SIGPIPE; the library
+ does that itself upon receiving EPIPE. So we can just
+ NOP such calls. */
+extern inline int
+send_sig (u_long signo, struct task_struct *task, int priv)
+{
+ assert (signo == SIGPIPE);
+ assert (task == current);
+ return 0;
+}
+
+
+#endif
diff --git a/pfinet/linux/un.h b/pfinet/glue-include/linux/slab.h
index e69de29b..e69de29b 100644
--- a/pfinet/linux/un.h
+++ 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/linux/stat.h b/pfinet/glue-include/linux/stat.h
index 5165069b..5165069b 100644
--- a/pfinet/linux/stat.h
+++ b/pfinet/glue-include/linux/stat.h
diff --git a/pfinet/linux/string.h b/pfinet/glue-include/linux/string.h
index 3b2f5900..3b2f5900 100644
--- a/pfinet/linux/string.h
+++ b/pfinet/glue-include/linux/string.h
diff --git a/pfinet/linux/termios.h b/pfinet/glue-include/linux/termios.h
index 9e269565..9e269565 100644
--- a/pfinet/linux/termios.h
+++ b/pfinet/glue-include/linux/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/linux/timer.h b/pfinet/glue-include/linux/timer.h
index 2458746e..cc8dec80 100644
--- a/pfinet/linux/timer.h
+++ b/pfinet/glue-include/linux/timer.h
@@ -11,10 +11,10 @@ enum tstate
TIMER_EXPIRED,
TIMER_FUNCTION_RUNNING,
};
-
+
struct timer_list
{
- struct timer_list *next, **prevp;
+ struct timer_list *next, **prev; /* things like to test "T->prev != NULL" */
unsigned long expires;
unsigned long data;
void (*function)(unsigned long);
@@ -22,6 +22,15 @@ struct timer_list
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
index b6831c31..c4cfc253 100644
--- a/pfinet/io-ops.c
+++ b/pfinet/io-ops.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ 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.
@@ -19,10 +19,14 @@
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 <linux/wait.h>
-#include <linux-inet/sock.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
@@ -37,15 +41,19 @@ S_io_write (struct sock_user *user,
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);
+ __mutex_lock (&global_lock);
become_task (user);
- err = (*user->sock->ops->write) (user->sock, data, datalen,
- user->sock->userflags);
- mutex_unlock (&global_lock);
+ 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;
@@ -67,6 +75,9 @@ S_io_read (struct sock_user *user,
{
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;
@@ -79,11 +90,16 @@ S_io_read (struct sock_user *user,
alloced = 1;
}
- mutex_lock (&global_lock);
+ iov.iov_base = *data;
+ iov.iov_len = amount;
+
+ __mutex_lock (&global_lock);
become_task (user);
- err = (*user->sock->ops->read) (user->sock, *data, amount,
- user->sock->userflags);
- mutex_unlock (&global_lock);
+ 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;
@@ -117,13 +133,13 @@ S_io_readable (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __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 = (struct sock *) user->sock->data;
+ sk = user->sock->sk;
err = 0;
/* Linux's af_inet.c ioctl routine just calls the protocol-specific
@@ -134,15 +150,7 @@ S_io_readable (struct sock_user *user,
{
case SOCK_STREAM:
case SOCK_SEQPACKET:
- /* These guts are copied from tcp.c:tcp_ioctl. */
- if (sk->state == TCP_LISTEN)
- err = EINVAL;
- else
- {
- sk->inuse = 1;
- *amount = tcp_readable (sk);
- release_sock (sk);
- }
+ err = tcp_tiocinq (sk, amount);
break;
case SOCK_DGRAM:
@@ -161,7 +169,7 @@ S_io_readable (struct sock_user *user,
break;
}
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return err;
}
@@ -172,12 +180,12 @@ S_io_set_all_openmodes (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
if (bits & O_NONBLOCK)
- user->sock->userflags |= O_NONBLOCK;
+ user->sock->flags |= O_NONBLOCK;
else
- user->sock->userflags &= ~O_NONBLOCK;
- mutex_unlock (&global_lock);
+ user->sock->flags &= ~O_NONBLOCK;
+ __mutex_unlock (&global_lock);
return 0;
}
@@ -190,18 +198,18 @@ S_io_get_openmodes (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
- sk = user->sock->data;
+ __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->userflags & O_NONBLOCK)
+ if (user->sock->flags & O_NONBLOCK)
*bits |= O_NONBLOCK;
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return 0;
}
@@ -212,10 +220,10 @@ S_io_set_some_openmodes (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
if (bits & O_NONBLOCK)
- user->sock->userflags |= O_NONBLOCK;
- mutex_unlock (&global_lock);
+ user->sock->flags |= O_NONBLOCK;
+ __mutex_unlock (&global_lock);
return 0;
}
@@ -226,114 +234,62 @@ S_io_clear_some_openmodes (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
if (bits & O_NONBLOCK)
- user->sock->userflags &= ~O_NONBLOCK;
- mutex_unlock (&global_lock);
+ 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,
+ mach_port_t reply,
+ mach_msg_type_name_t reply_type,
int *select_type)
{
- int avail = 0;
- int cancel = 0;
- int requested_notify = 0;
- select_table table;
- struct select_table_elt *elt, *nxt;
+ const int want = *select_type;
+ int avail;
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __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->select);
-
- /* The select function returns one if the specified I/O type is
- immediately possible. If it returns zero, then it is not
- immediately possible, and it has called select_wait. Eventually
- it will wakeup the wait queue specified in the select_wait call;
- at that point we should retry the call. */
+ assert (user->sock->ops->poll);
- for (;;)
+ avail = (*user->sock->ops->poll) ((void *) 0xdeadbeef,
+ user->sock,
+ (void *) 0xdeadbead);
+ if ((avail & want) == 0)
{
- condition_init (&table.master_condition);
- table.head = 0;
-
- if (*select_type & SELECT_READ)
- avail |= ((*user->sock->ops->select) (user->sock, SEL_IN, &table)
- ? SELECT_READ : 0);
- if (*select_type & SELECT_WRITE)
- avail |= ((*user->sock->ops->select) (user->sock, SEL_OUT, &table)
- ? SELECT_WRITE : 0);
- if (*select_type & SELECT_URG)
- avail |= ((*user->sock->ops->select) (user->sock, SEL_EX, &table)
- ? SELECT_URG : 0);
-
- if (!avail)
+ ports_interrupt_self_on_notification (user, reply,
+ MACH_NOTIFY_DEAD_NAME);
+
+ do
{
- if (! requested_notify)
+ /* Block until we are woken or cancelled. */
+ interruptible_sleep_on (user->sock->sk->sleep);
+ if (signal_pending (current)) /* This means we were cancelled. */
{
- ports_interrupt_self_on_notification (user, reply,
- MACH_NOTIFY_DEAD_NAME);
- requested_notify = 1;
+ __mutex_unlock (&global_lock);
+ return EINTR;
}
- cancel = hurd_condition_wait (&table.master_condition, &global_lock);
- }
-
- /* Drop the conditions implications and structures allocated in the
- select table. */
- for (elt = table.head; elt; elt = nxt)
- {
- condition_unimplies (elt->dependent_condition,
- &table.master_condition);
- nxt = elt->next;
- free (elt);
- }
-
- if (avail)
- {
- mutex_unlock (&global_lock);
- *select_type = avail;
- return 0;
- }
-
- if (cancel)
- {
- mutex_unlock (&global_lock);
- mach_port_deallocate (mach_task_self (), reply);
- return EINTR;
+ avail = (*user->sock->ops->poll) ((void *) 0xdeadbeef,
+ user->sock,
+ (void *) 0xdeadbead);
}
+ while ((avail & want) == 0);
}
-}
-/* Establish that the condition in WAIT_ADDRESS should imply
- the condition in P. Also, add us to the queue in P so
- that the relation can be undone at the proper time. */
-void
-select_wait (struct wait_queue **wait_address, select_table *p)
-{
- struct select_table_elt *elt;
+ /* We got something. */
+ *select_type = avail;
- /* tcp.c happens to use an uninitalized wait queue;
- so this special hack is for that. */
- if (*wait_address == 0)
- {
- *wait_address = malloc (sizeof (struct wait_queue));
- condition_init (&(*wait_address)->c);
- }
+ __mutex_unlock (&global_lock);
- elt = malloc (sizeof (struct select_table_elt));
- elt->dependent_condition = &(*wait_address)->c;
- elt->next = p->head;
- p->head = elt;
-
- condition_implies (elt->dependent_condition, &p->master_condition);
+ return 0;
}
error_t
@@ -349,7 +305,9 @@ S_io_stat (struct sock_user *user,
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;
}
@@ -375,7 +333,7 @@ S_io_reauthenticate (struct sock_user *user,
aux_uids = aubuf;
aux_gids = agbuf;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
newuser = make_sock_user (user->sock, 0, 1);
auth = getauth ();
@@ -408,7 +366,7 @@ S_io_reauthenticate (struct sock_user *user,
mach_port_move_member (mach_task_self (), newuser->pi.port_right,
pfinet_bucket->portset);
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
ports_port_deref (newuser);
@@ -440,7 +398,7 @@ S_io_restrict_auth (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
isroot = 0;
if (user->isroot)
@@ -452,7 +410,7 @@ S_io_restrict_auth (struct sock_user *user,
*newobject = ports_get_right (newuser);
*newobject_type = MACH_MSG_TYPE_MAKE_SEND;
ports_port_deref (newuser);
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return 0;
}
@@ -465,12 +423,12 @@ S_io_duplicate (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __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);
+ __mutex_unlock (&global_lock);
return 0;
}
@@ -487,14 +445,14 @@ S_io_identity (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __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);
+ __mutex_unlock (&global_lock);
return err;
}
}
@@ -505,7 +463,7 @@ S_io_identity (struct sock_user *user,
*fsystype = MACH_MSG_TYPE_MAKE_SEND;
*fileno = (ino_t) user->sock; /* matches S_io_stat above */
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return 0;
}
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-inet/af_inet.c b/pfinet/linux-inet/af_inet.c
deleted file mode 100644
index d20c8bfb..00000000
--- a/pfinet/linux-inet/af_inet.c
+++ /dev/null
@@ -1,1578 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * AF_INET protocol family socket handler.
- *
- * Version: @(#)af_inet.c (from sock.c) 1.0.17 06/02/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Florian La Roche, <flla@stud.uni-sb.de>
- * Alan Cox, <A.Cox@swansea.ac.uk>
- *
- * Changes (see also sock.c)
- *
- * A.N.Kuznetsov : Socket death error in accept().
- * John Richardson : Fix non blocking error in connect()
- * so sockets that fail to connect
- * don't return -EINPROGRESS.
- * Alan Cox : Asynchronous I/O support
- * Alan Cox : Keep correct socket pointer on sock structures
- * 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
- * some RPC stuff seems happier.
- * Niibe Yutaka : 4.4BSD style write async I/O
- * Alan Cox,
- * Tony Gale : Fixed reuse semantics.
- * Alan Cox : bind() shouldn't abort existing but dead
- * sockets. Stops FTP netin:.. I hope.
- * Alan Cox : bind() works correctly for RAW sockets. Note
- * that FreeBSD at least is broken in this respect
- * so be careful with compatibility tests...
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include "arp.h"
-#include "rarp.h"
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "raw.h"
-#include "icmp.h"
-
-#define min(a,b) ((a)<(b)?(a):(b))
-
-extern struct proto packet_prot;
-
-
-/*
- * See if a socket number is in use.
- */
-
-static int sk_inuse(struct proto *prot, int num)
-{
- struct sock *sk;
-
- for(sk = prot->sock_array[num & (SOCK_ARRAY_SIZE -1 )];
- sk != NULL; sk=sk->next)
- {
- if (sk->num == num)
- return(1);
- }
- return(0);
-}
-
-
-/*
- * Pick a new socket number
- */
-
-unsigned short get_new_socknum(struct proto *prot, unsigned short base)
-{
- static int start=0;
-
- /*
- * Used to cycle through the port numbers so the
- * chances of a confused connection drop.
- */
-
- int i, j;
- int best = 0;
- int size = 32767; /* a big num. */
- struct sock *sk;
-
- if (base == 0)
- base = PROT_SOCK+1+(start % 1024);
- if (base <= PROT_SOCK)
- {
- base += PROT_SOCK+(start % 1024);
- }
-
- /* Now look through the entire array and try to find an empty ptr. */
- for(i=0; i < SOCK_ARRAY_SIZE; i++)
- {
- j = 0;
- sk = prot->sock_array[(i+base+1) &(SOCK_ARRAY_SIZE -1)];
- while(sk != NULL)
- {
- sk = sk->next;
- j++;
- }
- if (j == 0)
- {
- start =(i+1+start )%1024;
- return(i+base+1);
- }
- if (j < size)
- {
- best = i;
- size = j;
- }
- }
-
- /* Now make sure the one we want is not in use. */
-
- while(sk_inuse(prot, base +best+1))
- {
- best += SOCK_ARRAY_SIZE;
- }
- return(best+base+1);
-}
-
-/*
- * Add a socket into the socket tables by number.
- */
-
-void put_sock(unsigned short num, struct sock *sk)
-{
- struct sock *sk1;
- struct sock *sk2;
- int mask;
- unsigned long flags;
-
- sk->num = num;
- sk->next = NULL;
- num = num &(SOCK_ARRAY_SIZE -1);
-
- /* We can't have an interrupt re-enter here. */
- save_flags(flags);
- cli();
-
- sk->prot->inuse += 1;
- if (sk->prot->highestinuse < sk->prot->inuse)
- sk->prot->highestinuse = sk->prot->inuse;
-
- if (sk->prot->sock_array[num] == NULL)
- {
- sk->prot->sock_array[num] = sk;
- restore_flags(flags);
- return;
- }
- restore_flags(flags);
- for(mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask)
- {
- if ((mask & sk->saddr) &&
- (mask & sk->saddr) != (mask & 0xffffffff))
- {
- mask = mask << 8;
- break;
- }
- }
- cli();
- sk1 = sk->prot->sock_array[num];
- for(sk2 = sk1; sk2 != NULL; sk2=sk2->next)
- {
- if (!(sk2->saddr & mask))
- {
- if (sk2 == sk1)
- {
- sk->next = sk->prot->sock_array[num];
- sk->prot->sock_array[num] = sk;
- sti();
- return;
- }
- sk->next = sk2;
- sk1->next= sk;
- sti();
- return;
- }
- sk1 = sk2;
- }
-
- /* Goes at the end. */
- sk->next = NULL;
- sk1->next = sk;
- sti();
-}
-
-/*
- * Remove a socket from the socket tables.
- */
-
-static void remove_sock(struct sock *sk1)
-{
- struct sock *sk2;
- unsigned long flags;
-
- if (!sk1->prot)
- {
- printk("sock.c: remove_sock: sk1->prot == NULL\n");
- return;
- }
-
- /* We can't have this changing out from under us. */
- save_flags(flags);
- cli();
- sk2 = sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)];
- if (sk2 == sk1)
- {
- sk1->prot->inuse -= 1;
- sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)] = sk1->next;
- restore_flags(flags);
- return;
- }
-
- while(sk2 && sk2->next != sk1)
- {
- sk2 = sk2->next;
- }
-
- if (sk2)
- {
- sk1->prot->inuse -= 1;
- sk2->next = sk1->next;
- restore_flags(flags);
- return;
- }
- restore_flags(flags);
-}
-
-/*
- * Destroy an AF_INET socket
- */
-
-void destroy_sock(struct sock *sk)
-{
- struct sk_buff *skb;
-
- sk->inuse = 1; /* just to be safe. */
-
- /* In case it's sleeping somewhere. */
- if (!sk->dead)
- sk->write_space(sk);
-
- remove_sock(sk);
-
- /* Now we can no longer get new packets. */
- delete_timer(sk);
- /* Nor send them */
- del_timer(&sk->retransmit_timer);
-
- while ((skb = tcp_dequeue_partial(sk)) != NULL) {
- IS_SKB(skb);
- kfree_skb(skb, FREE_WRITE);
- }
-
- /* Cleanup up the write buffer. */
- while((skb = skb_dequeue(&sk->write_queue)) != NULL) {
- IS_SKB(skb);
- kfree_skb(skb, FREE_WRITE);
- }
-
- /*
- * Don't discard received data until the user side kills its
- * half of the socket.
- */
-
- if (sk->dead)
- {
- while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
- {
- /*
- * This will take care of closing sockets that were
- * listening and didn't accept everything.
- */
- if (skb->sk != NULL && skb->sk != sk)
- {
- IS_SKB(skb);
- skb->sk->dead = 1;
- skb->sk->prot->close(skb->sk, 0);
- }
- IS_SKB(skb);
- kfree_skb(skb, FREE_READ);
- }
- }
-
- /* Now we need to clean up the send head. */
- cli();
- for(skb = sk->send_head; skb != NULL; )
- {
- struct sk_buff *skb2;
-
- /*
- * We need to remove skb from the transmit queue,
- * or maybe the arp queue.
- */
- if (skb->next && skb->prev) {
-/* printk("destroy_sock: unlinked skb\n");*/
- IS_SKB(skb);
- skb_unlink(skb);
- }
- skb->dev = NULL;
- skb2 = skb->link3;
- kfree_skb(skb, FREE_WRITE);
- skb = skb2;
- }
- sk->send_head = NULL;
- sti();
-
- /* And now the backlog. */
- while((skb=skb_dequeue(&sk->back_log))!=NULL)
- {
- /* this should never happen. */
-/* printk("cleaning back_log\n");*/
- kfree_skb(skb, FREE_READ);
- }
-
- /* Now if it has a half accepted/ closed socket. */
- if (sk->pair)
- {
- sk->pair->dead = 1;
- sk->pair->prot->close(sk->pair, 0);
- sk->pair = NULL;
- }
-
- /*
- * Now if everything is gone we can free the socket
- * structure, otherwise we need to keep it around until
- * everything is gone.
- */
-
- if (sk->dead && sk->rmem_alloc == 0 && sk->wmem_alloc == 0)
- {
- kfree_s((void *)sk,sizeof(*sk));
- }
- else
- {
- /* this should never happen. */
- /* actually it can if an ack has just been sent. */
- sk->destroy = 1;
- sk->ack_backlog = 0;
- sk->inuse = 0;
- reset_timer(sk, TIME_DESTROY, SOCK_DESTROY_TIME);
- }
-}
-
-/*
- * The routines beyond this point handle the behaviour of an AF_INET
- * socket object. Mostly it punts to the subprotocols of IP to do
- * the work.
- */
-
-static int inet_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- struct sock *sk;
-
- sk = (struct sock *) sock->data;
-
- switch(cmd)
- {
- case F_SETOWN:
- /*
- * This is a little restrictive, but it's the only
- * way to make sure that you can't send a sigurg to
- * another process.
- */
- if (!suser() && current->pgrp != -arg &&
- current->pid != arg) return(-EPERM);
- sk->proc = arg;
- return(0);
- case F_GETOWN:
- return(sk->proc);
- default:
- return(-EINVAL);
- }
-}
-
-/*
- * Set socket options on an inet socket.
- */
-
-static int inet_setsockopt(struct socket *sock, int level, int optname,
- char *optval, int optlen)
-{
- struct sock *sk = (struct sock *) sock->data;
- if (level == SOL_SOCKET)
- return sock_setsockopt(sk,level,optname,optval,optlen);
- if (sk->prot->setsockopt==NULL)
- return(-EOPNOTSUPP);
- else
- return sk->prot->setsockopt(sk,level,optname,optval,optlen);
-}
-
-/*
- * Get a socket option on an AF_INET socket.
- */
-
-static int inet_getsockopt(struct socket *sock, int level, int optname,
- char *optval, int *optlen)
-{
- struct sock *sk = (struct sock *) sock->data;
- if (level == SOL_SOCKET)
- return sock_getsockopt(sk,level,optname,optval,optlen);
- if(sk->prot->getsockopt==NULL)
- return(-EOPNOTSUPP);
- else
- return sk->prot->getsockopt(sk,level,optname,optval,optlen);
-}
-
-/*
- * Automatically bind an unbound socket.
- */
-
-static int inet_autobind(struct sock *sk)
-{
- /* We may need to bind the socket. */
- if (sk->num == 0)
- {
- sk->num = get_new_socknum(sk->prot, 0);
- if (sk->num == 0)
- return(-EAGAIN);
- put_sock(sk->num, sk);
- sk->dummy_th.source = ntohs(sk->num);
- }
- return 0;
-}
-
-/*
- * Move a socket into listening state.
- */
-
-static int inet_listen(struct socket *sock, int backlog)
-{
- struct sock *sk = (struct sock *) sock->data;
-
- if(inet_autobind(sk)!=0)
- return -EAGAIN;
-
- /* We might as well re use these. */
- /*
- * note that the backlog is "unsigned char", so truncate it
- * somewhere. We might as well truncate it to what everybody
- * else does..
- */
- if (backlog > 5)
- backlog = 5;
- sk->max_ack_backlog = backlog;
- if (sk->state != TCP_LISTEN)
- {
- sk->ack_backlog = 0;
- sk->state = TCP_LISTEN;
- }
- return(0);
-}
-
-/*
- * Default callbacks for user INET sockets. These just wake up
- * the user owning the socket.
- */
-
-static void def_callback1(struct sock *sk)
-{
- if(!sk->dead)
- wake_up_interruptible(sk->sleep);
-}
-
-static void def_callback2(struct sock *sk,int len)
-{
- if(!sk->dead)
- {
- wake_up_interruptible(sk->sleep);
- sock_wake_async(sk->socket, 1);
- }
-}
-
-static void def_callback3(struct sock *sk)
-{
- if(!sk->dead)
- {
- wake_up_interruptible(sk->sleep);
- sock_wake_async(sk->socket, 2);
- }
-}
-
-/*
- * Create an inet socket.
- *
- * FIXME: Gcc would generate much better code if we set the parameters
- * up in in-memory structure order. Gcc68K even more so
- */
-
-static int inet_create(struct socket *sock, int protocol)
-{
- struct sock *sk;
- struct proto *prot;
- int err;
-
- sk = (struct sock *) kmalloc(sizeof(*sk), GFP_KERNEL);
- if (sk == NULL)
- return(-ENOBUFS);
- sk->num = 0;
- sk->reuse = 0;
- switch(sock->type)
- {
- case SOCK_STREAM:
- case SOCK_SEQPACKET:
- if (protocol && protocol != IPPROTO_TCP)
- {
- kfree_s((void *)sk, sizeof(*sk));
- return(-EPROTONOSUPPORT);
- }
- protocol = IPPROTO_TCP;
- sk->no_check = TCP_NO_CHECK;
- prot = &tcp_prot;
- break;
-
- case SOCK_DGRAM:
- if (protocol && protocol != IPPROTO_UDP)
- {
- kfree_s((void *)sk, sizeof(*sk));
- return(-EPROTONOSUPPORT);
- }
- protocol = IPPROTO_UDP;
- sk->no_check = UDP_NO_CHECK;
- prot=&udp_prot;
- break;
-
- case SOCK_RAW:
- if (!suser())
- {
- kfree_s((void *)sk, sizeof(*sk));
- return(-EPERM);
- }
- if (!protocol)
- {
- kfree_s((void *)sk, sizeof(*sk));
- return(-EPROTONOSUPPORT);
- }
- prot = &raw_prot;
- sk->reuse = 1;
- sk->no_check = 0; /*
- * Doesn't matter no checksum is
- * performed anyway.
- */
- sk->num = protocol;
- break;
-
-#ifndef _HURD_
- case SOCK_PACKET:
- if (!suser())
- {
- kfree_s((void *)sk, sizeof(*sk));
- return(-EPERM);
- }
- if (!protocol)
- {
- kfree_s((void *)sk, sizeof(*sk));
- return(-EPROTONOSUPPORT);
- }
- prot = &packet_prot;
- sk->reuse = 1;
- sk->no_check = 0; /* Doesn't matter no checksum is
- * performed anyway.
- */
- sk->num = protocol;
- break;
-#endif
-
- default:
- kfree_s((void *)sk, sizeof(*sk));
- return(-ESOCKTNOSUPPORT);
- }
- sk->socket = sock;
-#ifdef CONFIG_TCP_NAGLE_OFF
- sk->nonagle = 1;
-#else
- sk->nonagle = 0;
-#endif
- sk->type = sock->type;
- sk->stamp.tv_sec=0;
- sk->protocol = protocol;
- sk->wmem_alloc = 0;
- sk->rmem_alloc = 0;
- sk->sndbuf = SK_WMEM_MAX;
- sk->rcvbuf = SK_RMEM_MAX;
- sk->pair = NULL;
- sk->opt = NULL;
- sk->write_seq = 0;
- sk->acked_seq = 0;
- sk->copied_seq = 0;
- sk->fin_seq = 0;
- sk->urg_seq = 0;
- sk->urg_data = 0;
- sk->proc = 0;
- sk->rtt = 0; /*TCP_WRITE_TIME << 3;*/
- sk->rto = TCP_TIMEOUT_INIT; /*TCP_WRITE_TIME*/
- sk->mdev = 0;
- sk->backoff = 0;
- sk->packets_out = 0;
- sk->cong_window = 1; /* start with only sending one packet at a time. */
- sk->cong_count = 0;
- sk->ssthresh = 0;
- sk->max_window = 0;
- sk->urginline = 0;
- sk->intr = 0;
- sk->linger = 0;
- sk->destroy = 0;
- sk->priority = 1;
- sk->shutdown = 0;
- sk->keepopen = 0;
- sk->zapped = 0;
- sk->done = 0;
- sk->ack_backlog = 0;
- sk->window = 0;
- sk->bytes_rcv = 0;
- sk->state = TCP_CLOSE;
- sk->dead = 0;
- sk->ack_timed = 0;
- sk->partial = NULL;
- sk->user_mss = 0;
- sk->debug = 0;
-
- /* this is how many unacked bytes we will accept for this socket. */
- sk->max_unacked = 2048; /* needs to be at most 2 full packets. */
-
- /* how many packets we should send before forcing an ack.
- if this is set to zero it is the same as sk->delay_acks = 0 */
- sk->max_ack_backlog = 0;
- sk->inuse = 0;
- sk->delay_acks = 0;
- skb_queue_head_init(&sk->write_queue);
- skb_queue_head_init(&sk->receive_queue);
- sk->mtu = 576;
- sk->prot = prot;
- sk->sleep = sock->wait;
- sk->daddr = 0;
- sk->saddr = 0 /* ip_my_addr() */;
- sk->err = 0;
- sk->next = NULL;
- sk->pair = NULL;
- sk->send_tail = NULL;
- sk->send_head = NULL;
- sk->timeout = 0;
- sk->broadcast = 0;
- sk->localroute = 0;
- init_timer(&sk->timer);
- init_timer(&sk->retransmit_timer);
- sk->timer.data = (unsigned long)sk;
- sk->timer.function = &net_timer;
- skb_queue_head_init(&sk->back_log);
- sk->blog = 0;
- sock->data =(void *) sk;
- sk->dummy_th.doff = sizeof(sk->dummy_th)/4;
- sk->dummy_th.res1=0;
- sk->dummy_th.res2=0;
- sk->dummy_th.urg_ptr = 0;
- sk->dummy_th.fin = 0;
- sk->dummy_th.syn = 0;
- sk->dummy_th.rst = 0;
- sk->dummy_th.psh = 0;
- sk->dummy_th.ack = 0;
- sk->dummy_th.urg = 0;
- sk->dummy_th.dest = 0;
- sk->ip_tos=0;
- sk->ip_ttl=64;
-#ifdef CONFIG_IP_MULTICAST
- sk->ip_mc_loop=1;
- sk->ip_mc_ttl=1;
- *sk->ip_mc_name=0;
- sk->ip_mc_list=NULL;
-#endif
-
- sk->state_change = def_callback1;
- sk->data_ready = def_callback2;
- sk->write_space = def_callback3;
- sk->error_report = def_callback1;
-
- if (sk->num)
- {
- /*
- * It assumes that any protocol which allows
- * the user to assign a number at socket
- * creation time automatically
- * shares.
- */
- put_sock(sk->num, sk);
- sk->dummy_th.source = ntohs(sk->num);
- }
-
- if (sk->prot->init)
- {
- err = sk->prot->init(sk);
- if (err != 0)
- {
- destroy_sock(sk);
- return(err);
- }
- }
- return(0);
-}
-
-
-/*
- * Duplicate a socket.
- */
-
-static int inet_dup(struct socket *newsock, struct socket *oldsock)
-{
- return(inet_create(newsock,((struct sock *)(oldsock->data))->protocol));
-}
-
-/*
- * Return 1 if we still have things to send in our buffers.
- */
-static inline int closing(struct sock * sk)
-{
- switch (sk->state) {
- case TCP_FIN_WAIT1:
- case TCP_CLOSING:
- case TCP_LAST_ACK:
- return 1;
- }
- return 0;
-}
-
-
-/*
- * The peer socket should always be NULL (or else). When we call this
- * function we are destroying the object and from then on nobody
- * should refer to it.
- */
-
-static int inet_release(struct socket *sock, struct socket *peer)
-{
- struct sock *sk = (struct sock *) sock->data;
- if (sk == NULL)
- return(0);
-
- sk->state_change(sk);
-
- /* Start closing the connection. This may take a while. */
-
-#ifdef CONFIG_IP_MULTICAST
- /* Applications forget to leave groups before exiting */
- ip_mc_drop_socket(sk);
-#endif
- /*
- * If linger is set, we don't return until the close
- * is complete. Other wise we return immediately. The
- * actually closing is done the same either way.
- *
- * If the close is due to the process exiting, we never
- * linger..
- */
-
- if (sk->linger == 0 || (current->flags & PF_EXITING))
- {
- sk->prot->close(sk,0);
- sk->dead = 1;
- }
- else
- {
- sk->prot->close(sk, 0);
- cli();
- if (sk->lingertime)
- current->timeout = jiffies + HZ*sk->lingertime;
- while(closing(sk) && current->timeout>0)
- {
- interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked)
- {
- break;
-#if 0
- /* not working now - closes can't be restarted */
- sti();
- current->timeout=0;
- return(-ERESTARTSYS);
-#endif
- }
- }
- current->timeout=0;
- sti();
- sk->dead = 1;
- }
- sk->inuse = 1;
-
- /* This will destroy it. */
- release_sock(sk);
- sock->data = NULL;
- sk->socket = NULL;
- return(0);
-}
-
-
-/* this needs to be changed to disallow
- the rebinding of sockets. What error
- should it return? */
-
-static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
- int addr_len)
-{
- struct sockaddr_in *addr=(struct sockaddr_in *)uaddr;
- struct sock *sk=(struct sock *)sock->data, *sk2;
- unsigned short snum = 0 /* Stoopid compiler.. this IS ok */;
- int chk_addr_ret;
-
- /* check this error. */
- if (sk->state != TCP_CLOSE)
- return(-EIO);
- if(addr_len<sizeof(struct sockaddr_in))
- return -EINVAL;
-
- if(sock->type != SOCK_RAW)
- {
- if (sk->num != 0)
- return(-EINVAL);
-
- snum = ntohs(addr->sin_port);
-
- /*
- * We can't just leave the socket bound wherever it is, it might
- * be bound to a privileged port. However, since there seems to
- * be a bug here, we will leave it if the port is not privileged.
- */
- if (snum == 0)
- {
- snum = get_new_socknum(sk->prot, 0);
- }
- if (snum < PROT_SOCK && !suser())
- return(-EACCES);
- }
-
- chk_addr_ret = ip_chk_addr(addr->sin_addr.s_addr);
- if (addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR && chk_addr_ret != IS_MULTICAST)
- return(-EADDRNOTAVAIL); /* Source address MUST be ours! */
-
- if (chk_addr_ret || addr->sin_addr.s_addr == 0)
- sk->saddr = addr->sin_addr.s_addr;
-
- if(sock->type != SOCK_RAW)
- {
- /* Make sure we are allowed to bind here. */
- cli();
- for(sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)];
- sk2 != NULL; sk2 = sk2->next)
- {
- /* should be below! */
- if (sk2->num != snum)
- continue;
- if (!sk->reuse)
- {
- sti();
- return(-EADDRINUSE);
- }
-
- if (sk2->num != snum)
- continue; /* more than one */
- if (sk2->saddr != sk->saddr)
- continue; /* socket per slot ! -FB */
- if (!sk2->reuse || sk2->state==TCP_LISTEN)
- {
- sti();
- return(-EADDRINUSE);
- }
- }
- sti();
-
- remove_sock(sk);
- put_sock(snum, sk);
- sk->dummy_th.source = ntohs(sk->num);
- sk->daddr = 0;
- sk->dummy_th.dest = 0;
- }
- return(0);
-}
-
-/*
- * Handle sk->err properly. The cli/sti matter.
- */
-
-static int inet_error(struct sock *sk)
-{
- unsigned long flags;
- int err;
- save_flags(flags);
- cli();
- err=sk->err;
- sk->err=0;
- restore_flags(flags);
- return -err;
-}
-
-/*
- * Connect to a remote host. There is regrettably still a little
- * TCP 'magic' in here.
- */
-
-static int inet_connect(struct socket *sock, struct sockaddr * uaddr,
- int addr_len, int flags)
-{
- struct sock *sk=(struct sock *)sock->data;
- int err;
- sock->conn = NULL;
-
- if (sock->state == SS_CONNECTING && tcp_connected(sk->state))
- {
- sock->state = SS_CONNECTED;
- /* Connection completing after a connect/EINPROGRESS/select/connect */
- return 0; /* Rock and roll */
- }
-
- if (sock->state == SS_CONNECTING && sk->protocol == IPPROTO_TCP && (flags & O_NONBLOCK))
- return -EALREADY; /* Connecting is currently in progress */
-
- if (sock->state != SS_CONNECTING)
- {
- /* We may need to bind the socket. */
- if(inet_autobind(sk)!=0)
- return(-EAGAIN);
- if (sk->prot->connect == NULL)
- return(-EOPNOTSUPP);
- err = sk->prot->connect(sk, (struct sockaddr_in *)uaddr, addr_len);
- if (err < 0)
- return(err);
- sock->state = SS_CONNECTING;
- }
-
- if (sk->state > TCP_FIN_WAIT2 && sock->state==SS_CONNECTING)
- {
- sock->state=SS_UNCONNECTED;
- cli();
- err=sk->err;
- sk->err=0;
- sti();
- return -err;
- }
-
- if (sk->state != TCP_ESTABLISHED &&(flags & O_NONBLOCK))
- return(-EINPROGRESS);
-
- cli(); /* avoid the race condition */
- while(sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
- {
- interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked)
- {
- sti();
- return(-ERESTARTSYS);
- }
- /* This fixes a nasty in the tcp/ip code. There is a hideous hassle with
- icmp error packets wanting to close a tcp or udp socket. */
- if(sk->err && sk->protocol == IPPROTO_TCP)
- {
- sti();
- sock->state = SS_UNCONNECTED;
- err = -sk->err;
- sk->err=0;
- return err; /* set by tcp_err() */
- }
- }
- sti();
- sock->state = SS_CONNECTED;
-
- if (sk->state != TCP_ESTABLISHED && sk->err)
- {
- sock->state = SS_UNCONNECTED;
- err=sk->err;
- sk->err=0;
- return(-err);
- }
- return(0);
-}
-
-
-static int inet_socketpair(struct socket *sock1, struct socket *sock2)
-{
- return(-EOPNOTSUPP);
-}
-
-
-/*
- * Accept a pending connection. The TCP layer now gives BSD semantics.
- */
-
-static int inet_accept(struct socket *sock, struct socket *newsock, int flags)
-{
- struct sock *sk1, *sk2;
- int err;
-
- sk1 = (struct sock *) sock->data;
-
- /*
- * We've been passed an extra socket.
- * We need to free it up because the tcp module creates
- * its own when it accepts one.
- */
- if (newsock->data)
- {
- struct sock *sk=(struct sock *)newsock->data;
- newsock->data=NULL;
- sk->dead = 1;
- destroy_sock(sk);
- }
-
- if (sk1->prot->accept == NULL)
- return(-EOPNOTSUPP);
-
- /* Restore the state if we have been interrupted, and then returned. */
- if (sk1->pair != NULL )
- {
- sk2 = sk1->pair;
- sk1->pair = NULL;
- }
- else
- {
- sk2 = sk1->prot->accept(sk1,flags);
- if (sk2 == NULL)
- {
- if (sk1->err <= 0)
- printk("Warning sock.c:sk1->err <= 0. Returning non-error.\n");
- err=sk1->err;
- sk1->err=0;
- return(-err);
- }
- }
- newsock->data = (void *)sk2;
- sk2->sleep = newsock->wait;
- sk2->socket = newsock;
- newsock->conn = NULL;
- if (flags & O_NONBLOCK)
- return(0);
-
- cli(); /* avoid the race. */
- while(sk2->state == TCP_SYN_RECV)
- {
- interruptible_sleep_on(sk2->sleep);
- if (current->signal & ~current->blocked)
- {
- sti();
- sk1->pair = sk2;
- sk2->sleep = NULL;
- sk2->socket=NULL;
- newsock->data = NULL;
- return(-ERESTARTSYS);
- }
- }
- sti();
-
- if (sk2->state != TCP_ESTABLISHED && sk2->err > 0)
- {
- err = -sk2->err;
- sk2->err=0;
- sk2->dead=1; /* ANK */
- destroy_sock(sk2);
- newsock->data = NULL;
- return(err);
- }
- newsock->state = SS_CONNECTED;
- return(0);
-}
-
-
-/*
- * This does both peername and sockname.
- */
-
-static int inet_getname(struct socket *sock, struct sockaddr *uaddr,
- int *uaddr_len, int peer)
-{
- struct sockaddr_in *sin=(struct sockaddr_in *)uaddr;
- struct sock *sk;
-
- sin->sin_family = AF_INET;
- sk = (struct sock *) sock->data;
- if (peer)
- {
- if (!tcp_connected(sk->state))
- return(-ENOTCONN);
- sin->sin_port = sk->dummy_th.dest;
- sin->sin_addr.s_addr = sk->daddr;
- }
- else
- {
- sin->sin_port = sk->dummy_th.source;
- if (sk->saddr == 0)
- sin->sin_addr.s_addr = ip_my_addr();
- else
- sin->sin_addr.s_addr = sk->saddr;
- }
- *uaddr_len = sizeof(*sin);
- return(0);
-}
-
-
-/*
- * The assorted BSD I/O operations
- */
-
-static int inet_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
- unsigned flags, struct sockaddr *sin, int *addr_len )
-{
- struct sock *sk = (struct sock *) sock->data;
-
- if (sk->prot->recvfrom == NULL)
- return(-EOPNOTSUPP);
- if(sk->err)
- return inet_error(sk);
- /* We may need to bind the socket. */
- if(inet_autobind(sk)!=0)
- return(-EAGAIN);
- return(sk->prot->recvfrom(sk, (unsigned char *) ubuf, size, noblock, flags,
- (struct sockaddr_in*)sin, addr_len));
-}
-
-
-static int inet_recv(struct socket *sock, void *ubuf, int size, int noblock,
- unsigned flags)
-{
- /* BSD explicitly states these are the same - so we do it this way to be sure */
- return inet_recvfrom(sock,ubuf,size,noblock,flags,NULL,NULL);
-}
-
-static int inet_read(struct socket *sock, char *ubuf, int size, int noblock)
-{
- struct sock *sk = (struct sock *) sock->data;
-
- if(sk->err)
- return inet_error(sk);
- /* We may need to bind the socket. */
- if(inet_autobind(sk))
- return(-EAGAIN);
- return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock, 0));
-}
-
-static int inet_send(struct socket *sock, void *ubuf, int size, int noblock,
- unsigned flags)
-{
- struct sock *sk = (struct sock *) sock->data;
- if (sk->shutdown & SEND_SHUTDOWN)
- {
- send_sig(SIGPIPE, current, 1);
- return(-EPIPE);
- }
- if(sk->err)
- return inet_error(sk);
- /* We may need to bind the socket. */
- if(inet_autobind(sk)!=0)
- return(-EAGAIN);
- return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, flags));
-}
-
-static int inet_write(struct socket *sock, char *ubuf, int size, int noblock)
-{
- return inet_send(sock,ubuf,size,noblock,0);
-}
-
-static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock,
- unsigned flags, struct sockaddr *sin, int addr_len)
-{
- struct sock *sk = (struct sock *) sock->data;
- if (sk->shutdown & SEND_SHUTDOWN)
- {
- send_sig(SIGPIPE, current, 1);
- return(-EPIPE);
- }
- if (sk->prot->sendto == NULL)
- return(-EOPNOTSUPP);
- if(sk->err)
- return inet_error(sk);
- /* We may need to bind the socket. */
- if(inet_autobind(sk)!=0)
- return -EAGAIN;
- return(sk->prot->sendto(sk, (unsigned char *) ubuf, size, noblock, flags,
- (struct sockaddr_in *)sin, addr_len));
-}
-
-
-static int inet_shutdown(struct socket *sock, int how)
-{
- struct sock *sk=(struct sock*)sock->data;
-
- /*
- * This should really check to make sure
- * the socket is a TCP socket. (WHY AC...)
- */
- how++; /* maps 0->1 has the advantage of making bit 1 rcvs and
- 1->2 bit 2 snds.
- 2->3 */
- if ((how & ~SHUTDOWN_MASK) || how==0) /* MAXINT->0 */
- return(-EINVAL);
- if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)
- sock->state = SS_CONNECTED;
- if (!tcp_connected(sk->state))
- return(-ENOTCONN);
- sk->shutdown |= how;
- if (sk->prot->shutdown)
- sk->prot->shutdown(sk, how);
- return(0);
-}
-
-
-static int inet_select(struct socket *sock, int sel_type, select_table *wait )
-{
- struct sock *sk=(struct sock *) sock->data;
- if (sk->prot->select == NULL)
- {
- return(0);
- }
- return(sk->prot->select(sk, sel_type, wait));
-}
-
-#ifndef _HURD_
-
-/*
- * ioctl() calls you can issue on an INET socket. Most of these are
- * device configuration and stuff and very rarely used. Some ioctls
- * pass on to the socket itself.
- *
- * NOTE: I like the idea of a module for the config stuff. ie ifconfig
- * loads the devconfigure module does its configuring and unloads it.
- * There's a good 20K of config code hanging around the kernel.
- */
-
-static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- struct sock *sk=(struct sock *)sock->data;
- int err;
-
- switch(cmd)
- {
- case FIOSETOWN:
- case SIOCSPGRP:
- err=verify_area(VERIFY_READ,(int *)arg,sizeof(long));
- if(err)
- return err;
- sk->proc = get_fs_long((int *) arg);
- return(0);
- case FIOGETOWN:
- case SIOCGPGRP:
- err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(long));
- if(err)
- return err;
- put_fs_long(sk->proc,(int *)arg);
- return(0);
- case SIOCGSTAMP:
- if(sk->stamp.tv_sec==0)
- return -ENOENT;
- err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
- if(err)
- return err;
- memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval));
- return 0;
- case SIOCADDRT: case SIOCADDRTOLD:
- case SIOCDELRT: case SIOCDELRTOLD:
- return(ip_rt_ioctl(cmd,(void *) arg));
- case SIOCDARP:
- case SIOCGARP:
- case SIOCSARP:
- return(arp_ioctl(cmd,(void *) arg));
-#ifdef CONFIG_INET_RARP
- case SIOCDRARP:
- case SIOCGRARP:
- case SIOCSRARP:
- return(rarp_ioctl(cmd,(void *) arg));
-#endif
- case SIOCGIFCONF:
- case SIOCGIFFLAGS:
- case SIOCSIFFLAGS:
- case SIOCGIFADDR:
- case SIOCSIFADDR:
-
-/* begin multicast support change */
- case SIOCADDMULTI:
- case SIOCDELMULTI:
-/* end multicast support change */
-
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCGIFBRDADDR:
- case SIOCSIFBRDADDR:
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- case SIOCGIFMETRIC:
- case SIOCSIFMETRIC:
- case SIOCGIFMEM:
- case SIOCSIFMEM:
- case SIOCGIFMTU:
- case SIOCSIFMTU:
- case SIOCSIFLINK:
- case SIOCGIFHWADDR:
- case SIOCSIFHWADDR:
- case OLD_SIOCGIFHWADDR:
- case SIOCSIFMAP:
- case SIOCGIFMAP:
- case SIOCSIFSLAVE:
- case SIOCGIFSLAVE:
- return(dev_ioctl(cmd,(void *) arg));
-
- default:
- if ((cmd >= SIOCDEVPRIVATE) &&
- (cmd <= (SIOCDEVPRIVATE + 15)))
- return(dev_ioctl(cmd,(void *) arg));
-
- if (sk->prot->ioctl==NULL)
- return(-EINVAL);
- return(sk->prot->ioctl(sk, cmd, arg));
- }
- /*NOTREACHED*/
- return(0);
-
-}
-#else /* _HURD_ */
-static int inet_ioctl (struct socket *sock,
- unsigned int cm,
- unsigned long arg)
-{
- return EOPNOTSUPP;
-}
-#endif
-
-
-/*
- * This routine must find a socket given a TCP or UDP header.
- * Everything is assumed to be in net order.
- *
- * We give priority to more closely bound ports: if some socket
- * is bound to a particular foreign address, it will get the packet
- * rather than somebody listening to any address..
- */
-
-struct sock *get_sock(struct proto *prot, unsigned short num,
- unsigned long raddr,
- unsigned short rnum, unsigned long laddr)
-{
- struct sock *s;
- struct sock *result = NULL;
- int badness = -1;
- unsigned short hnum;
-
- hnum = ntohs(num);
-
- /*
- * SOCK_ARRAY_SIZE must be a power of two. This will work better
- * than a prime unless 3 or more sockets end up using the same
- * array entry. This should not be a problem because most
- * well known sockets don't overlap that much, and for
- * the other ones, we can just be careful about picking our
- * socket number when we choose an arbitrary one.
- */
-
- for(s = prot->sock_array[hnum & (SOCK_ARRAY_SIZE - 1)];
- s != NULL; s = s->next)
- {
- int score = 0;
-
- if (s->num != hnum)
- continue;
-
- if(s->dead && (s->state == TCP_CLOSE))
- continue;
- /* local address matches? */
- if (s->saddr) {
- if (s->saddr != laddr)
- continue;
- score++;
- }
- /* remote address matches? */
- if (s->daddr) {
- if (s->daddr != raddr)
- continue;
- score++;
- }
- /* remote port matches? */
- if (s->dummy_th.dest) {
- if (s->dummy_th.dest != rnum)
- continue;
- score++;
- }
- /* perfect match? */
- if (score == 3)
- return s;
- /* no, check if this is the best so far.. */
- if (score <= badness)
- continue;
- result = s;
- badness = score;
- }
- return result;
-}
-
-/*
- * Deliver a datagram to raw sockets.
- */
-
-struct sock *get_sock_raw(struct sock *sk,
- unsigned short num,
- unsigned long raddr,
- unsigned long laddr)
-{
- struct sock *s;
-
- s=sk;
-
- for(; s != NULL; s = s->next)
- {
- if (s->num != num)
- continue;
- if(s->dead && (s->state == TCP_CLOSE))
- continue;
- if(s->daddr && s->daddr!=raddr)
- continue;
- if(s->saddr && s->saddr!=laddr)
- continue;
- return(s);
- }
- return(NULL);
-}
-
-#ifdef CONFIG_IP_MULTICAST
-/*
- * Deliver a datagram to broadcast/multicast sockets.
- */
-
-struct sock *get_sock_mcast(struct sock *sk,
- unsigned short num,
- unsigned long raddr,
- unsigned short rnum, unsigned long laddr)
-{
- struct sock *s;
- unsigned short hnum;
-
- hnum = ntohs(num);
-
- /*
- * SOCK_ARRAY_SIZE must be a power of two. This will work better
- * than a prime unless 3 or more sockets end up using the same
- * array entry. This should not be a problem because most
- * well known sockets don't overlap that much, and for
- * the other ones, we can just be careful about picking our
- * socket number when we choose an arbitrary one.
- */
-
- s=sk;
-
- for(; s != NULL; s = s->next)
- {
- if (s->num != hnum)
- continue;
- if(s->dead && (s->state == TCP_CLOSE))
- continue;
- if(s->daddr && s->daddr!=raddr)
- continue;
- if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0)
- continue;
- if(s->saddr && s->saddr!=laddr)
- continue;
- return(s);
- }
- return(NULL);
-}
-
-#endif
-
-static struct proto_ops inet_proto_ops = {
- AF_INET,
-
- inet_create,
- inet_dup,
- inet_release,
- inet_bind,
- inet_connect,
- inet_socketpair,
- inet_accept,
- inet_getname,
- inet_read,
- inet_write,
- inet_select,
- inet_ioctl,
- inet_listen,
- inet_send,
- inet_recv,
- inet_sendto,
- inet_recvfrom,
- inet_shutdown,
- inet_setsockopt,
- inet_getsockopt,
- inet_fcntl,
-};
-
-extern unsigned long seq_offset;
-
-/*
- * Called by socket.c on kernel startup.
- */
-
-void inet_proto_init(struct net_proto *pro)
-{
- struct inet_protocol *p;
- int i;
-
-
- printk("Swansea University Computer Society TCP/IP for NET3.019\n");
-
- /*
- * Tell SOCKET that we are alive...
- */
-
- (void) sock_register(inet_proto_ops.family, &inet_proto_ops);
-
- seq_offset = CURRENT_TIME*250;
-
- /*
- * Add all the protocols.
- */
-
- for(i = 0; i < SOCK_ARRAY_SIZE; i++)
- {
- tcp_prot.sock_array[i] = NULL;
- udp_prot.sock_array[i] = NULL;
- raw_prot.sock_array[i] = NULL;
- }
- tcp_prot.inuse = 0;
- tcp_prot.highestinuse = 0;
- udp_prot.inuse = 0;
- udp_prot.highestinuse = 0;
- raw_prot.inuse = 0;
- raw_prot.highestinuse = 0;
-
- printk("IP Protocols: ");
- for(p = inet_protocol_base; p != NULL;)
- {
- struct inet_protocol *tmp = (struct inet_protocol *) p->next;
- inet_add_protocol(p);
- printk("%s%s",p->name,tmp?", ":"\n");
- p = tmp;
- }
- /*
- * Set the ARP module up
- */
- arp_init();
- /*
- * Set the IP module up
- */
- ip_init();
-}
-
diff --git a/pfinet/linux-inet/arp.c b/pfinet/linux-inet/arp.c
deleted file mode 100644
index 5e00caf7..00000000
--- a/pfinet/linux-inet/arp.c
+++ /dev/null
@@ -1,1295 +0,0 @@
-/* linux/net/inet/arp.c
- *
- * Copyright (C) 1994 by Florian La Roche
- *
- * This module implements the Address Resolution Protocol ARP (RFC 826),
- * which is used to convert IP addresses (or in the future maybe other
- * high-level addresses into a low-level hardware address (like an Ethernet
- * address).
- *
- * FIXME:
- * Experiment with better retransmit timers
- * Clean up the timer deletions
- * If you create a proxy entry set your interface address to the address
- * and then delete it, proxies may get out of sync with reality - check this
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- *
- *
- * Fixes:
- * Alan Cox : Removed the ethernet assumptions in Florian's code
- * 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
- *
- * Ross Martin : Rewrote arp_rcv() and arp_get_info()
- * Stephen Henson : Add AX25 support to arp_get_info()
- * Alan Cox : Drop data when a device is downed.
- * Alan Cox : Use init_timer().
- * Alan Cox : Double lock fixes.
- * Martin Seine : Move the arphdr structure
- * to if_arp.h for compatibility.
- * with BSD based programs.
- * Andrew Tridgell : Added ARP netmask code and
- * re-arranged proxy handling.
- * Alan Cox : Changed to use notifiers.
- * Niibe Yutaka : Reply for this device or proxies only.
- * Alan Cox : Don't proxy across hardware types!
- */
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/config.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/in.h>
-#include <linux/mm.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <stdarg.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include "ip.h"
-#include "route.h"
-#include "protocol.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "arp.h"
-#ifdef CONFIG_AX25
-#include "ax25.h"
-#endif
-
-
-/*
- * This structure defines the ARP mapping cache. As long as we make changes
- * in this structure, we keep interrupts of. But normally we can copy the
- * hardware address and the device pointer in a local variable and then make
- * any "long calls" to send a packet out.
- */
-
-struct arp_table
-{
- struct arp_table *next; /* Linked entry list */
- unsigned long last_used; /* For expiry */
- unsigned int flags; /* Control status */
- unsigned long ip; /* ip address of entry */
- unsigned long mask; /* netmask - used for generalised proxy arps (tridge) */
- unsigned char ha[MAX_ADDR_LEN]; /* Hardware address */
- unsigned char hlen; /* Length of hardware address */
- unsigned short htype; /* Type of hardware in use */
- struct device *dev; /* Device the entry is tied to */
-
- /*
- * The following entries are only used for unresolved hw addresses.
- */
-
- struct timer_list timer; /* expire timer */
- int retries; /* remaining retries */
- struct sk_buff_head skb; /* list of queued packets */
-};
-
-
-/*
- * Configurable Parameters (don't touch unless you know what you are doing
- */
-
-/*
- * If an arp request is send, ARP_RES_TIME is the timeout value until the
- * next request is send.
- */
-
-#define ARP_RES_TIME (250*(HZ/10))
-
-/*
- * The number of times an arp request is send, until the host is
- * considered unreachable.
- */
-
-#define ARP_MAX_TRIES 3
-
-/*
- * After that time, an unused entry is deleted from the arp table.
- */
-
-#define ARP_TIMEOUT (600*HZ)
-
-/*
- * How often is the function 'arp_check_retries' called.
- * An entry is invalidated in the time between ARP_TIMEOUT and
- * (ARP_TIMEOUT+ARP_CHECK_INTERVAL).
- */
-
-#define ARP_CHECK_INTERVAL (60 * HZ)
-
-enum proxy {
- PROXY_EXACT=0,
- PROXY_ANY,
- PROXY_NONE,
-};
-
-/* Forward declarations. */
-static void arp_check_expire (unsigned long);
-static struct arp_table *arp_lookup(unsigned long paddr, enum proxy proxy);
-
-
-static struct timer_list arp_timer =
- { NULL, NULL, ARP_CHECK_INTERVAL, 0L, &arp_check_expire };
-
-/*
- * The default arp netmask is just 255.255.255.255 which means it's
- * a single machine entry. Only proxy entries can have other netmasks
- *
-*/
-
-#define DEF_ARP_NETMASK (~0)
-
-
-/*
- * The size of the hash table. Must be a power of two.
- * Maybe we should remove hashing in the future for arp and concentrate
- * on Patrick Schaaf's Host-Cache-Lookup...
- */
-
-
-#define ARP_TABLE_SIZE 16
-
-/* The ugly +1 here is to cater for proxy entries. They are put in their
- own list for efficiency of lookup. If you don't want to find a proxy
- entry then don't look in the last entry, otherwise do
-*/
-
-#define FULL_ARP_TABLE_SIZE (ARP_TABLE_SIZE+1)
-
-struct arp_table *arp_tables[FULL_ARP_TABLE_SIZE] =
-{
- NULL,
-};
-
-
-/*
- * The last bits in the IP address are used for the cache lookup.
- * A special entry is used for proxy arp entries
- */
-
-#define HASH(paddr) (htonl(paddr) & (ARP_TABLE_SIZE - 1))
-#define PROXY_HASH ARP_TABLE_SIZE
-
-/*
- * Check if there are too old entries and remove them. If the ATF_PERM
- * flag is set, they are always left in the arp cache (permanent entry).
- * Note: Only fully resolved entries, which don't have any packets in
- * the queue, can be deleted, since ARP_TIMEOUT is much greater than
- * ARP_MAX_TRIES*ARP_RES_TIME.
- */
-
-static void arp_check_expire(unsigned long dummy)
-{
- int i;
- unsigned long now = jiffies;
- unsigned long flags;
- save_flags(flags);
- cli();
-
- for (i = 0; i < FULL_ARP_TABLE_SIZE; i++)
- {
- struct arp_table *entry;
- struct arp_table **pentry = &arp_tables[i];
-
- while ((entry = *pentry) != NULL)
- {
- if ((now - entry->last_used) > ARP_TIMEOUT
- && !(entry->flags & ATF_PERM))
- {
- *pentry = entry->next; /* remove from list */
- del_timer(&entry->timer); /* Paranoia */
- kfree_s(entry, sizeof(struct arp_table));
- }
- else
- pentry = &entry->next; /* go to next entry */
- }
- }
- restore_flags(flags);
-
- /*
- * Set the timer again.
- */
-
- del_timer(&arp_timer);
- arp_timer.expires = ARP_CHECK_INTERVAL;
- add_timer(&arp_timer);
-}
-
-
-/*
- * Release all linked skb's and the memory for this entry.
- */
-
-static void arp_release_entry(struct arp_table *entry)
-{
- struct sk_buff *skb;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- /* Release the list of `skb' pointers. */
- while ((skb = skb_dequeue(&entry->skb)) != NULL)
- {
- skb_device_lock(skb);
- restore_flags(flags);
- dev_kfree_skb(skb, FREE_WRITE);
- }
- restore_flags(flags);
- del_timer(&entry->timer);
- kfree_s(entry, sizeof(struct arp_table));
- return;
-}
-
-/*
- * Purge a device from the ARP queue
- */
-
-int arp_device_event(unsigned long event, void *ptr)
-{
- struct device *dev=ptr;
- int i;
- unsigned long flags;
-
- if(event!=NETDEV_DOWN)
- return NOTIFY_DONE;
- /*
- * This is a bit OTT - maybe we need some arp semaphores instead.
- */
-
- save_flags(flags);
- cli();
- for (i = 0; i < FULL_ARP_TABLE_SIZE; i++)
- {
- struct arp_table *entry;
- struct arp_table **pentry = &arp_tables[i];
-
- while ((entry = *pentry) != NULL)
- {
- if(entry->dev==dev)
- {
- *pentry = entry->next; /* remove from list */
- del_timer(&entry->timer); /* Paranoia */
- kfree_s(entry, sizeof(struct arp_table));
- }
- else
- pentry = &entry->next; /* go to next entry */
- }
- }
- restore_flags(flags);
- return NOTIFY_DONE;
-}
-
-
-/*
- * Create and send an arp packet. If (dest_hw == NULL), we create a broadcast
- * message.
- */
-
-void arp_send(int type, int ptype, unsigned long dest_ip,
- struct device *dev, unsigned long src_ip,
- unsigned char *dest_hw, unsigned char *src_hw)
-{
- struct sk_buff *skb;
- struct arphdr *arp;
- unsigned char *arp_ptr;
-
- /*
- * 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, GFP_ATOMIC);
- if (skb == NULL)
- {
- printk("ARP: no memory to send an arp packet\n");
- return;
- }
- skb->len = sizeof(struct arphdr) + dev->hard_header_len + 2*(dev->addr_len+4);
- skb->arp = 1;
- skb->dev = dev;
- skb->free = 1;
-
- /*
- * Fill the device header for the ARP frame
- */
-
- dev->hard_header(skb->data,dev,ptype,dest_hw?dest_hw:dev->broadcast,src_hw?src_hw:NULL,skb->len,skb);
-
- /* Fill out the arp protocol part. */
- arp = (struct arphdr *) (skb->data + dev->hard_header_len);
- arp->ar_hrd = htons(dev->type);
-#ifdef CONFIG_AX25
- arp->ar_pro = (dev->type != ARPHRD_AX25)? htons(ETH_P_IP) : htons(AX25_P_IP);
-#else
- arp->ar_pro = htons(ETH_P_IP);
-#endif
- arp->ar_hln = dev->addr_len;
- arp->ar_pln = 4;
- arp->ar_op = htons(type);
-
- arp_ptr=(unsigned char *)(arp+1);
-
- memcpy(arp_ptr, src_hw, dev->addr_len);
- arp_ptr+=dev->addr_len;
- memcpy(arp_ptr, &src_ip,4);
- arp_ptr+=4;
- if (dest_hw != NULL)
- memcpy(arp_ptr, dest_hw, dev->addr_len);
- else
- memset(arp_ptr, 0, dev->addr_len);
- arp_ptr+=dev->addr_len;
- memcpy(arp_ptr, &dest_ip, 4);
-
- dev_queue_xmit(skb, dev, 0);
-}
-
-
-/*
- * This function is called, if an entry is not resolved in ARP_RES_TIME.
- * Either resend a request, or give it up and free the entry.
- */
-
-static void arp_expire_request (unsigned long arg)
-{
- struct arp_table *entry = (struct arp_table *) arg;
- struct arp_table **pentry;
- unsigned long hash;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- /*
- * Since all timeouts are handled with interrupts enabled, there is a
- * small chance, that this entry has just been resolved by an incoming
- * packet. This is the only race condition, but it is handled...
- */
-
- if (entry->flags & ATF_COM)
- {
- restore_flags(flags);
- return;
- }
-
- if (--entry->retries > 0)
- {
- unsigned long ip = entry->ip;
- struct device *dev = entry->dev;
-
- /* Set new timer. */
- del_timer(&entry->timer);
- entry->timer.expires = ARP_RES_TIME;
- add_timer(&entry->timer);
- restore_flags(flags);
- arp_send(ARPOP_REQUEST, ETH_P_ARP, ip, dev, dev->pa_addr,
- NULL, dev->dev_addr);
- return;
- }
-
- /*
- * Arp request timed out. Delete entry and all waiting packets.
- * If we give each entry a pointer to itself, we don't have to
- * loop through everything again. Maybe hash is good enough, but
- * I will look at it later.
- */
-
- hash = HASH(entry->ip);
-
- /* proxy entries shouldn't really time out so this is really
- only here for completeness
- */
- if (entry->flags & ATF_PUBL)
- pentry = &arp_tables[PROXY_HASH];
- else
- pentry = &arp_tables[hash];
- while (*pentry != NULL)
- {
- if (*pentry == entry)
- {
- *pentry = entry->next; /* delete from linked list */
- del_timer(&entry->timer);
- restore_flags(flags);
- arp_release_entry(entry);
- return;
- }
- pentry = &(*pentry)->next;
- }
- restore_flags(flags);
- printk("Possible ARP queue corruption.\n");
- /*
- * We should never arrive here.
- */
-}
-
-
-/*
- * This will try to retransmit everything on the queue.
- */
-
-static void arp_send_q(struct arp_table *entry, unsigned char *hw_dest)
-{
- struct sk_buff *skb;
-
- unsigned long flags;
-
- /*
- * Empty the entire queue, building its data up ready to send
- */
-
- if(!(entry->flags&ATF_COM))
- {
- printk("arp_send_q: incomplete entry for %s\n",
- in_ntoa(entry->ip));
- return;
- }
-
- save_flags(flags);
-
- cli();
- while((skb = skb_dequeue(&entry->skb)) != NULL)
- {
- IS_SKB(skb);
- skb_device_lock(skb);
- restore_flags(flags);
- if(!skb->dev->rebuild_header(skb->data,skb->dev,skb->raddr,skb))
- {
- skb->arp = 1;
- if(skb->sk==NULL)
- dev_queue_xmit(skb, skb->dev, 0);
- else
- dev_queue_xmit(skb,skb->dev,skb->sk->priority);
- }
- else
- {
- /* This routine is only ever called when 'entry' is
- complete. Thus this can't fail. */
- printk("arp_send_q: The impossible occurred. Please notify Alan.\n");
- printk("arp_send_q: active entity %s\n",in_ntoa(entry->ip));
- printk("arp_send_q: failed to find %s\n",in_ntoa(skb->raddr));
- }
- }
- restore_flags(flags);
-}
-
-
-/*
- * Delete an ARP mapping entry in the cache.
- */
-
-void arp_destroy(unsigned long ip_addr, int force)
-{
- int checked_proxies = 0;
- struct arp_table *entry;
- struct arp_table **pentry;
- unsigned long hash = HASH(ip_addr);
-
-ugly:
- cli();
- pentry = &arp_tables[hash];
- if (! *pentry) /* also check proxy entries */
- pentry = &arp_tables[PROXY_HASH];
-
- while ((entry = *pentry) != NULL)
- {
- if (entry->ip == ip_addr)
- {
- if ((entry->flags & ATF_PERM) && !force)
- return;
- *pentry = entry->next;
- del_timer(&entry->timer);
- sti();
- arp_release_entry(entry);
- /* this would have to be cleaned up */
- goto ugly;
- /* perhaps like this ?
- cli();
- entry = *pentry;
- */
- }
- pentry = &entry->next;
- if (!checked_proxies && ! *pentry)
- { /* ugly. we have to make sure we check proxy
- entries as well */
- checked_proxies = 1;
- pentry = &arp_tables[PROXY_HASH];
- }
- }
- sti();
-}
-
-
-/*
- * Receive an arp request by the device layer. Maybe I rewrite it, to
- * use the incoming packet for the reply. The time for the current
- * "overhead" isn't that high...
- */
-
-int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
-{
-/*
- * We shouldn't use this type conversion. Check later.
- */
-
- struct arphdr *arp = (struct arphdr *)skb->h.raw;
- unsigned char *arp_ptr= (unsigned char *)(arp+1);
- struct arp_table *entry;
- struct arp_table *proxy_entry;
- int addr_hint,hlen,htype;
- unsigned long hash;
- unsigned char ha[MAX_ADDR_LEN]; /* So we can enable ints again. */
- long sip,tip;
- unsigned char *sha,*tha;
-
-/*
- * The hardware length of the packet should match the hardware length
- * 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.
- */
- if (arp->ar_hln != dev->addr_len ||
- dev->type != ntohs(arp->ar_hrd) ||
- dev->flags & IFF_NOARP ||
- arp->ar_pln != 4)
- {
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
-/*
- * Another test.
- * The logic here is that the protocol being looked up by arp should
- * match the protocol the device speaks. If it doesn't, there is a
- * problem, so toss the packet.
- */
- switch(dev->type)
- {
-#ifdef CONFIG_AX25
- case ARPHRD_AX25:
- if(arp->ar_pro != htons(AX25_P_IP))
- {
- kfree_skb(skb, FREE_READ);
- return 0;
- }
- break;
-#endif
- case ARPHRD_ETHER:
- case ARPHRD_ARCNET:
- if(arp->ar_pro != htons(ETH_P_IP))
- {
- kfree_skb(skb, FREE_READ);
- return 0;
- }
- break;
-
- default:
- printk("ARP: dev->type mangled!\n");
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
-/*
- * Extract fields
- */
-
- hlen = dev->addr_len;
- htype = dev->type;
-
- sha=arp_ptr;
- arp_ptr+=hlen;
- memcpy(&sip,arp_ptr,4);
- arp_ptr+=4;
- tha=arp_ptr;
- arp_ptr+=hlen;
- memcpy(&tip,arp_ptr,4);
-
-/*
- * Check for bad requests for 127.0.0.1. If this is one such, delete it.
- */
- if(tip == INADDR_LOOPBACK)
- {
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
-/*
- * 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
- * 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
- * cache.
- */
-
- addr_hint = ip_chk_addr(tip);
-
- if(arp->ar_op == htons(ARPOP_REPLY))
- {
- if(addr_hint!=IS_MYADDR)
- {
-/*
- * Replies to other machines get tossed.
- */
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-/*
- * Fall through to code below that adds sender to cache.
- */
- }
- else
- {
-/*
- * It is now an arp request
- */
-/*
- * Only reply for the real device address or when it's in our proxy tables
- */
- if(tip!=dev->pa_addr)
- {
-/*
- * To get in here, it is a request for someone else. We need to
- * check if that someone else is one of our proxies. If it isn't,
- * we can toss it.
- */
- cli();
- for(proxy_entry=arp_tables[PROXY_HASH];
- proxy_entry;
- proxy_entry = proxy_entry->next)
- {
- /* we will respond to a proxy arp request
- if the masked arp table ip matches the masked
- tip. This allows a single proxy arp table
- entry to be used on a gateway machine to handle
- all requests for a whole network, rather than
- having to use a huge number of proxy arp entries
- and having to keep them uptodate.
- */
- if (proxy_entry->dev != dev && proxy_entry->htype == htype &&
- !((proxy_entry->ip^tip)&proxy_entry->mask))
- break;
-
- }
- if (proxy_entry)
- {
- memcpy(ha, proxy_entry->ha, hlen);
- sti();
- arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,ha);
- kfree_skb(skb, FREE_READ);
- return 0;
- }
- else
- {
- sti();
- kfree_skb(skb, FREE_READ);
- return 0;
- }
- }
- else
- {
-/*
- * To get here, it must be an arp request for us. We need to reply.
- */
- arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr);
- }
- }
-
-
-/*
- * Now all replies are handled. Next, anything that falls through to here
- * needs to be added to the arp cache, or have its entry updated if it is
- * there.
- */
-
- hash = HASH(sip);
- cli();
- for(entry=arp_tables[hash];entry;entry=entry->next)
- if(entry->ip==sip && entry->htype==htype)
- break;
-
- if(entry)
- {
-/*
- * Entry found; update it.
- */
- memcpy(entry->ha, sha, hlen);
- entry->hlen = hlen;
- entry->last_used = jiffies;
- if (!(entry->flags & ATF_COM))
- {
-/*
- * This entry was incomplete. Delete the retransmit timer
- * and switch to complete status.
- */
- del_timer(&entry->timer);
- entry->flags |= ATF_COM;
- sti();
-/*
- * Send out waiting packets. We might have problems, if someone is
- * manually removing entries right now -- entry might become invalid
- * underneath us.
- */
- arp_send_q(entry, sha);
- }
- else
- {
- sti();
- }
- }
- else
- {
-/*
- * No entry found. Need to add a new entry to the arp table.
- */
- entry = (struct arp_table *)kmalloc(sizeof(struct arp_table),GFP_ATOMIC);
- if(entry == NULL)
- {
- sti();
- printk("ARP: no memory for new arp entry\n");
-
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
- entry->mask = DEF_ARP_NETMASK;
- entry->ip = sip;
- entry->hlen = hlen;
- entry->htype = htype;
- entry->flags = ATF_COM;
- init_timer(&entry->timer);
- memcpy(entry->ha, sha, hlen);
- entry->last_used = jiffies;
- entry->dev = skb->dev;
- skb_queue_head_init(&entry->skb);
- entry->next = arp_tables[hash];
- arp_tables[hash] = entry;
- sti();
- }
-
-/*
- * Replies have been sent, and entries have been added. All done.
- */
- kfree_skb(skb, FREE_READ);
- return 0;
-}
-
-
-/*
- * Find an arp mapping in the cache. If not found, post a request.
- */
-
-int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
- unsigned long saddr, struct sk_buff *skb)
-{
- struct arp_table *entry;
- unsigned long hash;
-#ifdef CONFIG_IP_MULTICAST
- unsigned long taddr;
-#endif
-
- switch (ip_chk_addr(paddr))
- {
- case IS_MYADDR:
- printk("ARP: arp called for own IP address\n");
- memcpy(haddr, dev->dev_addr, dev->addr_len);
- skb->arp = 1;
- return 0;
-#ifdef CONFIG_IP_MULTICAST
- case IS_MULTICAST:
- if(dev->type==ARPHRD_ETHER || dev->type==ARPHRD_IEEE802)
- {
- haddr[0]=0x01;
- haddr[1]=0x00;
- haddr[2]=0x5e;
- taddr=ntohl(paddr);
- haddr[5]=taddr&0xff;
- taddr=taddr>>8;
- haddr[4]=taddr&0xff;
- taddr=taddr>>8;
- haddr[3]=taddr&0x7f;
- return 0;
- }
- /*
- * If a device does not support multicast broadcast the stuff (eg AX.25 for now)
- */
-#endif
-
- case IS_BROADCAST:
- memcpy(haddr, dev->broadcast, dev->addr_len);
- skb->arp = 1;
- return 0;
- }
-
- hash = HASH(paddr);
- cli();
-
- /*
- * Find an entry
- */
- entry = arp_lookup(paddr, PROXY_NONE);
-
- if (entry != NULL) /* It exists */
- {
- if (!(entry->flags & ATF_COM))
- {
- /*
- * A request was already send, but no reply yet. Thus
- * queue the packet with the previous attempt
- */
-
- if (skb != NULL)
- {
- skb_queue_tail(&entry->skb, skb);
- skb_device_unlock(skb);
- }
- sti();
- return 1;
- }
-
- /*
- * Update the record
- */
-
- entry->last_used = jiffies;
- memcpy(haddr, entry->ha, dev->addr_len);
- if (skb)
- skb->arp = 1;
- sti();
- return 0;
- }
-
- /*
- * Create a new unresolved entry.
- */
-
- entry = (struct arp_table *) kmalloc(sizeof(struct arp_table),
- GFP_ATOMIC);
- if (entry != NULL)
- {
- entry->mask = DEF_ARP_NETMASK;
- entry->ip = paddr;
- entry->hlen = dev->addr_len;
- entry->htype = dev->type;
- entry->flags = 0;
- memset(entry->ha, 0, dev->addr_len);
- entry->dev = dev;
- entry->last_used = jiffies;
- init_timer(&entry->timer);
- entry->timer.function = arp_expire_request;
- entry->timer.data = (unsigned long)entry;
- entry->timer.expires = ARP_RES_TIME;
- entry->next = arp_tables[hash];
- arp_tables[hash] = entry;
- add_timer(&entry->timer);
- entry->retries = ARP_MAX_TRIES;
- skb_queue_head_init(&entry->skb);
- if (skb != NULL)
- {
- skb_queue_tail(&entry->skb, skb);
- skb_device_unlock(skb);
- }
- }
- else
- {
- if (skb != NULL && skb->free)
- kfree_skb(skb, FREE_WRITE);
- }
- sti();
-
- /*
- * If we didn't find an entry, we will try to send an ARP packet.
- */
-
- arp_send(ARPOP_REQUEST, ETH_P_ARP, paddr, dev, saddr, NULL,
- dev->dev_addr);
-
- return 1;
-}
-
-
-/*
- * Write the contents of the ARP cache to a PROCfs file.
- */
-
-#define HBUFFERLEN 30
-
-int arp_get_info(char *buffer, char **start, off_t offset, int length)
-{
- int len=0;
- off_t begin=0;
- off_t pos=0;
- int size;
- struct arp_table *entry;
- char hbuffer[HBUFFERLEN];
- int i,j,k;
- const char hexbuf[] = "0123456789ABCDEF";
-
- size = sprintf(buffer,"IP address HW type Flags HW address Mask\n");
-
- pos+=size;
- len+=size;
-
- cli();
- for(i=0; i<FULL_ARP_TABLE_SIZE; i++)
- {
- for(entry=arp_tables[i]; entry!=NULL; entry=entry->next)
- {
-/*
- * Convert hardware address to XX:XX:XX:XX ... form.
- */
-#ifdef CONFIG_AX25
-
- if(entry->htype==ARPHRD_AX25)
- strcpy(hbuffer,ax2asc((ax25_address *)entry->ha));
- else {
-#endif
-
- for(k=0,j=0;k<HBUFFERLEN-3 && j<entry->hlen;j++)
- {
- hbuffer[k++]=hexbuf[ (entry->ha[j]>>4)&15 ];
- hbuffer[k++]=hexbuf[ entry->ha[j]&15 ];
- hbuffer[k++]=':';
- }
- hbuffer[--k]=0;
-
-#ifdef CONFIG_AX25
- }
-#endif
- size = sprintf(buffer+len,
- "%-17s0x%-10x0x%-10x%s",
- in_ntoa(entry->ip),
- (unsigned int)entry->htype,
- entry->flags,
- hbuffer);
- size += sprintf(buffer+len+size,
- " %-17s\n",
- entry->mask==DEF_ARP_NETMASK?
- "*":in_ntoa(entry->mask));
-
- len+=size;
- pos=begin+len;
-
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- }
- }
- sti();
-
- *start=buffer+(offset-begin); /* Start of wanted data */
- len-=(offset-begin); /* Start slop */
- if(len>length)
- len=length; /* Ending slop */
- return len;
-}
-
-
-/*
- * This will find an entry in the ARP table by looking at the IP address.
- * If proxy is PROXY_EXACT then only exact IP matches will be allowed
- * for proxy entries, otherwise the netmask will be used
- */
-
-static struct arp_table *arp_lookup(unsigned long paddr, enum proxy proxy)
-{
- struct arp_table *entry;
- unsigned long hash = HASH(paddr);
-
- for (entry = arp_tables[hash]; entry != NULL; entry = entry->next)
- if (entry->ip == paddr) break;
-
- /* it's possibly a proxy entry (with a netmask) */
- if (!entry && proxy != PROXY_NONE)
- for (entry=arp_tables[PROXY_HASH]; entry != NULL; entry = entry->next)
- if ((proxy==PROXY_EXACT) ? (entry->ip==paddr)
- : !((entry->ip^paddr)&entry->mask))
- break;
-
- return entry;
-}
-
-
-/*
- * Set (create) an ARP cache entry.
- */
-
-static int arp_req_set(struct arpreq *req)
-{
- struct arpreq r;
- struct arp_table *entry;
- struct sockaddr_in *si;
- int htype, hlen;
- unsigned long ip;
- struct rtable *rt;
-
- memcpy_fromfs(&r, req, sizeof(r));
-
- /* We only understand about IP addresses... */
- if (r.arp_pa.sa_family != AF_INET)
- return -EPFNOSUPPORT;
-
- /*
- * Find out about the hardware type.
- * We have to be compatible with BSD UNIX, so we have to
- * assume that a "not set" value (i.e. 0) means Ethernet.
- */
-
- switch (r.arp_ha.sa_family) {
- case ARPHRD_ETHER:
- htype = ARPHRD_ETHER;
- hlen = ETH_ALEN;
- break;
-
- case ARPHRD_ARCNET:
- htype = ARPHRD_ARCNET;
- hlen = 1; /* length of arcnet addresses */
- break;
-
-#ifdef CONFIG_AX25
- case ARPHRD_AX25:
- htype = ARPHRD_AX25;
- hlen = 7;
- break;
-#endif
- default:
- return -EPFNOSUPPORT;
- }
-
- si = (struct sockaddr_in *) &r.arp_pa;
- ip = si->sin_addr.s_addr;
- if (ip == 0)
- {
- printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
- return -EINVAL;
- }
-
- /*
- * Is it reachable directly ?
- */
-
- rt = ip_rt_route(ip, NULL, NULL);
- if (rt == NULL)
- return -ENETUNREACH;
-
- /*
- * Is there an existing entry for this address?
- */
-
- cli();
-
- /*
- * Find the entry
- */
- entry = arp_lookup(ip, PROXY_EXACT);
- if (entry && (entry->flags & ATF_PUBL) != (r.arp_flags & ATF_PUBL))
- {
- sti();
- arp_destroy(ip,1);
- cli();
- entry = NULL;
- }
-
- /*
- * Do we need to create a new entry
- */
-
- if (entry == NULL)
- {
- unsigned long hash = HASH(ip);
- if (r.arp_flags & ATF_PUBL)
- hash = PROXY_HASH;
-
- entry = (struct arp_table *) kmalloc(sizeof(struct arp_table),
- GFP_ATOMIC);
- if (entry == NULL)
- {
- sti();
- return -ENOMEM;
- }
- entry->ip = ip;
- entry->hlen = hlen;
- entry->htype = htype;
- init_timer(&entry->timer);
- entry->next = arp_tables[hash];
- arp_tables[hash] = entry;
- skb_queue_head_init(&entry->skb);
- }
- /*
- * We now have a pointer to an ARP entry. Update it!
- */
-
- memcpy(&entry->ha, &r.arp_ha.sa_data, hlen);
- entry->last_used = jiffies;
- entry->flags = r.arp_flags | ATF_COM;
- if ((entry->flags & ATF_PUBL) && (entry->flags & ATF_NETMASK))
- {
- si = (struct sockaddr_in *) &r.arp_netmask;
- entry->mask = si->sin_addr.s_addr;
- }
- else
- entry->mask = DEF_ARP_NETMASK;
- entry->dev = rt->rt_dev;
- sti();
-
- return 0;
-}
-
-
-/*
- * Get an ARP cache entry.
- */
-
-static int arp_req_get(struct arpreq *req)
-{
- struct arpreq r;
- struct arp_table *entry;
- struct sockaddr_in *si;
-
- /*
- * We only understand about IP addresses...
- */
-
- memcpy_fromfs(&r, req, sizeof(r));
-
- if (r.arp_pa.sa_family != AF_INET)
- return -EPFNOSUPPORT;
-
- /*
- * Is there an existing entry for this address?
- */
-
- si = (struct sockaddr_in *) &r.arp_pa;
- cli();
- entry = arp_lookup(si->sin_addr.s_addr,PROXY_ANY);
-
- if (entry == NULL)
- {
- sti();
- return -ENXIO;
- }
-
- /*
- * We found it; copy into structure.
- */
-
- memcpy(r.arp_ha.sa_data, &entry->ha, entry->hlen);
- r.arp_ha.sa_family = entry->htype;
- r.arp_flags = entry->flags;
- sti();
-
- /*
- * Copy the information back
- */
-
- memcpy_tofs(req, &r, sizeof(r));
- return 0;
-}
-
-
-#ifndef _HURD_
-/*
- * Handle an ARP layer I/O control request.
- */
-
-int arp_ioctl(unsigned int cmd, void *arg)
-{
- struct arpreq r;
- struct sockaddr_in *si;
- int err;
-
- switch(cmd)
- {
- case SIOCDARP:
- if (!suser())
- return -EPERM;
- err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
- if(err)
- return err;
- memcpy_fromfs(&r, arg, sizeof(r));
- if (r.arp_pa.sa_family != AF_INET)
- return -EPFNOSUPPORT;
- si = (struct sockaddr_in *) &r.arp_pa;
- arp_destroy(si->sin_addr.s_addr, 1);
- return 0;
- case SIOCGARP:
- err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
- if(err)
- return err;
- return arp_req_get((struct arpreq *)arg);
- case SIOCSARP:
- if (!suser())
- return -EPERM;
- err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
- if(err)
- return err;
- return arp_req_set((struct arpreq *)arg);
- default:
- return -EINVAL;
- }
- /*NOTREACHED*/
- return 0;
-}
-#endif
-
-/*
- * Called once on startup.
- */
-
-static struct packet_type arp_packet_type =
-{
- 0, /* Should be: __constant_htons(ETH_P_ARP) - but this _doesn't_ come out constant! */
- NULL, /* All devices */
- arp_rcv,
- NULL,
- NULL
-};
-
-static struct notifier_block arp_dev_notifier={
- arp_device_event,
- NULL,
- 0
-};
-
-void arp_init (void)
-{
- /* Register the packet type */
- arp_packet_type.type=htons(ETH_P_ARP);
- dev_add_pack(&arp_packet_type);
- /* Start with the regular checks for expired arp entries. */
- add_timer(&arp_timer);
- /* Register for device down reports */
- register_netdevice_notifier(&arp_dev_notifier);
-}
-
diff --git a/pfinet/linux-inet/arp.h b/pfinet/linux-inet/arp.h
deleted file mode 100644
index a68adc30..00000000
--- a/pfinet/linux-inet/arp.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/net/inet/arp.h */
-#ifndef _ARP_H
-#define _ARP_H
-
-extern void arp_init(void);
-extern void arp_destroy(unsigned long paddr, int force);
-extern void arp_device_down(struct device *dev);
-extern int arp_rcv(struct sk_buff *skb, struct device *dev,
- struct packet_type *pt);
-extern int arp_find(unsigned char *haddr, unsigned long paddr,
- struct device *dev, unsigned long saddr, struct sk_buff *skb);
-extern int arp_get_info(char *buffer, char **start, off_t origin, int length);
-extern int arp_ioctl(unsigned int cmd, void *arg);
-extern void arp_send(int type, int ptype, unsigned long dest_ip,
- struct device *dev, unsigned long src_ip,
- unsigned char *dest_hw, unsigned char *src_hw);
-
-#endif /* _ARP_H */
diff --git a/pfinet/linux-inet/datagram.c b/pfinet/linux-inet/datagram.c
deleted file mode 100644
index cd248cfb..00000000
--- a/pfinet/linux-inet/datagram.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * SUCS NET3:
- *
- * Generic datagram handling routines. These are generic for all protocols. Possibly a generic IP version on top
- * of these would make sense. Not tonight however 8-).
- * This is used because UDP, RAW, PACKET and the to be released IPX layer all have identical select code and mostly
- * identical recvfrom() code. So we share it here. The select was shared before but buried in udp.c so I moved it.
- *
- * Authors: Alan Cox <iiitac@pyr.swan.ac.uk>. (datagram_select() from old udp.c code)
- *
- * Fixes:
- * Alan Cox : NULL return from skb_peek_copy() understood
- * Alan Cox : Rewrote skb_read_datagram to avoid the skb_peek_copy stuff.
- * Alan Cox : Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but
- * AX.25 now works right, and SPX is feasible.
- * Alan Cox : Fixed write select of non IP protocol crash.
- * Florian La Roche: Changed for my new skbuff handling.
- *
- * Note:
- * A lot of this will change when the protocol/socket separation
- * occurs. Using this will make things reasonably clean.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-
-
-/*
- * Get a datagram skbuff, understands the peeking, nonblocking wakeups and possible
- * races. This replaces identical code in packet,raw and udp, as well as the yet to
- * be released IPX support. It also finally fixes the long standing peek and read
- * race for datagram sockets. If you alter this routine remember it must be
- * re-entrant.
- */
-
-struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
-{
- struct sk_buff *skb;
- unsigned long intflags;
-
- /* Socket is inuse - so the timer doesn't attack it */
- save_flags(intflags);
-restart:
- sk->inuse = 1;
- while(skb_peek(&sk->receive_queue) == NULL) /* No data */
- {
- /* If we are shutdown then no more data is going to appear. We are done */
- if (sk->shutdown & RCV_SHUTDOWN)
- {
- release_sock(sk);
- *err=0;
- return NULL;
- }
-
- if(sk->err)
- {
- release_sock(sk);
- *err=-sk->err;
- sk->err=0;
- return NULL;
- }
-
- /* Sequenced packets can come disconnected. If so we report the problem */
- if(sk->type==SOCK_SEQPACKET && sk->state!=TCP_ESTABLISHED)
- {
- release_sock(sk);
- *err=-ENOTCONN;
- return NULL;
- }
-
- /* User doesn't want to wait */
- if (noblock)
- {
- release_sock(sk);
- *err=-EAGAIN;
- return NULL;
- }
- release_sock(sk);
-
- /* Interrupts off so that no packet arrives before we begin sleeping.
- Otherwise we might miss our wake up */
- cli();
- if (skb_peek(&sk->receive_queue) == NULL)
- {
- interruptible_sleep_on(sk->sleep);
- /* Signals may need a restart of the syscall */
- if (current->signal & ~current->blocked)
- {
- restore_flags(intflags);;
- *err=-ERESTARTSYS;
- return(NULL);
- }
- if(sk->err != 0) /* Error while waiting for packet
- eg an icmp sent earlier by the
- peer has finally turned up now */
- {
- *err = -sk->err;
- sk->err=0;
- restore_flags(intflags);
- return NULL;
- }
- }
- sk->inuse = 1;
- restore_flags(intflags);
- }
- /* Again only user level code calls this function, so nothing interrupt level
- will suddenly eat the receive_queue */
- if (!(flags & MSG_PEEK))
- {
- skb=skb_dequeue(&sk->receive_queue);
- if(skb!=NULL)
- skb->users++;
- else
- goto restart; /* Avoid race if someone beats us to the data */
- }
- else
- {
- cli();
- skb=skb_peek(&sk->receive_queue);
- if(skb!=NULL)
- skb->users++;
- restore_flags(intflags);
- if(skb==NULL) /* shouldn't happen but .. */
- *err=-EAGAIN;
- }
- return skb;
-}
-
-void skb_free_datagram(struct sk_buff *skb)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- skb->users--;
- if(skb->users>0)
- {
- restore_flags(flags);
- return;
- }
- /* See if it needs destroying */
- if(!skb->next && !skb->prev) /* Been dequeued by someone - ie it's read */
- kfree_skb(skb,FREE_READ);
- restore_flags(flags);
-}
-
-void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
-{
- /* We will know all about the fraglist options to allow >4K receives
- but not this release */
- memcpy_tofs(to,skb->h.raw+offset,size);
-}
-
-/*
- * Datagram select: Again totally generic. Moved from udp.c
- * Now does seqpacket.
- */
-
-int datagram_select(struct sock *sk, int sel_type, select_table *wait)
-{
- select_wait(sk->sleep, wait);
- switch(sel_type)
- {
- case SEL_IN:
- if (sk->type==SOCK_SEQPACKET && sk->state==TCP_CLOSE)
- {
- /* Connection closed: Wake up */
- return(1);
- }
- if (skb_peek(&sk->receive_queue) != NULL || sk->err != 0)
- { /* This appears to be consistent
- with other stacks */
- return(1);
- }
- return(0);
-
- case SEL_OUT:
- if (sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
- {
- return(1);
- }
- if (sk->prot==NULL && sk->sndbuf-sk->wmem_alloc >= MIN_WRITE_SPACE)
- {
- return(1);
- }
- return(0);
-
- case SEL_EX:
- if (sk->err)
- return(1); /* Socket has gone into error state (eg icmp error) */
- return(0);
- }
- return(0);
-}
diff --git a/pfinet/linux-inet/datalink.h b/pfinet/linux-inet/datalink.h
deleted file mode 100644
index 34ae08da..00000000
--- a/pfinet/linux-inet/datalink.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _NET_INET_DATALINK_H_
-#define _NET_INET_DATALINK_H_
-
-struct datalink_proto {
- unsigned short type_len;
- unsigned char type[8];
- char *string_name;
- unsigned short header_length;
- int (*rcvfunc)(struct sk_buff *, struct device *,
- struct packet_type *);
- void (*datalink_header)(struct datalink_proto *, struct sk_buff *,
- unsigned char *);
- struct datalink_proto *next;
-};
-
-#endif
-
diff --git a/pfinet/linux-inet/dev.c b/pfinet/linux-inet/dev.c
deleted file mode 100644
index d393af11..00000000
--- a/pfinet/linux-inet/dev.c
+++ /dev/null
@@ -1,1449 +0,0 @@
-/*
- * NET3 Protocol independent device support routines.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- *
- * Derived from the non IP parts of dev.c 1.0.19
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Mark Evans, <evansmp@uhura.aston.ac.uk>
- *
- * Additional Authors:
- * Florian la Roche <rzsfl@rz.uni-sb.de>
- * Alan Cox <gw4pts@gw4pts.ampr.org>
- * David Hinds <dhinds@allegro.stanford.edu>
- *
- * Changes:
- * Alan Cox : device private ioctl copies fields back.
- * Alan Cox : Transmit queue code does relevant stunts to
- * keep the queue safe.
- * Alan Cox : Fixed double lock.
- * Alan Cox : Fixed promisc NULL pointer trap
- * ???????? : Support the full private ioctl range
- * Alan Cox : Moved ioctl permission check into drivers
- * Tim Kordas : SIOCADDMULTI/SIOCDELMULTI
- * Alan Cox : 100 backlog just doesn't cut it when
- * you start doing multicast video 8)
- * Alan Cox : Rewrote net_bh and list manager.
- * Alan Cox : Fix ETH_P_ALL echoback lengths.
- *
- * Cleaned up and recommented by Alan Cox 2nd April 1994. I hope to have
- * the rest as well commented in the end.
- */
-
-/*
- * A lot of these includes will be going walkies very soon
- */
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include "ip.h"
-#include "route.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "arp.h"
-
-
-/*
- * The list of packet types we will receive (as opposed to discard)
- * and the routines to invoke.
- */
-
-struct packet_type *ptype_base = NULL;
-
-/*
- * Our notifier list
- */
-
-struct notifier_block *netdev_chain=NULL;
-
-/*
- * Device drivers call our routines to queue packets here. We empty the
- * queue in the bottom half handler.
- */
-
-static struct sk_buff_head backlog =
-{
- (struct sk_buff *)&backlog, (struct sk_buff *)&backlog
-#ifdef CONFIG_SKB_CHECK
- ,SK_HEAD_SKB
-#endif
-};
-
-/*
- * We don't overdo the queue or we will thrash memory badly.
- */
-
-static int backlog_size = 0;
-
-/*
- * Return the lesser of the two values.
- */
-
-static __inline__ unsigned long min(unsigned long a, unsigned long b)
-{
- return (a < b)? a : b;
-}
-
-
-/******************************************************************************************
-
- Protocol management and registration routines
-
-*******************************************************************************************/
-
-/*
- * For efficiency
- */
-
-static int dev_nit=0;
-
-/*
- * Add a protocol ID to the list. Now that the input handler is
- * smarter we can dispense with all the messy stuff that used to be
- * here.
- */
-
-void dev_add_pack(struct packet_type *pt)
-{
- if(pt->type==htons(ETH_P_ALL))
- dev_nit++;
- pt->next = ptype_base;
- ptype_base = pt;
-}
-
-
-/*
- * Remove a protocol ID from the list.
- */
-
-void dev_remove_pack(struct packet_type *pt)
-{
- struct packet_type **pt1;
- if(pt->type==htons(ETH_P_ALL))
- dev_nit--;
- for(pt1=&ptype_base; (*pt1)!=NULL; pt1=&((*pt1)->next))
- {
- if(pt==(*pt1))
- {
- *pt1=pt->next;
- return;
- }
- }
-}
-
-/*****************************************************************************************
-
- Device Interface Subroutines
-
-******************************************************************************************/
-
-/*
- * Find an interface by name.
- */
-
-struct device *dev_get(char *name)
-{
- struct device *dev;
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (strcmp(dev->name, name) == 0)
- return(dev);
- }
- return(NULL);
-}
-
-
-/*
- * Prepare an interface for use.
- */
-
-int dev_open(struct device *dev)
-{
- int ret = 0;
-
- /*
- * Call device private open method
- */
- if (dev->open)
- ret = dev->open(dev);
-
- /*
- * If it went open OK then set the flags
- */
-
- if (ret == 0)
- {
- dev->flags |= (IFF_UP | IFF_RUNNING);
- /*
- * Initialise multicasting status
- */
-#ifdef CONFIG_IP_MULTICAST
- /*
- * Join the all host group
- */
- ip_mc_allhost(dev);
-#endif
- dev_mc_upload(dev);
- notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
- }
- return(ret);
-}
-
-
-/*
- * Completely shutdown an interface.
- */
-
-int dev_close(struct device *dev)
-{
- /*
- * Only close a device if it is up.
- */
-
- if (dev->flags != 0)
- {
- int ct=0;
- dev->flags = 0;
- /*
- * Call the device specific close. This cannot fail.
- */
- if (dev->stop)
- dev->stop(dev);
-
- notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
-#if 0
- /*
- * Delete the route to the device.
- */
-#ifdef CONFIG_INET
- ip_rt_flush(dev);
- arp_device_down(dev);
-#endif
-#ifdef CONFIG_IPX
- ipxrtr_device_down(dev);
-#endif
-#endif
- /*
- * Flush the multicast chain
- */
- dev_mc_discard(dev);
- /*
- * Blank the IP addresses
- */
- dev->pa_addr = 0;
- dev->pa_dstaddr = 0;
- dev->pa_brdaddr = 0;
- dev->pa_mask = 0;
- /*
- * Purge any queued packets when we down the link
- */
- while(ct<DEV_NUMBUFFS)
- {
- struct sk_buff *skb;
- while((skb=skb_dequeue(&dev->buffs[ct]))!=NULL)
- if(skb->free)
- kfree_skb(skb,FREE_WRITE);
- ct++;
- }
- }
- return(0);
-}
-
-
-/*
- * Device change register/unregister. These are not inline or static
- * as we export them to the world.
- */
-
-int register_netdevice_notifier(struct notifier_block *nb)
-{
- return notifier_chain_register(&netdev_chain, nb);
-}
-
-int unregister_netdevice_notifier(struct notifier_block *nb)
-{
- return notifier_chain_unregister(&netdev_chain,nb);
-}
-
-
-
-/*
- * Send (or queue for sending) a packet.
- *
- * IMPORTANT: When this is called to resend frames. The caller MUST
- * already have locked the sk_buff. Apart from that we do the
- * rest of the magic.
- */
-
-void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
-{
- unsigned long flags;
- int nitcount;
- struct packet_type *ptype;
- int where = 0; /* used to say if the packet should go */
- /* at the front or the back of the */
- /* queue - front is a retransmit try */
-
- if (dev == NULL)
- {
- printk("dev.c: dev_queue_xmit: dev = NULL\n");
- return;
- }
-
- if(pri>=0 && !skb_device_locked(skb))
- skb_device_lock(skb); /* Shove a lock on the frame */
-#ifdef CONFIG_SLAVE_BALANCING
- save_flags(flags);
- cli();
- if(dev->slave!=NULL && dev->slave->pkt_queue < dev->pkt_queue &&
- (dev->slave->flags & IFF_UP))
- dev=dev->slave;
- restore_flags(flags);
-#endif
-#ifdef CONFIG_SKB_CHECK
- IS_SKB(skb);
-#endif
- skb->dev = dev;
-
- /*
- * This just eliminates some race conditions, but not all...
- */
-
- if (skb->next != NULL)
- {
- /*
- * Make sure we haven't missed an interrupt.
- */
- printk("dev_queue_xmit: worked around a missed interrupt\n");
- dev->hard_start_xmit(NULL, dev);
- return;
- }
-
- /*
- * Negative priority is used to flag a frame that is being pulled from the
- * queue front as a retransmit attempt. It therefore goes back on the queue
- * start on a failure.
- */
-
- if (pri < 0)
- {
- pri = -pri-1;
- where = 1;
- }
-
- if (pri >= DEV_NUMBUFFS)
- {
- printk("bad priority in dev_queue_xmit.\n");
- pri = 1;
- }
-
- /*
- * If the address has not been resolved. Call the device header rebuilder.
- * This can cover all protocols and technically not just ARP either.
- */
-
- if (!skb->arp && dev->rebuild_header(skb->data, dev, skb->raddr, skb)) {
- return;
- }
-
- save_flags(flags);
- cli();
- if (!where) {
-#ifdef CONFIG_SLAVE_BALANCING
- skb->in_dev_queue=1;
-#endif
- skb_queue_tail(dev->buffs + pri,skb);
- skb_device_unlock(skb); /* Buffer is on the device queue and can be freed safely */
- skb = skb_dequeue(dev->buffs + pri);
- skb_device_lock(skb); /* New buffer needs locking down */
-#ifdef CONFIG_SLAVE_BALANCING
- skb->in_dev_queue=0;
-#endif
- }
- restore_flags(flags);
-
- /* copy outgoing packets to any sniffer packet handlers */
- if(!where)
- {
- for (nitcount= dev_nit, ptype = ptype_base; nitcount > 0 && ptype != NULL; ptype = ptype->next)
- {
- /* Never send packets back to the socket
- * they originated from - MvS (miquels@drinkel.ow.org)
- */
- if (ptype->type == htons(ETH_P_ALL) &&
- (ptype->dev == dev || !ptype->dev) &&
- ((struct sock *)ptype->data != skb->sk))
- {
- struct sk_buff *skb2;
- if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
- break;
- /*
- * The protocol knows this has (for other paths) been taken off
- * and adds it back.
- */
- skb2->len-=skb->dev->hard_header_len;
- ptype->func(skb2, skb->dev, ptype);
- nitcount--;
- }
- }
- }
- if (dev->hard_start_xmit(skb, dev) == 0) {
- /*
- * Packet is now solely the responsibility of the driver
- */
- return;
- }
-
- /*
- * Transmission failed, put skb back into a list. Once on the list it's safe and
- * no longer device locked (it can be freed safely from the device queue)
- */
- cli();
-#ifdef CONFIG_SLAVE_BALANCING
- skb->in_dev_queue=1;
- dev->pkt_queue++;
-#endif
- skb_device_unlock(skb);
- skb_queue_head(dev->buffs + pri,skb);
- restore_flags(flags);
-}
-
-/*
- * Receive a packet from a device driver and queue it for the upper
- * (protocol) levels. It always succeeds. This is the recommended
- * interface to use.
- */
-
-void netif_rx(struct sk_buff *skb)
-{
- static int dropping = 0;
-
- /*
- * Any received buffers are un-owned and should be discarded
- * when freed. These will be updated later as the frames get
- * owners.
- */
- skb->sk = NULL;
- skb->free = 1;
- if(skb->stamp.tv_sec==0)
- skb->stamp = xtime;
-
- /*
- * Check that we aren't overdoing things.
- */
-
- if (!backlog_size)
- dropping = 0;
- else if (backlog_size > 300)
- dropping = 1;
-
- if (dropping)
- {
- kfree_skb(skb, FREE_READ);
- return;
- }
-
- /*
- * Add it to the "backlog" queue.
- */
-#ifdef CONFIG_SKB_CHECK
- IS_SKB(skb);
-#endif
- skb_queue_tail(&backlog,skb);
- backlog_size++;
-
- /*
- * If any packet arrived, mark it for processing after the
- * hardware interrupt returns.
- */
-
- mark_bh(NET_BH);
- return;
-}
-
-
-/*
- * The old interface to fetch a packet from a device driver.
- * This function is the base level entry point for all drivers that
- * want to send a packet to the upper (protocol) levels. It takes
- * care of de-multiplexing the packet to the various modules based
- * on their protocol ID.
- *
- * Return values: 1 <- exit I can't do any more
- * 0 <- feed me more (i.e. "done", "OK").
- *
- * This function is OBSOLETE and should not be used by any new
- * device.
- */
-
-int dev_rint(unsigned char *buff, long len, int flags, struct device *dev)
-{
- static int dropping = 0;
- struct sk_buff *skb = NULL;
- unsigned char *to;
- int amount, left;
- int len2;
-
- if (dev == NULL || buff == NULL || len <= 0)
- return(1);
-
- if (flags & IN_SKBUFF)
- {
- skb = (struct sk_buff *) buff;
- }
- else
- {
- if (dropping)
- {
- if (skb_peek(&backlog) != NULL)
- return(1);
- printk("INET: dev_rint: no longer dropping packets.\n");
- dropping = 0;
- }
-
- skb = alloc_skb(len, GFP_ATOMIC);
- if (skb == NULL)
- {
- printk("dev_rint: packet dropped on %s (no memory) !\n",
- dev->name);
- dropping = 1;
- return(1);
- }
-
- /*
- * First we copy the packet into a buffer, and save it for later. We
- * in effect handle the incoming data as if it were from a circular buffer
- */
-
- to = skb->data;
- left = len;
-
- len2 = len;
- while (len2 > 0)
- {
- amount = min(len2, (unsigned long) dev->rmem_end -
- (unsigned long) buff);
- memcpy(to, buff, amount);
- len2 -= amount;
- left -= amount;
- buff += amount;
- to += amount;
- if ((unsigned long) buff == dev->rmem_end)
- buff = (unsigned char *) dev->rmem_start;
- }
- }
-
- /*
- * Tag the frame and kick it to the proper receive routine
- */
-
- skb->len = len;
- skb->dev = dev;
- skb->free = 1;
-
- netif_rx(skb);
- /*
- * OK, all done.
- */
- return(0);
-}
-
-
-/*
- * This routine causes all interfaces to try to send some data.
- */
-
-void dev_transmit(void)
-{
- struct device *dev;
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (dev->flags != 0 && !dev->tbusy) {
- /*
- * Kick the device
- */
- dev_tint(dev);
- }
- }
-}
-
-
-/**********************************************************************************
-
- Receive Queue Processor
-
-***********************************************************************************/
-
-/*
- * This is a single non-reentrant routine which takes the received packet
- * queue and throws it at the networking layers in the hope that something
- * useful will emerge.
- */
-
-volatile char in_bh = 0; /* Non-reentrant remember */
-
-int in_net_bh() /* Used by timer.c */
-{
- return(in_bh==0?0:1);
-}
-
-/*
- * When we are called the queue is ready to grab, the interrupts are
- * on and hardware can interrupt and queue to the receive queue a we
- * run with no problems.
- * This is run as a bottom half after an interrupt handler that does
- * mark_bh(NET_BH);
- */
-
-void net_bh(void *tmp)
-{
- struct sk_buff *skb;
- struct packet_type *ptype;
- struct packet_type *pt_prev;
- unsigned short type;
-
- /*
- * Atomically check and mark our BUSY state.
- */
-
- if (set_bit(1, (void*)&in_bh))
- return;
-
- /*
- * Can we send anything now? We want to clear the
- * decks for any more sends that get done as we
- * process the input.
- */
-
- dev_transmit();
-
- /*
- * Any data left to process. This may occur because a
- * mark_bh() is done after we empty the queue including
- * that from the device which does a mark_bh() just after
- */
-
- cli();
-
- /*
- * While the queue is not empty
- */
-
- while((skb=skb_dequeue(&backlog))!=NULL)
- {
- /*
- * We have a packet. Therefore the queue has shrunk
- */
- backlog_size--;
-
- sti();
-
- /*
- * Bump the pointer to the next structure.
- * This assumes that the basic 'skb' pointer points to
- * the MAC header, if any (as indicated by its "length"
- * field). Take care now!
- */
-
- skb->h.raw = skb->data + skb->dev->hard_header_len;
- skb->len -= skb->dev->hard_header_len;
-
- /*
- * Fetch the packet protocol ID. This is also quite ugly, as
- * it depends on the protocol driver (the interface itself) to
- * know what the type is, or where to get it from. The Ethernet
- * interfaces fetch the ID from the two bytes in the Ethernet MAC
- * header (the h_proto field in struct ethhdr), but other drivers
- * may either use the ethernet ID's or extra ones that do not
- * clash (eg ETH_P_AX25). We could set this before we queue the
- * frame. In fact I may change this when I have time.
- */
-
- type = skb->dev->type_trans(skb, skb->dev);
-
- /*
- * We got a packet ID. Now loop over the "known protocols"
- * table (which is actually a linked list, but this will
- * change soon if I get my way- FvK), and forward the packet
- * to anyone who wants it.
- *
- * [FvK didn't get his way but he is right this ought to be
- * hashed so we typically get a single hit. The speed cost
- * here is minimal but no doubt adds up at the 4,000+ pkts/second
- * rate we can hit flat out]
- */
- pt_prev = NULL;
- for (ptype = ptype_base; ptype != NULL; ptype = ptype->next)
- {
- if ((ptype->type == type || ptype->type == htons(ETH_P_ALL)) && (!ptype->dev || ptype->dev==skb->dev))
- {
- /*
- * We already have a match queued. Deliver
- * to it and then remember the new match
- */
- if(pt_prev)
- {
- struct sk_buff *skb2;
-
- skb2=skb_clone(skb, GFP_ATOMIC);
-
- /*
- * Kick the protocol handler. This should be fast
- * and efficient code.
- */
-
- if(skb2)
- pt_prev->func(skb2, skb->dev, pt_prev);
- }
- /* Remember the current last to do */
- pt_prev=ptype;
- }
- } /* End of protocol list loop */
-
- /*
- * Is there a last item to send to ?
- */
-
- if(pt_prev)
- pt_prev->func(skb, skb->dev, pt_prev);
- /*
- * Has an unknown packet has been received ?
- */
-
- else
- kfree_skb(skb, FREE_WRITE);
-
- /*
- * Again, see if we can transmit anything now.
- * [Ought to take this out judging by tests it slows
- * us down not speeds us up]
- */
-
- dev_transmit();
- cli();
- } /* End of queue loop */
-
- /*
- * We have emptied the queue
- */
-
- in_bh = 0;
- sti();
-
- /*
- * One last output flush.
- */
-
- dev_transmit();
-}
-
-
-/*
- * This routine is called when an device driver (i.e. an
- * interface) is ready to transmit a packet.
- */
-
-void dev_tint(struct device *dev)
-{
- int i;
- struct sk_buff *skb;
- unsigned long flags;
-
- save_flags(flags);
- /*
- * Work the queues in priority order
- */
-
- for(i = 0;i < DEV_NUMBUFFS; i++)
- {
- /*
- * Pull packets from the queue
- */
-
-
- cli();
- while((skb=skb_dequeue(&dev->buffs[i]))!=NULL)
- {
- /*
- * Stop anyone freeing the buffer while we retransmit it
- */
- skb_device_lock(skb);
- restore_flags(flags);
- /*
- * Feed them to the output stage and if it fails
- * indicate they re-queue at the front.
- */
- dev_queue_xmit(skb,dev,-i - 1);
- /*
- * If we can take no more then stop here.
- */
- if (dev->tbusy)
- return;
- cli();
- }
- }
- restore_flags(flags);
-}
-
-
-/*
- * Perform a SIOCGIFCONF call. This structure will change
- * size shortly, and there is nothing I can do about it.
- * Thus we will need a 'compatibility mode'.
- */
-
-static int dev_ifconf(char *arg)
-{
- struct ifconf ifc;
- struct ifreq ifr;
- struct device *dev;
- char *pos;
- int len;
- int err;
-
- /*
- * Fetch the caller's info block.
- */
-
- err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifconf));
- if(err)
- return err;
- memcpy_fromfs(&ifc, arg, sizeof(struct ifconf));
- len = ifc.ifc_len;
- pos = ifc.ifc_buf;
-
- /*
- * We now walk the device list filling each active device
- * into the array.
- */
-
- err=verify_area(VERIFY_WRITE,pos,len);
- if(err)
- return err;
-
- /*
- * Loop over the interfaces, and write an info block for each.
- */
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if(!(dev->flags & IFF_UP)) /* Downed devices don't count */
- continue;
- memset(&ifr, 0, sizeof(struct ifreq));
- strcpy(ifr.ifr_name, dev->name);
- (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family;
- (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
-
- /*
- * Write this block to the caller's space.
- */
-
- memcpy_tofs(pos, &ifr, sizeof(struct ifreq));
- pos += sizeof(struct ifreq);
- len -= sizeof(struct ifreq);
-
- /*
- * Have we run out of space here ?
- */
-
- if (len < sizeof(struct ifreq))
- break;
- }
-
- /*
- * All done. Write the updated control block back to the caller.
- */
-
- ifc.ifc_len = (pos - ifc.ifc_buf);
- ifc.ifc_req = (struct ifreq *) ifc.ifc_buf;
- memcpy_tofs(arg, &ifc, sizeof(struct ifconf));
-
- /*
- * Report how much was filled in
- */
-
- return(pos - arg);
-}
-
-
-/*
- * This is invoked by the /proc filesystem handler to display a device
- * in detail.
- */
-
-static int sprintf_stats(char *buffer, struct device *dev)
-{
- struct enet_statistics *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
- int size;
-
- if (stats)
- size = sprintf(buffer, "%6s:%7d %4d %4d %4d %4d %8d %4d %4d %4d %5d %4d\n",
- dev->name,
- stats->rx_packets, stats->rx_errors,
- stats->rx_dropped + stats->rx_missed_errors,
- stats->rx_fifo_errors,
- stats->rx_length_errors + stats->rx_over_errors
- + stats->rx_crc_errors + stats->rx_frame_errors,
- stats->tx_packets, stats->tx_errors, stats->tx_dropped,
- stats->tx_fifo_errors, stats->collisions,
- stats->tx_carrier_errors + stats->tx_aborted_errors
- + stats->tx_window_errors + stats->tx_heartbeat_errors);
- else
- size = sprintf(buffer, "%6s: No statistics available.\n", dev->name);
-
- return size;
-}
-
-/*
- * 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 len=0;
- off_t begin=0;
- off_t pos=0;
- int size;
-
- struct device *dev;
-
-
- size = sprintf(buffer, "Inter-| Receive | Transmit\n"
- " face |packets errs drop fifo frame|packets errs drop fifo colls carrier\n");
-
- pos+=size;
- len+=size;
-
-
- 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;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- }
-
- *start=buffer+(offset-begin); /* Start of wanted data */
- len-=(offset-begin); /* Start slop */
- if(len>length)
- len=length; /* Ending slop */
- return len;
-}
-
-
-/*
- * This checks bitmasks for the ioctl calls for devices.
- */
-
-static inline int bad_mask(unsigned long mask, unsigned long addr)
-{
- if (addr & (mask = ~mask))
- return 1;
- mask = ntohl(mask);
- if (mask & (mask+1))
- return 1;
- return 0;
-}
-
-#ifndef _HURD_
-/*
- * Perform the SIOCxIFxxx calls.
- *
- * The socket layer has seen an ioctl the address family thinks is
- * for the device. At this point we get invoked to make a decision
- */
-
-static int dev_ifsioc(void *arg, unsigned int getset)
-{
- struct ifreq ifr;
- struct device *dev;
- int ret;
-
- /*
- * Fetch the caller's info block into kernel space
- */
-
- int err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq));
- if(err)
- return err;
-
- memcpy_fromfs(&ifr, arg, sizeof(struct ifreq));
-
- /*
- * See which interface the caller is talking about.
- */
-
- if ((dev = dev_get(ifr.ifr_name)) == NULL)
- return(-ENODEV);
-
- switch(getset)
- {
- case SIOCGIFFLAGS: /* Get interface flags */
- ifr.ifr_flags = dev->flags;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
- case SIOCSIFFLAGS: /* Set interface flags */
- {
- int old_flags = dev->flags;
-#ifdef CONFIG_SLAVE_BALANCING
- if(dev->flags&IFF_SLAVE)
- return -EBUSY;
-#endif
- dev->flags = ifr.ifr_flags & (
- IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK |
- IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING |
- IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI | IFF_SLAVE | IFF_MASTER
- | IFF_MULTICAST);
-#ifdef CONFIG_SLAVE_BALANCING
- if(!(dev->flags&IFF_MASTER) && dev->slave)
- {
- dev->slave->flags&=~IFF_SLAVE;
- dev->slave=NULL;
- }
-#endif
- /*
- * Load in the correct multicast list now the flags have changed.
- */
-
- dev_mc_upload(dev);
-#if 0
- if( dev->set_multicast_list!=NULL)
- {
-
- /*
- * Has promiscuous mode been turned off
- */
-
- if ( (old_flags & IFF_PROMISC) && ((dev->flags & IFF_PROMISC) == 0))
- dev->set_multicast_list(dev,0,NULL);
-
- /*
- * Has it been turned on
- */
-
- if ( (dev->flags & IFF_PROMISC) && ((old_flags & IFF_PROMISC) == 0))
- dev->set_multicast_list(dev,-1,NULL);
- }
-#endif
- /*
- * Have we downed the interface
- */
-
- if ((old_flags & IFF_UP) && ((dev->flags & IFF_UP) == 0))
- {
- ret = dev_close(dev);
- }
- else
- {
- /*
- * Have we upped the interface
- */
-
- ret = (! (old_flags & IFF_UP) && (dev->flags & IFF_UP))
- ? dev_open(dev) : 0;
- /*
- * Check the flags.
- */
- if(ret<0)
- dev->flags&=~IFF_UP; /* Didn't open so down the if */
- }
- }
- break;
-
- case SIOCGIFADDR: /* Get interface address (and family) */
- (*(struct sockaddr_in *)
- &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
- (*(struct sockaddr_in *)
- &ifr.ifr_addr).sin_family = dev->family;
- (*(struct sockaddr_in *)
- &ifr.ifr_addr).sin_port = 0;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
-
- case SIOCSIFADDR: /* Set interface address (and family) */
- dev->pa_addr = (*(struct sockaddr_in *)
- &ifr.ifr_addr).sin_addr.s_addr;
- dev->family = ifr.ifr_addr.sa_family;
-
-#ifdef CONFIG_INET
- /* This is naughty. When net-032e comes out It wants moving into the net032
- code not the kernel. Till then it can sit here (SIGH) */
- dev->pa_mask = ip_get_mask(dev->pa_addr);
-#endif
- dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;
- ret = 0;
- break;
-
- case SIOCGIFBRDADDR: /* Get the broadcast address */
- (*(struct sockaddr_in *)
- &ifr.ifr_broadaddr).sin_addr.s_addr = dev->pa_brdaddr;
- (*(struct sockaddr_in *)
- &ifr.ifr_broadaddr).sin_family = dev->family;
- (*(struct sockaddr_in *)
- &ifr.ifr_broadaddr).sin_port = 0;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
-
- case SIOCSIFBRDADDR: /* Set the broadcast address */
- dev->pa_brdaddr = (*(struct sockaddr_in *)
- &ifr.ifr_broadaddr).sin_addr.s_addr;
- ret = 0;
- break;
-
- case SIOCGIFDSTADDR: /* Get the destination address (for point-to-point links) */
- (*(struct sockaddr_in *)
- &ifr.ifr_dstaddr).sin_addr.s_addr = dev->pa_dstaddr;
- (*(struct sockaddr_in *)
- &ifr.ifr_broadaddr).sin_family = dev->family;
- (*(struct sockaddr_in *)
- &ifr.ifr_broadaddr).sin_port = 0;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
-
- case SIOCSIFDSTADDR: /* Set the destination address (for point-to-point links) */
- dev->pa_dstaddr = (*(struct sockaddr_in *)
- &ifr.ifr_dstaddr).sin_addr.s_addr;
- ret = 0;
- break;
-
- case SIOCGIFNETMASK: /* Get the netmask for the interface */
- (*(struct sockaddr_in *)
- &ifr.ifr_netmask).sin_addr.s_addr = dev->pa_mask;
- (*(struct sockaddr_in *)
- &ifr.ifr_netmask).sin_family = dev->family;
- (*(struct sockaddr_in *)
- &ifr.ifr_netmask).sin_port = 0;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
-
- case SIOCSIFNETMASK: /* Set the netmask for the interface */
- {
- unsigned long mask = (*(struct sockaddr_in *)
- &ifr.ifr_netmask).sin_addr.s_addr;
- ret = -EINVAL;
- /*
- * The mask we set must be legal.
- */
- if (bad_mask(mask,0))
- break;
- dev->pa_mask = mask;
- ret = 0;
- }
- break;
-
- case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */
-
- ifr.ifr_metric = dev->metric;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
-
- case SIOCSIFMETRIC: /* Set the metric on the interface (currently unused) */
- dev->metric = ifr.ifr_metric;
- ret = 0;
- break;
-
- case SIOCGIFMTU: /* Get the MTU of a device */
- ifr.ifr_mtu = dev->mtu;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
-
- case SIOCSIFMTU: /* Set the MTU of a device */
-
- /*
- * MTU must be positive and under the page size problem
- */
-
- if(ifr.ifr_mtu<1 || ifr.ifr_mtu>3800)
- return -EINVAL;
- dev->mtu = ifr.ifr_mtu;
- ret = 0;
- break;
-
- case SIOCGIFMEM: /* Get the per device memory space. We can add this but currently
- do not support it */
- printk("NET: ioctl(SIOCGIFMEM, %p)\n", arg);
- ret = -EINVAL;
- break;
-
- case SIOCSIFMEM: /* Set the per device memory buffer space. Not applicable in our case */
- printk("NET: ioctl(SIOCSIFMEM, %p)\n", arg);
- ret = -EINVAL;
- break;
-
- case OLD_SIOCGIFHWADDR: /* Get the hardware address. This will change and SIFHWADDR will be added */
- memcpy(ifr.old_ifr_hwaddr,dev->dev_addr, MAX_ADDR_LEN);
- memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
- ret=0;
- break;
-
- case SIOCGIFHWADDR:
- memcpy(ifr.ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN);
- ifr.ifr_hwaddr.sa_family=dev->type;
- memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
- ret=0;
- break;
-
- case SIOCSIFHWADDR:
- if(dev->set_mac_address==NULL)
- return -EOPNOTSUPP;
- if(ifr.ifr_hwaddr.sa_family!=dev->type)
- return -EINVAL;
- ret=dev->set_mac_address(dev,ifr.ifr_hwaddr.sa_data);
- break;
-
- case SIOCGIFMAP:
- ifr.ifr_map.mem_start=dev->mem_start;
- ifr.ifr_map.mem_end=dev->mem_end;
- ifr.ifr_map.base_addr=dev->base_addr;
- ifr.ifr_map.irq=dev->irq;
- ifr.ifr_map.dma=dev->dma;
- ifr.ifr_map.port=dev->if_port;
- memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
- ret=0;
- break;
-
- case SIOCSIFMAP:
- if(dev->set_config==NULL)
- return -EOPNOTSUPP;
- return dev->set_config(dev,&ifr.ifr_map);
-
- case SIOCGIFSLAVE:
-#ifdef CONFIG_SLAVE_BALANCING
- if(dev->slave==NULL)
- return -ENOENT;
- strncpy(ifr.ifr_name,dev->name,sizeof(ifr.ifr_name));
- memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
- ret=0;
-#else
- return -ENOENT;
-#endif
- break;
-#ifdef CONFIG_SLAVE_BALANCING
- case SIOCSIFSLAVE:
- {
-
- /*
- * Fun game. Get the device up and the flags right without
- * letting some scummy user confuse us.
- */
- unsigned long flags;
- struct device *slave=dev_get(ifr.ifr_slave);
- save_flags(flags);
- if(slave==NULL)
- {
- return -ENODEV;
- }
- cli();
- if((slave->flags&(IFF_UP|IFF_RUNNING))!=(IFF_UP|IFF_RUNNING))
- {
- restore_flags(flags);
- return -EINVAL;
- }
- if(dev->flags&IFF_SLAVE)
- {
- restore_flags(flags);
- return -EBUSY;
- }
- if(dev->slave!=NULL)
- {
- restore_flags(flags);
- return -EBUSY;
- }
- if(slave->flags&IFF_SLAVE)
- {
- restore_flags(flags);
- return -EBUSY;
- }
- dev->slave=slave;
- slave->flags|=IFF_SLAVE;
- dev->flags|=IFF_MASTER;
- restore_flags(flags);
- ret=0;
- }
- break;
-#endif
-
- case SIOCADDMULTI:
- if(dev->set_multicast_list==NULL)
- return -EINVAL;
- if(ifr.ifr_hwaddr.sa_family!=AF_UNSPEC)
- return -EINVAL;
- dev_mc_add(dev,ifr.ifr_hwaddr.sa_data, dev->addr_len, 1);
- return 0;
-
- case SIOCDELMULTI:
- if(dev->set_multicast_list==NULL)
- return -EINVAL;
- if(ifr.ifr_hwaddr.sa_family!=AF_UNSPEC)
- return -EINVAL;
- dev_mc_delete(dev,ifr.ifr_hwaddr.sa_data,dev->addr_len, 1);
- return 0;
- /*
- * Unknown or private ioctl
- */
-
- default:
- if((getset >= SIOCDEVPRIVATE) &&
- (getset <= (SIOCDEVPRIVATE + 15))) {
- if(dev->do_ioctl==NULL)
- return -EOPNOTSUPP;
- ret=dev->do_ioctl(dev, &ifr, getset);
- memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
- break;
- }
-
- ret = -EINVAL;
- }
- return(ret);
-}
-
-
-/*
- * This function handles all "interface"-type I/O control requests. The actual
- * 'doing' part of this is dev_ifsioc above.
- */
-
-int dev_ioctl(unsigned int cmd, void *arg)
-{
- switch(cmd)
- {
- case SIOCGIFCONF:
- (void) dev_ifconf((char *) arg);
- return 0;
-
- /*
- * Ioctl calls that can be done by all.
- */
-
- case SIOCGIFFLAGS:
- case SIOCGIFADDR:
- case SIOCGIFDSTADDR:
- case SIOCGIFBRDADDR:
- case SIOCGIFNETMASK:
- case SIOCGIFMETRIC:
- case SIOCGIFMTU:
- case SIOCGIFMEM:
- case SIOCGIFHWADDR:
- case SIOCSIFHWADDR:
- case OLD_SIOCGIFHWADDR:
- case SIOCGIFSLAVE:
- case SIOCGIFMAP:
- return dev_ifsioc(arg, cmd);
-
- /*
- * Ioctl calls requiring the power of a superuser
- */
-
- case SIOCSIFFLAGS:
- case SIOCSIFADDR:
- case SIOCSIFDSTADDR:
- case SIOCSIFBRDADDR:
- case SIOCSIFNETMASK:
- case SIOCSIFMETRIC:
- case SIOCSIFMTU:
- case SIOCSIFMEM:
- case SIOCSIFMAP:
- case SIOCSIFSLAVE:
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- if (!suser())
- return -EPERM;
- return dev_ifsioc(arg, cmd);
-
- case SIOCSIFLINK:
- return -EINVAL;
-
- /*
- * Unknown or private ioctl.
- */
-
- default:
- if((cmd >= SIOCDEVPRIVATE) &&
- (cmd <= (SIOCDEVPRIVATE + 15))) {
- return dev_ifsioc(arg, cmd);
- }
- return -EINVAL;
- }
-}
-#endif
-
-
-/*
- * Initialize the DEV module. At boot time this walks the device list and
- * unhooks any devices that fail to initialise (normally hardware not
- * present) and leaves us with a valid list of present and active devices.
- *
- * The PCMCIA code may need to change this a little, and add a pair
- * of register_inet_device() unregister_inet_device() calls. This will be
- * needed for ethernet as modules support.
- */
-
-void dev_init(void)
-{
- struct device *dev, *dev2;
-
- /*
- * Add the devices.
- * If the call to dev->init fails, the dev is removed
- * from the chain disconnecting the device until the
- * next reboot.
- */
-
- dev2 = NULL;
- for (dev = dev_base; dev != NULL; dev=dev->next)
- {
- if (dev->init && dev->init(dev))
- {
- /*
- * It failed to come up. Unhook it.
- */
-
- if (dev2 == NULL)
- dev_base = dev->next;
- else
- dev2->next = dev->next;
- }
- else
- {
- dev2 = dev;
- }
- }
-}
diff --git a/pfinet/linux-inet/dev_mcast.c b/pfinet/linux-inet/dev_mcast.c
deleted file mode 100644
index cd5e356e..00000000
--- a/pfinet/linux-inet/dev_mcast.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Linux NET3: Multicast List maintenance.
- *
- * Authors:
- * Tim Kordas <tjk@nostromo.eeap.cwru.edu>
- * Richard Underwood <richard@wuzz.demon.co.uk>
- *
- * Stir fried together from the IP multicast and CAP patches above
- * Alan Cox <Alan.Cox@linux.org>
- *
- * Fixes:
- * Alan Cox : Update the device on a real delete
- * rather than any time but...
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include "ip.h"
-#include "route.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "arp.h"
-
-
-/*
- * Device multicast list maintenance. This knows about such little matters as promiscuous mode and
- * converting from the list to the array the drivers use. At least until I fix the drivers up.
- *
- * This is used both by IP and by the user level maintenance functions. Unlike BSD we maintain a usage count
- * on a given multicast address so that a casual user application can add/delete multicasts used by protocols
- * without doing damage to the protocols when it deletes the entries. It also helps IP as it tracks overlapping
- * maps.
- */
-
-
-/*
- * Update the multicast list into the physical NIC controller.
- */
-
-void dev_mc_upload(struct device *dev)
-{
- struct dev_mc_list *dmi;
- char *data, *tmp;
-
- /* Don't do anything till we up the interface
- [dev_open will call this function so the list will
- stay sane] */
-
- if(!(dev->flags&IFF_UP))
- return;
-
-
- /* Devices with no set multicast don't get set */
- if(dev->set_multicast_list==NULL)
- return;
- /* Promiscuous is promiscuous - so no filter needed */
- if(dev->flags&IFF_PROMISC)
- {
- dev->set_multicast_list(dev, -1, NULL);
- return;
- }
-
- if(dev->mc_count==0)
- {
- dev->set_multicast_list(dev,0,NULL);
- return;
- }
-
- data=kmalloc(dev->mc_count*dev->addr_len, GFP_KERNEL);
- if(data==NULL)
- {
- printk("Unable to get memory to set multicast list on %s\n",dev->name);
- return;
- }
- for(tmp = data, dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next)
- {
- memcpy(tmp,dmi->dmi_addr, dmi->dmi_addrlen);
- tmp+=dev->addr_len;
- }
- dev->set_multicast_list(dev,dev->mc_count,data);
- kfree(data);
-}
-
-/*
- * Delete a device level multicast
- */
-
-void dev_mc_delete(struct device *dev, void *addr, int alen, int all)
-{
- struct dev_mc_list **dmi;
- for(dmi=&dev->mc_list;*dmi!=NULL;dmi=&(*dmi)->next)
- {
- if(memcmp((*dmi)->dmi_addr,addr,(*dmi)->dmi_addrlen)==0 && alen==(*dmi)->dmi_addrlen)
- {
- struct dev_mc_list *tmp= *dmi;
- if(--(*dmi)->dmi_users && !all)
- return;
- *dmi=(*dmi)->next;
- dev->mc_count--;
- kfree_s(tmp,sizeof(*tmp));
- dev_mc_upload(dev);
- return;
- }
- }
-}
-
-/*
- * Add a device level multicast
- */
-
-void dev_mc_add(struct device *dev, void *addr, int alen, int newonly)
-{
- struct dev_mc_list *dmi;
- for(dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next)
- {
- if(memcmp(dmi->dmi_addr,addr,dmi->dmi_addrlen)==0 && dmi->dmi_addrlen==alen)
- {
- if(!newonly)
- dmi->dmi_users++;
- return;
- }
- }
- dmi=(struct dev_mc_list *)kmalloc(sizeof(*dmi),GFP_KERNEL);
- if(dmi==NULL)
- return; /* GFP_KERNEL so can't happen anyway */
- memcpy(dmi->dmi_addr, addr, alen);
- dmi->dmi_addrlen=alen;
- dmi->next=dev->mc_list;
- dmi->dmi_users=1;
- dev->mc_list=dmi;
- dev->mc_count++;
- dev_mc_upload(dev);
-}
-
-/*
- * Discard multicast list when a device is downed
- */
-
-void dev_mc_discard(struct device *dev)
-{
- while(dev->mc_list!=NULL)
- {
- struct dev_mc_list *tmp=dev->mc_list;
- dev->mc_list=dev->mc_list->next;
- kfree_s(tmp,sizeof(*tmp));
- }
- dev->mc_count=0;
-}
-
diff --git a/pfinet/linux-inet/devinet.c b/pfinet/linux-inet/devinet.c
deleted file mode 100644
index 946536be..00000000
--- a/pfinet/linux-inet/devinet.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * NET3 IP device support routines.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- *
- * Derived from the IP parts of dev.c 1.0.19
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Mark Evans, <evansmp@uhura.aston.ac.uk>
- *
- * Additional Authors:
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- */
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include "ip.h"
-#include "route.h"
-#include "protocol.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "arp.h"
-
-/*
- * Determine a default network mask, based on the IP address.
- */
-
-unsigned long ip_get_mask(unsigned long addr)
-{
- unsigned long dst;
-
- if (addr == 0L)
- return(0L); /* special case */
-
- dst = ntohl(addr);
- if (IN_CLASSA(dst))
- return(htonl(IN_CLASSA_NET));
- if (IN_CLASSB(dst))
- return(htonl(IN_CLASSB_NET));
- if (IN_CLASSC(dst))
- return(htonl(IN_CLASSC_NET));
-
- /*
- * Something else, probably a multicast.
- */
-
- return(0);
-}
-
-/*
- * Check the address for our address, broadcasts, etc.
- *
- * I intend to fix this to at the very least cache the last
- * resolved entry.
- */
-
-int ip_chk_addr(unsigned long addr)
-{
- struct device *dev;
- unsigned long mask;
-
- /*
- * Accept both `all ones' and `all zeros' as BROADCAST.
- * (Support old BSD in other words). This old BSD
- * support will go very soon as it messes other things
- * up.
- * Also accept `loopback broadcast' as BROADCAST.
- */
-
- if (addr == INADDR_ANY || addr == INADDR_BROADCAST ||
- addr == htonl(0x7FFFFFFFL))
- return IS_BROADCAST;
-
- mask = ip_get_mask(addr);
-
- /*
- * Accept all of the `loopback' class A net.
- */
-
- if ((addr & mask) == htonl(0x7F000000L))
- return IS_MYADDR;
-
- /*
- * OK, now check the interface addresses.
- */
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (!(dev->flags & IFF_UP))
- continue;
- /*
- * If the protocol address of the device is 0 this is special
- * and means we are address hunting (eg bootp).
- */
-
- if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
- return IS_MYADDR;
- /*
- * Is it the exact IP address?
- */
-
- if (addr == dev->pa_addr)
- return IS_MYADDR;
- /*
- * Is it our broadcast address?
- */
-
- if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr)
- return IS_BROADCAST;
- /*
- * Nope. Check for a subnetwork broadcast.
- */
-
- if (((addr ^ dev->pa_addr) & dev->pa_mask) == 0)
- {
- if ((addr & ~dev->pa_mask) == 0)
- return IS_BROADCAST;
- if ((addr & ~dev->pa_mask) == ~dev->pa_mask)
- return IS_BROADCAST;
- }
-
- /*
- * Nope. Check for Network broadcast.
- */
-
- if (((addr ^ dev->pa_addr) & mask) == 0)
- {
- if ((addr & ~mask) == 0)
- return IS_BROADCAST;
- if ((addr & ~mask) == ~mask)
- return IS_BROADCAST;
- }
- }
- if(IN_MULTICAST(ntohl(addr)))
- return IS_MULTICAST;
- return 0; /* no match at all */
-}
-
-
-/*
- * Retrieve our own address.
- *
- * Because the loopback address (127.0.0.1) is already recognized
- * automatically, we can use the loopback interface's address as
- * our "primary" interface. This is the address used by IP et
- * al when it doesn't know which address to use (i.e. it does not
- * yet know from or to which interface to go...).
- */
-
-unsigned long ip_my_addr(void)
-{
- struct device *dev;
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (dev->flags & IFF_LOOPBACK)
- return(dev->pa_addr);
- }
- return(0);
-}
-
-/*
- * Find an interface that can handle addresses for a certain address.
- *
- * This needs optimising, since it's relatively trivial to collapse
- * the two loops into one.
- */
-
-struct device * ip_dev_check(unsigned long addr)
-{
- struct device *dev;
-
- for (dev = dev_base; dev; dev = dev->next)
- {
- if (!(dev->flags & IFF_UP))
- continue;
- if (!(dev->flags & IFF_POINTOPOINT))
- continue;
- if (addr != dev->pa_dstaddr)
- continue;
- return dev;
- }
- for (dev = dev_base; dev; dev = dev->next)
- {
- if (!(dev->flags & IFF_UP))
- continue;
- if (dev->flags & IFF_POINTOPOINT)
- continue;
- if (dev->pa_mask & (addr ^ dev->pa_addr))
- continue;
- return dev;
- }
- return NULL;
-}
diff --git a/pfinet/linux-inet/eth.c b/pfinet/linux-inet/eth.c
deleted file mode 100644
index cbd2c94b..00000000
--- a/pfinet/linux-inet/eth.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Ethernet-type device handling.
- *
- * Version: @(#)eth.c 1.0.7 05/25/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Mark Evans, <evansmp@uhura.aston.ac.uk>
- * Florian La Roche, <rzsfl@rz.uni-sb.de>
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- *
- * Fixes:
- * Mr Linux : Arp problems
- * Alan Cox : Generic queue tidyup (very tiny here)
- * Alan Cox : eth_header ntohs should be htons
- * Alan Cox : eth_rebuild_header missing an htons and
- * minor other things.
- * Tegge : Arp bug fixes.
- * Florian : Removed many unnecessary functions, code cleanup
- * and changes for new arp and skbuff.
- * Alan Cox : Redid header building to reflect new format.
- * Alan Cox : ARP only when compiled with CONFIG_INET
- * Greg Page : 802.2 and SNAP stuff
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/config.h>
-
-#include "arp.h"
-
-void eth_setup(char *str, int *ints)
-{
- struct device *d = dev_base;
-
- if (!str || !*str)
- return;
- while (d)
- {
- if (!strcmp(str,d->name))
- {
- if (ints[0] > 0)
- d->irq=ints[1];
- if (ints[0] > 1)
- d->base_addr=ints[2];
- if (ints[0] > 2)
- d->mem_start=ints[3];
- if (ints[0] > 3)
- d->mem_end=ints[4];
- break;
- }
- d=d->next;
- }
-}
-
-
-/*
- * Create the Ethernet MAC header for an arbitrary protocol layer
- *
- * saddr=NULL means use device source address
- * daddr=NULL means leave destination address (eg unresolved arp)
- */
-
-int eth_header(unsigned char *buff, struct device *dev, unsigned short type,
- void *daddr, void *saddr, unsigned len,
- struct sk_buff *skb)
-{
- struct ethhdr *eth = (struct ethhdr *)buff;
-
- /*
- * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
- * in here instead. It is up to the 802.2 layer to carry protocol information.
- */
-
- if(type!=ETH_P_802_3)
- eth->h_proto = htons(type);
- else
- eth->h_proto = htons(len);
-
- /*
- * Set the source hardware address.
- */
-
- if(saddr)
- memcpy(eth->h_source,saddr,dev->addr_len);
- else
- memcpy(eth->h_source,dev->dev_addr,dev->addr_len);
-
- /*
- * Anyway, the loopback-device should never use this function...
- */
-
- if (dev->flags & IFF_LOOPBACK)
- {
- memset(eth->h_dest, 0, dev->addr_len);
- return(dev->hard_header_len);
- }
-
- if(daddr)
- {
- memcpy(eth->h_dest,daddr,dev->addr_len);
- return dev->hard_header_len;
- }
-
- return -dev->hard_header_len;
-}
-
-
-/*
- * Rebuild the Ethernet MAC header. This is called after an ARP
- * (or in future other address resolution) has completed on this
- * sk_buff. We now let ARP fill in the other fields.
- */
-
-int eth_rebuild_header(void *buff, struct device *dev, unsigned long dst,
- struct sk_buff *skb)
-{
- struct ethhdr *eth = (struct ethhdr *)buff;
-
- /*
- * Only ARP/IP is currently supported
- */
-
- if(eth->h_proto != htons(ETH_P_IP))
- {
- printk("eth_rebuild_header: Don't know how to resolve type %d addresses?\n",(int)eth->h_proto);
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
- return 0;
- }
-
- /*
- * Try and get ARP to resolve the header.
- */
-#ifdef CONFIG_INET
- return arp_find(eth->h_dest, dst, dev, dev->pa_addr, skb)? 1 : 0;
-#else
- return 0;
-#endif
-}
-
-
-/*
- * Determine the packet's protocol ID. The rule here is that we
- * assume 802.3 if the type field is short enough to be a length.
- * This is normal practice and works for any 'now in use' protocol.
- */
-
-unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
-{
- struct ethhdr *eth = (struct ethhdr *) skb->data;
- unsigned char *rawp;
-
- if(*eth->h_dest&1)
- {
- if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
- skb->pkt_type=PACKET_BROADCAST;
- else
- skb->pkt_type=PACKET_MULTICAST;
- }
-
- if(dev->flags&IFF_PROMISC)
- {
- if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
- skb->pkt_type=PACKET_OTHERHOST;
- }
-
- if (ntohs(eth->h_proto) >= 1536)
- return eth->h_proto;
-
- rawp = (unsigned char *)(eth + 1);
-
- if (*(unsigned short *)rawp == 0xFFFF)
- return htons(ETH_P_802_3);
-
- return htons(ETH_P_802_2);
-}
diff --git a/pfinet/linux-inet/eth.h b/pfinet/linux-inet/eth.h
deleted file mode 100644
index f8fed44e..00000000
--- a/pfinet/linux-inet/eth.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. NET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the Ethernet handlers.
- *
- * Version: @(#)eth.h 1.0.4 05/13/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _ETH_H
-#define _ETH_H
-
-
-#include <linux/if_ether.h>
-
-
-extern char *eth_print(unsigned char *ptr);
-extern void eth_dump(struct ethhdr *eth);
-extern int eth_header(unsigned char *buff, struct device *dev,
- unsigned short type, unsigned long daddr,
- unsigned long saddr, unsigned len);
-extern int eth_rebuild_header(void *buff, struct device *dev);
-extern void eth_add_arp(unsigned long addr, struct sk_buff *skb,
- struct device *dev);
-extern unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev);
-
-#endif /* _ETH_H */
diff --git a/pfinet/linux-inet/icmp.c b/pfinet/linux-inet/icmp.c
deleted file mode 100644
index c023eab2..00000000
--- a/pfinet/linux-inet/icmp.c
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Internet Control Message Protocol (ICMP)
- *
- * Version: @(#)icmp.c 1.0.11 06/02/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Mark Evans, <evansmp@uhura.aston.ac.uk>
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- * Stefan Becker, <stefanb@yello.ping.de>
- *
- * Fixes:
- * Alan Cox : Generic queue usage.
- * Gerhard Koerting: ICMP addressing corrected
- * Alan Cox : Use tos/ttl settings
- * Alan Cox : Protocol violations
- * Alan Cox : SNMP Statistics
- * Alan Cox : Routing errors
- * Alan Cox : Changes for newer routing code
- * Alan Cox : Removed old debugging junk
- * Alan Cox : Fixed the ICMP error status of net/host unreachable
- * Gerhard Koerting : Fixed broadcast ping properly
- * Ulrich Kunitz : Fixed ICMP timestamp reply
- * A.N.Kuznetsov : Multihoming fixes.
- * Laco Rusnak : Multihoming fixes.
- * Alan Cox : Tightened up icmp_send().
- * Alan Cox : Multicasts.
- * Stefan Becker : ICMP redirects in icmp_send().
- *
- *
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/string.h>
-#include "snmp.h"
-#include "ip.h"
-#include "route.h"
-#include "protocol.h"
-#include "icmp.h"
-#include "tcp.h"
-#include "snmp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-
-
-#define min(a,b) ((a)<(b)?(a):(b))
-
-
-/*
- * Statistics
- */
-
-struct icmp_mib icmp_statistics={0,};
-
-
-/* An array of errno for error messages from dest unreach. */
-struct icmp_err icmp_err_convert[] = {
- { ENETUNREACH, 0 }, /* ICMP_NET_UNREACH */
- { EHOSTUNREACH, 0 }, /* ICMP_HOST_UNREACH */
- { ENOPROTOOPT, 1 }, /* ICMP_PROT_UNREACH */
- { ECONNREFUSED, 1 }, /* ICMP_PORT_UNREACH */
- { EOPNOTSUPP, 0 }, /* ICMP_FRAG_NEEDED */
- { EOPNOTSUPP, 0 }, /* ICMP_SR_FAILED */
- { ENETUNREACH, 1 }, /* ICMP_NET_UNKNOWN */
- { EHOSTDOWN, 1 }, /* ICMP_HOST_UNKNOWN */
- { ENONET, 1 }, /* ICMP_HOST_ISOLATED */
- { ENETUNREACH, 1 }, /* ICMP_NET_ANO */
- { EHOSTUNREACH, 1 }, /* ICMP_HOST_ANO */
- { EOPNOTSUPP, 0 }, /* ICMP_NET_UNR_TOS */
- { EOPNOTSUPP, 0 } /* ICMP_HOST_UNR_TOS */
-};
-
-
-/*
- * Send an ICMP message in response to a situation
- *
- * Fixme: Fragment handling is wrong really.
- */
-
-void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, struct device *dev)
-{
- struct sk_buff *skb;
- struct iphdr *iph;
- int offset;
- struct icmphdr *icmph;
- int len;
- struct device *ndev=NULL; /* Make this =dev to force replies on the same interface */
- unsigned long our_addr;
- int atype;
-
- /*
- * Find the original IP header.
- */
-
- iph = (struct iphdr *) (skb_in->data + dev->hard_header_len);
-
- /*
- * No replies to MAC multicast
- */
-
- if(skb_in->pkt_type!=PACKET_HOST)
- return;
-
- /*
- * No replies to IP multicasting
- */
-
- atype=ip_chk_addr(iph->daddr);
- if(atype==IS_BROADCAST || IN_MULTICAST(iph->daddr))
- return;
-
- /*
- * Only reply to first fragment.
- */
-
- if(ntohs(iph->frag_off)&IP_OFFSET)
- return;
-
- /*
- * We must NEVER NEVER send an ICMP error to an ICMP error message
- */
-
- if(type==ICMP_DEST_UNREACH||type==ICMP_REDIRECT||type==ICMP_SOURCE_QUENCH||type==ICMP_TIME_EXCEEDED)
- {
-
- /*
- * Is the original packet an ICMP packet?
- */
-
- if(iph->protocol==IPPROTO_ICMP)
- {
- icmph = (struct icmphdr *) ((char *) iph +
- 4 * iph->ihl);
- /*
- * Check for ICMP error packets (Must never reply to
- * an ICMP error).
- */
-
- if (icmph->type == ICMP_DEST_UNREACH ||
- icmph->type == ICMP_SOURCE_QUENCH ||
- icmph->type == ICMP_REDIRECT ||
- icmph->type == ICMP_TIME_EXCEEDED ||
- icmph->type == ICMP_PARAMETERPROB)
- return;
- }
- }
- icmp_statistics.IcmpOutMsgs++;
-
- /*
- * This needs a tidy.
- */
-
- switch(type)
- {
- case ICMP_DEST_UNREACH:
- icmp_statistics.IcmpOutDestUnreachs++;
- break;
- case ICMP_SOURCE_QUENCH:
- icmp_statistics.IcmpOutSrcQuenchs++;
- break;
- case ICMP_REDIRECT:
- icmp_statistics.IcmpOutRedirects++;
- break;
- case ICMP_ECHO:
- icmp_statistics.IcmpOutEchos++;
- break;
- case ICMP_ECHOREPLY:
- icmp_statistics.IcmpOutEchoReps++;
- break;
- case ICMP_TIME_EXCEEDED:
- icmp_statistics.IcmpOutTimeExcds++;
- break;
- case ICMP_PARAMETERPROB:
- icmp_statistics.IcmpOutParmProbs++;
- break;
- case ICMP_TIMESTAMP:
- icmp_statistics.IcmpOutTimestamps++;
- break;
- case ICMP_TIMESTAMPREPLY:
- icmp_statistics.IcmpOutTimestampReps++;
- break;
- case ICMP_ADDRESS:
- icmp_statistics.IcmpOutAddrMasks++;
- break;
- case ICMP_ADDRESSREPLY:
- icmp_statistics.IcmpOutAddrMaskReps++;
- break;
- }
- /*
- * Get some memory for the reply.
- */
-
- len = dev->hard_header_len + sizeof(struct iphdr) + sizeof(struct icmphdr) +
- sizeof(struct iphdr) + 32; /* amount of header to return */
-
- skb = (struct sk_buff *) alloc_skb(len, GFP_ATOMIC);
- if (skb == NULL)
- {
- icmp_statistics.IcmpOutErrors++;
- return;
- }
- skb->free = 1;
-
- /*
- * Build Layer 2-3 headers for message back to source.
- */
-
- our_addr = dev->pa_addr;
- if (iph->daddr != our_addr && ip_chk_addr(iph->daddr) == IS_MYADDR)
- our_addr = iph->daddr;
- offset = ip_build_header(skb, our_addr, iph->saddr,
- &ndev, IPPROTO_ICMP, NULL, len,
- skb_in->ip_hdr->tos,255);
- if (offset < 0)
- {
- icmp_statistics.IcmpOutErrors++;
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
- return;
- }
-
- /*
- * Re-adjust length according to actual IP header size.
- */
-
- skb->len = offset + sizeof(struct icmphdr) + sizeof(struct iphdr) + 8;
-
- /*
- * Fill in the frame
- */
-
- icmph = (struct icmphdr *) (skb->data + offset);
- icmph->type = type;
- icmph->code = code;
- icmph->checksum = 0;
- icmph->un.gateway = info; /* This might not be meant for
- this form of the union but it will
- be right anyway */
- memcpy(icmph + 1, iph, sizeof(struct iphdr) + 8);
-
- icmph->checksum = ip_compute_csum((unsigned char *)icmph,
- sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
-
- /*
- * Send it and free it once sent.
- */
- ip_queue_xmit(NULL, ndev, skb, 1);
-}
-
-
-/*
- * Handle ICMP_UNREACH and ICMP_QUENCH.
- */
-
-static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
-{
- struct inet_protocol *ipprot;
- struct iphdr *iph;
- unsigned char hash;
- int err;
-
- err = (icmph->type << 8) | icmph->code;
- iph = (struct iphdr *) (icmph + 1);
-
- switch(icmph->code & 7)
- {
- case ICMP_NET_UNREACH:
- break;
- case ICMP_HOST_UNREACH:
- break;
- case ICMP_PROT_UNREACH:
- printk("ICMP: %s:%d: protocol unreachable.\n",
- in_ntoa(iph->daddr), ntohs(iph->protocol));
- break;
- case ICMP_PORT_UNREACH:
- break;
- case ICMP_FRAG_NEEDED:
- printk("ICMP: %s: fragmentation needed and DF set.\n",
- in_ntoa(iph->daddr));
- break;
- case ICMP_SR_FAILED:
- printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
- break;
- default:
- break;
- }
-
- /*
- * Get the protocol(s).
- */
-
- hash = iph->protocol & (MAX_INET_PROTOS -1);
-
- /*
- * This can't change while we are doing it.
- */
-
- ipprot = (struct inet_protocol *) inet_protos[hash];
- while(ipprot != NULL)
- {
- struct inet_protocol *nextip;
-
- nextip = (struct inet_protocol *) ipprot->next;
-
- /*
- * Pass it off to everyone who wants it.
- */
- if (iph->protocol == ipprot->protocol && ipprot->err_handler)
- {
- ipprot->err_handler(err, (unsigned char *)(icmph + 1),
- iph->daddr, iph->saddr, ipprot);
- }
-
- ipprot = nextip;
- }
- kfree_skb(skb, FREE_READ);
-}
-
-
-/*
- * Handle ICMP_REDIRECT.
- */
-
-static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb,
- struct device *dev, unsigned long source)
-{
- struct rtable *rt;
- struct iphdr *iph;
- unsigned long ip;
-
- /*
- * Get the copied header of the packet that caused the redirect
- */
-
- iph = (struct iphdr *) (icmph + 1);
- ip = iph->daddr;
-
- switch(icmph->code & 7)
- {
- case ICMP_REDIR_NET:
- /*
- * This causes a problem with subnetted networks. What we should do
- * is use ICMP_ADDRESS to get the subnet mask of the problem route
- * and set both. But we don't..
- */
-#ifdef not_a_good_idea
- ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
- ip, 0, icmph->un.gateway, dev,0, 0);
- break;
-#endif
- case ICMP_REDIR_HOST:
- /*
- * Add better route to host.
- * But first check that the redirect
- * comes from the old gateway..
- * And make sure it's an ok host address
- * (not some confused thing sending our
- * address)
- */
- rt = ip_rt_route(ip, NULL, NULL);
- if (!rt)
- break;
- if (rt->rt_gateway != source || ip_chk_addr(icmph->un.gateway))
- break;
- printk("redirect from %s\n", in_ntoa(source));
- ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
- ip, 0, icmph->un.gateway, dev,0, 0);
- break;
- case ICMP_REDIR_NETTOS:
- case ICMP_REDIR_HOSTTOS:
- printk("ICMP: cannot handle TOS redirects yet!\n");
- break;
- default:
- break;
- }
-
- /*
- * Discard the original packet
- */
-
- kfree_skb(skb, FREE_READ);
-}
-
-
-/*
- * Handle ICMP_ECHO ("ping") requests.
- */
-
-static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
- unsigned long saddr, unsigned long daddr, int len,
- struct options *opt)
-{
- struct icmphdr *icmphr;
- struct sk_buff *skb2;
- struct device *ndev=NULL;
- int size, offset;
-
- icmp_statistics.IcmpOutEchoReps++;
- icmp_statistics.IcmpOutMsgs++;
-
- size = dev->hard_header_len + 64 + len;
- skb2 = alloc_skb(size, GFP_ATOMIC);
-
- if (skb2 == NULL)
- {
- icmp_statistics.IcmpOutErrors++;
- kfree_skb(skb, FREE_READ);
- return;
- }
- skb2->free = 1;
-
- /* Build Layer 2-3 headers for message back to source */
- offset = ip_build_header(skb2, daddr, saddr, &ndev,
- IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
- if (offset < 0)
- {
- icmp_statistics.IcmpOutErrors++;
- printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
- kfree_skb(skb2,FREE_WRITE);
- kfree_skb(skb, FREE_READ);
- return;
- }
-
- /*
- * Re-adjust length according to actual IP header size.
- */
-
- skb2->len = offset + len;
-
- /*
- * Build ICMP_ECHO Response message.
- */
- icmphr = (struct icmphdr *) (skb2->data + offset);
- memcpy((char *) icmphr, (char *) icmph, len);
- icmphr->type = ICMP_ECHOREPLY;
- icmphr->code = 0;
- icmphr->checksum = 0;
- icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
-
- /*
- * Ship it out - free it when done
- */
- ip_queue_xmit((struct sock *)NULL, ndev, skb2, 1);
-
- /*
- * Free the received frame
- */
-
- kfree_skb(skb, FREE_READ);
-}
-
-/*
- * Handle ICMP Timestamp requests.
- */
-
-static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
- unsigned long saddr, unsigned long daddr, int len,
- struct options *opt)
-{
- struct icmphdr *icmphr;
- struct sk_buff *skb2;
- int size, offset;
- unsigned long *timeptr, midtime;
- struct device *ndev=NULL;
-
- if (len != 20)
- {
- printk(
- "ICMP: Size (%d) of ICMP_TIMESTAMP request should be 20!\n",
- len);
- icmp_statistics.IcmpInErrors++;
-#if 1
- /* correct answers are possible for everything >= 12 */
- if (len < 12)
-#endif
- return;
- }
-
- size = dev->hard_header_len + 84;
-
- if (! (skb2 = alloc_skb(size, GFP_ATOMIC)))
- {
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
- icmp_statistics.IcmpOutErrors++;
- return;
- }
- skb2->free = 1;
-
-/*
- * Build Layer 2-3 headers for message back to source
- */
-
- offset = ip_build_header(skb2, daddr, saddr, &ndev, IPPROTO_ICMP, opt, len,
- skb->ip_hdr->tos, 255);
- if (offset < 0)
- {
- printk("ICMP: Could not build IP Header for ICMP TIMESTAMP Response\n");
- kfree_skb(skb2, FREE_WRITE);
- kfree_skb(skb, FREE_READ);
- icmp_statistics.IcmpOutErrors++;
- return;
- }
-
- /*
- * Re-adjust length according to actual IP header size.
- */
- skb2->len = offset + 20;
-
- /*
- * Build ICMP_TIMESTAMP Response message.
- */
-
- icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
- memcpy((char *) icmphr, (char *) icmph, 12);
- icmphr->type = ICMP_TIMESTAMPREPLY;
- icmphr->code = icmphr->checksum = 0;
-
- /* fill in the current time as ms since midnight UT: */
- midtime = (xtime.tv_sec % 86400) * 1000 + xtime.tv_usec / 1000;
- timeptr = (unsigned long *) (icmphr + 1);
- /*
- * the originate timestamp (timeptr [0]) is still in the copy:
- */
- timeptr [1] = timeptr [2] = htonl(midtime);
-
- icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, 20);
-
- /*
- * Ship it out - free it when done
- */
-
- ip_queue_xmit((struct sock *) NULL, ndev, skb2, 1);
- icmp_statistics.IcmpOutTimestampReps++;
- kfree_skb(skb, FREE_READ);
-}
-
-
-
-
-/*
- * Handle the ICMP INFORMATION REQUEST.
- */
-
-static void icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
- unsigned long saddr, unsigned long daddr, int len,
- struct options *opt)
-{
- /* Obsolete */
- kfree_skb(skb, FREE_READ);
-}
-
-
-/*
- * Handle ICMP_ADDRESS_MASK requests.
- */
-
-static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
- unsigned long saddr, unsigned long daddr, int len,
- struct options *opt)
-{
- struct icmphdr *icmphr;
- struct sk_buff *skb2;
- int size, offset;
- struct device *ndev=NULL;
-
- icmp_statistics.IcmpOutMsgs++;
- icmp_statistics.IcmpOutAddrMaskReps++;
-
- size = dev->hard_header_len + 64 + len;
- skb2 = alloc_skb(size, GFP_ATOMIC);
- if (skb2 == NULL)
- {
- icmp_statistics.IcmpOutErrors++;
- kfree_skb(skb, FREE_READ);
- return;
- }
- skb2->free = 1;
-
- /*
- * Build Layer 2-3 headers for message back to source
- */
-
- offset = ip_build_header(skb2, daddr, saddr, &ndev,
- IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
- if (offset < 0)
- {
- icmp_statistics.IcmpOutErrors++;
- printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
- kfree_skb(skb2,FREE_WRITE);
- kfree_skb(skb, FREE_READ);
- return;
- }
-
- /*
- * Re-adjust length according to actual IP header size.
- */
-
- skb2->len = offset + len;
-
- /*
- * Build ICMP ADDRESS MASK Response message.
- */
-
- icmphr = (struct icmphdr *) (skb2->data + offset);
- icmphr->type = ICMP_ADDRESSREPLY;
- icmphr->code = 0;
- icmphr->checksum = 0;
- icmphr->un.echo.id = icmph->un.echo.id;
- icmphr->un.echo.sequence = icmph->un.echo.sequence;
- memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
-
- icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
-
- /* Ship it out - free it when done */
- ip_queue_xmit((struct sock *)NULL, ndev, skb2, 1);
-
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
-}
-
-
-/*
- * Deal with incoming ICMP packets.
- */
-
-int icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
- unsigned long daddr, unsigned short len,
- unsigned long saddr, int redo, struct inet_protocol *protocol)
-{
- struct icmphdr *icmph;
- unsigned char *buff;
-
- /*
- * Drop broadcast packets. IP has done a broadcast check and ought one day
- * to pass on that information.
- */
-
- icmp_statistics.IcmpInMsgs++;
-
-
- /*
- * Grab the packet as an icmp object
- */
-
- buff = skb1->h.raw;
- icmph = (struct icmphdr *) buff;
-
- /*
- * Validate the packet first
- */
-
- if (ip_compute_csum((unsigned char *) icmph, len))
- {
- /* Failed checksum! */
- icmp_statistics.IcmpInErrors++;
- printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
- kfree_skb(skb1, FREE_READ);
- return(0);
- }
-
- /*
- * Parse the ICMP message
- */
-
- if (ip_chk_addr(daddr) != IS_MYADDR)
- {
- if (icmph->type != ICMP_ECHO)
- {
- icmp_statistics.IcmpInErrors++;
- kfree_skb(skb1, FREE_READ);
- return(0);
- }
- daddr=dev->pa_addr;
- }
-
- switch(icmph->type)
- {
- case ICMP_TIME_EXCEEDED:
- icmp_statistics.IcmpInTimeExcds++;
- icmp_unreach(icmph, skb1);
- return 0;
- case ICMP_DEST_UNREACH:
- icmp_statistics.IcmpInDestUnreachs++;
- icmp_unreach(icmph, skb1);
- return 0;
- case ICMP_SOURCE_QUENCH:
- icmp_statistics.IcmpInSrcQuenchs++;
- icmp_unreach(icmph, skb1);
- return(0);
- case ICMP_REDIRECT:
- icmp_statistics.IcmpInRedirects++;
- icmp_redirect(icmph, skb1, dev, saddr);
- return(0);
- case ICMP_ECHO:
- icmp_statistics.IcmpInEchos++;
- icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
- return 0;
- case ICMP_ECHOREPLY:
- icmp_statistics.IcmpInEchoReps++;
- kfree_skb(skb1, FREE_READ);
- return(0);
- case ICMP_TIMESTAMP:
- icmp_statistics.IcmpInTimestamps++;
- icmp_timestamp(icmph, skb1, dev, saddr, daddr, len, opt);
- return 0;
- case ICMP_TIMESTAMPREPLY:
- icmp_statistics.IcmpInTimestampReps++;
- kfree_skb(skb1,FREE_READ);
- return 0;
- /* INFO is obsolete and doesn't even feature in the SNMP stats */
- case ICMP_INFO_REQUEST:
- icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
- return 0;
- case ICMP_INFO_REPLY:
- skb1->sk = NULL;
- kfree_skb(skb1, FREE_READ);
- return(0);
- case ICMP_ADDRESS:
- icmp_statistics.IcmpInAddrMasks++;
- icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
- return 0;
- case ICMP_ADDRESSREPLY:
- /*
- * We ought to set our netmask on receiving this, but
- * experience shows it's a waste of effort.
- */
- icmp_statistics.IcmpInAddrMaskReps++;
- kfree_skb(skb1, FREE_READ);
- return(0);
- default:
- icmp_statistics.IcmpInErrors++;
- kfree_skb(skb1, FREE_READ);
- return(0);
- }
- /*NOTREACHED*/
- kfree_skb(skb1, FREE_READ);
- return(-1);
-}
-
-
-/*
- * Perform any ICMP-related I/O control requests.
- * [to vanish soon]
- */
-
-int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
-{
- switch(cmd)
- {
- default:
- return(-EINVAL);
- }
- return(0);
-}
diff --git a/pfinet/linux-inet/icmp.h b/pfinet/linux-inet/icmp.h
deleted file mode 100644
index 8f1c3498..00000000
--- a/pfinet/linux-inet/icmp.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the ICMP module.
- *
- * Version: @(#)icmp.h 1.0.4 05/13/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _ICMP_H
-#define _ICMP_H
-
-#include <linux/icmp.h>
-
-
-extern struct icmp_err icmp_err_convert[];
-extern struct icmp_mib icmp_statistics;
-
-
-extern void icmp_send(struct sk_buff *skb_in, int type, int code,
- unsigned long info, struct device *dev);
-extern int icmp_rcv(struct sk_buff *skb1, struct device *dev,
- struct options *opt, unsigned long daddr,
- unsigned short len, unsigned long saddr,
- int redo, struct inet_protocol *protocol);
-
-extern int icmp_ioctl(struct sock *sk, int cmd,
- unsigned long arg);
-
-#endif /* _ICMP_H */
diff --git a/pfinet/linux-inet/igmp.c b/pfinet/linux-inet/igmp.c
deleted file mode 100644
index 32e42213..00000000
--- a/pfinet/linux-inet/igmp.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Linux NET3: Internet Gateway Management Protocol [IGMP]
- *
- * Authors:
- * Alan Cox <Alan.Cox@linux.org>
- *
- * WARNING:
- * This is a 'preliminary' implementation... on your own head
- * be it.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/config.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include "route.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include <linux/igmp.h>
-
-#ifdef CONFIG_IP_MULTICAST
-
-
-/*
- * Timer management
- */
-
-
-static void igmp_stop_timer(struct ip_mc_list *im)
-{
- del_timer(&im->timer);
- im->tm_running=0;
-}
-
-static int igmp_random(void)
-{
- static unsigned long seed=152L;
- seed=seed*69069L+1;
- return seed^jiffies;
-}
-
-
-static void igmp_start_timer(struct ip_mc_list *im)
-{
- int tv;
- if(im->tm_running)
- return;
- tv=igmp_random()%(10*HZ); /* Pick a number any number 8) */
- im->timer.expires=tv;
- im->tm_running=1;
- add_timer(&im->timer);
-}
-
-/*
- * Send an IGMP report.
- */
-
-#define MAX_IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+64)
-
-static void igmp_send_report(struct device *dev, unsigned long address, int type)
-{
- struct sk_buff *skb=alloc_skb(MAX_IGMP_SIZE, GFP_ATOMIC);
- int tmp;
- struct igmphdr *igh;
-
- if(skb==NULL)
- return;
- tmp=ip_build_header(skb, INADDR_ANY, address, &dev, IPPROTO_IGMP, NULL,
- skb->mem_len, 0, 1);
- if(tmp<0)
- {
- kfree_skb(skb, FREE_WRITE);
- return;
- }
- igh=(struct igmphdr *)(skb->data+tmp);
- skb->len=tmp+sizeof(*igh);
- igh->csum=0;
- igh->unused=0;
- igh->type=type;
- igh->group=address;
- igh->csum=ip_compute_csum((void *)igh,sizeof(*igh));
- ip_queue_xmit(NULL,dev,skb,1);
-}
-
-
-static void igmp_timer_expire(unsigned long data)
-{
- struct ip_mc_list *im=(struct ip_mc_list *)data;
- igmp_stop_timer(im);
- igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
-}
-
-static void igmp_init_timer(struct ip_mc_list *im)
-{
- im->tm_running=0;
- init_timer(&im->timer);
- im->timer.data=(unsigned long)im;
- im->timer.function=&igmp_timer_expire;
-}
-
-
-static void igmp_heard_report(struct device *dev, unsigned long address)
-{
- struct ip_mc_list *im;
- for(im=dev->ip_mc_list;im!=NULL;im=im->next)
- if(im->multiaddr==address)
- igmp_stop_timer(im);
-}
-
-static void igmp_heard_query(struct device *dev)
-{
- struct ip_mc_list *im;
- for(im=dev->ip_mc_list;im!=NULL;im=im->next)
- if(!im->tm_running && im->multiaddr!=IGMP_ALL_HOSTS)
- igmp_start_timer(im);
-}
-
-/*
- * Map a multicast IP onto multicast MAC for type ethernet.
- */
-
-static void ip_mc_map(unsigned long addr, char *buf)
-{
- addr=ntohl(addr);
- buf[0]=0x01;
- buf[1]=0x00;
- buf[2]=0x5e;
- buf[5]=addr&0xFF;
- addr>>=8;
- buf[4]=addr&0xFF;
- addr>>=8;
- buf[3]=addr&0x7F;
-}
-
-/*
- * Add a filter to a device
- */
-
-void ip_mc_filter_add(struct device *dev, unsigned long addr)
-{
- char buf[6];
- if(dev->type!=ARPHRD_ETHER)
- return; /* Only do ethernet now */
- ip_mc_map(addr,buf);
- dev_mc_add(dev,buf,ETH_ALEN,0);
-}
-
-/*
- * Remove a filter from a device
- */
-
-void ip_mc_filter_del(struct device *dev, unsigned long addr)
-{
- char buf[6];
- if(dev->type!=ARPHRD_ETHER)
- return; /* Only do ethernet now */
- ip_mc_map(addr,buf);
- dev_mc_delete(dev,buf,ETH_ALEN,0);
-}
-
-static void igmp_group_dropped(struct ip_mc_list *im)
-{
- del_timer(&im->timer);
- igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_LEAVE_MESSAGE);
- ip_mc_filter_del(im->interface, im->multiaddr);
-/* printk("Left group %lX\n",im->multiaddr);*/
-}
-
-static void igmp_group_added(struct ip_mc_list *im)
-{
- igmp_init_timer(im);
- igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
- ip_mc_filter_add(im->interface, im->multiaddr);
-/* printk("Joined group %lX\n",im->multiaddr);*/
-}
-
-int igmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
- unsigned long daddr, unsigned short len, unsigned long saddr, int redo,
- struct inet_protocol *protocol)
-{
- /* This basically follows the spec line by line -- see RFC1112 */
- struct igmphdr *igh=(struct igmphdr *)skb->h.raw;
-
- if(skb->ip_hdr->ttl!=1 || ip_compute_csum((void *)igh,sizeof(*igh)))
- {
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
- if(igh->type==IGMP_HOST_MEMBERSHIP_QUERY && daddr==IGMP_ALL_HOSTS)
- igmp_heard_query(dev);
- if(igh->type==IGMP_HOST_MEMBERSHIP_REPORT && daddr==igh->group)
- igmp_heard_report(dev,igh->group);
- kfree_skb(skb, FREE_READ);
- return 0;
-}
-
-/*
- * Multicast list managers
- */
-
-
-/*
- * A socket has joined a multicast group on device dev.
- */
-
-static void ip_mc_inc_group(struct device *dev, unsigned long addr)
-{
- struct ip_mc_list *i;
- for(i=dev->ip_mc_list;i!=NULL;i=i->next)
- {
- if(i->multiaddr==addr)
- {
- i->users++;
- return;
- }
- }
- i=(struct ip_mc_list *)kmalloc(sizeof(*i), GFP_KERNEL);
- if(!i)
- return;
- i->users=1;
- i->interface=dev;
- i->multiaddr=addr;
- i->next=dev->ip_mc_list;
- igmp_group_added(i);
- dev->ip_mc_list=i;
-}
-
-/*
- * A socket has left a multicast group on device dev
- */
-
-static void ip_mc_dec_group(struct device *dev, unsigned long addr)
-{
- struct ip_mc_list **i;
- for(i=&(dev->ip_mc_list);(*i)!=NULL;i=&(*i)->next)
- {
- if((*i)->multiaddr==addr)
- {
- if(--((*i)->users))
- return;
- else
- {
- struct ip_mc_list *tmp= *i;
- igmp_group_dropped(tmp);
- *i=(*i)->next;
- kfree_s(tmp,sizeof(*tmp));
- }
- }
- }
-}
-
-/*
- * Device going down: Clean up.
- */
-
-void ip_mc_drop_device(struct device *dev)
-{
- struct ip_mc_list *i;
- struct ip_mc_list *j;
- for(i=dev->ip_mc_list;i!=NULL;i=j)
- {
- j=i->next;
- kfree_s(i,sizeof(*i));
- }
- dev->ip_mc_list=NULL;
-}
-
-/*
- * Device going up. Make sure it is in all hosts
- */
-
-void ip_mc_allhost(struct device *dev)
-{
- struct ip_mc_list *i;
- for(i=dev->ip_mc_list;i!=NULL;i=i->next)
- if(i->multiaddr==IGMP_ALL_HOSTS)
- return;
- i=(struct ip_mc_list *)kmalloc(sizeof(*i), GFP_KERNEL);
- if(!i)
- return;
- i->users=1;
- i->interface=dev;
- i->multiaddr=IGMP_ALL_HOSTS;
- i->next=dev->ip_mc_list;
- dev->ip_mc_list=i;
- ip_mc_filter_add(i->interface, i->multiaddr);
-
-}
-
-/*
- * Join a socket to a group
- */
-
-int ip_mc_join_group(struct sock *sk , struct device *dev, unsigned long addr)
-{
- int unused= -1;
- int i;
- if(!MULTICAST(addr))
- return -EINVAL;
- if(!(dev->flags&IFF_MULTICAST))
- return -EADDRNOTAVAIL;
- if(sk->ip_mc_list==NULL)
- {
- if((sk->ip_mc_list=(struct ip_mc_socklist *)kmalloc(sizeof(*sk->ip_mc_list), GFP_KERNEL))==NULL)
- return -ENOMEM;
- memset(sk->ip_mc_list,'\0',sizeof(*sk->ip_mc_list));
- }
- for(i=0;i<IP_MAX_MEMBERSHIPS;i++)
- {
- if(sk->ip_mc_list->multiaddr[i]==addr && sk->ip_mc_list->multidev[i]==dev)
- return -EADDRINUSE;
- if(sk->ip_mc_list->multidev[i]==NULL)
- unused=i;
- }
-
- if(unused==-1)
- return -ENOBUFS;
- sk->ip_mc_list->multiaddr[unused]=addr;
- sk->ip_mc_list->multidev[unused]=dev;
- ip_mc_inc_group(dev,addr);
- return 0;
-}
-
-/*
- * Ask a socket to leave a group.
- */
-
-int ip_mc_leave_group(struct sock *sk, struct device *dev, unsigned long addr)
-{
- int i;
- if(!MULTICAST(addr))
- return -EINVAL;
- if(!(dev->flags&IFF_MULTICAST))
- return -EADDRNOTAVAIL;
- if(sk->ip_mc_list==NULL)
- return -EADDRNOTAVAIL;
-
- for(i=0;i<IP_MAX_MEMBERSHIPS;i++)
- {
- if(sk->ip_mc_list->multiaddr[i]==addr && sk->ip_mc_list->multidev[i]==dev)
- {
- sk->ip_mc_list->multidev[i]=NULL;
- ip_mc_dec_group(dev,addr);
- return 0;
- }
- }
- return -EADDRNOTAVAIL;
-}
-
-/*
- * A socket is closing.
- */
-
-void ip_mc_drop_socket(struct sock *sk)
-{
- int i;
-
- if(sk->ip_mc_list==NULL)
- return;
-
- for(i=0;i<IP_MAX_MEMBERSHIPS;i++)
- {
- if(sk->ip_mc_list->multidev[i])
- {
- ip_mc_dec_group(sk->ip_mc_list->multidev[i], sk->ip_mc_list->multiaddr[i]);
- sk->ip_mc_list->multidev[i]=NULL;
- }
- }
- kfree_s(sk->ip_mc_list,sizeof(*sk->ip_mc_list));
- sk->ip_mc_list=NULL;
-}
-
-#endif
diff --git a/pfinet/linux-inet/ip.c b/pfinet/linux-inet/ip.c
deleted file mode 100644
index dd188f54..00000000
--- a/pfinet/linux-inet/ip.c
+++ /dev/null
@@ -1,2427 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * The Internet Protocol (IP) module.
- *
- * Version: @(#)ip.c 1.0.16b 9/1/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Donald Becker, <becker@super.org>
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- * Richard Underwood
- * Stefan Becker, <stefanb@yello.ping.de>
- *
- *
- * Fixes:
- * Alan Cox : Commented a couple of minor bits of surplus code
- * Alan Cox : Undefining IP_FORWARD doesn't include the code
- * (just stops a compiler warning).
- * Alan Cox : Frames with >=MAX_ROUTE record routes, strict routes or loose routes
- * are junked rather than corrupting things.
- * Alan Cox : Frames to bad broadcast subnets are dumped
- * We used to process them non broadcast and
- * boy could that cause havoc.
- * Alan Cox : ip_forward sets the free flag on the
- * new frame it queues. Still crap because
- * it copies the frame but at least it
- * doesn't eat memory too.
- * Alan Cox : Generic queue code and memory fixes.
- * Fred Van Kempen : IP fragment support (borrowed from NET2E)
- * Gerhard Koerting: Forward fragmented frames correctly.
- * Gerhard Koerting: Fixes to my fix of the above 8-).
- * Gerhard Koerting: IP interface addressing fix.
- * Linus Torvalds : More robustness checks
- * Alan Cox : Even more checks: Still not as robust as it ought to be
- * Alan Cox : Save IP header pointer for later
- * Alan Cox : ip option setting
- * Alan Cox : Use ip_tos/ip_ttl settings
- * Alan Cox : Fragmentation bogosity removed
- * (Thanks to Mark.Bush@prg.ox.ac.uk)
- * Dmitry Gorodchanin : Send of a raw packet crash fix.
- * Alan Cox : Silly ip bug when an overlength
- * fragment turns up. Now frees the
- * queue.
- * Linus Torvalds/ : Memory leakage on fragmentation
- * Alan Cox : handling.
- * Gerhard Koerting: Forwarding uses IP priority hints
- * Teemu Rantanen : Fragment problems.
- * Alan Cox : General cleanup, comments and reformat
- * Alan Cox : SNMP statistics
- * Alan Cox : BSD address rule semantics. Also see
- * UDP as there is a nasty checksum issue
- * if you do things the wrong way.
- * Alan Cox : Always defrag, moved IP_FORWARD to the config.in file
- * Alan Cox : IP options adjust sk->priority.
- * Pedro Roque : Fix mtu/length error in ip_forward.
- * Alan Cox : Avoid ip_chk_addr when possible.
- * Richard Underwood : IP multicasting.
- * Alan Cox : Cleaned up multicast handlers.
- * Alan Cox : RAW sockets demultiplex in the BSD style.
- * Gunther Mayer : Fix the SNMP reporting typo
- * Alan Cox : Always in group 224.0.0.1
- * Alan Cox : Multicast loopback error for 224.0.0.1
- * Alan Cox : IP_MULTICAST_LOOP option.
- * Alan Cox : Use notifiers.
- * Bjorn Ekwall : Removed ip_csum (from slhc.c too)
- * Bjorn Ekwall : Moved ip_fast_csum to ip.h (inline!)
- * Stefan Becker : Send out ICMP HOST REDIRECT
- * Alan Cox : Only send ICMP_REDIRECT if src/dest are the same net.
- *
- *
- * To Fix:
- * IP option processing is mostly not needed. ip_forward needs to know about routing rules
- * and time stamp but that's about all. Use the route mtu field here too
- * IP fragmentation wants rewriting cleanly. The RFC815 algorithm is much more efficient
- * and could be made very efficient with the addition of some virtual memory hacks to permit
- * the allocation of a buffer that can then be 'grown' by twiddling page tables.
- * Output fragmentation wants updating along with the buffer management to use a single
- * interleaved copy algorithm so that fragmenting has a one copy overhead. Actual packet
- * output should probably do its own fragmentation at the UDP/RAW layer. TCP shouldn't cause
- * fragmentation anyway.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/config.h>
-
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include "snmp.h"
-#include "ip.h"
-#include "protocol.h"
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "arp.h"
-#include "icmp.h"
-#include "raw.h"
-#include <linux/igmp.h>
-#include <linux/ip_fw.h>
-
-#define CONFIG_IP_DEFRAG
-
-extern int last_retran;
-extern void sort_send(struct sock *sk);
-
-#define min(a,b) ((a)<(b)?(a):(b))
-#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
-
-/*
- * SNMP management statistics
- */
-
-#ifdef CONFIG_IP_FORWARD
-struct ip_mib ip_statistics={1,64,}; /* Forwarding=Yes, Default TTL=64 */
-#else
-struct ip_mib ip_statistics={0,64,}; /* Forwarding=No, Default TTL=64 */
-#endif
-
-/*
- * Handle the issuing of an ioctl() request
- * for the ip device. This is scheduled to
- * disappear
- */
-
-int ip_ioctl(struct sock *sk, int cmd, unsigned long arg)
-{
- switch(cmd)
- {
- default:
- return(-EINVAL);
- }
-}
-
-
-/* these two routines will do routing. */
-
-static void
-strict_route(struct iphdr *iph, struct options *opt)
-{
-}
-
-
-static void
-loose_route(struct iphdr *iph, struct options *opt)
-{
-}
-
-
-
-
-/* This routine will check to see if we have lost a gateway. */
-void
-ip_route_check(unsigned long daddr)
-{
-}
-
-
-#if 0
-/* this routine puts the options at the end of an ip header. */
-static int
-build_options(struct iphdr *iph, struct options *opt)
-{
- unsigned char *ptr;
- /* currently we don't support any options. */
- ptr = (unsigned char *)(iph+1);
- *ptr = 0;
- return (4);
-}
-#endif
-
-
-/*
- * Take an skb, and fill in the MAC header.
- */
-
-static int ip_send(struct sk_buff *skb, unsigned long daddr, int len, struct device *dev, unsigned long saddr)
-{
- int mac = 0;
-
- skb->dev = dev;
- skb->arp = 1;
- if (dev->hard_header)
- {
- /*
- * Build a hardware header. Source address is our mac, destination unknown
- * (rebuild header will sort this out)
- */
- mac = dev->hard_header(skb->data, dev, ETH_P_IP, NULL, NULL, len, skb);
- if (mac < 0)
- {
- mac = -mac;
- skb->arp = 0;
- skb->raddr = daddr; /* next routing address */
- }
- }
- return mac;
-}
-
-int ip_id_count = 0;
-
-/*
- * This routine builds the appropriate hardware/IP headers for
- * the routine. It assumes that if *dev != NULL then the
- * protocol knows what it's doing, otherwise it uses the
- * routing/ARP tables to select a device struct.
- */
-int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long daddr,
- struct device **dev, int type, struct options *opt, int len, int tos, int ttl)
-{
- static struct options optmem;
- struct iphdr *iph;
- struct rtable *rt;
- unsigned char *buff;
- unsigned long raddr;
- int tmp;
- unsigned long src;
-
- buff = skb->data;
-
- /*
- * See if we need to look up the device.
- */
-
-#ifdef CONFIG_INET_MULTICAST
- if(MULTICAST(daddr) && *dev==NULL && skb->sk && *skb->sk->ip_mc_name)
- *dev=dev_get(skb->sk->ip_mc_name);
-#endif
- if (*dev == NULL)
- {
- if(skb->localroute)
- rt = ip_rt_local(daddr, &optmem, &src);
- else
- rt = ip_rt_route(daddr, &optmem, &src);
- if (rt == NULL)
- {
- ip_statistics.IpOutNoRoutes++;
- return(-ENETUNREACH);
- }
-
- *dev = rt->rt_dev;
- /*
- * If the frame is from us and going off machine it MUST MUST MUST
- * have the output device ip address and never the loopback
- */
- if (LOOPBACK(saddr) && !LOOPBACK(daddr))
- saddr = src;/*rt->rt_dev->pa_addr;*/
- raddr = rt->rt_gateway;
-
- opt = &optmem;
- }
- else
- {
- /*
- * We still need the address of the first hop.
- */
- if(skb->localroute)
- rt = ip_rt_local(daddr, &optmem, &src);
- else
- rt = ip_rt_route(daddr, &optmem, &src);
- /*
- * If the frame is from us and going off machine it MUST MUST MUST
- * have the output device ip address and never the loopback
- */
- if (LOOPBACK(saddr) && !LOOPBACK(daddr))
- saddr = src;/*rt->rt_dev->pa_addr;*/
-
- raddr = (rt == NULL) ? 0 : rt->rt_gateway;
- }
-
- /*
- * No source addr so make it our addr
- */
- if (saddr == 0)
- saddr = src;
-
- /*
- * No gateway so aim at the real destination
- */
- if (raddr == 0)
- raddr = daddr;
-
- /*
- * Now build the MAC header.
- */
-
- tmp = ip_send(skb, raddr, len, *dev, saddr);
- buff += tmp;
- len -= tmp;
-
- /*
- * Book keeping
- */
-
- skb->dev = *dev;
- skb->saddr = saddr;
- if (skb->sk)
- skb->sk->saddr = saddr;
-
- /*
- * Now build the IP header.
- */
-
- /*
- * If we are using IPPROTO_RAW, then we don't need an IP header, since
- * one is being supplied to us by the user
- */
-
- if(type == IPPROTO_RAW)
- return (tmp);
-
- iph = (struct iphdr *)buff;
- iph->version = 4;
- iph->tos = tos;
- iph->frag_off = 0;
- iph->ttl = ttl;
- iph->daddr = daddr;
- iph->saddr = saddr;
- iph->protocol = type;
- iph->ihl = 5;
- skb->ip_hdr = iph;
-
- /* Setup the IP options. */
-#ifdef Not_Yet_Avail
- build_options(iph, opt);
-#endif
-
- return(20 + tmp); /* IP header plus MAC header size */
-}
-
-
-static int
-do_options(struct iphdr *iph, struct options *opt)
-{
- unsigned char *buff;
- int done = 0;
- int i, len = sizeof(struct iphdr);
-
- /* Zero out the options. */
- opt->record_route.route_size = 0;
- opt->loose_route.route_size = 0;
- opt->strict_route.route_size = 0;
- opt->tstamp.ptr = 0;
- opt->security = 0;
- opt->compartment = 0;
- opt->handling = 0;
- opt->stream = 0;
- opt->tcc = 0;
- return(0);
-
- /* Advance the pointer to start at the options. */
- buff = (unsigned char *)(iph + 1);
-
- /* Now start the processing. */
- while (!done && len < iph->ihl*4) switch(*buff) {
- case IPOPT_END:
- done = 1;
- break;
- case IPOPT_NOOP:
- buff++;
- len++;
- break;
- case IPOPT_SEC:
- buff++;
- if (*buff != 11) return(1);
- buff++;
- opt->security = ntohs(*(unsigned short *)buff);
- buff += 2;
- opt->compartment = ntohs(*(unsigned short *)buff);
- buff += 2;
- opt->handling = ntohs(*(unsigned short *)buff);
- buff += 2;
- opt->tcc = ((*buff) << 16) + ntohs(*(unsigned short *)(buff+1));
- buff += 3;
- len += 11;
- break;
- case IPOPT_LSRR:
- buff++;
- if ((*buff - 3)% 4 != 0) return(1);
- len += *buff;
- opt->loose_route.route_size = (*buff -3)/4;
- buff++;
- if (*buff % 4 != 0) return(1);
- opt->loose_route.pointer = *buff/4 - 1;
- buff++;
- buff++;
- for (i = 0; i < opt->loose_route.route_size; i++) {
- if(i>=MAX_ROUTE)
- return(1);
- opt->loose_route.route[i] = *(unsigned long *)buff;
- buff += 4;
- }
- break;
- case IPOPT_SSRR:
- buff++;
- if ((*buff - 3)% 4 != 0) return(1);
- len += *buff;
- opt->strict_route.route_size = (*buff -3)/4;
- buff++;
- if (*buff % 4 != 0) return(1);
- opt->strict_route.pointer = *buff/4 - 1;
- buff++;
- buff++;
- for (i = 0; i < opt->strict_route.route_size; i++) {
- if(i>=MAX_ROUTE)
- return(1);
- opt->strict_route.route[i] = *(unsigned long *)buff;
- buff += 4;
- }
- break;
- case IPOPT_RR:
- buff++;
- if ((*buff - 3)% 4 != 0) return(1);
- len += *buff;
- opt->record_route.route_size = (*buff -3)/4;
- buff++;
- if (*buff % 4 != 0) return(1);
- opt->record_route.pointer = *buff/4 - 1;
- buff++;
- buff++;
- for (i = 0; i < opt->record_route.route_size; i++) {
- if(i>=MAX_ROUTE)
- return 1;
- opt->record_route.route[i] = *(unsigned long *)buff;
- buff += 4;
- }
- break;
- case IPOPT_SID:
- len += 4;
- buff +=2;
- opt->stream = *(unsigned short *)buff;
- buff += 2;
- break;
- case IPOPT_TIMESTAMP:
- buff++;
- len += *buff;
- if (*buff % 4 != 0) return(1);
- opt->tstamp.len = *buff / 4 - 1;
- buff++;
- if ((*buff - 1) % 4 != 0) return(1);
- opt->tstamp.ptr = (*buff-1)/4;
- buff++;
- opt->tstamp.x.full_char = *buff;
- buff++;
- for (i = 0; i < opt->tstamp.len; i++) {
- opt->tstamp.data[i] = *(unsigned long *)buff;
- buff += 4;
- }
- break;
- default:
- return(1);
- }
-
- if (opt->record_route.route_size == 0) {
- if (opt->strict_route.route_size != 0) {
- memcpy(&(opt->record_route), &(opt->strict_route),
- sizeof(opt->record_route));
- } else if (opt->loose_route.route_size != 0) {
- memcpy(&(opt->record_route), &(opt->loose_route),
- sizeof(opt->record_route));
- }
- }
-
- if (opt->strict_route.route_size != 0 &&
- opt->strict_route.route_size != opt->strict_route.pointer) {
- strict_route(iph, opt);
- return(0);
- }
-
- if (opt->loose_route.route_size != 0 &&
- opt->loose_route.route_size != opt->loose_route.pointer) {
- loose_route(iph, opt);
- return(0);
- }
-
- return(0);
-}
-
-/*
- * This routine does all the checksum computations that don't
- * require anything special (like copying or special headers).
- */
-
-unsigned short ip_compute_csum(unsigned char * buff, int len)
-{
- unsigned long sum = 0;
-
- /* Do the first multiple of 4 bytes and convert to 16 bits. */
- if (len > 3)
- {
- __asm__("clc\n"
- "1:\t"
- "lodsl\n\t"
- "adcl %%eax, %%ebx\n\t"
- "loop 1b\n\t"
- "adcl $0, %%ebx\n\t"
- "movl %%ebx, %%eax\n\t"
- "shrl $16, %%eax\n\t"
- "addw %%ax, %%bx\n\t"
- "adcw $0, %%bx"
- : "=b" (sum) , "=S" (buff)
- : "0" (sum), "c" (len >> 2) ,"1" (buff)
- : "ax", "cx", "si", "bx" );
- }
- if (len & 2)
- {
- __asm__("lodsw\n\t"
- "addw %%ax, %%bx\n\t"
- "adcw $0, %%bx"
- : "=b" (sum), "=S" (buff)
- : "0" (sum), "1" (buff)
- : "bx", "ax", "si");
- }
- if (len & 1)
- {
- __asm__("lodsb\n\t"
- "movb $0, %%ah\n\t"
- "addw %%ax, %%bx\n\t"
- "adcw $0, %%bx"
- : "=b" (sum), "=S" (buff)
- : "0" (sum), "1" (buff)
- : "bx", "ax", "si");
- }
- sum =~sum;
- return(sum & 0xffff);
-}
-
-/*
- * Generate a checksum for an outgoing IP datagram.
- */
-
-void ip_send_check(struct iphdr *iph)
-{
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-}
-
-/************************ Fragment Handlers From NET2E **********************************/
-
-
-/*
- * This fragment handler is a bit of a heap. On the other hand it works quite
- * happily and handles things quite well.
- */
-
-static struct ipq *ipqueue = NULL; /* IP fragment queue */
-
-/*
- * Create a new fragment entry.
- */
-
-static struct ipfrag *ip_frag_create(int offset, int end, struct sk_buff *skb, unsigned char *ptr)
-{
- struct ipfrag *fp;
-
- fp = (struct ipfrag *) kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);
- if (fp == NULL)
- {
- printk("IP: frag_create: no memory left !\n");
- return(NULL);
- }
- memset(fp, 0, sizeof(struct ipfrag));
-
- /* Fill in the structure. */
- fp->offset = offset;
- fp->end = end;
- fp->len = end - offset;
- fp->skb = skb;
- fp->ptr = ptr;
-
- return(fp);
-}
-
-
-/*
- * Find the correct entry in the "incomplete datagrams" queue for
- * this IP datagram, and return the queue entry address if found.
- */
-
-static struct ipq *ip_find(struct iphdr *iph)
-{
- struct ipq *qp;
- struct ipq *qplast;
-
- cli();
- qplast = NULL;
- for(qp = ipqueue; qp != NULL; qplast = qp, qp = qp->next)
- {
- if (iph->id== qp->iph->id && iph->saddr == qp->iph->saddr &&
- iph->daddr == qp->iph->daddr && iph->protocol == qp->iph->protocol)
- {
- del_timer(&qp->timer); /* So it doesn't vanish on us. The timer will be reset anyway */
- sti();
- return(qp);
- }
- }
- sti();
- return(NULL);
-}
-
-
-/*
- * Remove an entry from the "incomplete datagrams" queue, either
- * because we completed, reassembled and processed it, or because
- * it timed out.
- */
-
-static void ip_free(struct ipq *qp)
-{
- struct ipfrag *fp;
- struct ipfrag *xp;
-
- /*
- * Stop the timer for this entry.
- */
-
- del_timer(&qp->timer);
-
- /* Remove this entry from the "incomplete datagrams" queue. */
- cli();
- if (qp->prev == NULL)
- {
- ipqueue = qp->next;
- if (ipqueue != NULL)
- ipqueue->prev = NULL;
- }
- else
- {
- qp->prev->next = qp->next;
- if (qp->next != NULL)
- qp->next->prev = qp->prev;
- }
-
- /* Release all fragment data. */
-
- fp = qp->fragments;
- while (fp != NULL)
- {
- xp = fp->next;
- IS_SKB(fp->skb);
- kfree_skb(fp->skb,FREE_READ);
- kfree_s(fp, sizeof(struct ipfrag));
- fp = xp;
- }
-
- /* Release the MAC header. */
- kfree_s(qp->mac, qp->maclen);
-
- /* Release the IP header. */
- kfree_s(qp->iph, qp->ihlen + 8);
-
- /* Finally, release the queue descriptor itself. */
- kfree_s(qp, sizeof(struct ipq));
- sti();
-}
-
-
-/*
- * Oops- a fragment queue timed out. Kill it and send an ICMP reply.
- */
-
-static void ip_expire(unsigned long arg)
-{
- struct ipq *qp;
-
- qp = (struct ipq *)arg;
-
- /*
- * Send an ICMP "Fragment Reassembly Timeout" message.
- */
-
- ip_statistics.IpReasmTimeout++;
- ip_statistics.IpReasmFails++;
- /* This if is always true... shrug */
- if(qp->fragments!=NULL)
- icmp_send(qp->fragments->skb,ICMP_TIME_EXCEEDED,
- ICMP_EXC_FRAGTIME, 0, qp->dev);
-
- /*
- * Nuke the fragment queue.
- */
- ip_free(qp);
-}
-
-
-/*
- * Add an entry to the 'ipq' queue for a newly received IP datagram.
- * We will (hopefully :-) receive all other fragments of this datagram
- * in time, so we just create a queue for this datagram, in which we
- * will insert the received fragments at their respective positions.
- */
-
-static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph, struct device *dev)
-{
- struct ipq *qp;
- int maclen;
- int ihlen;
-
- qp = (struct ipq *) kmalloc(sizeof(struct ipq), GFP_ATOMIC);
- if (qp == NULL)
- {
- printk("IP: create: no memory left !\n");
- return(NULL);
- skb->dev = qp->dev;
- }
- memset(qp, 0, sizeof(struct ipq));
-
- /*
- * Allocate memory for the MAC header.
- *
- * FIXME: We have a maximum MAC address size limit and define
- * elsewhere. We should use it here and avoid the 3 kmalloc() calls
- */
-
- maclen = ((unsigned long) iph) - ((unsigned long) skb->data);
- qp->mac = (unsigned char *) kmalloc(maclen, GFP_ATOMIC);
- if (qp->mac == NULL)
- {
- printk("IP: create: no memory left !\n");
- kfree_s(qp, sizeof(struct ipq));
- return(NULL);
- }
-
- /*
- * Allocate memory for the IP header (plus 8 octets for ICMP).
- */
-
- ihlen = (iph->ihl * sizeof(unsigned long));
- qp->iph = (struct iphdr *) kmalloc(ihlen + 8, GFP_ATOMIC);
- if (qp->iph == NULL)
- {
- printk("IP: create: no memory left !\n");
- kfree_s(qp->mac, maclen);
- kfree_s(qp, sizeof(struct ipq));
- return(NULL);
- }
-
- /* Fill in the structure. */
- memcpy(qp->mac, skb->data, maclen);
- memcpy(qp->iph, iph, ihlen + 8);
- qp->len = 0;
- qp->ihlen = ihlen;
- qp->maclen = maclen;
- qp->fragments = NULL;
- qp->dev = dev;
-
- /* Start a timer for this entry. */
- qp->timer.expires = IP_FRAG_TIME; /* about 30 seconds */
- qp->timer.data = (unsigned long) qp; /* pointer to queue */
- qp->timer.function = ip_expire; /* expire function */
- add_timer(&qp->timer);
-
- /* Add this entry to the queue. */
- qp->prev = NULL;
- cli();
- qp->next = ipqueue;
- if (qp->next != NULL)
- qp->next->prev = qp;
- ipqueue = qp;
- sti();
- return(qp);
-}
-
-
-/*
- * See if a fragment queue is complete.
- */
-
-static int ip_done(struct ipq *qp)
-{
- struct ipfrag *fp;
- int offset;
-
- /* Only possible if we received the final fragment. */
- if (qp->len == 0)
- return(0);
-
- /* Check all fragment offsets to see if they connect. */
- fp = qp->fragments;
- offset = 0;
- while (fp != NULL)
- {
- if (fp->offset > offset)
- return(0); /* fragment(s) missing */
- offset = fp->end;
- fp = fp->next;
- }
-
- /* All fragments are present. */
- return(1);
-}
-
-
-/*
- * Build a new IP datagram from all its fragments.
- *
- * FIXME: We copy here because we lack an effective way of handling lists
- * of bits on input. Until the new skb data handling is in I'm not going
- * to touch this with a bargepole. This also causes a 4Kish limit on
- * packet sizes.
- */
-
-static struct sk_buff *ip_glue(struct ipq *qp)
-{
- struct sk_buff *skb;
- struct iphdr *iph;
- struct ipfrag *fp;
- unsigned char *ptr;
- int count, len;
-
- /*
- * Allocate a new buffer for the datagram.
- */
-
- len = qp->maclen + qp->ihlen + qp->len;
-
- if ((skb = alloc_skb(len,GFP_ATOMIC)) == NULL)
- {
- ip_statistics.IpReasmFails++;
- printk("IP: queue_glue: no memory for gluing queue 0x%X\n", (int) qp);
- ip_free(qp);
- return(NULL);
- }
-
- /* Fill in the basic details. */
- skb->len = (len - qp->maclen);
- skb->h.raw = skb->data;
- skb->free = 1;
-
- /* Copy the original MAC and IP headers into the new buffer. */
- ptr = (unsigned char *) skb->h.raw;
- memcpy(ptr, ((unsigned char *) qp->mac), qp->maclen);
- ptr += qp->maclen;
- memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen);
- ptr += qp->ihlen;
- skb->h.raw += qp->maclen;
-
- count = 0;
-
- /* Copy the data portions of all fragments into the new buffer. */
- fp = qp->fragments;
- while(fp != NULL)
- {
- if(count+fp->len > skb->len)
- {
- printk("Invalid fragment list: Fragment over size.\n");
- ip_free(qp);
- kfree_skb(skb,FREE_WRITE);
- ip_statistics.IpReasmFails++;
- return NULL;
- }
- memcpy((ptr + fp->offset), fp->ptr, fp->len);
- count += fp->len;
- fp = fp->next;
- }
-
- /* We glued together all fragments, so remove the queue entry. */
- ip_free(qp);
-
- /* Done with all fragments. Fixup the new IP header. */
- iph = skb->h.iph;
- iph->frag_off = 0;
- iph->tot_len = htons((iph->ihl * sizeof(unsigned long)) + count);
- skb->ip_hdr = iph;
-
- ip_statistics.IpReasmOKs++;
- return(skb);
-}
-
-
-/*
- * Process an incoming IP datagram fragment.
- */
-
-static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct device *dev)
-{
- struct ipfrag *prev, *next;
- struct ipfrag *tfp;
- struct ipq *qp;
- struct sk_buff *skb2;
- unsigned char *ptr;
- int flags, offset;
- int i, ihl, end;
-
- ip_statistics.IpReasmReqds++;
-
- /* Find the entry of this IP datagram in the "incomplete datagrams" queue. */
- qp = ip_find(iph);
-
- /* Is this a non-fragmented datagram? */
- offset = ntohs(iph->frag_off);
- flags = offset & ~IP_OFFSET;
- offset &= IP_OFFSET;
- if (((flags & IP_MF) == 0) && (offset == 0))
- {
- if (qp != NULL)
- ip_free(qp); /* Huh? How could this exist?? */
- return(skb);
- }
-
- offset <<= 3; /* offset is in 8-byte chunks */
-
- /*
- * If the queue already existed, keep restarting its timer as long
- * as we still are receiving fragments. Otherwise, create a fresh
- * queue entry.
- */
-
- if (qp != NULL)
- {
- del_timer(&qp->timer);
- qp->timer.expires = IP_FRAG_TIME; /* about 30 seconds */
- qp->timer.data = (unsigned long) qp; /* pointer to queue */
- qp->timer.function = ip_expire; /* expire function */
- add_timer(&qp->timer);
- }
- else
- {
- /*
- * If we failed to create it, then discard the frame
- */
- if ((qp = ip_create(skb, iph, dev)) == NULL)
- {
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
- ip_statistics.IpReasmFails++;
- return NULL;
- }
- }
-
- /*
- * Determine the position of this fragment.
- */
-
- ihl = (iph->ihl * sizeof(unsigned long));
- end = offset + ntohs(iph->tot_len) - ihl;
-
- /*
- * Point into the IP datagram 'data' part.
- */
-
- ptr = skb->data + dev->hard_header_len + ihl;
-
- /*
- * Is this the final fragment?
- */
-
- if ((flags & IP_MF) == 0)
- qp->len = end;
-
- /*
- * Find out which fragments are in front and at the back of us
- * in the chain of fragments so far. We must know where to put
- * this fragment, right?
- */
-
- prev = NULL;
- for(next = qp->fragments; next != NULL; next = next->next)
- {
- if (next->offset > offset)
- break; /* bingo! */
- prev = next;
- }
-
- /*
- * We found where to put this one.
- * Check for overlap with preceding fragment, and, if needed,
- * align things so that any overlaps are eliminated.
- */
- if (prev != NULL && offset < prev->end)
- {
- i = prev->end - offset;
- offset += i; /* ptr into datagram */
- ptr += i; /* ptr into fragment data */
- }
-
- /*
- * Look for overlap with succeeding segments.
- * If we can merge fragments, do it.
- */
-
- for(; next != NULL; next = tfp)
- {
- tfp = next->next;
- if (next->offset >= end)
- break; /* no overlaps at all */
-
- i = end - next->offset; /* overlap is 'i' bytes */
- next->len -= i; /* so reduce size of */
- next->offset += i; /* next fragment */
- next->ptr += i;
-
- /*
- * If we get a frag size of <= 0, remove it and the packet
- * that it goes with.
- */
- if (next->len <= 0)
- {
- if (next->prev != NULL)
- next->prev->next = next->next;
- else
- qp->fragments = next->next;
-
- if (tfp->next != NULL)
- next->next->prev = next->prev;
-
- kfree_skb(next->skb,FREE_READ);
- kfree_s(next, sizeof(struct ipfrag));
- }
- }
-
- /*
- * Insert this fragment in the chain of fragments.
- */
-
- tfp = NULL;
- tfp = ip_frag_create(offset, end, skb, ptr);
-
- /*
- * No memory to save the fragment - so throw the lot
- */
-
- if (!tfp)
- {
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
- return NULL;
- }
- tfp->prev = prev;
- tfp->next = next;
- if (prev != NULL)
- prev->next = tfp;
- else
- qp->fragments = tfp;
-
- if (next != NULL)
- next->prev = tfp;
-
- /*
- * OK, so we inserted this new fragment into the chain.
- * Check if we now have a full IP datagram which we can
- * bump up to the IP layer...
- */
-
- if (ip_done(qp))
- {
- skb2 = ip_glue(qp); /* glue together the fragments */
- return(skb2);
- }
- return(NULL);
-}
-
-
-/*
- * This IP datagram is too large to be sent in one piece. Break it up into
- * smaller pieces (each of size equal to the MAC header plus IP header plus
- * a block of the data of the original IP data part) that will yet fit in a
- * single device frame, and queue such a frame for sending by calling the
- * ip_queue_xmit(). Note that this is recursion, and bad things will happen
- * if this function causes a loop...
- *
- * Yes this is inefficient, feel free to submit a quicker one.
- *
- * **Protocol Violation**
- * We copy all the options to each fragment. !FIXME!
- */
-void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int is_frag)
-{
- struct iphdr *iph;
- unsigned char *raw;
- unsigned char *ptr;
- struct sk_buff *skb2;
- int left, mtu, hlen, len;
- int offset;
- unsigned long flags;
-
- /*
- * Point into the IP datagram header.
- */
-
- raw = skb->data;
- iph = (struct iphdr *) (raw + dev->hard_header_len);
-
- skb->ip_hdr = iph;
-
- /*
- * Setup starting values.
- */
-
- hlen = (iph->ihl * sizeof(unsigned long));
- left = ntohs(iph->tot_len) - hlen; /* Space per frame */
- hlen += dev->hard_header_len; /* Total header size */
- mtu = (dev->mtu - hlen); /* Size of data space */
- ptr = (raw + hlen); /* Where to start from */
-
- /*
- * Check for any "DF" flag. [DF means do not fragment]
- */
-
- if (ntohs(iph->frag_off) & IP_DF)
- {
- /*
- * Reply giving the MTU of the failed hop.
- */
- ip_statistics.IpFragFails++;
- icmp_send(skb,ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev->mtu, dev);
- return;
- }
-
- /*
- * The protocol doesn't seem to say what to do in the case that the
- * frame + options doesn't fit the mtu. As it used to fall down dead
- * in this case we were fortunate it didn't happen
- */
-
- if(mtu<8)
- {
- /* It's wrong but it's better than nothing */
- icmp_send(skb,ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED,dev->mtu, dev);
- ip_statistics.IpFragFails++;
- return;
- }
-
- /*
- * Fragment the datagram.
- */
-
- /*
- * The initial offset is 0 for a complete frame. When
- * fragmenting fragments it's wherever this one starts.
- */
-
- if (is_frag & 2)
- offset = (ntohs(iph->frag_off) & 0x1fff) << 3;
- else
- offset = 0;
-
-
- /*
- * Keep copying data until we run out.
- */
-
- while(left > 0)
- {
- len = left;
- /* IF: it doesn't fit, use 'mtu' - the data space left */
- if (len > mtu)
- len = mtu;
- /* IF: we are not sending upto and including the packet end
- then align the next start on an eight byte boundary */
- if (len < left)
- {
- len/=8;
- len*=8;
- }
- /*
- * Allocate buffer.
- */
-
- if ((skb2 = alloc_skb(len + hlen,GFP_ATOMIC)) == NULL)
- {
- printk("IP: frag: no memory for new fragment!\n");
- ip_statistics.IpFragFails++;
- return;
- }
-
- /*
- * Set up data on packet
- */
-
- skb2->arp = skb->arp;
- if(skb->free==0)
- printk("IP fragmenter: BUG free!=1 in fragmenter\n");
- skb2->free = 1;
- skb2->len = len + hlen;
- skb2->h.raw=(char *) skb2->data;
- /*
- * Charge the memory for the fragment to any owner
- * it might possess
- */
-
- save_flags(flags);
- if (sk)
- {
- cli();
- sk->wmem_alloc += skb2->mem_len;
- skb2->sk=sk;
- }
- restore_flags(flags);
- skb2->raddr = skb->raddr; /* For rebuild_header - must be here */
-
- /*
- * Copy the packet header into the new buffer.
- */
-
- memcpy(skb2->h.raw, raw, hlen);
-
- /*
- * Copy a block of the IP datagram.
- */
- memcpy(skb2->h.raw + hlen, ptr, len);
- left -= len;
-
- skb2->h.raw+=dev->hard_header_len;
-
- /*
- * Fill in the new header fields.
- */
- iph = (struct iphdr *)(skb2->h.raw/*+dev->hard_header_len*/);
- iph->frag_off = htons((offset >> 3));
- /*
- * Added AC : If we are fragmenting a fragment thats not the
- * last fragment then keep MF on each bit
- */
- if (left > 0 || (is_frag & 1))
- iph->frag_off |= htons(IP_MF);
- ptr += len;
- offset += len;
-
- /*
- * Put this fragment into the sending queue.
- */
-
- ip_statistics.IpFragCreates++;
-
- ip_queue_xmit(sk, dev, skb2, 2);
- }
- ip_statistics.IpFragOKs++;
-}
-
-
-
-#ifdef CONFIG_IP_FORWARD
-
-/*
- * Forward an IP datagram to its next destination.
- */
-
-static void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag)
-{
- struct device *dev2; /* Output device */
- struct iphdr *iph; /* Our header */
- struct sk_buff *skb2; /* Output packet */
- struct rtable *rt; /* Route we use */
- unsigned char *ptr; /* Data pointer */
- unsigned long raddr; /* Router IP address */
-
- /*
- * See if we are allowed to forward this.
- */
-
-#ifdef CONFIG_IP_FIREWALL
- int err;
-
- if((err=ip_fw_chk(skb->h.iph, dev, ip_fw_fwd_chain, ip_fw_fwd_policy, 0))!=1)
- {
- if(err==-1)
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
- return;
- }
-#endif
- /*
- * According to the RFC, we must first decrease the TTL field. If
- * that reaches zero, we must reply an ICMP control message telling
- * that the packet's lifetime expired.
- *
- * Exception:
- * We may not generate an ICMP for an ICMP. icmp_send does the
- * enforcement of this so we can forget it here. It is however
- * sometimes VERY important.
- */
-
- iph = skb->h.iph;
- iph->ttl--;
- if (iph->ttl <= 0)
- {
- /* Tell the sender its packet died... */
- icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);
- return;
- }
-
- /*
- * Re-compute the IP header checksum.
- * This is inefficient. We know what has happened to the header
- * and could thus adjust the checksum as Phil Karn does in KA9Q
- */
-
- ip_send_check(iph);
-
- /*
- * OK, the packet is still valid. Fetch its destination address,
- * and give it to the IP sender for further processing.
- */
-
- rt = ip_rt_route(iph->daddr, NULL, NULL);
- if (rt == NULL)
- {
- /*
- * Tell the sender its packet cannot be delivered. Again
- * ICMP is screened later.
- */
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
- return;
- }
-
-
- /*
- * Gosh. Not only is the packet valid; we even know how to
- * forward it onto its final destination. Can we say this
- * is being plain lucky?
- * If the router told us that there is no GW, use the dest.
- * IP address itself- we seem to be connected directly...
- */
-
- raddr = rt->rt_gateway;
-
- if (raddr != 0)
- {
- /*
- * There is a gateway so find the correct route for it.
- * Gateways cannot in turn be gatewayed.
- */
- rt = ip_rt_route(raddr, NULL, NULL);
- if (rt == NULL)
- {
- /*
- * Tell the sender its packet cannot be delivered...
- */
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
- return;
- }
- if (rt->rt_gateway != 0)
- raddr = rt->rt_gateway;
- }
- else
- raddr = iph->daddr;
-
- /*
- * Having picked a route we can now send the frame out.
- */
-
- dev2 = rt->rt_dev;
-
- /*
- * In IP you never have to forward a frame on the interface that it
- * arrived upon. We now generate an ICMP HOST REDIRECT giving the route
- * we calculated.
- */
-#ifdef CONFIG_IP_NO_ICMP_REDIRECT
- if (dev == dev2)
- return;
-#else
- if (dev == dev2 && (iph->saddr&dev->pa_mask) == (iph->daddr & dev->pa_mask))
- icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
-#endif
-
- /*
- * We now allocate a new buffer, and copy the datagram into it.
- * If the indicated interface is up and running, kick it.
- */
-
- if (dev2->flags & IFF_UP)
- {
-
- /*
- * Current design decrees we copy the packet. For identical header
- * lengths we could avoid it. The new skb code will let us push
- * data so the problem goes away then.
- */
-
- skb2 = alloc_skb(dev2->hard_header_len + skb->len, GFP_ATOMIC);
- /*
- * This is rare and since IP is tolerant of network failures
- * quite harmless.
- */
- if (skb2 == NULL)
- {
- printk("\nIP: No memory available for IP forward\n");
- return;
- }
- ptr = skb2->data;
- skb2->free = 1;
- skb2->len = skb->len + dev2->hard_header_len;
- skb2->h.raw = ptr;
-
- /*
- * Copy the packet data into the new buffer.
- */
- memcpy(ptr + dev2->hard_header_len, skb->h.raw, skb->len);
-
- /* Now build the MAC header. */
- (void) ip_send(skb2, raddr, skb->len, dev2, dev2->pa_addr);
-
- ip_statistics.IpForwDatagrams++;
-
- /*
- * See if it needs fragmenting. Note in ip_rcv we tagged
- * the fragment type. This must be right so that
- * the fragmenter does the right thing.
- */
-
- if(skb2->len > dev2->mtu + dev2->hard_header_len)
- {
- ip_fragment(NULL,skb2,dev2, is_frag);
- kfree_skb(skb2,FREE_WRITE);
- }
- else
- {
-#ifdef CONFIG_IP_ACCT
- /*
- * Count mapping we shortcut
- */
-
- ip_acct_cnt(iph,dev,ip_acct_chain);
-#endif
-
- /*
- * Map service types to priority. We lie about
- * throughput being low priority, but it's a good
- * choice to help improve general usage.
- */
- if(iph->tos & IPTOS_LOWDELAY)
- dev_queue_xmit(skb2, dev2, SOPRI_INTERACTIVE);
- else if(iph->tos & IPTOS_THROUGHPUT)
- dev_queue_xmit(skb2, dev2, SOPRI_BACKGROUND);
- else
- dev_queue_xmit(skb2, dev2, SOPRI_NORMAL);
- }
- }
-}
-
-
-#endif
-
-/*
- * This function receives all incoming IP datagrams.
- */
-
-int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
-{
- struct iphdr *iph = skb->h.iph;
- struct sock *raw_sk=NULL;
- unsigned char hash;
- unsigned char flag = 0;
- unsigned char opts_p = 0; /* Set iff the packet has options. */
- struct inet_protocol *ipprot;
- static struct options opt; /* since we don't use these yet, and they
- take up stack space. */
- int brd=IS_MYADDR;
- int is_frag=0;
-#ifdef CONFIG_IP_FIREWALL
- int err;
-#endif
-
- ip_statistics.IpInReceives++;
-
- /*
- * Tag the ip header of this packet so we can find it
- */
-
- skb->ip_hdr = iph;
-
- /*
- * Is the datagram acceptable?
- *
- * 1. Length at least the size of an ip header
- * 2. Version of 4
- * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums]
- * (4. We ought to check for IP multicast addresses and undefined types.. does this matter ?)
- */
-
- if (skb->len<sizeof(struct iphdr) || iph->ihl<5 || iph->version != 4 || ip_fast_csum((unsigned char *)iph, iph->ihl) !=0)
- {
- ip_statistics.IpInHdrErrors++;
- kfree_skb(skb, FREE_WRITE);
- return(0);
- }
-
- /*
- * See if the firewall wants to dispose of the packet.
- */
-
-#ifdef CONFIG_IP_FIREWALL
-
- if ((err=ip_fw_chk(iph,dev,ip_fw_blk_chain,ip_fw_blk_policy, 0))!=1)
- {
- if(err==-1)
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
- kfree_skb(skb, FREE_WRITE);
- return 0;
- }
-
-#endif
-
- /*
- * Our transport medium may have padded the buffer out. Now we know it
- * is IP we can trim to the true length of the frame.
- */
-
- skb->len=ntohs(iph->tot_len);
-
- /*
- * Next analyse the packet for options. Studies show under one packet in
- * a thousand have options....
- */
-
- if (iph->ihl != 5)
- { /* Fast path for the typical optionless IP packet. */
- memset((char *) &opt, 0, sizeof(opt));
- if (do_options(iph, &opt) != 0)
- return 0;
- opts_p = 1;
- }
-
- /*
- * Remember if the frame is fragmented.
- */
-
- if(iph->frag_off)
- {
- if (iph->frag_off & 0x0020)
- is_frag|=1;
- /*
- * Last fragment ?
- */
-
- if (ntohs(iph->frag_off) & 0x1fff)
- is_frag|=2;
- }
-
- /*
- * Do any IP forwarding required. chk_addr() is expensive -- avoid it someday.
- *
- * This is inefficient. While finding out if it is for us we could also compute
- * the routing table entry. This is where the great unified cache theory comes
- * in as and when someone implements it
- *
- * For most hosts over 99% of packets match the first conditional
- * and don't go via ip_chk_addr. Note: brd is set to IS_MYADDR at
- * function entry.
- */
-
- if ( iph->daddr != skb->dev->pa_addr && (brd = ip_chk_addr(iph->daddr)) == 0)
- {
- /*
- * Don't forward multicast or broadcast frames.
- */
-
- if(skb->pkt_type!=PACKET_HOST || brd==IS_BROADCAST)
- {
- kfree_skb(skb,FREE_WRITE);
- return 0;
- }
-
- /*
- * The packet is for another target. Forward the frame
- */
-
-#ifdef CONFIG_IP_FORWARD
- ip_forward(skb, dev, is_frag);
-#else
-/* printk("Machine %lx tried to use us as a forwarder to %lx but we have forwarding disabled!\n",
- iph->saddr,iph->daddr);*/
- ip_statistics.IpInAddrErrors++;
-#endif
- /*
- * The forwarder is inefficient and copies the packet. We
- * free the original now.
- */
-
- kfree_skb(skb, FREE_WRITE);
- return(0);
- }
-
-#ifdef CONFIG_IP_MULTICAST
-
- if(brd==IS_MULTICAST && iph->daddr!=IGMP_ALL_HOSTS && !(dev->flags&IFF_LOOPBACK))
- {
- /*
- * Check it is for one of our groups
- */
- struct ip_mc_list *ip_mc=dev->ip_mc_list;
- do
- {
- if(ip_mc==NULL)
- {
- kfree_skb(skb, FREE_WRITE);
- return 0;
- }
- if(ip_mc->multiaddr==iph->daddr)
- break;
- ip_mc=ip_mc->next;
- }
- while(1);
- }
-#endif
- /*
- * Account for the packet
- */
-
-#ifdef CONFIG_IP_ACCT
- ip_acct_cnt(iph,dev, ip_acct_chain);
-#endif
-
- /*
- * Reassemble IP fragments.
- */
-
- if(is_frag)
- {
- /* Defragment. Obtain the complete packet if there is one */
- skb=ip_defrag(iph,skb,dev);
- if(skb==NULL)
- return 0;
- skb->dev = dev;
- iph=skb->h.iph;
- }
-
-
-
- /*
- * Point into the IP datagram, just past the header.
- */
-
- skb->ip_hdr = iph;
- skb->h.raw += iph->ihl*4;
-
- /*
- * Deliver to raw sockets. This is fun as to avoid copies we want to make no surplus copies.
- */
-
- hash = iph->protocol & (SOCK_ARRAY_SIZE-1);
-
- /* If there maybe a raw socket we must check - if not we don't care less */
- if((raw_sk=raw_prot.sock_array[hash])!=NULL)
- {
- struct sock *sknext=NULL;
- struct sk_buff *skb1;
- raw_sk=get_sock_raw(raw_sk, hash, iph->saddr, iph->daddr);
- if(raw_sk) /* Any raw sockets */
- {
- do
- {
- /* Find the next */
- sknext=get_sock_raw(raw_sk->next, hash, iph->saddr, iph->daddr);
- if(sknext)
- skb1=skb_clone(skb, GFP_ATOMIC);
- else
- break; /* One pending raw socket left */
- if(skb1)
- raw_rcv(raw_sk, skb1, dev, iph->saddr,iph->daddr);
- raw_sk=sknext;
- }
- while(raw_sk!=NULL);
- /* Here either raw_sk is the last raw socket, or NULL if none */
- /* We deliver to the last raw socket AFTER the protocol checks as it avoids a surplus copy */
- }
- }
-
- /*
- * skb->h.raw now points at the protocol beyond the IP header.
- */
-
- hash = iph->protocol & (MAX_INET_PROTOS -1);
- for (ipprot = (struct inet_protocol *)inet_protos[hash];ipprot != NULL;ipprot=(struct inet_protocol *)ipprot->next)
- {
- struct sk_buff *skb2;
-
- if (ipprot->protocol != iph->protocol)
- continue;
- /*
- * See if we need to make a copy of it. This will
- * only be set if more than one protocol wants it.
- * and then not for the last one. If there is a pending
- * raw delivery wait for that
- */
- if (ipprot->copy || raw_sk)
- {
- skb2 = skb_clone(skb, GFP_ATOMIC);
- if(skb2==NULL)
- continue;
- }
- else
- {
- skb2 = skb;
- }
- flag = 1;
-
- /*
- * Pass on the datagram to each protocol that wants it,
- * based on the datagram protocol. We should really
- * check the protocol handler's return values here...
- */
- ipprot->handler(skb2, dev, opts_p ? &opt : 0, iph->daddr,
- (ntohs(iph->tot_len) - (iph->ihl * 4)),
- iph->saddr, 0, ipprot);
-
- }
-
- /*
- * All protocols checked.
- * If this packet was a broadcast, we may *not* reply to it, since that
- * causes (proven, grin) ARP storms and a leakage of memory (i.e. all
- * ICMP reply messages get queued up for transmission...)
- */
-
- if(raw_sk!=NULL) /* Shift to last raw user */
- raw_rcv(raw_sk, skb, dev, iph->saddr, iph->daddr);
- else if (!flag) /* Free and report errors */
- {
- if (brd != IS_BROADCAST && brd!=IS_MULTICAST)
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0, dev);
- kfree_skb(skb, FREE_WRITE);
- }
-
- return(0);
-}
-
-/*
- * Loop a packet back to the sender.
- */
-
-static void ip_loopback(struct device *old_dev, struct sk_buff *skb)
-{
- extern struct device loopback_dev;
- struct device *dev=&loopback_dev;
- int len=skb->len-old_dev->hard_header_len;
- struct sk_buff *newskb=alloc_skb(len+dev->hard_header_len, GFP_ATOMIC);
-
- if(newskb==NULL)
- return;
-
- newskb->link3=NULL;
- newskb->sk=NULL;
- newskb->dev=dev;
- newskb->saddr=skb->saddr;
- newskb->daddr=skb->daddr;
- newskb->raddr=skb->raddr;
- newskb->free=1;
- newskb->lock=0;
- newskb->users=0;
- newskb->pkt_type=skb->pkt_type;
- newskb->len=len+dev->hard_header_len;
-
-
- newskb->ip_hdr=(struct iphdr *)(newskb->data+ip_send(newskb, skb->ip_hdr->daddr, len, dev, skb->ip_hdr->saddr));
- memcpy(newskb->ip_hdr,skb->ip_hdr,len);
-
- /* Recurse. The device check against IFF_LOOPBACK will stop infinite recursion */
-
- /*printk("Loopback output queued [%lX to %lX].\n", newskb->ip_hdr->saddr,newskb->ip_hdr->daddr);*/
- ip_queue_xmit(NULL, dev, newskb, 1);
-}
-
-
-/*
- * Queues a packet to be sent, and starts the transmitter
- * if necessary. if free = 1 then we free the block after
- * transmit, otherwise we don't. If free==2 we not only
- * free the block but also don't assign a new ip seq number.
- * This routine also needs to put in the total length,
- * and compute the checksum
- */
-
-void ip_queue_xmit(struct sock *sk, struct device *dev,
- struct sk_buff *skb, int free)
-{
- struct iphdr *iph;
- unsigned char *ptr;
-
- /* Sanity check */
- if (dev == NULL)
- {
- printk("IP: ip_queue_xmit dev = NULL\n");
- return;
- }
-
- IS_SKB(skb);
-
- /*
- * Do some book-keeping in the packet for later
- */
-
-
- skb->dev = dev;
- skb->when = jiffies;
-
- /*
- * Find the IP header and set the length. This is bad
- * but once we get the skb data handling code in the
- * hardware will push its header sensibly and we will
- * set skb->ip_hdr to avoid this mess and the fixed
- * header length problem
- */
-
- ptr = skb->data;
- ptr += dev->hard_header_len;
- iph = (struct iphdr *)ptr;
- skb->ip_hdr = iph;
- iph->tot_len = ntohs(skb->len-dev->hard_header_len);
-
-#ifdef CONFIG_IP_FIREWALL
- if(ip_fw_chk(iph, dev, ip_fw_blk_chain, ip_fw_blk_policy, 0) != 1)
- /* just don't send this packet */
- return;
-#endif
-
- /*
- * No reassigning numbers to fragments...
- */
-
- if(free!=2)
- iph->id = htons(ip_id_count++);
- else
- free=1;
-
- /* All buffers without an owner socket get freed */
- if (sk == NULL)
- free = 1;
-
- skb->free = free;
-
- /*
- * Do we need to fragment. Again this is inefficient.
- * We need to somehow lock the original buffer and use
- * bits of it.
- */
-
- if(skb->len > dev->mtu + dev->hard_header_len)
- {
- ip_fragment(sk,skb,dev,0);
- IS_SKB(skb);
- kfree_skb(skb,FREE_WRITE);
- return;
- }
-
- /*
- * Add an IP checksum
- */
-
- ip_send_check(iph);
-
- /*
- * Print the frame when debugging
- */
-
- /*
- * More debugging. You cannot queue a packet already on a list
- * Spot this and moan loudly.
- */
- if (skb->next != NULL)
- {
- printk("ip_queue_xmit: next != NULL\n");
- skb_unlink(skb);
- }
-
- /*
- * If a sender wishes the packet to remain unfreed
- * we add it to his send queue. This arguably belongs
- * in the TCP level since nobody else uses it. BUT
- * remember IPng might change all the rules.
- */
-
- if (!free)
- {
- unsigned long flags;
- /* The socket now has more outstanding blocks */
-
- sk->packets_out++;
-
- /* Protect the list for a moment */
- save_flags(flags);
- cli();
-
- if (skb->link3 != NULL)
- {
- printk("ip.c: link3 != NULL\n");
- skb->link3 = NULL;
- }
- if (sk->send_head == NULL)
- {
- sk->send_tail = skb;
- sk->send_head = skb;
- }
- else
- {
- sk->send_tail->link3 = skb;
- sk->send_tail = skb;
- }
- /* skb->link3 is NULL */
-
- /* Interrupt restore */
- restore_flags(flags);
- }
- else
- /* Remember who owns the buffer */
- skb->sk = sk;
-
- /*
- * If the indicated interface is up and running, send the packet.
- */
-
- ip_statistics.IpOutRequests++;
-#ifdef CONFIG_IP_ACCT
- ip_acct_cnt(iph,dev, ip_acct_chain);
-#endif
-
-#ifdef CONFIG_IP_MULTICAST
-
- /*
- * Multicasts are looped back for other local users
- */
-
- if (MULTICAST(iph->daddr) && !(dev->flags&IFF_LOOPBACK))
- {
- if(sk==NULL || sk->ip_mc_loop)
- {
- if(iph->daddr==IGMP_ALL_HOSTS)
- ip_loopback(dev,skb);
- else
- {
- struct ip_mc_list *imc=dev->ip_mc_list;
- while(imc!=NULL)
- {
- if(imc->multiaddr==iph->daddr)
- {
- ip_loopback(dev,skb);
- break;
- }
- imc=imc->next;
- }
- }
- }
- /* Multicasts with ttl 0 must not go beyond the host */
-
- if(skb->ip_hdr->ttl==0)
- {
- kfree_skb(skb, FREE_READ);
- return;
- }
- }
-#endif
- if((dev->flags&IFF_BROADCAST) && iph->daddr==dev->pa_brdaddr && !(dev->flags&IFF_LOOPBACK))
- ip_loopback(dev,skb);
-
- if (dev->flags & IFF_UP)
- {
- /*
- * If we have an owner use its priority setting,
- * otherwise use NORMAL
- */
-
- if (sk != NULL)
- {
- dev_queue_xmit(skb, dev, sk->priority);
- }
- else
- {
- dev_queue_xmit(skb, dev, SOPRI_NORMAL);
- }
- }
- else
- {
- ip_statistics.IpOutDiscards++;
- if (free)
- kfree_skb(skb, FREE_WRITE);
- }
-}
-
-
-
-#ifdef CONFIG_IP_MULTICAST
-
-/*
- * Write an multicast group list table for the IGMP daemon to
- * read.
- */
-
-int ip_mc_procinfo(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos=0, begin=0;
- struct ip_mc_list *im;
- unsigned long flags;
- int len=0;
- struct device *dev;
-
- len=sprintf(buffer,"Device : Count\tGroup Users Timer\n");
- save_flags(flags);
- cli();
-
- for(dev = dev_base; dev; dev = dev->next)
- {
- if((dev->flags&IFF_UP)&&(dev->flags&IFF_MULTICAST))
- {
- len+=sprintf(buffer+len,"%-10s: %5d\n",
- dev->name, dev->mc_count);
- for(im = dev->ip_mc_list; im; im = im->next)
- {
- len+=sprintf(buffer+len,
- "\t\t\t%08lX %5d %d:%08lX\n",
- im->multiaddr, im->users,
- im->tm_running, im->timer.expires);
- pos=begin+len;
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- }
- }
- }
- restore_flags(flags);
- *start=buffer+(offset-begin);
- len-=(offset-begin);
- if(len>length)
- len=length;
- return len;
-}
-
-
-#endif
-/*
- * Socket option code for IP. This is the end of the line after any TCP,UDP etc options on
- * an IP socket.
- *
- * We implement IP_TOS (type of service), IP_TTL (time to live).
- *
- * Next release we will sort out IP_OPTIONS since for some people are kind of important.
- */
-
-int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
-{
- int val,err;
-#if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
- struct ip_fw tmp_fw;
-#endif
- if (optval == NULL)
- return(-EINVAL);
-
- err=verify_area(VERIFY_READ, optval, sizeof(int));
- if(err)
- return err;
-
- val = get_fs_long((unsigned long *)optval);
-
- if(level!=SOL_IP)
- return -EOPNOTSUPP;
-
- switch(optname)
- {
- case IP_TOS:
- if(val<0||val>255)
- return -EINVAL;
- sk->ip_tos=val;
- if(val==IPTOS_LOWDELAY)
- sk->priority=SOPRI_INTERACTIVE;
- if(val==IPTOS_THROUGHPUT)
- sk->priority=SOPRI_BACKGROUND;
- return 0;
- case IP_TTL:
- if(val<1||val>255)
- return -EINVAL;
- sk->ip_ttl=val;
- return 0;
-#ifdef CONFIG_IP_MULTICAST
- case IP_MULTICAST_TTL:
- {
- unsigned char ucval;
-
- ucval=get_fs_byte((unsigned char *)optval);
- if(ucval<1||ucval>255)
- return -EINVAL;
- sk->ip_mc_ttl=(int)ucval;
- return 0;
- }
- case IP_MULTICAST_LOOP:
- {
- unsigned char ucval;
-
- ucval=get_fs_byte((unsigned char *)optval);
- if(ucval!=0 && ucval!=1)
- return -EINVAL;
- sk->ip_mc_loop=(int)ucval;
- return 0;
- }
- case IP_MULTICAST_IF:
- {
- /* Not fully tested */
- struct in_addr addr;
- struct device *dev=NULL;
-
- /*
- * Check the arguments are allowable
- */
-
- err=verify_area(VERIFY_READ, optval, sizeof(addr));
- if(err)
- return err;
-
- memcpy_fromfs(&addr,optval,sizeof(addr));
-
- printk("MC bind %s\n", in_ntoa(addr.s_addr));
-
- /*
- * What address has been requested
- */
-
- if(addr.s_addr==INADDR_ANY) /* Default */
- {
- sk->ip_mc_name[0]=0;
- return 0;
- }
-
- /*
- * Find the device
- */
-
- for(dev = dev_base; dev; dev = dev->next)
- {
- if((dev->flags&IFF_UP)&&(dev->flags&IFF_MULTICAST)&&
- (dev->pa_addr==addr.s_addr))
- break;
- }
-
- /*
- * Did we find one
- */
-
- if(dev)
- {
- strcpy(sk->ip_mc_name,dev->name);
- return 0;
- }
- return -EADDRNOTAVAIL;
- }
-
- case IP_ADD_MEMBERSHIP:
- {
-
-/*
- * FIXME: Add/Del membership should have a semaphore protecting them from re-entry
- */
- struct ip_mreq mreq;
- static struct options optmem;
- unsigned long route_src;
- struct rtable *rt;
- struct device *dev=NULL;
-
- /*
- * Check the arguments.
- */
-
- err=verify_area(VERIFY_READ, optval, sizeof(mreq));
- if(err)
- return err;
-
- memcpy_fromfs(&mreq,optval,sizeof(mreq));
-
- /*
- * Get device for use later
- */
-
- if(mreq.imr_interface.s_addr==INADDR_ANY)
- {
- /*
- * Not set so scan.
- */
- if((rt=ip_rt_route(mreq.imr_multiaddr.s_addr,&optmem, &route_src))!=NULL)
- {
- dev=rt->rt_dev;
- rt->rt_use--;
- }
- }
- else
- {
- /*
- * Find a suitable device.
- */
- for(dev = dev_base; dev; dev = dev->next)
- {
- if((dev->flags&IFF_UP)&&(dev->flags&IFF_MULTICAST)&&
- (dev->pa_addr==mreq.imr_interface.s_addr))
- break;
- }
- }
-
- /*
- * No device, no cookies.
- */
-
- if(!dev)
- return -ENODEV;
-
- /*
- * Join group.
- */
-
- return ip_mc_join_group(sk,dev,mreq.imr_multiaddr.s_addr);
- }
-
- case IP_DROP_MEMBERSHIP:
- {
- struct ip_mreq mreq;
- struct rtable *rt;
- static struct options optmem;
- unsigned long route_src;
- struct device *dev=NULL;
-
- /*
- * Check the arguments
- */
-
- err=verify_area(VERIFY_READ, optval, sizeof(mreq));
- if(err)
- return err;
-
- memcpy_fromfs(&mreq,optval,sizeof(mreq));
-
- /*
- * Get device for use later
- */
-
- if(mreq.imr_interface.s_addr==INADDR_ANY)
- {
- if((rt=ip_rt_route(mreq.imr_multiaddr.s_addr,&optmem, &route_src))!=NULL)
- {
- dev=rt->rt_dev;
- rt->rt_use--;
- }
- }
- else
- {
- for(dev = dev_base; dev; dev = dev->next)
- {
- if((dev->flags&IFF_UP)&& (dev->flags&IFF_MULTICAST)&&
- (dev->pa_addr==mreq.imr_interface.s_addr))
- break;
- }
- }
-
- /*
- * Did we find a suitable device.
- */
-
- if(!dev)
- return -ENODEV;
-
- /*
- * Leave group
- */
-
- return ip_mc_leave_group(sk,dev,mreq.imr_multiaddr.s_addr);
- }
-#endif
-#ifdef CONFIG_IP_FIREWALL
- case IP_FW_ADD_BLK:
- case IP_FW_DEL_BLK:
- case IP_FW_ADD_FWD:
- case IP_FW_DEL_FWD:
- case IP_FW_CHK_BLK:
- case IP_FW_CHK_FWD:
- case IP_FW_FLUSH_BLK:
- case IP_FW_FLUSH_FWD:
- case IP_FW_ZERO_BLK:
- case IP_FW_ZERO_FWD:
- case IP_FW_POLICY_BLK:
- case IP_FW_POLICY_FWD:
- if(!suser())
- return -EPERM;
- if(optlen>sizeof(tmp_fw) || optlen<1)
- return -EINVAL;
- err=verify_area(VERIFY_READ,optval,optlen);
- if(err)
- return err;
- memcpy_fromfs(&tmp_fw,optval,optlen);
- err=ip_fw_ctl(optname, &tmp_fw,optlen);
- return -err; /* -0 is 0 after all */
-
-#endif
-#ifdef CONFIG_IP_ACCT
- case IP_ACCT_DEL:
- case IP_ACCT_ADD:
- case IP_ACCT_FLUSH:
- case IP_ACCT_ZERO:
- if(!suser())
- return -EPERM;
- if(optlen>sizeof(tmp_fw) || optlen<1)
- return -EINVAL;
- err=verify_area(VERIFY_READ,optval,optlen);
- if(err)
- return err;
- memcpy_fromfs(&tmp_fw, optval,optlen);
- err=ip_acct_ctl(optname, &tmp_fw,optlen);
- return -err; /* -0 is 0 after all */
-#endif
- /* IP_OPTIONS and friends go here eventually */
- default:
- return(-ENOPROTOOPT);
- }
-}
-
-/*
- * Get the options. Note for future reference. The GET of IP options gets the
- * _received_ ones. The set sets the _sent_ ones.
- */
-
-int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
-{
- int val,err;
-#ifdef CONFIG_IP_MULTICAST
- int len;
-#endif
-
- if(level!=SOL_IP)
- return -EOPNOTSUPP;
-
- switch(optname)
- {
- case IP_TOS:
- val=sk->ip_tos;
- break;
- case IP_TTL:
- val=sk->ip_ttl;
- break;
-#ifdef CONFIG_IP_MULTICAST
- case IP_MULTICAST_TTL:
- val=sk->ip_mc_ttl;
- break;
- case IP_MULTICAST_LOOP:
- val=sk->ip_mc_loop;
- break;
- case IP_MULTICAST_IF:
- err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
- if(err)
- return err;
- len=strlen(sk->ip_mc_name);
- err=verify_area(VERIFY_WRITE, optval, len);
- if(err)
- return err;
- put_fs_long(len,(unsigned long *) optlen);
- memcpy_tofs((void *)optval,sk->ip_mc_name, len);
- return 0;
-#endif
- default:
- return(-ENOPROTOOPT);
- }
- err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
- if(err)
- return err;
- put_fs_long(sizeof(int),(unsigned long *) optlen);
-
- err=verify_area(VERIFY_WRITE, optval, sizeof(int));
- if(err)
- return err;
- put_fs_long(val,(unsigned long *)optval);
-
- return(0);
-}
-
-/*
- * IP protocol layer initialiser
- */
-
-static struct packet_type ip_packet_type =
-{
- 0, /* MUTTER ntohs(ETH_P_IP),*/
- NULL, /* All devices */
- ip_rcv,
- NULL,
- NULL,
-};
-
-/*
- * Device notifier
- */
-
-static int ip_rt_event(unsigned long event, void *ptr)
-{
- if(event==NETDEV_DOWN)
- ip_rt_flush(ptr);
- return NOTIFY_DONE;
-}
-
-struct notifier_block ip_rt_notifier={
- ip_rt_event,
- NULL,
- 0
-};
-
-/*
- * IP registers the packet type and then calls the subprotocol initialisers
- */
-
-void ip_init(void)
-{
- ip_packet_type.type=htons(ETH_P_IP);
- dev_add_pack(&ip_packet_type);
-
- /* So we flush routes when a device is downed */
- register_netdevice_notifier(&ip_rt_notifier);
-/* ip_raw_init();
- ip_packet_init();
- ip_tcp_init();
- ip_udp_init();*/
-}
diff --git a/pfinet/linux-inet/ip.h b/pfinet/linux-inet/ip.h
deleted file mode 100644
index 95954a8c..00000000
--- a/pfinet/linux-inet/ip.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the IP module.
- *
- * Version: @(#)ip.h 1.0.2 05/07/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _IP_H
-#define _IP_H
-
-
-#include <linux/ip.h>
-#include <linux/config.h>
-
-#ifndef _SNMP_H
-#include "snmp.h"
-#endif
-
-#include "sock.h" /* struct sock */
-
-/* IP flags. */
-#define IP_CE 0x8000 /* Flag: "Congestion" */
-#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
-#define IP_MF 0x2000 /* Flag: "More Fragments" */
-#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
-
-#define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */
-
-#ifdef CONFIG_IP_MULTICAST
-extern void ip_mc_dropsocket(struct sock *);
-extern void ip_mc_dropdevice(struct device *dev);
-extern int ip_mc_procinfo(char *, char **, off_t, int);
-#define MULTICAST(x) (IN_MULTICAST(htonl(x)))
-#endif
-
-
-/* Describe an IP fragment. */
-struct ipfrag {
- int offset; /* offset of fragment in IP datagram */
- int end; /* last byte of data in datagram */
- int len; /* length of this fragment */
- struct sk_buff *skb; /* complete received fragment */
- unsigned char *ptr; /* pointer into real fragment data */
- struct ipfrag *next; /* linked list pointers */
- struct ipfrag *prev;
-};
-
-/* Describe an entry in the "incomplete datagrams" queue. */
-struct ipq {
- unsigned char *mac; /* pointer to MAC header */
- struct iphdr *iph; /* pointer to IP header */
- int len; /* total length of original datagram */
- short ihlen; /* length of the IP header */
- short maclen; /* length of the MAC header */
- struct timer_list timer; /* when will this queue expire? */
- struct ipfrag *fragments; /* linked list of received fragments */
- struct ipq *next; /* linked list pointers */
- struct ipq *prev;
- struct device *dev; /* Device - for icmp replies */
-};
-
-
-extern int backoff(int n);
-
-extern void ip_print(const struct iphdr *ip);
-extern int ip_ioctl(struct sock *sk, int cmd,
- unsigned long arg);
-extern void ip_route_check(unsigned long daddr);
-extern int ip_build_header(struct sk_buff *skb,
- unsigned long saddr,
- unsigned long daddr,
- struct device **dev, int type,
- struct options *opt, int len,
- int tos,int ttl);
-extern unsigned short ip_compute_csum(unsigned char * buff, int len);
-extern int ip_rcv(struct sk_buff *skb, struct device *dev,
- struct packet_type *pt);
-extern void ip_send_check(struct iphdr *ip);
-extern int ip_id_count;
-extern void ip_queue_xmit(struct sock *sk,
- struct device *dev, struct sk_buff *skb,
- int free);
-extern int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen);
-extern int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen);
-extern void ip_init(void);
-
-extern struct ip_mib ip_statistics;
-
-/*
- * This is a version of ip_compute_csum() optimized for IP headers, which
- * always checksum on 4 octet boundaries.
- * Used by ip.c and slhc.c (the net driver module)
- * (Moved to here by bj0rn@blox.se)
- */
-
-static inline unsigned short ip_fast_csum(unsigned char * buff, int wlen)
-{
- unsigned long sum = 0;
-
- if (wlen)
- {
- unsigned long bogus;
- __asm__("clc\n"
- "1:\t"
- "lodsl\n\t"
- "adcl %3, %0\n\t"
- "decl %2\n\t"
- "jne 1b\n\t"
- "adcl $0, %0\n\t"
- "movl %0, %3\n\t"
- "shrl $16, %3\n\t"
- "addw %w3, %w0\n\t"
- "adcw $0, %w0"
- : "=r" (sum), "=S" (buff), "=r" (wlen), "=a" (bogus)
- : "0" (sum), "1" (buff), "2" (wlen));
- }
- return (~sum) & 0xffff;
-}
-#endif /* _IP_H */
diff --git a/pfinet/linux-inet/ip_fw.c b/pfinet/linux-inet/ip_fw.c
deleted file mode 100644
index 0572c8f1..00000000
--- a/pfinet/linux-inet/ip_fw.c
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * IP firewalling code. This is taken from 4.4BSD. Please note the
- * copyright message below. As per the GPL it must be maintained
- * and the licenses thus do not conflict. While this port is subject
- * to the GPL I also place my modifications under the original
- * license in recognition of the original copyright.
- * -- Alan Cox.
- *
- * Ported from BSD to Linux,
- * Alan Cox 22/Nov/1994.
- * Zeroing /proc and other additions
- * Jos Vos 4/Feb/1995.
- * Merged and included the FreeBSD-Current changes at Ugen's request
- * (but hey it's a lot cleaner now). Ugen would prefer in some ways
- * we waited for his final product but since Linux 1.2.0 is about to
- * appear it's not practical - Read: It works, it's not clean but please
- * don't consider it to be his standard of finished work.
- * Alan Cox 12/Feb/1995
- * Porting bidirectional entries from BSD, fixing accounting issues,
- * adding struct ip_fwpkt for checking packets with interface address
- * Jos Vos 5/Mar/1995.
- *
- * All the real work was done by .....
- */
-
-/*
- * Copyright (c) 1993 Daniel Boulet
- * Copyright (c) 1994 Ugen J.S.Antsilevich
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- */
-
-#include <linux/config.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/config.h>
-
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/icmp.h>
-#include <linux/udp.h>
-#include "ip.h"
-#include "protocol.h"
-#include "route.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "icmp.h"
-#include <linux/ip_fw.h>
-
-/*
- * Implement IP packet firewall
- */
-
-#ifdef CONFIG_IPFIREWALL_DEBUG
-#define dprintf1(a) printk(a)
-#define dprintf2(a1,a2) printk(a1,a2)
-#define dprintf3(a1,a2,a3) printk(a1,a2,a3)
-#define dprintf4(a1,a2,a3,a4) printk(a1,a2,a3,a4)
-#else
-#define dprintf1(a)
-#define dprintf2(a1,a2)
-#define dprintf3(a1,a2,a3)
-#define dprintf4(a1,a2,a3,a4)
-#endif
-
-#define print_ip(a) printf("%d.%d.%d.%d",(ntohl(a.s_addr)>>24)&0xFF,\
- (ntohl(a.s_addr)>>16)&0xFF,\
- (ntohl(a.s_addr)>>8)&0xFF,\
- (ntohl(a.s_addr))&0xFF);
-
-#ifdef IPFIREWALL_DEBUG
-#define dprint_ip(a) print_ip(a)
-#else
-#define dprint_ip(a)
-#endif
-
-#ifdef CONFIG_IP_FIREWALL
-struct ip_fw *ip_fw_fwd_chain;
-struct ip_fw *ip_fw_blk_chain;
-int ip_fw_blk_policy=IP_FW_F_ACCEPT;
-int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
-#endif
-#ifdef CONFIG_IP_ACCT
-struct ip_fw *ip_acct_chain;
-#endif
-
-#define IP_INFO_BLK 0
-#define IP_INFO_FWD 1
-#define IP_INFO_ACCT 2
-
-
-/*
- * Returns 1 if the port is matched by the vector, 0 otherwise
- */
-
-extern inline int port_match(unsigned short *portptr,int nports,unsigned short port,int range_flag)
-{
- if (!nports)
- return 1;
- if ( range_flag )
- {
- if ( portptr[0] <= port && port <= portptr[1] )
- {
- return( 1 );
- }
- nports -= 2;
- portptr += 2;
- }
- while ( nports-- > 0 )
- {
- if ( *portptr++ == port )
- {
- return( 1 );
- }
- }
- return(0);
-}
-
-#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
-
-
-/*
- * Returns 0 if packet should be dropped, 1 if it should be accepted,
- * and -1 if an ICMP host unreachable packet should be sent.
- * Also does accounting so you can feed it the accounting chain.
- * If opt is set to 1, it means that we do this for accounting
- * purposes (searches all entries and handles fragments different).
- * If opt is set to 2, it doesn't count a matching packet, which
- * is used when calling this for checking purposes (IP_FW_CHK_*).
- */
-
-
-int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
-{
- struct ip_fw *f;
- struct tcphdr *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
- struct udphdr *udp=(struct udphdr *)((unsigned long *)ip+ip->ihl);
- __u32 src, dst;
- __u16 src_port=0, dst_port=0;
- unsigned short f_prt=0, prt;
- char notcpsyn=1, frag1, match;
- unsigned short f_flag;
-
- /*
- * If the chain is empty follow policy. The BSD one
- * accepts anything giving you a time window while
- * flushing and rebuilding the tables.
- */
-
- src = ip->saddr;
- dst = ip->daddr;
-
- /*
- * This way we handle fragmented packets.
- * we ignore all fragments but the first one
- * so the whole packet can't be reassembled.
- * This way we relay on the full info which
- * stored only in first packet.
- *
- * Note that this theoretically allows partial packet
- * spoofing. Not very dangerous but paranoid people may
- * wish to play with this. It also allows the so called
- * "fragment bomb" denial of service attack on some types
- * of system.
- */
-
- frag1 = ((ntohs(ip->frag_off) & IP_OFFSET) == 0);
- if (!frag1 && (opt != 1) && (ip->protocol == IPPROTO_TCP ||
- ip->protocol == IPPROTO_UDP))
- return(1);
-
- src = ip->saddr;
- dst = ip->daddr;
-
- /*
- * If we got interface from which packet came
- * we can use the address directly. This is unlike
- * 4.4BSD derived systems that have an address chain
- * per device. We have a device per address with dummy
- * devices instead.
- */
-
- dprintf1("Packet ");
- switch(ip->protocol)
- {
- case IPPROTO_TCP:
- dprintf1("TCP ");
- /* ports stay 0 if it is not the first fragment */
- if (frag1) {
- src_port=ntohs(tcp->source);
- dst_port=ntohs(tcp->dest);
- if(tcp->syn && !tcp->ack)
- /* We *DO* have SYN, value FALSE */
- notcpsyn=0;
- }
- prt=IP_FW_F_TCP;
- break;
- case IPPROTO_UDP:
- dprintf1("UDP ");
- /* ports stay 0 if it is not the first fragment */
- if (frag1) {
- src_port=ntohs(udp->source);
- dst_port=ntohs(udp->dest);
- }
- prt=IP_FW_F_UDP;
- break;
- case IPPROTO_ICMP:
- dprintf2("ICMP:%d ",((char *)portptr)[0]&0xff);
- prt=IP_FW_F_ICMP;
- break;
- default:
- dprintf2("p=%d ",ip->protocol);
- prt=IP_FW_F_ALL;
- break;
- }
- dprint_ip(ip->saddr);
-
- if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
- /* This will print 0 when it is not the first fragment! */
- dprintf2(":%d ", src_port);
- dprint_ip(ip->daddr);
- if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)
- /* This will print 0 when it is not the first fragment! */
- dprintf2(":%d ",dst_port);
- dprintf1("\n");
-
- for (f=chain;f;f=f->fw_next)
- {
- /*
- * This is a bit simpler as we don't have to walk
- * an interface chain as you do in BSD - same logic
- * however.
- */
-
- /*
- * Match can become 0x01 (a "normal" match was found),
- * 0x02 (a reverse match was found), and 0x03 (the
- * IP addresses match in both directions).
- * Now we know in which direction(s) we should look
- * for a match for the TCP/UDP ports. Both directions
- * might match (e.g., when both addresses are on the
- * same network for which an address/mask is given), but
- * the ports might only match in one direction.
- * This was obviously wrong in the original BSD code.
- */
- match = 0x00;
-
- if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr
- && (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
- /* normal direction */
- match |= 0x01;
-
- if ((f->fw_flg & IP_FW_F_BIDIR) &&
- (dst&f->fw_smsk.s_addr)==f->fw_src.s_addr
- && (src&f->fw_dmsk.s_addr)==f->fw_dst.s_addr)
- /* reverse direction */
- match |= 0x02;
-
- if (match)
- {
- /*
- * Look for a VIA match
- */
- if(f->fw_via.s_addr && rif)
- {
- if(rif->pa_addr!=f->fw_via.s_addr)
- continue; /* Mismatch */
- }
- /*
- * Drop through - this is a match
- */
- }
- else
- continue;
-
- /*
- * Ok the chain addresses match.
- */
-
- f_prt=f->fw_flg&IP_FW_F_KIND;
- if (f_prt!=IP_FW_F_ALL)
- {
- /*
- * This is actually buggy as if you set SYN flag
- * on UDP or ICMP firewall it will never work,but
- * actually it is a concern of software which sets
- * firewall entries.
- */
-
- if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
- continue;
- /*
- * Specific firewall - packet's protocol
- * must match firewall's.
- */
-
- if(prt!=f_prt)
- continue;
-
- if(!(prt==IP_FW_F_ICMP || ((match & 0x01) &&
- port_match(&f->fw_pts[0], f->fw_nsp, src_port,
- f->fw_flg&IP_FW_F_SRNG) &&
- port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
- f->fw_flg&IP_FW_F_DRNG)) || ((match & 0x02) &&
- port_match(&f->fw_pts[0], f->fw_nsp, dst_port,
- f->fw_flg&IP_FW_F_SRNG) &&
- port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, src_port,
- f->fw_flg&IP_FW_F_DRNG))))
- {
- continue;
- }
- }
-#ifdef CONFIG_IP_FIREWALL_VERBOSE
- /*
- * VERY ugly piece of code which actually
- * makes kernel printf for denied packets...
- */
-
- if (f->fw_flg & IP_FW_F_PRN)
- {
- if(opt != 1) {
- if(f->fw_flg&IP_FW_F_ACCEPT)
- printk("Accept ");
- else if(f->fw_flg&IP_FW_F_ICMPRPL)
- printk("Reject ");
- else
- printk("Deny ");
- }
- switch(ip->protocol)
- {
- case IPPROTO_TCP:
- printk("TCP ");
- break;
- case IPPROTO_UDP:
- printk("UDP ");
- case IPPROTO_ICMP:
- printk("ICMP ");
- break;
- default:
- printk("p=%d ",ip->protocol);
- break;
- }
- print_ip(ip->saddr);
- if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
- printk(":%d", src_port);
- printk(" ");
- print_ip(ip->daddr);
- if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
- printk(":%d",dst_port);
- printk("\n");
- }
-#endif
- if (opt != 2) {
- f->fw_bcnt+=ntohs(ip->tot_len);
- f->fw_pcnt++;
- }
- if (opt != 1)
- break;
- } /* Loop */
-
- if(opt == 1)
- return 0;
-
- /*
- * We rely on policy defined in the rejecting entry or, if no match
- * was found, we rely on the general policy variable for this type
- * of firewall.
- */
-
- if(f!=NULL) /* A match was found */
- f_flag=f->fw_flg;
- else
- f_flag=policy;
- if(f_flag&IP_FW_F_ACCEPT)
- return 1;
- if(f_flag&IP_FW_F_ICMPRPL)
- return -1;
- return 0;
-}
-
-
-static void zero_fw_chain(struct ip_fw *chainptr)
-{
- struct ip_fw *ctmp=chainptr;
- while(ctmp)
- {
- ctmp->fw_pcnt=0L;
- ctmp->fw_bcnt=0L;
- ctmp=ctmp->fw_next;
- }
-}
-
-static void free_fw_chain(struct ip_fw *volatile* chainptr)
-{
- unsigned long flags;
- save_flags(flags);
- cli();
- while ( *chainptr != NULL )
- {
- struct ip_fw *ftmp;
- ftmp = *chainptr;
- *chainptr = ftmp->fw_next;
- kfree_s(ftmp,sizeof(*ftmp));
- }
- restore_flags(flags);
-}
-
-/* Volatiles to keep some of the compiler versions amused */
-
-static int add_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl)
-{
- struct ip_fw *ftmp;
- struct ip_fw *chtmp=NULL;
- struct ip_fw *volatile chtmp_prev=NULL;
- unsigned long flags;
- unsigned long m_src_mask,m_dst_mask;
- unsigned long n_sa,n_da,o_sa,o_da,o_sm,o_dm,n_sm,n_dm;
- unsigned short n_sr,n_dr,o_sr,o_dr;
- unsigned short oldkind,newkind;
- int addb4=0;
- int n_o,n_n;
-
- save_flags(flags);
-
- ftmp = kmalloc( sizeof(struct ip_fw), GFP_ATOMIC );
- if ( ftmp == NULL )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_fw_ctl: malloc said no\n");
-#endif
- return( ENOMEM );
- }
-
- memcpy(ftmp, frwl, sizeof( struct ip_fw ) );
-
- ftmp->fw_pcnt=0L;
- ftmp->fw_bcnt=0L;
-
- ftmp->fw_next = NULL;
-
- cli();
-
- if (*chainptr==NULL)
- {
- *chainptr=ftmp;
- }
- else
- {
- chtmp_prev=NULL;
- for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next)
- {
- addb4=0;
- newkind=ftmp->fw_flg & IP_FW_F_KIND;
- oldkind=chtmp->fw_flg & IP_FW_F_KIND;
-
- if (newkind!=IP_FW_F_ALL
- && oldkind!=IP_FW_F_ALL
- && oldkind!=newkind)
- {
- chtmp_prev=chtmp;
- continue;
- }
-
- /*
- * Very very *UGLY* code...
- * Sorry,but i had to do this....
- */
-
- n_sa=ntohl(ftmp->fw_src.s_addr);
- n_da=ntohl(ftmp->fw_dst.s_addr);
- n_sm=ntohl(ftmp->fw_smsk.s_addr);
- n_dm=ntohl(ftmp->fw_dmsk.s_addr);
-
- o_sa=ntohl(chtmp->fw_src.s_addr);
- o_da=ntohl(chtmp->fw_dst.s_addr);
- o_sm=ntohl(chtmp->fw_smsk.s_addr);
- o_dm=ntohl(chtmp->fw_dmsk.s_addr);
-
- m_src_mask = o_sm & n_sm;
- m_dst_mask = o_dm & n_dm;
-
- if ((o_sa & m_src_mask) == (n_sa & m_src_mask))
- {
- if (n_sm > o_sm)
- addb4++;
- if (n_sm < o_sm)
- addb4--;
- }
-
- if ((o_da & m_dst_mask) == (n_da & m_dst_mask))
- {
- if (n_dm > o_dm)
- addb4++;
- if (n_dm < o_dm)
- addb4--;
- }
-
- if (((o_da & o_dm) == (n_da & n_dm))
- &&((o_sa & o_sm) == (n_sa & n_sm)))
- {
- if (newkind!=IP_FW_F_ALL &&
- oldkind==IP_FW_F_ALL)
- addb4++;
- if (newkind==oldkind && (oldkind==IP_FW_F_TCP
- || oldkind==IP_FW_F_UDP))
- {
-
- /*
- * Here the main idea is to check the size
- * of port range which the frwl covers
- * We actually don't check their values but
- * just the wideness of range they have
- * so that less wide ranges or single ports
- * go first and wide ranges go later. No ports
- * at all treated as a range of maximum number
- * of ports.
- */
-
- if (ftmp->fw_flg & IP_FW_F_SRNG)
- n_sr=ftmp->fw_pts[1]-ftmp->fw_pts[0];
- else
- n_sr=(ftmp->fw_nsp)?
- ftmp->fw_nsp : 0xFFFF;
-
- if (chtmp->fw_flg & IP_FW_F_SRNG)
- o_sr=chtmp->fw_pts[1]-chtmp->fw_pts[0];
- else
- o_sr=(chtmp->fw_nsp)?chtmp->fw_nsp : 0xFFFF;
-
- if (n_sr<o_sr)
- addb4++;
- if (n_sr>o_sr)
- addb4--;
-
- n_n=ftmp->fw_nsp;
- n_o=chtmp->fw_nsp;
-
- /*
- * Actually this cannot happen as the frwl control
- * procedure checks for number of ports in source and
- * destination range but we will try to be more safe.
- */
-
- if ((n_n>(IP_FW_MAX_PORTS-2)) ||
- (n_o>(IP_FW_MAX_PORTS-2)))
- goto skip_check;
-
- if (ftmp->fw_flg & IP_FW_F_DRNG)
- n_dr=ftmp->fw_pts[n_n+1]-ftmp->fw_pts[n_n];
- else
- n_dr=(ftmp->fw_ndp)? ftmp->fw_ndp : 0xFFFF;
-
- if (chtmp->fw_flg & IP_FW_F_DRNG)
- o_dr=chtmp->fw_pts[n_o+1]-chtmp->fw_pts[n_o];
- else
- o_dr=(chtmp->fw_ndp)? chtmp->fw_ndp : 0xFFFF;
- if (n_dr<o_dr)
- addb4++;
- if (n_dr>o_dr)
- addb4--;
-skip_check:
- }
- /* finally look at the interface address */
- if ((addb4 == 0) && ftmp->fw_via.s_addr &&
- !(chtmp->fw_via.s_addr))
- addb4++;
- }
- if (addb4>0)
- {
- if (chtmp_prev)
- {
- chtmp_prev->fw_next=ftmp;
- ftmp->fw_next=chtmp;
- }
- else
- {
- *chainptr=ftmp;
- ftmp->fw_next=chtmp;
- }
- restore_flags(flags);
- return 0;
- }
- chtmp_prev=chtmp;
- }
- }
-
- if (chtmp_prev)
- chtmp_prev->fw_next=ftmp;
- else
- *chainptr=ftmp;
- restore_flags(flags);
- return(0);
-}
-
-static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl)
-{
- struct ip_fw *ftmp,*ltmp;
- unsigned short tport1,tport2,tmpnum;
- char matches,was_found;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- ftmp=*chainptr;
-
- if ( ftmp == NULL )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: chain is empty\n");
-#endif
- restore_flags(flags);
- return( EINVAL );
- }
-
- ltmp=NULL;
- was_found=0;
-
- while( ftmp != NULL )
- {
- matches=1;
- if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr
- || ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
- || ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
- || ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
- || ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
- || ftmp->fw_flg!=frwl->fw_flg)
- matches=0;
-
- tport1=ftmp->fw_nsp+ftmp->fw_ndp;
- tport2=frwl->fw_nsp+frwl->fw_ndp;
- if (tport1!=tport2)
- matches=0;
- else if (tport1!=0)
- {
- for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
- if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
- matches=0;
- }
- if(matches)
- {
- was_found=1;
- if (ltmp)
- {
- ltmp->fw_next=ftmp->fw_next;
- kfree_s(ftmp,sizeof(*ftmp));
- ftmp=ltmp->fw_next;
- }
- else
- {
- *chainptr=ftmp->fw_next;
- kfree_s(ftmp,sizeof(*ftmp));
- ftmp=*chainptr;
- }
- }
- else
- {
- ltmp = ftmp;
- ftmp = ftmp->fw_next;
- }
- }
- restore_flags(flags);
- if (was_found)
- return 0;
- else
- return(EINVAL);
-}
-
-#endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
-
-struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
-{
-
- if ( len != sizeof(struct ip_fw) )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: len=%d, want %d\n",m->m_len,
- sizeof(struct ip_fw));
-#endif
- return(NULL);
- }
-
- if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
- frwl->fw_flg);
-#endif
- return(NULL);
- }
-
- if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: src range set but n_src_p=%d\n",
- frwl->fw_nsp);
-#endif
- return(NULL);
- }
-
- if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: dst range set but n_dst_p=%d\n",
- frwl->fw_ndp);
-#endif
- return(NULL);
- }
-
- if ( frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: too many ports (%d+%d)\n",
- frwl->fw_nsp,frwl->fw_ndp);
-#endif
- return(NULL);
- }
-
- return frwl;
-}
-
-
-
-
-#ifdef CONFIG_IP_ACCT
-
-void ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
-{
- (void) ip_fw_chk(iph, dev, f, 0, 1);
- return;
-}
-
-int ip_acct_ctl(int stage, void *m, int len)
-{
- if ( stage == IP_ACCT_FLUSH )
- {
- free_fw_chain(&ip_acct_chain);
- return(0);
- }
- if ( stage == IP_ACCT_ZERO )
- {
- zero_fw_chain(ip_acct_chain);
- return(0);
- }
- if ( stage == IP_ACCT_ADD
- || stage == IP_ACCT_DEL
- )
- {
- struct ip_fw *frwl;
-
- if (!(frwl=check_ipfw_struct(m,len)))
- return (EINVAL);
-
- switch (stage)
- {
- case IP_ACCT_ADD:
- return( add_to_chain(&ip_acct_chain,frwl));
- case IP_ACCT_DEL:
- return( del_from_chain(&ip_acct_chain,frwl));
- default:
- /*
- * Should be panic but... (Why ??? - AC)
- */
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_acct_ctl: unknown request %d\n",stage);
-#endif
- return(EINVAL);
- }
- }
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_acct_ctl: unknown request %d\n",stage);
-#endif
- return(EINVAL);
-}
-#endif
-
-#ifdef CONFIG_IP_FIREWALL
-int ip_fw_ctl(int stage, void *m, int len)
-{
- int ret;
-
- if ( stage == IP_FW_FLUSH_BLK )
- {
- free_fw_chain(&ip_fw_blk_chain);
- return(0);
- }
-
- if ( stage == IP_FW_FLUSH_FWD )
- {
- free_fw_chain(&ip_fw_fwd_chain);
- return(0);
- }
-
- if ( stage == IP_FW_ZERO_BLK )
- {
- zero_fw_chain(ip_fw_blk_chain);
- return(0);
- }
-
- if ( stage == IP_FW_ZERO_FWD )
- {
- zero_fw_chain(ip_fw_fwd_chain);
- return(0);
- }
-
- if ( stage == IP_FW_POLICY_BLK || stage == IP_FW_POLICY_FWD )
- {
- int *tmp_policy_ptr;
- tmp_policy_ptr=(int *)m;
- if ( stage == IP_FW_POLICY_BLK )
- ip_fw_blk_policy=*tmp_policy_ptr;
- else
- ip_fw_fwd_policy=*tmp_policy_ptr;
- return 0;
- }
-
- if ( stage == IP_FW_CHK_BLK || stage == IP_FW_CHK_FWD )
- {
- struct device viadev;
- struct ip_fwpkt *ipfwp;
- struct iphdr *ip;
-
- if ( len < sizeof(struct ip_fwpkt) )
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_fw_ctl: length=%d, expected %d\n",
- len, sizeof(struct ip_fwpkt));
-#endif
- return( EINVAL );
- }
-
- ipfwp = (struct ip_fwpkt *)m;
- ip = &(ipfwp->fwp_iph);
-
- if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
- {
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
- sizeof(struct ip)/sizeof(int));
-#endif
- return(EINVAL);
- }
-
- viadev.pa_addr = ipfwp->fwp_via.s_addr;
-
- if ((ret = ip_fw_chk(ip, &viadev,
- stage == IP_FW_CHK_BLK ?
- ip_fw_blk_chain : ip_fw_fwd_chain,
- stage == IP_FW_CHK_BLK ?
- ip_fw_blk_policy : ip_fw_fwd_policy, 2 )) > 0
- )
- return(0);
- else if (ret == -1)
- return(ECONNREFUSED);
- else
- return(ETIMEDOUT);
- }
-
-/*
- * Here we really working hard-adding new elements
- * to blocking/forwarding chains or deleting 'em
- */
-
- if ( stage == IP_FW_ADD_BLK || stage == IP_FW_ADD_FWD
- || stage == IP_FW_DEL_BLK || stage == IP_FW_DEL_FWD
- )
- {
- struct ip_fw *frwl;
- frwl=check_ipfw_struct(m,len);
- if (frwl==NULL)
- return (EINVAL);
-
- switch (stage)
- {
- case IP_FW_ADD_BLK:
- return(add_to_chain(&ip_fw_blk_chain,frwl));
- case IP_FW_ADD_FWD:
- return(add_to_chain(&ip_fw_fwd_chain,frwl));
- case IP_FW_DEL_BLK:
- return(del_from_chain(&ip_fw_blk_chain,frwl));
- case IP_FW_DEL_FWD:
- return(del_from_chain(&ip_fw_fwd_chain,frwl));
- default:
- /*
- * Should be panic but... (Why are BSD people panic obsessed ??)
- */
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printk("ip_fw_ctl: unknown request %d\n",stage);
-#endif
- return(EINVAL);
- }
- }
-
-#ifdef DEBUG_CONFIG_IP_FIREWALL
- printf("ip_fw_ctl: unknown request %d\n",stage);
-#endif
- return(EINVAL);
-}
-#endif /* CONFIG_IP_FIREWALL */
-
-#if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
-
-static int ip_chain_procinfo(int stage, char *buffer, char **start,
- off_t offset, int length, int reset)
-{
- off_t pos=0, begin=0;
- struct ip_fw *i;
- unsigned long flags;
- int len, p;
-
-
- switch(stage)
- {
-#ifdef CONFIG_IP_FIREWALL
- case IP_INFO_BLK:
- i = ip_fw_blk_chain;
- len=sprintf(buffer, "IP firewall block rules, default %d\n",
- ip_fw_blk_policy);
- break;
- case IP_INFO_FWD:
- i = ip_fw_fwd_chain;
- len=sprintf(buffer, "IP firewall forward rules, default %d\n",
- ip_fw_fwd_policy);
- break;
-#endif
-#ifdef CONFIG_IP_ACCT
- case IP_INFO_ACCT:
- i = ip_acct_chain;
- len=sprintf(buffer,"IP accounting rules\n");
- break;
-#endif
- default:
- /* this should never be reached, but safety first... */
- i = NULL;
- len=0;
- break;
- }
-
- save_flags(flags);
- cli();
-
- while(i!=NULL)
- {
- len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %08lX %X ",
- ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
- ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
- ntohl(i->fw_via.s_addr),i->fw_flg);
- len+=sprintf(buffer+len,"%u %u %lu %lu",
- i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
- for (p = 0; p < IP_FW_MAX_PORTS; p++)
- len+=sprintf(buffer+len, " %u", i->fw_pts[p]);
- buffer[len++]='\n';
- buffer[len]='\0';
- pos=begin+len;
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- else if(reset)
- {
- /* This needs to be done at this specific place! */
- i->fw_pcnt=0L;
- i->fw_bcnt=0L;
- }
- if(pos>offset+length)
- break;
- i=i->fw_next;
- }
- restore_flags(flags);
- *start=buffer+(offset-begin);
- len-=(offset-begin);
- if(len>length)
- len=length;
- return len;
-}
-#endif
-
-#ifdef CONFIG_IP_ACCT
-
-int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
-{
- return ip_chain_procinfo(IP_INFO_ACCT, buffer,start,offset,length,reset);
-}
-
-#endif
-
-#ifdef CONFIG_IP_FIREWALL
-
-int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
-{
- return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,reset);
-}
-
-int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
-{
- return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,reset);
-}
-
-#endif
diff --git a/pfinet/linux-inet/ipx.c b/pfinet/linux-inet/ipx.c
deleted file mode 100644
index 88b53c30..00000000
--- a/pfinet/linux-inet/ipx.c
+++ /dev/null
@@ -1,1947 +0,0 @@
-/*
- * Implements an IPX socket layer (badly - but I'm working on it).
- *
- * This code is derived from work by
- * Ross Biro : Writing the original IP stack
- * Fred Van Kempen : Tidying up the TCP/IP
- *
- * Many thanks go to Keith Baker, Institute For Industrial Information
- * Technology Ltd, Swansea University for allowing me to work on this
- * in my own time even though it was in some ways related to commercial
- * work I am currently employed to do there.
- *
- * All the material in this file is subject to the Gnu license version 2.
- * Neither Alan Cox nor the Swansea University Computer Society admit liability
- * nor provide warranty for any of this software. This material is provided
- * as is and at no charge.
- *
- * Revision 0.21: Uses the new generic socket option code.
- * Revision 0.22: Gcc clean ups and drop out device registration. Use the
- * new multi-protocol edition of hard_header
- * Revision 0.23: IPX /proc by Mark Evans.
- * Adding a route will overwrite any existing route to the same
- * network.
- * Revision 0.24: Supports new /proc with no 4K limit
- * Revision 0.25: Add ephemeral sockets, passive local network
- * identification, support for local net 0 and
- * multiple datalinks <Greg Page>
- * Revision 0.26: Device drop kills IPX routes via it. (needed for modules)
- * Revision 0.27: Autobind <Mark Evans>
- * Revision 0.28: Small fix for multiple local networks <Thomas Winder>
- * Revision 0.29: Assorted major errors removed <Mark Evans>
- * Small correction to promisc mode error fix <Alan Cox>
- * Asynchronous I/O support.
- * Changed to use notifiers and the newer packet_type stuff.
- * Assorted major fixes <Alejandro Liu>
- *
- * Portions Copyright (c) 1995 Caldera, Inc. <greg@caldera.com>
- * Neither Greg Page nor Caldera, Inc. admit liability nor provide
- * warranty for any of this software. This material is provided
- * "AS-IS" and at no charge.
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/ipx.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include "sock.h"
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/termios.h> /* For TIOCOUTQ/INQ */
-#include <linux/interrupt.h>
-#include "p8022.h"
-#include "psnap.h"
-
-#ifdef CONFIG_IPX
-/* Configuration Variables */
-static unsigned char ipxcfg_max_hops = 16;
-static char ipxcfg_auto_select_primary = 0;
-static char ipxcfg_auto_create_interfaces = 0;
-
-/* Global Variables */
-static struct datalink_proto *p8022_datalink = NULL;
-static struct datalink_proto *pEII_datalink = NULL;
-static struct datalink_proto *p8023_datalink = NULL;
-static struct datalink_proto *pSNAP_datalink = NULL;
-
-static ipx_interface *ipx_interfaces = NULL;
-static ipx_route *ipx_routes = NULL;
-static ipx_interface *ipx_internal_net = NULL;
-static ipx_interface *ipx_primary_net = NULL;
-
-static int
-ipxcfg_set_auto_create(char val)
-{
- ipxcfg_auto_create_interfaces = val;
- return 0;
-}
-
-static int
-ipxcfg_set_auto_select(char val)
-{
- ipxcfg_auto_select_primary = val;
- if (val && (ipx_primary_net == NULL))
- ipx_primary_net = ipx_interfaces;
- return 0;
-}
-
-static int
-ipxcfg_get_config_data(ipx_config_data *arg)
-{
- ipx_config_data vals;
-
- vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
- vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
- memcpy_tofs(arg, &vals, sizeof(vals));
- return 0;
-}
-
-
-/***********************************************************************************************************************\
-* *
-* Handlers for the socket list. *
-* *
-\***********************************************************************************************************************/
-
-/*
- * Note: Sockets may not be removed _during_ an interrupt or inet_bh
- * handler using this technique. They can be added although we do not
- * use this facility.
- */
-
-static void
-ipx_remove_socket(ipx_socket *sk)
-{
- ipx_socket *s;
- ipx_interface *intrfc;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- /* Determine interface with which socket is associated */
- intrfc = sk->ipx_intrfc;
- if (intrfc == NULL) {
- restore_flags(flags);
- return;
- }
-
- s=intrfc->if_sklist;
- if(s==sk) {
- intrfc->if_sklist=s->next;
- restore_flags(flags);
- return;
- }
-
- while(s && s->next) {
- if(s->next==sk) {
- s->next=sk->next;
- restore_flags(flags);
- return;
- }
- s=s->next;
- }
- restore_flags(flags);
-}
-
-/*
- * This is only called from user mode. Thus it protects itself against
- * interrupt users but doesn't worry about being called during work.
- * Once it is removed from the queue no interrupt or bottom half will
- * touch it and we are (fairly 8-) ) safe.
- */
-
-static void
-ipx_destroy_socket(ipx_socket *sk)
-{
- struct sk_buff *skb;
-
- ipx_remove_socket(sk);
- while((skb=skb_dequeue(&sk->receive_queue))!=NULL) {
- kfree_skb(skb,FREE_READ);
- }
-
- kfree_s(sk,sizeof(*sk));
-}
-
-/* The following code is used to support IPX Interfaces (IPXITF). An
- * IPX interface is defined by a physical device and a frame type.
- */
-
-static ipx_route * ipxrtr_lookup(unsigned long);
-
-static void
-ipxitf_clear_primary_net(void)
-{
- if (ipxcfg_auto_select_primary && (ipx_interfaces != NULL))
- ipx_primary_net = ipx_interfaces;
- else
- ipx_primary_net = NULL;
-}
-
-static ipx_interface *
-ipxitf_find_using_phys(struct device *dev, unsigned short datalink)
-{
- ipx_interface *i;
-
- for (i=ipx_interfaces;
- i && ((i->if_dev!=dev) || (i->if_dlink_type!=datalink));
- i=i->if_next)
- ;
- return i;
-}
-
-static ipx_interface *
-ipxitf_find_using_net(unsigned long net)
-{
- ipx_interface *i;
-
- if (net == 0L)
- return ipx_primary_net;
-
- for (i=ipx_interfaces; i && (i->if_netnum!=net); i=i->if_next)
- ;
-
- return i;
-}
-
-/* Sockets are bound to a particular IPX interface. */
-static void
-ipxitf_insert_socket(ipx_interface *intrfc, ipx_socket *sk)
-{
- ipx_socket *s;
-
- sk->ipx_intrfc = intrfc;
- sk->next = NULL;
- if (intrfc->if_sklist == NULL) {
- intrfc->if_sklist = sk;
- } else {
- for (s = intrfc->if_sklist; s->next != NULL; s = s->next)
- ;
- s->next = sk;
- }
-}
-
-static ipx_socket *
-ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
-{
- ipx_socket *s;
-
- for (s=intrfc->if_sklist;
- (s != NULL) && (s->ipx_port != port);
- s=s->next)
- ;
-
- return s;
-}
-
-static void ipxrtr_del_routes(ipx_interface *);
-
-static void
-ipxitf_down(ipx_interface *intrfc)
-{
- ipx_interface *i;
- ipx_socket *s, *t;
-
- /* Delete all routes associated with this interface */
- ipxrtr_del_routes(intrfc);
-
- /* error sockets */
- for (s = intrfc->if_sklist; s != NULL; ) {
- s->err = ENOLINK;
- s->error_report(s);
- s->ipx_intrfc = NULL;
- s->ipx_port = 0;
- s->zapped=1; /* Indicates it is no longer bound */
- t = s;
- s = s->next;
- t->next = NULL;
- }
- intrfc->if_sklist = NULL;
-
- /* remove this interface from list */
- if (intrfc == ipx_interfaces) {
- ipx_interfaces = intrfc->if_next;
- } else {
- for (i = ipx_interfaces;
- (i != NULL) && (i->if_next != intrfc);
- i = i->if_next)
- ;
- if ((i != NULL) && (i->if_next == intrfc))
- i->if_next = intrfc->if_next;
- }
-
- /* remove this interface from *special* networks */
- if (intrfc == ipx_primary_net)
- ipxitf_clear_primary_net();
- if (intrfc == ipx_internal_net)
- ipx_internal_net = NULL;
-
- kfree_s(intrfc, sizeof(*intrfc));
-}
-
-static int
-ipxitf_device_event(unsigned long event, void *ptr)
-{
- struct device *dev = ptr;
- ipx_interface *i, *tmp;
-
- if(event!=NETDEV_DOWN)
- return NOTIFY_DONE;
-
- for (i = ipx_interfaces; i != NULL; ) {
-
- tmp = i->if_next;
- if (i->if_dev == dev)
- ipxitf_down(i);
- i = tmp;
-
- }
-
- return NOTIFY_DONE;
-}
-
-static int
-ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
-{
- int retval;
-
- if((retval = sock_queue_rcv_skb(sock, skb))<0) {
- /*
- * We do a FREE_WRITE here because this indicates how
- * to treat the socket with which the packet is
- * associated. If this packet is associated with a
- * socket at all, it must be the originator of the
- * packet. Incoming packets will have no socket
- * associated with them at this point.
- */
- kfree_skb(skb,FREE_WRITE);
- }
- return retval;
-}
-
-static int
-ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
-{
- ipx_packet *ipx = (ipx_packet *)(skb->h.raw);
- ipx_socket *sock1 = NULL, *sock2 = NULL;
- struct sk_buff *skb1 = NULL, *skb2 = NULL;
- int ipx_offset;
-
- sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
-
- /*
- * We need to check if there is a primary net and if
- * this is addressed to one of the *SPECIAL* sockets because
- * these need to be propagated to the primary net.
- * The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and
- * 0x456(Diagnostic).
- */
- if (ipx_primary_net && (intrfc != ipx_primary_net)) {
- switch (ntohs(ipx->ipx_dest.sock)) {
- case 0x452:
- case 0x453:
- case 0x456:
- /*
- * The appropriate thing to do here is to
- * dup the packet and route to the primary net
- * interface via ipxitf_send; however, we'll cheat
- * and just demux it here.
- */
- sock2 = ipxitf_find_socket(ipx_primary_net,
- ipx->ipx_dest.sock);
- break;
- default:
- break;
- }
- }
-
- /* if there is nothing to do, return */
- if ((sock1 == NULL) && (sock2 == NULL)) {
- if (!copy)
- kfree_skb(skb,FREE_WRITE);
- return 0;
- }
-
- ipx_offset = (char *)(skb->h.raw) - (char *)(skb->data);
-
- /* This next segment of code is a little awkward, but it sets it up
- * so that the appropriate number of copies of the SKB are made and
- * that skb1 and skb2 point to it (them) so that it (they) can be
- * demuxed to sock1 and/or sock2. If we are unable to make enough
- * copies, we do as much as is possible.
- */
- if (copy) {
- skb1 = skb_clone(skb, GFP_ATOMIC);
- if (skb1 != NULL) {
- skb1->h.raw = (unsigned char *)&(skb1->data[ipx_offset]);
- skb1->arp = skb1->free = 1;
- }
- } else {
- skb1 = skb;
- }
-
- if (skb1 == NULL) return -ENOMEM;
-
- /* Do we need 2 SKBs? */
- if (sock1 && sock2) {
- skb2 = skb_clone(skb1, GFP_ATOMIC);
- if (skb2 != NULL) {
- skb2->h.raw = (unsigned char *)&(skb2->data[ipx_offset]);
- skb2->arp = skb2->free = 1;
- }
- } else {
- skb2 = skb1;
- }
-
- if (sock1) {
- (void) ipxitf_def_skb_handler(sock1, skb1);
- }
-
- if (skb2 == NULL) return -ENOMEM;
-
- if (sock2) {
- (void) ipxitf_def_skb_handler(sock2, skb2);
- }
-
- return 0;
-}
-
-static struct sk_buff *
-ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buff *skb)
-{
- struct sk_buff *skb2;
- int in_offset = skb->h.raw - skb->data;
- int out_offset = intrfc->if_ipx_offset;
- char *oldraw;
- int len;
-
- /* Hopefully, most cases */
- if (in_offset == out_offset) {
- skb->len += out_offset;
- skb->arp = skb->free = 1;
- return skb;
- }
-
- /* Existing SKB will work, just need to move things around a little */
- if (in_offset > out_offset) {
- oldraw = skb->h.raw;
- skb->h.raw = &(skb->data[out_offset]);
- memmove(skb->h.raw, oldraw, skb->len);
- skb->len += out_offset;
- skb->arp = skb->free = 1;
- return skb;
- }
-
- /* Need new SKB */
- len = skb->len + out_offset;
- skb2 = alloc_skb(len, GFP_ATOMIC);
- if (skb2 != NULL) {
- skb2->h.raw = &(skb2->data[out_offset]);
- skb2->len = len;
- skb2->free=1;
- skb2->arp=1;
- memcpy(skb2->h.raw, skb->h.raw, skb->len);
- }
- kfree_skb(skb, FREE_WRITE);
- return skb2;
-}
-
-static int
-ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
-{
- ipx_packet *ipx = (ipx_packet *)(skb->h.raw);
- struct device *dev = intrfc->if_dev;
- struct datalink_proto *dl = intrfc->if_dlink;
- char dest_node[IPX_NODE_LEN];
- int send_to_wire = 1;
- int addr_len;
-
- /* We need to know how many skbuffs it will take to send out this
- * packet to avoid unnecessary copies.
- */
- if ((dl == NULL) || (dev == NULL) || (dev->flags & IFF_LOOPBACK))
- send_to_wire = 0;
-
- /* See if this should be demuxed to sockets on this interface */
- if (ipx->ipx_dest.net == intrfc->if_netnum) {
- if (memcmp(intrfc->if_node, node, IPX_NODE_LEN) == 0)
- return ipxitf_demux_socket(intrfc, skb, 0);
- if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0) {
- ipxitf_demux_socket(intrfc, skb, send_to_wire);
- if (!send_to_wire) return 0;
- }
- }
-
- /* if the originating net is not equal to our net; this is routed */
- if (ipx->ipx_source.net != intrfc->if_netnum) {
- if (++(ipx->ipx_tctrl) > ipxcfg_max_hops)
- send_to_wire = 0;
- }
-
- if (!send_to_wire) {
- /*
- * We do a FREE_WRITE here because this indicates how
- * to treat the socket with which the packet is
- * associated. If this packet is associated with a
- * socket at all, it must be the originator of the
- * packet. Routed packets will have no socket associated
- * with them.
- */
- kfree_skb(skb,FREE_WRITE);
- return 0;
- }
-
- /* determine the appropriate hardware address */
- addr_len = dev->addr_len;
- if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0) {
- memcpy(dest_node, dev->broadcast, addr_len);
- } else {
- memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len);
- }
-
- /* make any compensation for differing physical/data link size */
- skb = ipxitf_adjust_skbuff(intrfc, skb);
- if (skb == NULL) return 0;
-
- /* set up data link and physical headers */
- skb->dev = dev;
- dl->datalink_header(dl, skb, dest_node);
-
- if (skb->sk != NULL) {
- /* This is an outbound packet from this host. We need to
- * increment the write count.
- */
- skb->sk->wmem_alloc += skb->mem_len;
- }
-
- /* Send it out */
- dev_queue_xmit(skb, dev, SOPRI_NORMAL);
- return 0;
-}
-
-static int
-ipxrtr_add_route(unsigned long, ipx_interface *, unsigned char *);
-
-static int
-ipxitf_add_local_route(ipx_interface *intrfc)
-{
- return ipxrtr_add_route(intrfc->if_netnum, intrfc, NULL);
-}
-
-static char * ipx_frame_name(unsigned short);
-static char * ipx_device_name(ipx_interface *);
-static int ipxrtr_route_skb(struct sk_buff *);
-
-static int
-ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
-{
- ipx_packet *ipx = (ipx_packet *) (skb->h.raw);
- ipx_interface *i;
-
- /* See if we should update our network number */
- if ((intrfc->if_netnum == 0L) &&
- (ipx->ipx_source.net == ipx->ipx_dest.net) &&
- (ipx->ipx_source.net != 0L)) {
- /* NB: NetWare servers lie about their hop count so we
- * dropped the test based on it. This is the best way
- * to determine this is a 0 hop count packet.
- */
- if ((i=ipxitf_find_using_net(ipx->ipx_source.net))==NULL) {
- intrfc->if_netnum = ipx->ipx_source.net;
- (void) ipxitf_add_local_route(intrfc);
- } else {
- printk("IPX: Network number collision %lx\n\t%s %s and %s %s\n",
- htonl(ipx->ipx_source.net),
- ipx_device_name(i),
- ipx_frame_name(i->if_dlink_type),
- ipx_device_name(intrfc),
- ipx_frame_name(intrfc->if_dlink_type));
- }
- }
-
- if (ipx->ipx_dest.net == 0L)
- ipx->ipx_dest.net = intrfc->if_netnum;
- if (ipx->ipx_source.net == 0L)
- ipx->ipx_source.net = intrfc->if_netnum;
-
- if (intrfc->if_netnum != ipx->ipx_dest.net) {
- /* We only route point-to-point packets. */
- if ((skb->pkt_type != PACKET_BROADCAST) &&
- (skb->pkt_type != PACKET_MULTICAST))
- return ipxrtr_route_skb(skb);
-
- kfree_skb(skb,FREE_READ);
- return 0;
- }
-
- /* see if we should keep it */
- if ((memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0)
- || (memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0)) {
- return ipxitf_demux_socket(intrfc, skb, 0);
- }
-
- /* we couldn't pawn it off so unload it */
- kfree_skb(skb,FREE_READ);
- return 0;
-}
-
-static void
-ipxitf_insert(ipx_interface *intrfc)
-{
- ipx_interface *i;
-
- intrfc->if_next = NULL;
- if (ipx_interfaces == NULL) {
- ipx_interfaces = intrfc;
- } else {
- for (i = ipx_interfaces; i->if_next != NULL; i = i->if_next)
- ;
- i->if_next = intrfc;
- }
-
- if (ipxcfg_auto_select_primary && (ipx_primary_net == NULL))
- ipx_primary_net = intrfc;
-}
-
-static int
-ipxitf_create_internal(ipx_interface_definition *idef)
-{
- ipx_interface *intrfc;
-
- /* Only one primary network allowed */
- if (ipx_primary_net != NULL) return -EEXIST;
-
- /* Must have a valid network number */
- if (idef->ipx_network == 0L) return -EADDRNOTAVAIL;
- if (ipxitf_find_using_net(idef->ipx_network) != NULL)
- return -EADDRINUSE;
-
- intrfc=(ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
- if (intrfc==NULL)
- return -EAGAIN;
- intrfc->if_dev=NULL;
- intrfc->if_netnum=idef->ipx_network;
- intrfc->if_dlink_type = 0;
- intrfc->if_dlink = NULL;
- intrfc->if_sklist = NULL;
- intrfc->if_internal = 1;
- intrfc->if_ipx_offset = 0;
- intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
- memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN);
- ipx_internal_net = intrfc;
- ipx_primary_net = intrfc;
- ipxitf_insert(intrfc);
- return ipxitf_add_local_route(intrfc);
-}
-
-static int
-ipx_map_frame_type(unsigned char type)
-{
- switch (type) {
- case IPX_FRAME_ETHERII: return htons(ETH_P_IPX);
- case IPX_FRAME_8022: return htons(ETH_P_802_2);
- case IPX_FRAME_SNAP: return htons(ETH_P_SNAP);
- case IPX_FRAME_8023: return htons(ETH_P_802_3);
- }
- return 0;
-}
-
-static int
-ipxitf_create(ipx_interface_definition *idef)
-{
- struct device *dev;
- unsigned short dlink_type = 0;
- struct datalink_proto *datalink = NULL;
- ipx_interface *intrfc;
-
- if (idef->ipx_special == IPX_INTERNAL)
- return ipxitf_create_internal(idef);
-
- if ((idef->ipx_special == IPX_PRIMARY) && (ipx_primary_net != NULL))
- return -EEXIST;
-
- if ((idef->ipx_network != 0L) &&
- (ipxitf_find_using_net(idef->ipx_network) != NULL))
- return -EADDRINUSE;
-
- switch (idef->ipx_dlink_type) {
- case IPX_FRAME_ETHERII:
- dlink_type = htons(ETH_P_IPX);
- datalink = pEII_datalink;
- break;
- case IPX_FRAME_8022:
- dlink_type = htons(ETH_P_802_2);
- datalink = p8022_datalink;
- break;
- case IPX_FRAME_SNAP:
- dlink_type = htons(ETH_P_SNAP);
- datalink = pSNAP_datalink;
- break;
- case IPX_FRAME_8023:
- dlink_type = htons(ETH_P_802_3);
- datalink = p8023_datalink;
- break;
- case IPX_FRAME_NONE:
- default:
- break;
- }
-
- if (datalink == NULL)
- return -EPROTONOSUPPORT;
-
- dev=dev_get(idef->ipx_device);
- if (dev==NULL)
- return -ENODEV;
-
- if (!(dev->flags & IFF_UP))
- return -ENETDOWN;
-
- /* Check addresses are suitable */
- if(dev->addr_len>IPX_NODE_LEN)
- return -EINVAL;
-
- if ((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL) {
-
- /* Ok now create */
- intrfc=(ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
- if (intrfc==NULL)
- return -EAGAIN;
- intrfc->if_dev=dev;
- intrfc->if_netnum=idef->ipx_network;
- intrfc->if_dlink_type = dlink_type;
- intrfc->if_dlink = datalink;
- intrfc->if_sklist = NULL;
- intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
- /* Setup primary if necessary */
- if ((idef->ipx_special == IPX_PRIMARY))
- ipx_primary_net = intrfc;
- intrfc->if_internal = 0;
- intrfc->if_ipx_offset = dev->hard_header_len + datalink->header_length;
- memset(intrfc->if_node, 0, IPX_NODE_LEN);
- memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]), dev->dev_addr, dev->addr_len);
-
- ipxitf_insert(intrfc);
- }
-
- /* If the network number is known, add a route */
- if (intrfc->if_netnum == 0L)
- return 0;
-
- return ipxitf_add_local_route(intrfc);
-}
-
-static int
-ipxitf_delete(ipx_interface_definition *idef)
-{
- struct device *dev = NULL;
- unsigned short dlink_type = 0;
- ipx_interface *intrfc;
-
- if (idef->ipx_special == IPX_INTERNAL) {
- if (ipx_internal_net != NULL) {
- ipxitf_down(ipx_internal_net);
- return 0;
- }
- return -ENOENT;
- }
-
- dlink_type = ipx_map_frame_type(idef->ipx_dlink_type);
- if (dlink_type == 0)
- return -EPROTONOSUPPORT;
-
- dev=dev_get(idef->ipx_device);
- if(dev==NULL) return -ENODEV;
-
- intrfc = ipxitf_find_using_phys(dev, dlink_type);
- if (intrfc != NULL) {
- ipxitf_down(intrfc);
- return 0;
- }
- return -EINVAL;
-}
-
-static ipx_interface *
-ipxitf_auto_create(struct device *dev, unsigned short dlink_type)
-{
- struct datalink_proto *datalink = NULL;
- ipx_interface *intrfc;
-
- switch (htons(dlink_type)) {
- case ETH_P_IPX: datalink = pEII_datalink; break;
- case ETH_P_802_2: datalink = p8022_datalink; break;
- case ETH_P_SNAP: datalink = pSNAP_datalink; break;
- case ETH_P_802_3: datalink = p8023_datalink; break;
- default: return NULL;
- }
-
- if (dev == NULL)
- return NULL;
-
- /* Check addresses are suitable */
- if(dev->addr_len>IPX_NODE_LEN) return NULL;
-
- intrfc=(ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
- if (intrfc!=NULL) {
- intrfc->if_dev=dev;
- intrfc->if_netnum=0L;
- intrfc->if_dlink_type = dlink_type;
- intrfc->if_dlink = datalink;
- intrfc->if_sklist = NULL;
- intrfc->if_internal = 0;
- intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
- intrfc->if_ipx_offset = dev->hard_header_len +
- datalink->header_length;
- memset(intrfc->if_node, 0, IPX_NODE_LEN);
- memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
- dev->dev_addr, dev->addr_len);
- ipxitf_insert(intrfc);
- }
-
- return intrfc;
-}
-
-static int
-ipxitf_ioctl(unsigned int cmd, void *arg)
-{
- int err;
- switch(cmd)
- {
- case SIOCSIFADDR:
- {
- struct ifreq ifr;
- struct sockaddr_ipx *sipx;
- ipx_interface_definition f;
- err=verify_area(VERIFY_READ,arg,sizeof(ifr));
- if(err)
- return err;
- memcpy_fromfs(&ifr,arg,sizeof(ifr));
- sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
- if(sipx->sipx_family!=AF_IPX)
- return -EINVAL;
- f.ipx_network=sipx->sipx_network;
- memcpy(f.ipx_device, ifr.ifr_name, sizeof(f.ipx_device));
- memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN);
- f.ipx_dlink_type=sipx->sipx_type;
- f.ipx_special=sipx->sipx_special;
- if(sipx->sipx_action==IPX_DLTITF)
- return ipxitf_delete(&f);
- else
- return ipxitf_create(&f);
- }
- case SIOCGIFADDR:
- {
- struct ifreq ifr;
- struct sockaddr_ipx *sipx;
- ipx_interface *ipxif;
- struct device *dev;
- err=verify_area(VERIFY_WRITE,arg,sizeof(ifr));
- if(err)
- return err;
- memcpy_fromfs(&ifr,arg,sizeof(ifr));
- sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
- dev=dev_get(ifr.ifr_name);
- if(!dev)
- return -ENODEV;
- ipxif=ipxitf_find_using_phys(dev, ipx_map_frame_type(sipx->sipx_type));
- if(ipxif==NULL)
- return -EADDRNOTAVAIL;
- sipx->sipx_network=ipxif->if_netnum;
- memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node));
- memcpy_tofs(arg,&ifr,sizeof(ifr));
- return 0;
- }
- case SIOCAIPXITFCRT:
- err=verify_area(VERIFY_READ,arg,sizeof(char));
- if(err)
- return err;
- return ipxcfg_set_auto_create(get_fs_byte(arg));
- case SIOCAIPXPRISLT:
- err=verify_area(VERIFY_READ,arg,sizeof(char));
- if(err)
- return err;
- return ipxcfg_set_auto_select(get_fs_byte(arg));
- default:
- return -EINVAL;
- }
-}
-
-/*******************************************************************************************************************\
-* *
-* Routing tables for the IPX socket layer *
-* *
-\*******************************************************************************************************************/
-
-static ipx_route *
-ipxrtr_lookup(unsigned long net)
-{
- ipx_route *r;
-
- for (r=ipx_routes; (r!=NULL) && (r->ir_net!=net); r=r->ir_next)
- ;
-
- return r;
-}
-
-static int
-ipxrtr_add_route(unsigned long network, ipx_interface *intrfc, unsigned char *node)
-{
- ipx_route *rt;
-
- /* Get a route structure; either existing or create */
- rt = ipxrtr_lookup(network);
- if (rt==NULL) {
- rt=(ipx_route *)kmalloc(sizeof(ipx_route),GFP_ATOMIC);
- if(rt==NULL)
- return -EAGAIN;
- rt->ir_next=ipx_routes;
- ipx_routes=rt;
- }
-
- rt->ir_net = network;
- rt->ir_intrfc = intrfc;
- if (node == NULL) {
- memset(rt->ir_router_node, '\0', IPX_NODE_LEN);
- rt->ir_routed = 0;
- } else {
- memcpy(rt->ir_router_node, node, IPX_NODE_LEN);
- rt->ir_routed=1;
- }
- return 0;
-}
-
-static void
-ipxrtr_del_routes(ipx_interface *intrfc)
-{
- ipx_route **r, *tmp;
-
- for (r = &ipx_routes; (tmp = *r) != NULL; ) {
- if (tmp->ir_intrfc == intrfc) {
- *r = tmp->ir_next;
- kfree_s(tmp, sizeof(ipx_route));
- } else {
- r = &(tmp->ir_next);
- }
- }
-}
-
-static int
-ipxrtr_create(ipx_route_definition *rd)
-{
- ipx_interface *intrfc;
-
- /* Find the appropriate interface */
- intrfc = ipxitf_find_using_net(rd->ipx_router_network);
- if (intrfc == NULL)
- return -ENETUNREACH;
-
- return ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node);
-}
-
-
-static int
-ipxrtr_delete(long net)
-{
- ipx_route **r;
- ipx_route *tmp;
-
- for (r = &ipx_routes; (tmp = *r) != NULL; ) {
- if (tmp->ir_net == net) {
- if (!(tmp->ir_routed)) {
- /* Directly connected; can't lose route */
- return -EPERM;
- }
- *r = tmp->ir_next;
- kfree_s(tmp, sizeof(ipx_route));
- return 0;
- }
- r = &(tmp->ir_next);
- }
-
- return -ENOENT;
-}
-
-static int
-ipxrtr_route_packet(ipx_socket *sk, struct sockaddr_ipx *usipx, void *ubuf, int len)
-{
- struct sk_buff *skb;
- ipx_interface *intrfc;
- ipx_packet *ipx;
- int size;
- int ipx_offset;
- ipx_route *rt = NULL;
-
- /* Find the appropriate interface on which to send packet */
- if ((usipx->sipx_network == 0L) && (ipx_primary_net != NULL)) {
- usipx->sipx_network = ipx_primary_net->if_netnum;
- intrfc = ipx_primary_net;
- } else {
- rt = ipxrtr_lookup(usipx->sipx_network);
- if (rt==NULL) {
- return -ENETUNREACH;
- }
- intrfc = rt->ir_intrfc;
- }
-
- ipx_offset = intrfc->if_ipx_offset;
- size=sizeof(ipx_packet)+len;
- size += ipx_offset;
-
- if(size+sk->wmem_alloc>sk->sndbuf) return -EAGAIN;
-
- skb=alloc_skb(size,GFP_KERNEL);
- if(skb==NULL) return -ENOMEM;
-
- skb->sk=sk;
- skb->len=size;
- skb->free=1;
- skb->arp=1;
-
- /* Fill in IPX header */
- ipx=(ipx_packet *)&(skb->data[ipx_offset]);
- ipx->ipx_checksum=0xFFFF;
- ipx->ipx_pktsize=htons(len+sizeof(ipx_packet));
- ipx->ipx_tctrl=0;
- ipx->ipx_type=usipx->sipx_type;
- skb->h.raw = (unsigned char *)ipx;
-
- ipx->ipx_source.net = sk->ipx_intrfc->if_netnum;
- memcpy(ipx->ipx_source.node, sk->ipx_intrfc->if_node, IPX_NODE_LEN);
- ipx->ipx_source.sock = sk->ipx_port;
- ipx->ipx_dest.net=usipx->sipx_network;
- memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
- ipx->ipx_dest.sock=usipx->sipx_port;
-
- memcpy_fromfs((char *)(ipx+1),ubuf,len);
- return ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
- rt->ir_router_node : ipx->ipx_dest.node);
-}
-
-static int
-ipxrtr_route_skb(struct sk_buff *skb)
-{
- ipx_packet *ipx = (ipx_packet *) (skb->h.raw);
- ipx_route *r;
- ipx_interface *i;
-
- r = ipxrtr_lookup(ipx->ipx_dest.net);
- if (r == NULL) {
- /* no known route */
- kfree_skb(skb,FREE_READ);
- return 0;
- }
- i = r->ir_intrfc;
- (void)ipxitf_send(i, skb, (r->ir_routed) ?
- r->ir_router_node : ipx->ipx_dest.node);
- return 0;
-}
-
-/*
- * We use a normal struct rtentry for route handling
- */
-
-static int ipxrtr_ioctl(unsigned int cmd, void *arg)
-{
- int err;
- struct rtentry rt; /* Use these to behave like 'other' stacks */
- struct sockaddr_ipx *sg,*st;
-
- err=verify_area(VERIFY_READ,arg,sizeof(rt));
- if(err)
- return err;
-
- memcpy_fromfs(&rt,arg,sizeof(rt));
-
- sg=(struct sockaddr_ipx *)&rt.rt_gateway;
- st=(struct sockaddr_ipx *)&rt.rt_dst;
-
- if(!(rt.rt_flags&RTF_GATEWAY))
- return -EINVAL; /* Direct routes are fixed */
- if(sg->sipx_family!=AF_IPX)
- return -EINVAL;
- if(st->sipx_family!=AF_IPX)
- return -EINVAL;
-
- switch(cmd)
- {
- case SIOCDELRT:
- return ipxrtr_delete(st->sipx_network);
- case SIOCADDRT:
- {
- struct ipx_route_definition f;
- f.ipx_network=st->sipx_network;
- f.ipx_router_network=sg->sipx_network;
- memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN);
- return ipxrtr_create(&f);
- }
- default:
- return -EINVAL;
- }
-}
-
-static char *
-ipx_frame_name(unsigned short frame)
-{
- switch (ntohs(frame)) {
- case ETH_P_IPX: return "EtherII";
- case ETH_P_802_2: return "802.2";
- case ETH_P_SNAP: return "SNAP";
- case ETH_P_802_3: return "802.3";
- default: return "None";
- }
-}
-
-static char *
-ipx_device_name(ipx_interface *intrfc)
-{
- return (intrfc->if_internal ? "Internal" :
- (intrfc->if_dev ? intrfc->if_dev->name : "Unknown"));
-}
-
-/* Called from proc fs */
-int
-ipx_get_interface_info(char *buffer, char **start, off_t offset, int length)
-{
- ipx_interface *i;
- int len=0;
- off_t pos=0;
- off_t begin=0;
-
- /* Theory.. Keep printing in the same place until we pass offset */
-
- len += sprintf (buffer,"%-11s%-15s%-9s%-11s%s\n", "Network",
- "Node_Address", "Primary", "Device", "Frame_Type");
- for (i = ipx_interfaces; i != NULL; i = i->if_next) {
- len += sprintf(buffer+len, "%08lX ", ntohl(i->if_netnum));
- len += sprintf (buffer+len,"%02X%02X%02X%02X%02X%02X ",
- i->if_node[0], i->if_node[1], i->if_node[2],
- i->if_node[3], i->if_node[4], i->if_node[5]);
- len += sprintf(buffer+len, "%-9s", (i == ipx_primary_net) ?
- "Yes" : "No");
- len += sprintf (buffer+len, "%-11s", ipx_device_name(i));
- len += sprintf (buffer+len, "%s\n",
- ipx_frame_name(i->if_dlink_type));
-
- /* Are we still dumping unwanted data then discard the record */
- pos=begin+len;
-
- if(pos<offset) {
- len=0; /* Keep dumping into the buffer start */
- begin=pos;
- }
- if(pos>offset+length) /* We have dumped enough */
- break;
- }
-
- /* The data in question runs from begin to begin+len */
- *start=buffer+(offset-begin); /* Start of wanted data */
- len-=(offset-begin); /* Remove unwanted header data from length */
- if(len>length)
- len=length; /* Remove unwanted tail data from length */
-
- return len;
-}
-
-int
-ipx_get_info(char *buffer, char **start, off_t offset, int length)
-{
- ipx_socket *s;
- ipx_interface *i;
- int len=0;
- off_t pos=0;
- off_t begin=0;
-
- /* Theory.. Keep printing in the same place until we pass offset */
-
- len += sprintf (buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
- "Remote_Address", "Tx_Queue", "Rx_Queue",
- "State", "Uid");
- for (i = ipx_interfaces; i != NULL; i = i->if_next) {
- for (s = i->if_sklist; s != NULL; s = s->next) {
- len += sprintf (buffer+len,"%08lX:%04X ",
- htonl(i->if_netnum),
- htons(s->ipx_port));
- if (s->state!=TCP_ESTABLISHED) {
- len += sprintf(buffer+len, "%-28s", "Not_Connected");
- } else {
- len += sprintf (buffer+len,
- "%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
- htonl(s->ipx_dest_addr.net),
- s->ipx_dest_addr.node[0], s->ipx_dest_addr.node[1],
- s->ipx_dest_addr.node[2], s->ipx_dest_addr.node[3],
- s->ipx_dest_addr.node[4], s->ipx_dest_addr.node[5],
- htons(s->ipx_dest_addr.sock));
- }
- len += sprintf (buffer+len,"%08lX %08lX ",
- s->wmem_alloc, s->rmem_alloc);
- len += sprintf (buffer+len,"%02X %03d\n",
- s->state, SOCK_INODE(s->socket)->i_uid);
-
- /* Are we still dumping unwanted data then discard the record */
- pos=begin+len;
-
- if(pos<offset)
- {
- len=0; /* Keep dumping into the buffer start */
- begin=pos;
- }
- if(pos>offset+length) /* We have dumped enough */
- break;
- }
- }
-
- /* The data in question runs from begin to begin+len */
- *start=buffer+(offset-begin); /* Start of wanted data */
- len-=(offset-begin); /* Remove unwanted header data from length */
- if(len>length)
- len=length; /* Remove unwanted tail data from length */
-
- return len;
-}
-
-int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length)
-{
- ipx_route *rt;
- int len=0;
- off_t pos=0;
- off_t begin=0;
-
- len += sprintf (buffer,"%-11s%-13s%s\n",
- "Network", "Router_Net", "Router_Node");
- for (rt = ipx_routes; rt != NULL; rt = rt->ir_next)
- {
- len += sprintf (buffer+len,"%08lX ", ntohl(rt->ir_net));
- if (rt->ir_routed) {
- len += sprintf (buffer+len,"%08lX %02X%02X%02X%02X%02X%02X\n",
- ntohl(rt->ir_intrfc->if_netnum),
- rt->ir_router_node[0], rt->ir_router_node[1],
- rt->ir_router_node[2], rt->ir_router_node[3],
- rt->ir_router_node[4], rt->ir_router_node[5]);
- } else {
- len += sprintf (buffer+len, "%-13s%s\n",
- "Directly", "Connected");
- }
- pos=begin+len;
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- }
- *start=buffer+(offset-begin);
- len-=(offset-begin);
- if(len>length)
- len=length;
- return len;
-}
-
-/*******************************************************************************************************************\
-* *
-* Handling for system calls applied via the various interfaces to an IPX socket object *
-* *
-\*******************************************************************************************************************/
-
-static int ipx_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- switch(cmd)
- {
- default:
- return(-EINVAL);
- }
-}
-
-static int ipx_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
-{
- ipx_socket *sk;
- int err,opt;
-
- sk=(ipx_socket *)sock->data;
-
- if(optval==NULL)
- return(-EINVAL);
-
- err=verify_area(VERIFY_READ,optval,sizeof(int));
- if(err)
- return err;
- opt=get_fs_long((unsigned long *)optval);
-
- switch(level)
- {
- case SOL_IPX:
- switch(optname)
- {
- case IPX_TYPE:
- sk->ipx_type=opt;
- return 0;
- default:
- return -EOPNOTSUPP;
- }
- break;
-
- case SOL_SOCKET:
- return sock_setsockopt(sk,level,optname,optval,optlen);
-
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static int ipx_getsockopt(struct socket *sock, int level, int optname,
- char *optval, int *optlen)
-{
- ipx_socket *sk;
- int val=0;
- int err;
-
- sk=(ipx_socket *)sock->data;
-
- switch(level)
- {
-
- case SOL_IPX:
- switch(optname)
- {
- case IPX_TYPE:
- val=sk->ipx_type;
- break;
- default:
- return -ENOPROTOOPT;
- }
- break;
-
- case SOL_SOCKET:
- return sock_getsockopt(sk,level,optname,optval,optlen);
-
- default:
- return -EOPNOTSUPP;
- }
- err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
- if(err)
- return err;
- put_fs_long(sizeof(int),(unsigned long *)optlen);
- err=verify_area(VERIFY_WRITE,optval,sizeof(int));
- put_fs_long(val,(unsigned long *)optval);
- return(0);
-}
-
-static int ipx_listen(struct socket *sock, int backlog)
-{
- return -EOPNOTSUPP;
-}
-
-static void def_callback1(struct sock *sk)
-{
- if(!sk->dead)
- wake_up_interruptible(sk->sleep);
-}
-
-static void def_callback2(struct sock *sk, int len)
-{
- if(!sk->dead)
- {
- wake_up_interruptible(sk->sleep);
- sock_wake_async(sk->socket, 1);
- }
-}
-
-static int
-ipx_create(struct socket *sock, int protocol)
-{
- ipx_socket *sk;
- sk=(ipx_socket *)kmalloc(sizeof(*sk),GFP_KERNEL);
- if(sk==NULL)
- return(-ENOMEM);
- switch(sock->type)
- {
- case SOCK_DGRAM:
- break;
- default:
- kfree_s((void *)sk,sizeof(*sk));
- return(-ESOCKTNOSUPPORT);
- }
- sk->dead=0;
- sk->next=NULL;
- sk->broadcast=0;
- sk->rcvbuf=SK_RMEM_MAX;
- sk->sndbuf=SK_WMEM_MAX;
- sk->wmem_alloc=0;
- sk->rmem_alloc=0;
- sk->inuse=0;
- sk->shutdown=0;
- sk->prot=NULL; /* So we use default free mechanisms */
- sk->broadcast=0;
- sk->err=0;
- skb_queue_head_init(&sk->receive_queue);
- skb_queue_head_init(&sk->write_queue);
- sk->send_head=NULL;
- skb_queue_head_init(&sk->back_log);
- sk->state=TCP_CLOSE;
- sk->socket=sock;
- sk->type=sock->type;
- sk->ipx_type=0; /* General user level IPX */
- sk->debug=0;
- sk->ipx_intrfc = NULL;
- memset(&sk->ipx_dest_addr,'\0',sizeof(sk->ipx_dest_addr));
- sk->ipx_port = 0;
- sk->mtu=IPX_MTU;
-
- if(sock!=NULL)
- {
- sock->data=(void *)sk;
- sk->sleep=sock->wait;
- }
-
- sk->state_change=def_callback1;
- sk->data_ready=def_callback2;
- sk->write_space=def_callback1;
- sk->error_report=def_callback1;
-
- sk->zapped=1;
- return 0;
-}
-
-static int ipx_release(struct socket *sock, struct socket *peer)
-{
- ipx_socket *sk=(ipx_socket *)sock->data;
- if(sk==NULL)
- return(0);
- if(!sk->dead)
- sk->state_change(sk);
- sk->dead=1;
- sock->data=NULL;
- ipx_destroy_socket(sk);
- return(0);
-}
-
-static int ipx_dup(struct socket *newsock,struct socket *oldsock)
-{
- return(ipx_create(newsock,SOCK_DGRAM));
-}
-
-static unsigned short
-ipx_first_free_socketnum(ipx_interface *intrfc)
-{
- unsigned short socketNum = intrfc->if_sknum;
-
- if (socketNum < IPX_MIN_EPHEMERAL_SOCKET)
- socketNum = IPX_MIN_EPHEMERAL_SOCKET;
-
- while (ipxitf_find_socket(intrfc, ntohs(socketNum)) != NULL)
- if (socketNum > IPX_MAX_EPHEMERAL_SOCKET)
- socketNum = IPX_MIN_EPHEMERAL_SOCKET;
- else
- socketNum++;
-
- intrfc->if_sknum = socketNum;
- return ntohs(socketNum);
-}
-
-static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
-{
- ipx_socket *sk;
- ipx_interface *intrfc;
- struct sockaddr_ipx *addr=(struct sockaddr_ipx *)uaddr;
-
- sk=(ipx_socket *)sock->data;
-
- if(sk->zapped==0)
- return -EIO;
-
- if(addr_len!=sizeof(struct sockaddr_ipx))
- return -EINVAL;
-
- intrfc = ipxitf_find_using_net(addr->sipx_network);
- if (intrfc == NULL)
- return -EADDRNOTAVAIL;
-
- if (addr->sipx_port == 0) {
- addr->sipx_port = ipx_first_free_socketnum(intrfc);
- if (addr->sipx_port == 0)
- return -EINVAL;
- }
-
- if(ntohs(addr->sipx_port)<IPX_MIN_EPHEMERAL_SOCKET && !suser())
- return -EPERM; /* protect IPX system stuff like routing/sap */
-
- /* Source addresses are easy. It must be our network:node pair for
- an interface routed to IPX with the ipx routing ioctl() */
-
- if(ipxitf_find_socket(intrfc, addr->sipx_port)!=NULL) {
- if(sk->debug)
- printk("IPX: bind failed because port %X in use.\n",
- (int)addr->sipx_port);
- return -EADDRINUSE;
- }
-
- sk->ipx_port=addr->sipx_port;
- ipxitf_insert_socket(intrfc, sk);
- sk->zapped=0;
- if(sk->debug)
- printk("IPX: socket is bound.\n");
- return 0;
-}
-
-static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
- int addr_len, int flags)
-{
- ipx_socket *sk=(ipx_socket *)sock->data;
- struct sockaddr_ipx *addr;
-
- sk->state = TCP_CLOSE;
- sock->state = SS_UNCONNECTED;
-
- if(addr_len!=sizeof(*addr))
- return(-EINVAL);
- addr=(struct sockaddr_ipx *)uaddr;
-
- if(sk->ipx_port==0)
- /* put the autobinding in */
- {
- struct sockaddr_ipx uaddr;
- int ret;
-
- uaddr.sipx_port = 0;
- uaddr.sipx_network = 0L;
- ret = ipx_bind (sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx));
- if (ret != 0) return (ret);
- }
-
- if(ipxrtr_lookup(addr->sipx_network)==NULL)
- return -ENETUNREACH;
- sk->ipx_dest_addr.net=addr->sipx_network;
- sk->ipx_dest_addr.sock=addr->sipx_port;
- memcpy(sk->ipx_dest_addr.node,addr->sipx_node,IPX_NODE_LEN);
- sk->ipx_type=addr->sipx_type;
- sock->state = SS_CONNECTED;
- sk->state=TCP_ESTABLISHED;
- return 0;
-}
-
-static int ipx_socketpair(struct socket *sock1, struct socket *sock2)
-{
- return(-EOPNOTSUPP);
-}
-
-static int ipx_accept(struct socket *sock, struct socket *newsock, int flags)
-{
- if(newsock->data)
- kfree_s(newsock->data,sizeof(ipx_socket));
- return -EOPNOTSUPP;
-}
-
-static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
- int *uaddr_len, int peer)
-{
- ipx_address *addr;
- struct sockaddr_ipx sipx;
- ipx_socket *sk;
-
- sk=(ipx_socket *)sock->data;
-
- *uaddr_len = sizeof(struct sockaddr_ipx);
-
- if(peer) {
- if(sk->state!=TCP_ESTABLISHED)
- return -ENOTCONN;
- addr=&sk->ipx_dest_addr;
- sipx.sipx_network = addr->net;
- memcpy(sipx.sipx_node,addr->node,IPX_NODE_LEN);
- sipx.sipx_port = addr->sock;
- } else {
- if (sk->ipx_intrfc != NULL) {
- sipx.sipx_network = sk->ipx_intrfc->if_netnum;
- memcpy(sipx.sipx_node, sk->ipx_intrfc->if_node,
- IPX_NODE_LEN);
- } else {
- sipx.sipx_network = 0L;
- memset(sipx.sipx_node, '\0', IPX_NODE_LEN);
- }
- sipx.sipx_port = sk->ipx_port;
- }
-
- sipx.sipx_family = AF_IPX;
- sipx.sipx_type = sk->ipx_type;
- memcpy(uaddr,&sipx,sizeof(sipx));
- return 0;
-}
-
-#if 0
-/*
- * User to dump IPX packets (debugging)
- */
-void dump_data(char *str,unsigned char *d) {
- static char h2c[] = "0123456789ABCDEF";
- int l,i;
- char *p, b[64];
- for (l=0;l<16;l++) {
- p = b;
- for (i=0; i < 8 ; i++) {
- *(p++) = h2c[d[i] & 0x0f];
- *(p++) = h2c[(d[i] >> 4) & 0x0f];
- *(p++) = ' ';
- }
- *(p++) = '-';
- *(p++) = ' ';
- for (i=0; i < 8 ; i++) *(p++) = ' '<= d[i] && d[i]<'\177' ? d[i] : '.';
- *p = '\000';
- d += i;
- printk("%s-%04X: %s\n",str,l*8,b);
- }
-}
-
-void dump_addr(char *str,ipx_address *p) {
- printk("%s: %08X:%02X%02X%02X%02X%02X%02X:%04X\n",
- str,ntohl(p->net),p->node[0],p->node[1],p->node[2],
- p->node[3],p->node[4],p->node[5],ntohs(p->sock));
-}
-
-void dump_hdr(char *str,ipx_packet *p) {
- printk("%s: CHKSUM=%04X SIZE=%d (%04X) HOPS=%d (%02X) TYPE=%02X\n",
- str,p->ipx_checksum,ntohs(p->ipx_pktsize),ntohs(p->ipx_pktsize),
- p->ipx_tctrl,p->ipx_tctrl,p->ipx_type);
- dump_addr(" IPX-DST",&p->ipx_dest);
- dump_addr(" IPX-SRC",&p->ipx_source);
-}
-
-void dump_pkt(char *str,ipx_packet *p) {
- dump_hdr(str,p);
- dump_data(str,(unsigned char *)p);
-}
-#endif
-
-int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
-{
- /* NULL here for pt means the packet was looped back */
- ipx_interface *intrfc;
- ipx_packet *ipx;
-
- ipx=(ipx_packet *)skb->h.raw;
-
- if(ipx->ipx_checksum!=IPX_NO_CHECKSUM) {
- /* We don't do checksum options. We can't really. Novell don't seem to have documented them.
- If you need them try the XNS checksum since IPX is basically XNS in disguise. It might be
- the same... */
- kfree_skb(skb,FREE_READ);
- return 0;
- }
-
- /* Too small */
- if(htons(ipx->ipx_pktsize)<sizeof(ipx_packet)) {
- kfree_skb(skb,FREE_READ);
- return 0;
- }
-
- /* Determine what local ipx endpoint this is */
- intrfc = ipxitf_find_using_phys(dev, pt->type);
- if (intrfc == NULL) {
- if (ipxcfg_auto_create_interfaces) {
- intrfc = ipxitf_auto_create(dev, pt->type);
- }
-
- if (intrfc == NULL) {
- /* Not one of ours */
- kfree_skb(skb,FREE_READ);
- return 0;
- }
- }
-
- return ipxitf_rcv(intrfc, skb);
-}
-
-static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
- unsigned flags, struct sockaddr *usip, int addr_len)
-{
- ipx_socket *sk=(ipx_socket *)sock->data;
- struct sockaddr_ipx *usipx=(struct sockaddr_ipx *)usip;
- struct sockaddr_ipx local_sipx;
- int retval;
-
- if (sk->zapped) return -EIO; /* Socket not bound */
- if(flags) return -EINVAL;
-
- if(usipx) {
- if(sk->ipx_port == 0) {
- struct sockaddr_ipx uaddr;
- int ret;
-
- uaddr.sipx_port = 0;
- uaddr.sipx_network = 0L;
- ret = ipx_bind (sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx));
- if (ret != 0) return ret;
- }
-
- if(addr_len <sizeof(*usipx))
- return -EINVAL;
- if(usipx->sipx_family != AF_IPX)
- return -EINVAL;
- } else {
- if(sk->state!=TCP_ESTABLISHED)
- return -ENOTCONN;
- usipx=&local_sipx;
- usipx->sipx_family=AF_IPX;
- usipx->sipx_type=sk->ipx_type;
- usipx->sipx_port=sk->ipx_dest_addr.sock;
- usipx->sipx_network=sk->ipx_dest_addr.net;
- memcpy(usipx->sipx_node,sk->ipx_dest_addr.node,IPX_NODE_LEN);
- }
-
- retval = ipxrtr_route_packet(sk, usipx, ubuf, len);
- if (retval < 0) return retval;
-
- return len;
-}
-
-static int ipx_send(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags)
-{
- return ipx_sendto(sock,ubuf,size,noblock,flags,NULL,0);
-}
-
-static int ipx_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
- unsigned flags, struct sockaddr *sip, int *addr_len)
-{
- ipx_socket *sk=(ipx_socket *)sock->data;
- struct sockaddr_ipx *sipx=(struct sockaddr_ipx *)sip;
- struct ipx_packet *ipx = NULL;
- int copied = 0;
- int truesize;
- struct sk_buff *skb;
- int er;
-
- if(sk->err)
- {
- er= -sk->err;
- sk->err=0;
- return er;
- }
-
- if (sk->zapped)
- return -EIO;
-
- if(addr_len)
- *addr_len=sizeof(*sipx);
-
- skb=skb_recv_datagram(sk,flags,noblock,&er);
- if(skb==NULL)
- return er;
-
- ipx = (ipx_packet *)(skb->h.raw);
- truesize=ntohs(ipx->ipx_pktsize) - sizeof(ipx_packet);
- copied = (truesize > size) ? size : truesize;
- skb_copy_datagram(skb,sizeof(struct ipx_packet),ubuf,copied);
-
- if(sipx)
- {
- sipx->sipx_family=AF_IPX;
- sipx->sipx_port=ipx->ipx_source.sock;
- memcpy(sipx->sipx_node,ipx->ipx_source.node,IPX_NODE_LEN);
- sipx->sipx_network=ipx->ipx_source.net;
- sipx->sipx_type = ipx->ipx_type;
- }
- skb_free_datagram(skb);
- return(truesize);
-}
-
-static int ipx_write(struct socket *sock, char *ubuf, int size, int noblock)
-{
- return ipx_send(sock,ubuf,size,noblock,0);
-}
-
-
-static int ipx_recv(struct socket *sock, void *ubuf, int size , int noblock,
- unsigned flags)
-{
- ipx_socket *sk=(ipx_socket *)sock->data;
- if(sk->zapped)
- return -ENOTCONN;
- return ipx_recvfrom(sock,ubuf,size,noblock,flags,NULL, NULL);
-}
-
-static int ipx_read(struct socket *sock, char *ubuf, int size, int noblock)
-{
- return ipx_recv(sock,ubuf,size,noblock,0);
-}
-
-
-static int ipx_shutdown(struct socket *sk,int how)
-{
- return -EOPNOTSUPP;
-}
-
-static int ipx_select(struct socket *sock , int sel_type, select_table *wait)
-{
- ipx_socket *sk=(ipx_socket *)sock->data;
-
- return datagram_select(sk,sel_type,wait);
-}
-
-static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
-{
- int err;
- long amount=0;
- ipx_socket *sk=(ipx_socket *)sock->data;
-
- switch(cmd)
- {
- case TIOCOUTQ:
- err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
- if(err)
- return err;
- amount=sk->sndbuf-sk->wmem_alloc;
- if(amount<0)
- amount=0;
- put_fs_long(amount,(unsigned long *)arg);
- return 0;
- case TIOCINQ:
- {
- struct sk_buff *skb;
- /* These two are safe on a single CPU system as only user tasks fiddle here */
- if((skb=skb_peek(&sk->receive_queue))!=NULL)
- amount=skb->len;
- err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
- put_fs_long(amount,(unsigned long *)arg);
- return 0;
- }
- case SIOCADDRT:
- case SIOCDELRT:
- if(!suser())
- return -EPERM;
- return(ipxrtr_ioctl(cmd,(void *)arg));
- case SIOCSIFADDR:
- case SIOCGIFADDR:
- case SIOCAIPXITFCRT:
- case SIOCAIPXPRISLT:
- if(!suser())
- return -EPERM;
- return(ipxitf_ioctl(cmd,(void *)arg));
- case SIOCIPXCFGDATA:
- {
- err=verify_area(VERIFY_WRITE,(void *)arg,
- sizeof(ipx_config_data));
- if(err) return err;
- return(ipxcfg_get_config_data((void *)arg));
- }
- case SIOCGSTAMP:
- if (sk)
- {
- if(sk->stamp.tv_sec==0)
- return -ENOENT;
- err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
- if(err)
- return err;
- memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval));
- return 0;
- }
- return -EINVAL;
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCGIFBRDADDR:
- case SIOCSIFBRDADDR:
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- return -EINVAL;
- default:
- return(dev_ioctl(cmd,(void *) arg));
- }
- /*NOTREACHED*/
- return(0);
-}
-
-static struct proto_ops ipx_proto_ops = {
- AF_IPX,
-
- ipx_create,
- ipx_dup,
- ipx_release,
- ipx_bind,
- ipx_connect,
- ipx_socketpair,
- ipx_accept,
- ipx_getname,
- ipx_read,
- ipx_write,
- ipx_select,
- ipx_ioctl,
- ipx_listen,
- ipx_send,
- ipx_recv,
- ipx_sendto,
- ipx_recvfrom,
- ipx_shutdown,
- ipx_setsockopt,
- ipx_getsockopt,
- ipx_fcntl,
-};
-
-/* Called by ddi.c on kernel start up */
-
-static struct packet_type ipx_8023_packet_type =
-
-{
- 0, /* MUTTER ntohs(ETH_P_8023),*/
- NULL, /* All devices */
- ipx_rcv,
- NULL,
- NULL,
-};
-
-static struct packet_type ipx_dix_packet_type =
-{
- 0, /* MUTTER ntohs(ETH_P_IPX),*/
- NULL, /* All devices */
- ipx_rcv,
- NULL,
- NULL,
-};
-
-static struct notifier_block ipx_dev_notifier={
- ipxitf_device_event,
- NULL,
- 0
-};
-
-
-extern struct datalink_proto *make_EII_client(void);
-extern struct datalink_proto *make_8023_client(void);
-
-void ipx_proto_init(struct net_proto *pro)
-{
- unsigned char val = 0xE0;
- unsigned char snapval[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
-
- (void) sock_register(ipx_proto_ops.family, &ipx_proto_ops);
-
- pEII_datalink = make_EII_client();
- ipx_dix_packet_type.type=htons(ETH_P_IPX);
- dev_add_pack(&ipx_dix_packet_type);
-
- p8023_datalink = make_8023_client();
- ipx_8023_packet_type.type=htons(ETH_P_802_3);
- dev_add_pack(&ipx_8023_packet_type);
-
- if ((p8022_datalink = register_8022_client(val, ipx_rcv)) == NULL)
- printk("IPX: Unable to register with 802.2\n");
-
- if ((pSNAP_datalink = register_snap_client(snapval, ipx_rcv)) == NULL)
- printk("IPX: Unable to register with SNAP\n");
-
- register_netdevice_notifier(&ipx_dev_notifier);
-
- printk("Swansea University Computer Society IPX 0.29 BETA for NET3.019\n");
- printk("IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
-}
-#endif
diff --git a/pfinet/linux-inet/ipx.h b/pfinet/linux-inet/ipx.h
deleted file mode 100644
index 6842c832..00000000
--- a/pfinet/linux-inet/ipx.h
+++ /dev/null
@@ -1,84 +0,0 @@
-
-/*
- * The following information is in its entirety obtained from:
- *
- * Novell 'IPX Router Specification' Version 1.10
- * Part No. 107-000029-001
- *
- * Which is available from ftp.novell.com
- */
-
-#ifndef _NET_INET_IPX_H_
-#define _NET_INET_IPX_H_
-
-#include <linux/skbuff.h>
-#include "datalink.h"
-#include <linux/ipx.h>
-
-typedef struct
-{
- unsigned long net;
- unsigned char node[IPX_NODE_LEN];
- unsigned short sock;
-} ipx_address;
-
-#define ipx_broadcast_node "\377\377\377\377\377\377"
-
-typedef struct ipx_packet
-{
- unsigned short ipx_checksum;
-#define IPX_NO_CHECKSUM 0xFFFF
- unsigned short ipx_pktsize;
- unsigned char ipx_tctrl;
- unsigned char ipx_type;
-#define IPX_TYPE_UNKNOWN 0x00
-#define IPX_TYPE_RIP 0x01 /* may also be 0 */
-#define IPX_TYPE_SAP 0x04 /* may also be 0 */
-#define IPX_TYPE_SPX 0x05 /* Not yet implemented */
-#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
-#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
- ipx_address ipx_dest __attribute__ ((packed));
- ipx_address ipx_source __attribute__ ((packed));
-} ipx_packet;
-
-
-typedef struct sock ipx_socket;
-
-#include "ipxcall.h"
-extern int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt);
-extern void ipxrtr_device_down(struct device *dev);
-
-typedef struct ipx_interface {
- /* IPX address */
- unsigned long if_netnum;
- unsigned char if_node[IPX_NODE_LEN];
-
- /* physical device info */
- struct device *if_dev;
- struct datalink_proto *if_dlink;
- unsigned short if_dlink_type;
-
- /* socket support */
- unsigned short if_sknum;
- ipx_socket *if_sklist;
-
- /* administrative overhead */
- int if_ipx_offset;
- unsigned char if_internal;
- unsigned char if_primary;
-
- struct ipx_interface *if_next;
-} ipx_interface;
-
-typedef struct ipx_route {
- unsigned long ir_net;
- ipx_interface *ir_intrfc;
- unsigned char ir_routed;
- unsigned char ir_router_node[IPX_NODE_LEN];
- struct ipx_route *ir_next;
-} ipx_route;
-
-#define IPX_MIN_EPHEMERAL_SOCKET 0x4000
-#define IPX_MAX_EPHEMERAL_SOCKET 0x7fff
-
-#endif
diff --git a/pfinet/linux-inet/ipxcall.h b/pfinet/linux-inet/ipxcall.h
deleted file mode 100644
index eb5bd2bd..00000000
--- a/pfinet/linux-inet/ipxcall.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Separate to keep compilation of protocols.c simpler */
-extern void ipx_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-inet/p8022.c b/pfinet/linux-inet/p8022.c
deleted file mode 100644
index 8ff3ec60..00000000
--- a/pfinet/linux-inet/p8022.c
+++ /dev/null
@@ -1,98 +0,0 @@
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include "datalink.h"
-#include <linux/mm.h>
-#include <linux/in.h>
-
-static struct datalink_proto *p8022_list = NULL;
-
-static struct datalink_proto *
-find_8022_client(unsigned char type)
-{
- struct datalink_proto *proto;
-
- for (proto = p8022_list;
- ((proto != NULL) && (*(proto->type) != type));
- proto = proto->next)
- ;
-
- return proto;
-}
-
-int
-p8022_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
-{
- struct datalink_proto *proto;
-
- proto = find_8022_client(*(skb->h.raw));
- if (proto != NULL) {
- skb->h.raw += 3;
- skb->len -= 3;
- return proto->rcvfunc(skb, dev, pt);
- }
-
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
- return 0;
-}
-
-static void
-p8022_datalink_header(struct datalink_proto *dl,
- struct sk_buff *skb, unsigned char *dest_node)
-{
- struct device *dev = skb->dev;
- unsigned long len = skb->len;
- unsigned long hard_len = dev->hard_header_len;
- unsigned char *rawp;
-
- dev->hard_header(skb->data, dev, len - hard_len,
- dest_node, NULL, len - hard_len, skb);
- rawp = skb->data + hard_len;
- *rawp = dl->type[0];
- rawp++;
- *rawp = dl->type[0];
- rawp++;
- *rawp = 0x03; /* UI */
- rawp++;
- skb->h.raw = rawp;
-}
-
-static struct packet_type p8022_packet_type =
-{
- 0, /* MUTTER ntohs(ETH_P_IPX),*/
- NULL, /* All devices */
- p8022_rcv,
- NULL,
- NULL,
-};
-
-
-void p8022_proto_init(struct net_proto *pro)
-{
- p8022_packet_type.type=htons(ETH_P_802_2);
- dev_add_pack(&p8022_packet_type);
-}
-
-struct datalink_proto *
-register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
-{
- struct datalink_proto *proto;
-
- if (find_8022_client(type) != NULL)
- return NULL;
-
- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
- if (proto != NULL) {
- proto->type[0] = type;
- proto->type_len = 1;
- proto->rcvfunc = rcvfunc;
- proto->header_length = 3;
- proto->datalink_header = p8022_datalink_header;
- proto->string_name = "802.2";
- proto->next = p8022_list;
- p8022_list = proto;
- }
-
- return proto;
-}
-
diff --git a/pfinet/linux-inet/p8022.h b/pfinet/linux-inet/p8022.h
deleted file mode 100644
index 52c676be..00000000
--- a/pfinet/linux-inet/p8022.h
+++ /dev/null
@@ -1,2 +0,0 @@
-struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *));
-
diff --git a/pfinet/linux-inet/p8022call.h b/pfinet/linux-inet/p8022call.h
deleted file mode 100644
index 14f0c2ce..00000000
--- a/pfinet/linux-inet/p8022call.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Separate to keep compilation of Space.c simpler */
-extern void p8022_proto_init(struct net_proto *);
diff --git a/pfinet/linux-inet/p8023.c b/pfinet/linux-inet/p8023.c
deleted file mode 100644
index 7c76223d..00000000
--- a/pfinet/linux-inet/p8023.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include "datalink.h"
-#include <linux/mm.h>
-#include <linux/in.h>
-
-static void
-p8023_datalink_header(struct datalink_proto *dl,
- struct sk_buff *skb, unsigned char *dest_node)
-{
- struct device *dev = skb->dev;
- unsigned long len = skb->len;
- unsigned long hard_len = dev->hard_header_len;
-
- dev->hard_header(skb->data, dev, len - hard_len,
- dest_node, NULL, len - hard_len, skb);
- skb->h.raw = skb->data + hard_len;
-}
-
-struct datalink_proto *
-make_8023_client(void)
-{
- struct datalink_proto *proto;
-
- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
- if (proto != NULL) {
- proto->type_len = 0;
- proto->header_length = 0;
- proto->datalink_header = p8023_datalink_header;
- proto->string_name = "802.3";
- }
-
- return proto;
-}
-
diff --git a/pfinet/linux-inet/packet.c b/pfinet/linux-inet/packet.c
deleted file mode 100644
index ab031c81..00000000
--- a/pfinet/linux-inet/packet.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * PACKET - implements raw packet sockets.
- *
- * Version: @(#)packet.c 1.0.6 05/25/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- *
- * Fixes:
- * Alan Cox : verify_area() now used correctly
- * Alan Cox : new skbuff lists, look ma no backlogs!
- * Alan Cox : tidied skbuff lists.
- * Alan Cox : Now uses generic datagram routines I
- * added. Also fixed the peek/read crash
- * from all old Linux datagram code.
- * Alan Cox : Uses the improved datagram code.
- * Alan Cox : Added NULL's for socket options.
- * Alan Cox : Re-commented the code.
- * Alan Cox : Use new kernel side addressing
- * Rob Janssen : Correct MTU usage.
- * Dave Platt : Counter leaks caused by incorrect
- * interrupt locking and some slightly
- * dubious gcc output. Can you read
- * compiler: it said _VOLATILE_
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fcntl.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-
-/*
- * We really ought to have a single public _inline_ min function!
- */
-
-static unsigned long min(unsigned long a, unsigned long b)
-{
- if (a < b)
- return(a);
- return(b);
-}
-
-
-/*
- * This should be the easiest of all, all we do is copy it into a buffer.
- */
-
-int packet_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
-{
- struct sock *sk;
- unsigned long flags;
-
- /*
- * When we registered the protocol we saved the socket in the data
- * field for just this event.
- */
-
- sk = (struct sock *) pt->data;
-
- /*
- * The SOCK_PACKET socket receives _all_ frames, and as such
- * therefore needs to put the header back onto the buffer.
- * (it was removed by inet_bh()).
- */
-
- skb->dev = dev;
- skb->len += dev->hard_header_len;
-
- /*
- * Charge the memory to the socket. This is done specifically
- * to prevent sockets using all the memory up.
- */
-
- if (sk->rmem_alloc & 0xFF000000) {
- printk("packet_rcv: sk->rmem_alloc = %ld\n", sk->rmem_alloc);
- sk->rmem_alloc = 0;
- }
-
- if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
- {
-/* printk("packet_rcv: drop, %d+%d>%d\n", sk->rmem_alloc, skb->mem_len, sk->rcvbuf); */
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
- return(0);
- }
-
- save_flags(flags);
- cli();
-
- skb->sk = sk;
- sk->rmem_alloc += skb->mem_len;
-
- /*
- * Queue the packet up, and wake anyone waiting for it.
- */
-
- skb_queue_tail(&sk->receive_queue,skb);
- if(!sk->dead)
- sk->data_ready(sk,skb->len);
-
- restore_flags(flags);
-
- /*
- * Processing complete.
- */
-
- release_sock(sk); /* This is now effectively surplus in this layer */
- return(0);
-}
-
-
-/*
- * Output a raw packet to a device layer. This bypasses all the other
- * protocol layers and you must therefore supply it with a complete frame
- */
-
-static int packet_sendto(struct sock *sk, unsigned char *from, int len,
- int noblock, unsigned flags, struct sockaddr_in *usin,
- int addr_len)
-{
- struct sk_buff *skb;
- struct device *dev;
- struct sockaddr *saddr=(struct sockaddr *)usin;
-
- /*
- * Check the flags.
- */
-
- if (flags)
- return(-EINVAL);
-
- /*
- * Get and verify the address.
- */
-
- if (usin)
- {
- if (addr_len < sizeof(*saddr))
- return(-EINVAL);
- }
- else
- return(-EINVAL); /* SOCK_PACKET must be sent giving an address */
-
- /*
- * Find the device first to size check it
- */
-
- saddr->sa_data[13] = 0;
- dev = dev_get(saddr->sa_data);
- if (dev == NULL)
- {
- return(-ENXIO);
- }
-
- /*
- * You may not queue a frame bigger than the mtu. This is the lowest level
- * raw protocol and you must do your own fragmentation at this level.
- */
-
- if(len>dev->mtu+dev->hard_header_len)
- return -EMSGSIZE;
-
- skb = sk->prot->wmalloc(sk, len, 0, GFP_KERNEL);
-
- /*
- * If the write buffer is full, then tough. At this level the user gets to
- * deal with the problem - do your own algorithmic backoffs.
- */
-
- if (skb == NULL)
- {
- return(-ENOBUFS);
- }
-
- /*
- * Fill it in
- */
-
- skb->sk = sk;
- skb->free = 1;
- memcpy_fromfs(skb->data, from, len);
- skb->len = len;
- skb->arp = 1; /* No ARP needs doing on this (complete) frame */
-
- /*
- * Now send it
- */
-
- if (dev->flags & IFF_UP)
- dev_queue_xmit(skb, dev, sk->priority);
- else
- kfree_skb(skb, FREE_WRITE);
- return(len);
-}
-
-/*
- * A write to a SOCK_PACKET can't actually do anything useful and will
- * always fail but we include it for completeness and future expansion.
- */
-
-static int packet_write(struct sock *sk, unsigned char *buff,
- int len, int noblock, unsigned flags)
-{
- return(packet_sendto(sk, buff, len, noblock, flags, NULL, 0));
-}
-
-/*
- * Close a SOCK_PACKET socket. This is fairly simple. We immediately go
- * to 'closed' state and remove our protocol entry in the device list.
- * The release_sock() will destroy the socket if a user has closed the
- * file side of the object.
- */
-
-static void packet_close(struct sock *sk, int timeout)
-{
- sk->inuse = 1;
- sk->state = TCP_CLOSE;
- dev_remove_pack((struct packet_type *)sk->pair);
- kfree_s((void *)sk->pair, sizeof(struct packet_type));
- sk->pair = NULL;
- release_sock(sk);
-}
-
-/*
- * Create a packet of type SOCK_PACKET. We do one slightly irregular
- * thing here that wants tidying up. We borrow the 'pair' pointer in
- * the socket object so we can find the packet_type entry in the
- * device list. The reverse is easy as we use the data field of the
- * packet type to point to our socket.
- */
-
-static int packet_init(struct sock *sk)
-{
- struct packet_type *p;
-
- p = (struct packet_type *) kmalloc(sizeof(*p), GFP_KERNEL);
- if (p == NULL)
- return(-ENOMEM);
-
- p->func = packet_rcv;
- p->type = sk->num;
- p->data = (void *)sk;
- p->dev = NULL;
- dev_add_pack(p);
-
- /*
- * We need to remember this somewhere.
- */
-
- sk->pair = (struct sock *)p;
-
- return(0);
-}
-
-
-/*
- * Pull a packet from our receive queue and hand it to the user.
- * If necessary we block.
- */
-
-int packet_recvfrom(struct sock *sk, unsigned char *to, int len,
- int noblock, unsigned flags, struct sockaddr_in *sin,
- int *addr_len)
-{
- int copied=0;
- struct sk_buff *skb;
- struct sockaddr *saddr;
- int err;
- int truesize;
-
- saddr = (struct sockaddr *)sin;
-
- if (sk->shutdown & RCV_SHUTDOWN)
- return(0);
-
- /*
- * If the address length field is there to be filled in, we fill
- * it in now.
- */
-
- if (addr_len)
- *addr_len=sizeof(*saddr);
-
- /*
- * Call the generic datagram receiver. This handles all sorts
- * of horrible races and re-entrancy so we can forget about it
- * in the protocol layers.
- */
-
- skb=skb_recv_datagram(sk,flags,noblock,&err);
-
- /*
- * An error occurred so return it. Because skb_recv_datagram()
- * handles the blocking we don't see and worry about blocking
- * retries.
- */
-
- if(skb==NULL)
- return err;
-
- /*
- * You lose any data beyond the buffer you gave. If it worries a
- * user program they can ask the device for its MTU anyway.
- */
-
- truesize = skb->len;
- copied = min(len, truesize);
-
- memcpy_tofs(to, skb->data, copied); /* We can't use skb_copy_datagram here */
-
- /*
- * Copy the address.
- */
-
- if (saddr)
- {
- saddr->sa_family = skb->dev->type;
- memcpy(saddr->sa_data,skb->dev->name, 14);
- }
-
- /*
- * Free or return the buffer as appropriate. Again this hides all the
- * races and re-entrancy issues from us.
- */
-
- skb_free_datagram(skb);
-
- /*
- * We are done.
- */
-
- release_sock(sk);
- return(truesize);
-}
-
-
-/*
- * A packet read can succeed and is just the same as a recvfrom but without the
- * addresses being recorded.
- */
-
-int packet_read(struct sock *sk, unsigned char *buff,
- int len, int noblock, unsigned flags)
-{
- return(packet_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
-}
-
-
-/*
- * This structure declares to the lower layer socket subsystem currently
- * incorrectly embedded in the IP code how to behave. This interface needs
- * a lot of work and will change.
- */
-
-struct proto packet_prot =
-{
- sock_wmalloc,
- sock_rmalloc,
- sock_wfree,
- sock_rfree,
- sock_rspace,
- sock_wspace,
- packet_close,
- packet_read,
- packet_write,
- packet_sendto,
- packet_recvfrom,
- ip_build_header, /* Not actually used */
- NULL,
- NULL,
- ip_queue_xmit, /* These two are not actually used */
- NULL,
- NULL,
- NULL,
- NULL,
- datagram_select,
- NULL,
- packet_init,
- NULL,
- NULL, /* No set/get socket options */
- NULL,
- 128,
- 0,
- {NULL,},
- "PACKET",
- 0, 0
-};
diff --git a/pfinet/linux-inet/pe2.c b/pfinet/linux-inet/pe2.c
deleted file mode 100644
index 856e454b..00000000
--- a/pfinet/linux-inet/pe2.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include "datalink.h"
-#include <linux/mm.h>
-#include <linux/in.h>
-
-static void
-pEII_datalink_header(struct datalink_proto *dl,
- struct sk_buff *skb, unsigned char *dest_node)
-{
- struct device *dev = skb->dev;
- unsigned long len = skb->len;
- unsigned long hard_len = dev->hard_header_len;
-
- dev->hard_header(skb->data, dev, ETH_P_IPX,
- dest_node, NULL, len - hard_len, skb);
- skb->h.raw = skb->data + hard_len;
-}
-
-struct datalink_proto *
-make_EII_client(void)
-{
- struct datalink_proto *proto;
-
- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
- if (proto != NULL) {
- proto->type_len = 0;
- proto->header_length = 0;
- proto->datalink_header = pEII_datalink_header;
- proto->string_name = "EtherII";
- }
-
- return proto;
-}
-
diff --git a/pfinet/linux-inet/proc.c b/pfinet/linux-inet/proc.c
deleted file mode 100644
index aec473a2..00000000
--- a/pfinet/linux-inet/proc.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * This file implements the various access functions for the
- * PROC file system. It is mainly used for debugging and
- * statistics.
- *
- * Version: @(#)proc.c 1.0.5 05/27/93
- *
- * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
- * Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
- * Erik Schoenfelder, <schoenfr@ibr.cs.tu-bs.de>
- *
- * Fixes:
- * Alan Cox : UDP sockets show the rxqueue/txqueue
- * using hint flag for the netinfo.
- * Pauline Middelink : identd support
- * Alan Cox : Make /proc safer.
- * Erik Schoenfelder : /proc/net/snmp
- * Alan Cox : Handle dead sockets properly.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#include <asm/system.h>
-#include <linux/autoconf.h>
-#include <linux/sched.h>
-#include <linux/socket.h>
-#include <linux/net.h>
-#include <linux/un.h>
-#include <linux/in.h>
-#include <linux/param.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "icmp.h"
-#include "protocol.h"
-#include "tcp.h"
-#include "udp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "raw.h"
-
-/*
- * Get__netinfo returns the length of that string.
- *
- * KNOWN BUGS
- * As in get_unix_netinfo, the buffer might be too small. If this
- * happens, get__netinfo returns only part of the available infos.
- */
-static int
-get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t offset, int length)
-{
- struct sock **s_array;
- struct sock *sp;
- int i;
- int timer_active;
- unsigned long dest, src;
- unsigned short destp, srcp;
- int len=0;
- off_t pos=0;
- off_t begin=0;
-
- s_array = pro->sock_array;
- len+=sprintf(buffer, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
-/*
- * This was very pretty but didn't work when a socket is destroyed at the wrong moment
- * (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing
- * with timers we just concede defeat and cli().
- */
- for(i = 0; i < SOCK_ARRAY_SIZE; i++)
- {
- cli();
- sp = s_array[i];
- while(sp != NULL)
- {
- dest = sp->daddr;
- src = sp->saddr;
- destp = sp->dummy_th.dest;
- srcp = sp->dummy_th.source;
-
- /* Since we are Little Endian we need to swap the bytes :-( */
- destp = ntohs(destp);
- srcp = ntohs(srcp);
- timer_active = del_timer(&sp->timer);
- if (!timer_active)
- sp->timer.expires = 0;
- len+=sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d %d\n",
- i, src, srcp, dest, destp, sp->state,
- format==0?sp->write_seq-sp->rcv_ack_seq:sp->rmem_alloc,
- format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
- timer_active, sp->timer.expires, (unsigned) sp->retransmits,
- sp->socket?SOCK_INODE(sp->socket)->i_uid:0,
- timer_active?sp->timeout:0);
- if (timer_active)
- add_timer(&sp->timer);
- /*
- * All sockets with (port mod SOCK_ARRAY_SIZE) = i
- * are kept in sock_array[i], so we must follow the
- * 'next' link to get them all.
- */
- sp = sp->next;
- pos=begin+len;
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- }
- sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
- before this will clear before we jump back and cli, so it's not as bad as it looks */
- if(pos>offset+length)
- break;
- }
- *start=buffer+(offset-begin);
- len-=(offset-begin);
- if(len>length)
- len=length;
- return len;
-}
-
-
-int tcp_get_info(char *buffer, char **start, off_t offset, int length)
-{
- return get__netinfo(&tcp_prot, buffer,0, start, offset, length);
-}
-
-
-int udp_get_info(char *buffer, char **start, off_t offset, int length)
-{
- return get__netinfo(&udp_prot, buffer,1, start, offset, length);
-}
-
-
-int raw_get_info(char *buffer, char **start, off_t offset, int length)
-{
- return get__netinfo(&raw_prot, buffer,1, start, offset, length);
-}
-
-
-/*
- * Report socket allocation statistics [mea@utu.fi]
- */
-int afinet_get_info(char *buffer, char **start, off_t offset, int length)
-{
- /* From net/socket.c */
- extern int socket_get_info(char *, char **, off_t, int);
-#ifndef _HURD_
- extern struct proto packet_prot;
- int len = socket_get_info(buffer,start,offset,length);
-#else
- int len = 0;
-#endif
-
-
- len += sprintf(buffer+len,"SOCK_ARRAY_SIZE=%d\n",SOCK_ARRAY_SIZE);
- len += sprintf(buffer+len,"TCP: inuse %d highest %d\n",
- tcp_prot.inuse, tcp_prot.highestinuse);
- len += sprintf(buffer+len,"UDP: inuse %d highest %d\n",
- udp_prot.inuse, udp_prot.highestinuse);
- len += sprintf(buffer+len,"RAW: inuse %d highest %d\n",
- raw_prot.inuse, raw_prot.highestinuse);
-#ifndef _HURD_
- len += sprintf(buffer+len,"PAC: inuse %d highest %d\n",
- packet_prot.inuse, packet_prot.highestinuse);
-#endif
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
- return len;
-}
-
-
-/*
- * Called from the PROCfs module. This outputs /proc/net/snmp.
- */
-
-int snmp_get_info(char *buffer, char **start, off_t offset, int length)
-{
- extern struct tcp_mib tcp_statistics;
- extern struct udp_mib udp_statistics;
- int len;
-/*
- extern unsigned long tcp_rx_miss, tcp_rx_hit1,tcp_rx_hit2;
-*/
-
- len = sprintf (buffer,
- "Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates\n"
- "Ip: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
- ip_statistics.IpForwarding, ip_statistics.IpDefaultTTL,
- ip_statistics.IpInReceives, ip_statistics.IpInHdrErrors,
- ip_statistics.IpInAddrErrors, ip_statistics.IpForwDatagrams,
- ip_statistics.IpInUnknownProtos, ip_statistics.IpInDiscards,
- ip_statistics.IpInDelivers, ip_statistics.IpOutRequests,
- ip_statistics.IpOutDiscards, ip_statistics.IpOutNoRoutes,
- ip_statistics.IpReasmTimeout, ip_statistics.IpReasmReqds,
- ip_statistics.IpReasmOKs, ip_statistics.IpReasmFails,
- ip_statistics.IpFragOKs, ip_statistics.IpFragFails,
- ip_statistics.IpFragCreates);
-
- len += sprintf (buffer + len,
- "Icmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps\n"
- "Icmp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
- icmp_statistics.IcmpInMsgs, icmp_statistics.IcmpInErrors,
- icmp_statistics.IcmpInDestUnreachs, icmp_statistics.IcmpInTimeExcds,
- icmp_statistics.IcmpInParmProbs, icmp_statistics.IcmpInSrcQuenchs,
- icmp_statistics.IcmpInRedirects, icmp_statistics.IcmpInEchos,
- icmp_statistics.IcmpInEchoReps, icmp_statistics.IcmpInTimestamps,
- icmp_statistics.IcmpInTimestampReps, icmp_statistics.IcmpInAddrMasks,
- icmp_statistics.IcmpInAddrMaskReps, icmp_statistics.IcmpOutMsgs,
- icmp_statistics.IcmpOutErrors, icmp_statistics.IcmpOutDestUnreachs,
- icmp_statistics.IcmpOutTimeExcds, icmp_statistics.IcmpOutParmProbs,
- icmp_statistics.IcmpOutSrcQuenchs, icmp_statistics.IcmpOutRedirects,
- icmp_statistics.IcmpOutEchos, icmp_statistics.IcmpOutEchoReps,
- icmp_statistics.IcmpOutTimestamps, icmp_statistics.IcmpOutTimestampReps,
- icmp_statistics.IcmpOutAddrMasks, icmp_statistics.IcmpOutAddrMaskReps);
-
- len += sprintf (buffer + len,
- "Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs\n"
- "Tcp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
- tcp_statistics.TcpRtoAlgorithm, tcp_statistics.TcpRtoMin,
- tcp_statistics.TcpRtoMax, tcp_statistics.TcpMaxConn,
- tcp_statistics.TcpActiveOpens, tcp_statistics.TcpPassiveOpens,
- tcp_statistics.TcpAttemptFails, tcp_statistics.TcpEstabResets,
- tcp_statistics.TcpCurrEstab, tcp_statistics.TcpInSegs,
- tcp_statistics.TcpOutSegs, tcp_statistics.TcpRetransSegs);
-
- len += sprintf (buffer + len,
- "Udp: InDatagrams NoPorts InErrors OutDatagrams\nUdp: %lu %lu %lu %lu\n",
- udp_statistics.UdpInDatagrams, udp_statistics.UdpNoPorts,
- udp_statistics.UdpInErrors, udp_statistics.UdpOutDatagrams);
-/*
- len += sprintf( buffer + len,
- "TCP fast path RX: H2: %ul H1: %ul L: %ul\n",
- tcp_rx_hit2,tcp_rx_hit1,tcp_rx_miss);
-*/
-
- if (offset >= len)
- {
- *start = buffer;
- return 0;
- }
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
- return len;
-}
-
diff --git a/pfinet/linux-inet/protocol.c b/pfinet/linux-inet/protocol.c
deleted file mode 100644
index a47d27cd..00000000
--- a/pfinet/linux-inet/protocol.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * INET protocol dispatch tables.
- *
- * Version: @(#)protocol.c 1.0.5 05/25/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Fixes:
- * Alan Cox : Ahah! udp icmp errors don't work because
- * udp_err is never called!
- * Alan Cox : Added new fields for init and ready for
- * proper fragmentation (_NO_ 4K limits!)
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/config.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/timer.h>
-#include "ip.h"
-#include "protocol.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "icmp.h"
-#include "udp.h"
-#include <linux/igmp.h>
-
-
-static struct inet_protocol tcp_protocol = {
- tcp_rcv, /* TCP handler */
- NULL, /* No fragment handler (and won't be for a long time) */
- tcp_err, /* TCP error control */
- NULL, /* next */
- IPPROTO_TCP, /* protocol ID */
- 0, /* copy */
- NULL, /* data */
- "TCP" /* name */
-};
-
-
-static struct inet_protocol udp_protocol = {
- udp_rcv, /* UDP handler */
- NULL, /* Will be UDP fraglist handler */
- udp_err, /* UDP error control */
- &tcp_protocol, /* next */
- IPPROTO_UDP, /* protocol ID */
- 0, /* copy */
- NULL, /* data */
- "UDP" /* name */
-};
-
-
-static struct inet_protocol icmp_protocol = {
- icmp_rcv, /* ICMP handler */
- NULL, /* ICMP never fragments anyway */
- NULL, /* ICMP error control */
- &udp_protocol, /* next */
- IPPROTO_ICMP, /* protocol ID */
- 0, /* copy */
- NULL, /* data */
- "ICMP" /* name */
-};
-
-#ifndef CONFIG_IP_MULTICAST
-struct inet_protocol *inet_protocol_base = &icmp_protocol;
-#else
-static struct inet_protocol igmp_protocol = {
- igmp_rcv, /* IGMP handler */
- NULL, /* IGMP never fragments anyway */
- NULL, /* IGMP error control */
- &icmp_protocol, /* next */
- IPPROTO_IGMP, /* protocol ID */
- 0, /* copy */
- NULL, /* data */
- "IGMP" /* name */
-};
-
-struct inet_protocol *inet_protocol_base = &igmp_protocol;
-#endif
-
-struct inet_protocol *inet_protos[MAX_INET_PROTOS] = {
- NULL
-};
-
-
-struct inet_protocol *
-inet_get_protocol(unsigned char prot)
-{
- unsigned char hash;
- struct inet_protocol *p;
-
- hash = prot & (MAX_INET_PROTOS - 1);
- for (p = inet_protos[hash] ; p != NULL; p=p->next) {
- if (p->protocol == prot) return((struct inet_protocol *) p);
- }
- return(NULL);
-}
-
-
-void
-inet_add_protocol(struct inet_protocol *prot)
-{
- unsigned char hash;
- struct inet_protocol *p2;
-
- hash = prot->protocol & (MAX_INET_PROTOS - 1);
- prot ->next = inet_protos[hash];
- inet_protos[hash] = prot;
- prot->copy = 0;
-
- /* Set the copy bit if we need to. */
- p2 = (struct inet_protocol *) prot->next;
- while(p2 != NULL) {
- if (p2->protocol == prot->protocol) {
- prot->copy = 1;
- break;
- }
- p2 = (struct inet_protocol *) prot->next;
- }
-}
-
-
-int
-inet_del_protocol(struct inet_protocol *prot)
-{
- struct inet_protocol *p;
- struct inet_protocol *lp = NULL;
- unsigned char hash;
-
- hash = prot->protocol & (MAX_INET_PROTOS - 1);
- if (prot == inet_protos[hash]) {
- inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
- return(0);
- }
-
- p = (struct inet_protocol *) inet_protos[hash];
- while(p != NULL) {
- /*
- * We have to worry if the protocol being deleted is
- * the last one on the list, then we may need to reset
- * someone's copied bit.
- */
- if (p->next != NULL && p->next == prot) {
- /*
- * if we are the last one with this protocol and
- * there is a previous one, reset its copy bit.
- */
- if (p->copy == 0 && lp != NULL) lp->copy = 0;
- p->next = prot->next;
- return(0);
- }
-
- if (p->next != NULL && p->next->protocol == prot->protocol) {
- lp = p;
- }
-
- p = (struct inet_protocol *) p->next;
- }
- return(-1);
-}
diff --git a/pfinet/linux-inet/protocol.h b/pfinet/linux-inet/protocol.h
deleted file mode 100644
index 3e0b6fb3..00000000
--- a/pfinet/linux-inet/protocol.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the protocol dispatcher.
- *
- * Version: @(#)protocol.h 1.0.2 05/07/93
- *
- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- *
- * Changes:
- * Alan Cox : Added a name field and a frag handler
- * field for later.
- */
-
-#ifndef _PROTOCOL_H
-#define _PROTOCOL_H
-
-
-#define MAX_INET_PROTOS 32 /* Must be a power of 2 */
-
-
-/* This is used to register protocols. */
-struct inet_protocol {
- int (*handler)(struct sk_buff *skb, struct device *dev,
- struct options *opt, unsigned long daddr,
- unsigned short len, unsigned long saddr,
- int redo, struct inet_protocol *protocol);
- int (*frag_handler)(struct sk_buff *skb, struct device *dev,
- struct options *opt, unsigned long daddr,
- unsigned short len, unsigned long saddr,
- int redo, struct inet_protocol *protocol);
- void (*err_handler)(int err, unsigned char *buff,
- unsigned long daddr,
- unsigned long saddr,
- struct inet_protocol *protocol);
- struct inet_protocol *next;
- unsigned char protocol;
- unsigned char copy:1;
- void *data;
- char *name;
-};
-
-
-extern struct inet_protocol *inet_protocol_base;
-extern struct inet_protocol *inet_protos[MAX_INET_PROTOS];
-
-
-extern void inet_add_protocol(struct inet_protocol *prot);
-extern int inet_del_protocol(struct inet_protocol *prot);
-
-
-#endif /* _PROTOCOL_H */
diff --git a/pfinet/linux-inet/psnap.c b/pfinet/linux-inet/psnap.c
deleted file mode 100644
index 287b3353..00000000
--- a/pfinet/linux-inet/psnap.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * SNAP data link layer. Derived from 802.2
- *
- * Alan Cox <Alan.Cox@linux.org>, from the 802.2 layer by Greg Page.
- * Merged in additions from Greg Page's psnap.c.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include "datalink.h"
-#include "p8022.h"
-#include "psnap.h"
-#include <linux/mm.h>
-#include <linux/in.h>
-
-static struct datalink_proto *snap_list = NULL;
-static struct datalink_proto *snap_dl = NULL; /* 802.2 DL for SNAP */
-
-/*
- * Find a snap client by matching the 5 bytes.
- */
-
-static struct datalink_proto *find_snap_client(unsigned char *desc)
-{
- struct datalink_proto *proto;
-
- for (proto = snap_list; proto != NULL && memcmp(proto->type, desc, 5) ; proto = proto->next);
- return proto;
-}
-
-/*
- * A SNAP packet has arrived
- */
-
-int snap_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
-{
- static struct packet_type psnap_packet_type =
- {
- 0,
- NULL, /* All Devices */
- snap_rcv,
- NULL,
- NULL,
- };
-
- struct datalink_proto *proto;
-
- proto = find_snap_client(skb->h.raw);
- if (proto != NULL)
- {
- /*
- * Pass the frame on.
- */
-
- skb->h.raw += 5;
- skb->len -= 5;
- if (psnap_packet_type.type == 0)
- psnap_packet_type.type=htons(ETH_P_SNAP);
- return proto->rcvfunc(skb, dev, &psnap_packet_type);
- }
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
- return 0;
-}
-
-/*
- * Put a SNAP header on a frame and pass to 802.2
- */
-
-static void snap_datalink_header(struct datalink_proto *dl, struct sk_buff *skb, unsigned char *dest_node)
-{
- struct device *dev = skb->dev;
- unsigned char *rawp;
-
- rawp = skb->data + snap_dl->header_length+dev->hard_header_len;
- memcpy(rawp,dl->type,5);
- skb->h.raw = rawp+5;
- snap_dl->datalink_header(snap_dl, skb, dest_node);
-}
-
-/*
- * Set up the SNAP layer
- */
-
-void snap_proto_init(struct net_proto *pro)
-{
- snap_dl=register_8022_client(0xAA, snap_rcv);
- if(snap_dl==NULL)
- printk("SNAP - unable to register with 802.2\n");
-}
-
-/*
- * Register SNAP clients. We don't yet use this for IP or IPX.
- */
-
-struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
-{
- struct datalink_proto *proto;
-
- if (find_snap_client(desc) != NULL)
- return NULL;
-
- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
- if (proto != NULL)
- {
- memcpy(proto->type, desc,5);
- proto->type_len = 5;
- proto->rcvfunc = rcvfunc;
- proto->header_length = 5+snap_dl->header_length;
- proto->datalink_header = snap_datalink_header;
- proto->string_name = "SNAP";
- proto->next = snap_list;
- snap_list = proto;
- }
-
- return proto;
-}
-
diff --git a/pfinet/linux-inet/psnap.h b/pfinet/linux-inet/psnap.h
deleted file mode 100644
index b69859db..00000000
--- a/pfinet/linux-inet/psnap.h
+++ /dev/null
@@ -1,2 +0,0 @@
-struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *));
-
diff --git a/pfinet/linux-inet/psnapcall.h b/pfinet/linux-inet/psnapcall.h
deleted file mode 100644
index 9da5763c..00000000
--- a/pfinet/linux-inet/psnapcall.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Separate to keep compilation of Space.c simpler */
-extern void snap_proto_init(struct net_proto *);
diff --git a/pfinet/linux-inet/rarp.c b/pfinet/linux-inet/rarp.c
deleted file mode 100644
index 72924bb2..00000000
--- a/pfinet/linux-inet/rarp.c
+++ /dev/null
@@ -1,491 +0,0 @@
-/* linux/net/inet/rarp.c
- *
- * Copyright (C) 1994 by Ross Martin
- * Based on linux/net/inet/arp.c, Copyright (C) 1994 by Florian La Roche
- *
- * This module implements the Reverse Address Resolution Protocol
- * (RARP, RFC 903), which is used to convert low level addresses such
- * as ethernet addresses into high level addresses such as IP addresses.
- * The most common use of RARP is as a means for a diskless workstation
- * to discover its IP address during a network boot.
- *
- **
- *** WARNING:::::::::::::::::::::::::::::::::WARNING
- ****
- ***** SUN machines seem determined to boot solely from the person who
- **** answered their RARP query. NEVER add a SUN to your RARP table
- *** unless you have all the rest to boot the box from it.
- **
- *
- * Currently, only ethernet address -> IP address is likely to work.
- * (Is RARP ever used for anything else?)
- *
- * This code 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 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/config.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/in.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <stdarg.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include "ip.h"
-#include "route.h"
-#include "protocol.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "arp.h"
-#include "rarp.h"
-#ifdef CONFIG_AX25
-#include "ax25.h"
-#endif
-
-#ifdef CONFIG_INET_RARP
-
-/*
- * This structure defines the RARP mapping cache. As long as we make
- * changes in this structure, we keep interrupts off.
- */
-
-struct rarp_table
-{
- struct rarp_table *next; /* Linked entry list */
- unsigned long ip; /* ip address of entry */
- unsigned char ha[MAX_ADDR_LEN]; /* Hardware address */
- unsigned char hlen; /* Length of hardware address */
- unsigned char htype; /* Type of hardware in use */
- struct device *dev; /* Device the entry is tied to */
-};
-
-struct rarp_table *rarp_tables = NULL;
-
-
-static struct packet_type rarp_packet_type =
-{
- 0, /* Should be: __constant_htons(ETH_P_RARP) - but this _doesn't_ come out constant! */
- 0, /* copy */
- rarp_rcv,
- NULL,
- NULL
-};
-
-static initflag = 1;
-
-/*
- * Called once when data first added to rarp cache with ioctl.
- */
-
-static void rarp_init (void)
-{
- /* Register the packet type */
- rarp_packet_type.type=htons(ETH_P_RARP);
- dev_add_pack(&rarp_packet_type);
-}
-
-/*
- * Release the memory for this entry.
- */
-
-static inline void rarp_release_entry(struct rarp_table *entry)
-{
- kfree_s(entry, sizeof(struct rarp_table));
- return;
-}
-
-/*
- * Delete a RARP mapping entry in the cache.
- */
-
-static void rarp_destroy(unsigned long ip_addr)
-{
- struct rarp_table *entry;
- struct rarp_table **pentry;
-
- cli();
- pentry = &rarp_tables;
- while ((entry = *pentry) != NULL)
- {
- if (entry->ip == ip_addr)
- {
- *pentry = entry->next;
- sti();
- rarp_release_entry(entry);
- return;
- }
- pentry = &entry->next;
- }
- sti();
-}
-
-
-/*
- * Receive an arp request by the device layer. Maybe it should be
- * rewritten to use the incoming packet for the reply. The current
- * "overhead" time isn't that high...
- */
-
-int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
-{
-/*
- * We shouldn't use this type conversion. Check later.
- */
- struct arphdr *rarp = (struct arphdr *)skb->h.raw;
- unsigned char *rarp_ptr = (unsigned char *)(rarp+1);
- struct rarp_table *entry;
- long sip,tip;
- unsigned char *sha,*tha; /* s for "source", t for "target" */
-
-/*
- * If this test doesn't pass, it's not IP, or we should ignore it anyway
- */
-
- if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)
- || dev->flags&IFF_NOARP)
- {
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
-/*
- * If it's not a RARP request, delete it.
- */
- if (rarp->ar_op != htons(ARPOP_RREQUEST))
- {
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-
-/*
- * For now we will only deal with IP addresses.
- */
-
- if (
-#ifdef CONFIG_AX25
- (rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
-#endif
- (rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25)
- || rarp->ar_pln != 4)
- {
- /*
- * This packet is not for us. Remove it.
- */
- kfree_skb(skb, FREE_READ);
- return 0;
-}
-
-/*
- * Extract variable width fields
- */
-
- sha=rarp_ptr;
- rarp_ptr+=dev->addr_len;
- memcpy(&sip,rarp_ptr,4);
- rarp_ptr+=4;
- tha=rarp_ptr;
- rarp_ptr+=dev->addr_len;
- memcpy(&tip,rarp_ptr,4);
-
-/*
- * Process entry. Use tha for table lookup according to RFC903.
- */
-
- cli();
- for (entry = rarp_tables; entry != NULL; entry = entry->next)
- if (!memcmp(entry->ha, tha, rarp->ar_hln))
- break;
-
- if (entry != NULL)
- {
- sip=entry->ip;
- sti();
-
- arp_send(ARPOP_RREPLY, ETH_P_RARP, sip, dev, dev->pa_addr, sha,
- dev->dev_addr);
- }
- else
- sti();
-
- kfree_skb(skb, FREE_READ);
- return 0;
-}
-
-
-/*
- * Set (create) a RARP cache entry.
- */
-
-static int rarp_req_set(struct arpreq *req)
-{
- struct arpreq r;
- struct rarp_table *entry;
- struct sockaddr_in *si;
- int htype, hlen;
- unsigned long ip;
- struct rtable *rt;
-
- memcpy_fromfs(&r, req, sizeof(r));
-
- /*
- * We only understand about IP addresses...
- */
-
- if (r.arp_pa.sa_family != AF_INET)
- return -EPFNOSUPPORT;
-
- switch (r.arp_ha.sa_family)
- {
- case ARPHRD_ETHER:
- htype = ARPHRD_ETHER;
- hlen = ETH_ALEN;
- break;
-#ifdef CONFIG_AX25
- case ARPHRD_AX25:
- htype = ARPHRD_AX25;
- hlen = 7;
- break;
-#endif
- default:
- return -EPFNOSUPPORT;
- }
-
- si = (struct sockaddr_in *) &r.arp_pa;
- ip = si->sin_addr.s_addr;
- if (ip == 0)
- {
- printk("RARP: SETRARP: requested PA is 0.0.0.0 !\n");
- return -EINVAL;
- }
-
-/*
- * Is it reachable directly ?
- */
-
- rt = ip_rt_route(ip, NULL, NULL);
- if (rt == NULL)
- return -ENETUNREACH;
-
-/*
- * Is there an existing entry for this address? Find out...
- */
-
- cli();
- for (entry = rarp_tables; entry != NULL; entry = entry->next)
- if (entry->ip == ip)
- break;
-
-/*
- * If no entry was found, create a new one.
- */
-
- if (entry == NULL)
- {
- entry = (struct rarp_table *) kmalloc(sizeof(struct rarp_table),
- GFP_ATOMIC);
- if (entry == NULL)
- {
- sti();
- return -ENOMEM;
- }
- if(initflag)
- {
- rarp_init();
- initflag=0;
- }
-
- entry->next = rarp_tables;
- rarp_tables = entry;
- }
-
- entry->ip = ip;
- entry->hlen = hlen;
- entry->htype = htype;
- memcpy(&entry->ha, &r.arp_ha.sa_data, hlen);
- entry->dev = rt->rt_dev;
-
- sti();
-
- return 0;
-}
-
-
-/*
- * Get a RARP cache entry.
- */
-
-static int rarp_req_get(struct arpreq *req)
-{
- struct arpreq r;
- struct rarp_table *entry;
- struct sockaddr_in *si;
- unsigned long ip;
-
-/*
- * We only understand about IP addresses...
- */
-
- memcpy_fromfs(&r, req, sizeof(r));
-
- if (r.arp_pa.sa_family != AF_INET)
- return -EPFNOSUPPORT;
-
-/*
- * Is there an existing entry for this address?
- */
-
- si = (struct sockaddr_in *) &r.arp_pa;
- ip = si->sin_addr.s_addr;
-
- cli();
- for (entry = rarp_tables; entry != NULL; entry = entry->next)
- if (entry->ip == ip)
- break;
-
- if (entry == NULL)
- {
- sti();
- return -ENXIO;
- }
-
-/*
- * We found it; copy into structure.
- */
-
- memcpy(r.arp_ha.sa_data, &entry->ha, entry->hlen);
- r.arp_ha.sa_family = entry->htype;
- sti();
-
-/*
- * Copy the information back
- */
-
- memcpy_tofs(req, &r, sizeof(r));
- return 0;
-}
-
-
-/*
- * Handle a RARP layer I/O control request.
- */
-
-int rarp_ioctl(unsigned int cmd, void *arg)
-{
- struct arpreq r;
- struct sockaddr_in *si;
- int err;
-
- switch(cmd)
- {
- case SIOCDRARP:
- if (!suser())
- return -EPERM;
- err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
- if(err)
- return err;
- memcpy_fromfs(&r, arg, sizeof(r));
- if (r.arp_pa.sa_family != AF_INET)
- return -EPFNOSUPPORT;
- si = (struct sockaddr_in *) &r.arp_pa;
- rarp_destroy(si->sin_addr.s_addr);
- return 0;
-
- case SIOCGRARP:
- err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
- if(err)
- return err;
- return rarp_req_get((struct arpreq *)arg);
- case SIOCSRARP:
- if (!suser())
- return -EPERM;
- err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
- if(err)
- return err;
- return rarp_req_set((struct arpreq *)arg);
- default:
- return -EINVAL;
- }
-
- /*NOTREACHED*/
- return 0;
-}
-
-int rarp_get_info(char *buffer, char **start, off_t offset, int length)
-{
- int len=0;
- off_t begin=0;
- off_t pos=0;
- int size;
- struct rarp_table *entry;
- char ipbuffer[20];
- unsigned long netip;
- if(initflag)
- {
- size = sprintf(buffer,"RARP disabled until entries added to cache.\n");
- pos+=size;
- len+=size;
- }
- else
- {
- size = sprintf(buffer,
- "IP address HW type HW address\n");
- pos+=size;
- len+=size;
-
- cli();
- for(entry=rarp_tables; entry!=NULL; entry=entry->next)
- {
- netip=htonl(entry->ip); /* switch to network order */
- sprintf(ipbuffer,"%d.%d.%d.%d",
- (unsigned int)(netip>>24)&255,
- (unsigned int)(netip>>16)&255,
- (unsigned int)(netip>>8)&255,
- (unsigned int)(netip)&255);
-
- size = sprintf(buffer+len,
- "%-17s%-20s%02x:%02x:%02x:%02x:%02x:%02x\n",
- ipbuffer,
- "10Mbps Ethernet",
- (unsigned int)entry->ha[0],
- (unsigned int)entry->ha[1],
- (unsigned int)entry->ha[2],
- (unsigned int)entry->ha[3],
- (unsigned int)entry->ha[4],
- (unsigned int)entry->ha[5]);
-
- len+=size;
- pos=begin+len;
-
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- }
- sti();
- }
-
- *start=buffer+(offset-begin); /* Start of wanted data */
- len-=(offset-begin); /* Start slop */
- if(len>length)
- len=length; /* Ending slop */
- return len;
-}
-
-#endif
diff --git a/pfinet/linux-inet/rarp.h b/pfinet/linux-inet/rarp.h
deleted file mode 100644
index 02ee7784..00000000
--- a/pfinet/linux-inet/rarp.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* linux/net/inet/rarp.h */
-#ifndef _RARP_H
-#define _RARP_H
-
-extern int rarp_ioctl(unsigned int cmd, void *arg);
-extern int rarp_rcv(struct sk_buff *skb,
- struct device *dev,
- struct packet_type *pt);
-extern int rarp_get_info(char *buffer,
- char **start,
- off_t offset,
- int length);
-#endif /* _RARP_H */
-
diff --git a/pfinet/linux-inet/raw.c b/pfinet/linux-inet/raw.c
deleted file mode 100644
index b7d34a37..00000000
--- a/pfinet/linux-inet/raw.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * RAW - implementation of IP "raw" sockets.
- *
- * Version: @(#)raw.c 1.0.4 05/25/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Fixes:
- * Alan Cox : verify_area() fixed up
- * Alan Cox : ICMP error handling
- * Alan Cox : EMSGSIZE if you send too big a packet
- * Alan Cox : Now uses generic datagrams and shared skbuff
- * library. No more peek crashes, no more backlogs
- * Alan Cox : Checks sk->broadcast.
- * Alan Cox : Uses skb_free_datagram/skb_copy_datagram
- * Alan Cox : Raw passes ip options too
- * Alan Cox : Setsocketopt added
- * Alan Cox : Fixed error return for broadcasts
- * Alan Cox : Removed wake_up calls
- * Alan Cox : Use ttl/tos
- * Alan Cox : Cleaned up old debugging
- * Alan Cox : Use new kernel side addresses
- * Arnt Gulbrandsen : Fixed MSG_DONTROUTE in raw sockets.
- * Alan Cox : BSD style RAW socket demultiplexing.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "icmp.h"
-#include "udp.h"
-
-
-static inline unsigned long min(unsigned long a, unsigned long b)
-{
- if (a < b)
- return(a);
- return(b);
-}
-
-
-/* raw_err gets called by the icmp module. */
-void raw_err (int err, unsigned char *header, unsigned long daddr,
- unsigned long saddr, struct inet_protocol *protocol)
-{
- struct sock *sk;
-
- if (protocol == NULL)
- return;
- sk = (struct sock *) protocol->data;
- if (sk == NULL)
- return;
-
- /* This is meaningless in raw sockets. */
- if (err & 0xff00 == (ICMP_SOURCE_QUENCH << 8))
- {
- if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
- return;
- }
-
- sk->err = icmp_err_convert[err & 0xff].error;
- sk->error_report(sk);
-
- return;
-}
-
-
-/*
- * This should be the easiest of all, all we do is
- * copy it into a buffer. All demultiplexing is done
- * in ip.c
- */
-
-int raw_rcv(struct sock *sk, struct sk_buff *skb, struct device *dev, long saddr, long daddr)
-{
- /* Now we need to copy this into memory. */
- skb->sk = sk;
- skb->len = ntohs(skb->ip_hdr->tot_len);
- skb->h.raw = (unsigned char *) skb->ip_hdr;
- skb->dev = dev;
- skb->saddr = daddr;
- skb->daddr = saddr;
-
- /* Charge it to the socket. */
-
- if(sock_queue_rcv_skb(sk,skb)<0)
- {
- ip_statistics.IpInDiscards++;
- skb->sk=NULL;
- kfree_skb(skb, FREE_READ);
- return(0);
- }
-
- ip_statistics.IpInDelivers++;
- release_sock(sk);
- return(0);
-}
-
-/*
- * Send a RAW IP packet.
- */
-
-static int raw_sendto(struct sock *sk, unsigned char *from,
- int len, int noblock, unsigned flags, struct sockaddr_in *usin, int addr_len)
-{
- struct sk_buff *skb;
- struct device *dev=NULL;
- struct sockaddr_in sin;
- int tmp;
- int err;
-
- /*
- * Check the flags. Only MSG_DONTROUTE is permitted.
- */
-
- if (flags & MSG_OOB) /* Mirror BSD error message compatibility */
- return -EOPNOTSUPP;
-
- if (flags & ~MSG_DONTROUTE)
- return(-EINVAL);
- /*
- * Get and verify the address.
- */
-
- if (usin)
- {
- if (addr_len < sizeof(sin))
- return(-EINVAL);
- memcpy(&sin, usin, sizeof(sin));
- if (sin.sin_family && sin.sin_family != AF_INET)
- return(-EINVAL);
- }
- else
- {
- if (sk->state != TCP_ESTABLISHED)
- return(-EINVAL);
- sin.sin_family = AF_INET;
- sin.sin_port = sk->protocol;
- sin.sin_addr.s_addr = sk->daddr;
- }
- if (sin.sin_port == 0)
- sin.sin_port = sk->protocol;
-
- if (sin.sin_addr.s_addr == INADDR_ANY)
- sin.sin_addr.s_addr = ip_my_addr();
-
- if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
- return -EACCES;
-
- skb=sock_alloc_send_skb(sk, len+sk->prot->max_header, noblock, &err);
- if(skb==NULL)
- return err;
-
- skb->sk = sk;
- skb->free = 1;
- skb->localroute = sk->localroute | (flags&MSG_DONTROUTE);
-
- tmp = sk->prot->build_header(skb, sk->saddr,
- sin.sin_addr.s_addr, &dev,
- sk->protocol, sk->opt, skb->mem_len, sk->ip_tos,sk->ip_ttl);
- if (tmp < 0)
- {
- kfree_skb(skb,FREE_WRITE);
- release_sock(sk);
- return(tmp);
- }
-
- memcpy_fromfs(skb->data + tmp, from, len);
-
- /*
- * If we are using IPPROTO_RAW, we need to fill in the source address in
- * the IP header
- */
-
- if(sk->protocol==IPPROTO_RAW)
- {
- unsigned char *buff;
- struct iphdr *iph;
-
- buff = skb->data;
- buff += tmp;
-
- iph = (struct iphdr *)buff;
- iph->saddr = sk->saddr;
- }
-
- skb->len = tmp + len;
-
- sk->prot->queue_xmit(sk, dev, skb, 1);
- release_sock(sk);
- return(len);
-}
-
-
-static int raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
- unsigned flags)
-{
- return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
-}
-
-
-static void raw_close(struct sock *sk, int timeout)
-{
- sk->state = TCP_CLOSE;
-}
-
-
-static int raw_init(struct sock *sk)
-{
- return(0);
-}
-
-
-/*
- * This should be easy, if there is something there
- * we return it, otherwise we block.
- */
-
-int raw_recvfrom(struct sock *sk, unsigned char *to, int len,
- int noblock, unsigned flags, struct sockaddr_in *sin,
- int *addr_len)
-{
- int copied=0;
- struct sk_buff *skb;
- int err;
- int truesize;
-
- if (flags & MSG_OOB)
- return -EOPNOTSUPP;
-
- if (sk->shutdown & RCV_SHUTDOWN)
- return(0);
-
- if (addr_len)
- *addr_len=sizeof(*sin);
-
- skb=skb_recv_datagram(sk,flags,noblock,&err);
- if(skb==NULL)
- return err;
-
- truesize=skb->len;
- copied = min(len, truesize);
-
- skb_copy_datagram(skb, 0, to, copied);
- sk->stamp=skb->stamp;
-
- /* Copy the address. */
- if (sin)
- {
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = skb->daddr;
- }
- skb_free_datagram(skb);
- release_sock(sk);
- return (truesize); /* len not copied. BSD returns the true size of the message so you know a bit fell off! */
-}
-
-
-int raw_read (struct sock *sk, unsigned char *buff, int len, int noblock,unsigned flags)
-{
- return(raw_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
-}
-
-
-struct proto raw_prot = {
- sock_wmalloc,
- sock_rmalloc,
- sock_wfree,
- sock_rfree,
- sock_rspace,
- sock_wspace,
- raw_close,
- raw_read,
- raw_write,
- raw_sendto,
- raw_recvfrom,
- ip_build_header,
- udp_connect,
- NULL,
- ip_queue_xmit,
- NULL,
- NULL,
- NULL,
- NULL,
- datagram_select,
- NULL,
- raw_init,
- NULL,
- ip_setsockopt,
- ip_getsockopt,
- 128,
- 0,
- {NULL,},
- "RAW",
- 0, 0
-};
diff --git a/pfinet/linux-inet/raw.h b/pfinet/linux-inet/raw.h
deleted file mode 100644
index 8f1cf0c2..00000000
--- a/pfinet/linux-inet/raw.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the RAW-IP module.
- *
- * Version: @(#)raw.h 1.0.2 05/07/93
- *
- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _RAW_H
-#define _RAW_H
-
-
-extern struct proto raw_prot;
-
-
-extern void raw_err(int err, unsigned char *header, unsigned long daddr,
- unsigned long saddr, struct inet_protocol *protocol);
-extern int raw_recvfrom(struct sock *sk, unsigned char *to,
- int len, int noblock, unsigned flags,
- struct sockaddr_in *sin, int *addr_len);
-extern int raw_read(struct sock *sk, unsigned char *buff,
- int len, int noblock, unsigned flags);
-extern int raw_rcv(struct sock *, struct sk_buff *, struct device *,
- long, long);
-
-#endif /* _RAW_H */
diff --git a/pfinet/linux-inet/route.c b/pfinet/linux-inet/route.c
deleted file mode 100644
index ce06dcfe..00000000
--- a/pfinet/linux-inet/route.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * ROUTE - implementation of the IP router.
- *
- * Version: @(#)route.c 1.0.14 05/31/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- * Linus Torvalds, <Linus.Torvalds@helsinki.fi>
- *
- * Fixes:
- * Alan Cox : Verify area fixes.
- * Alan Cox : cli() protects routing changes
- * Rui Oliveira : ICMP routing table updates
- * (rco@di.uminho.pt) Routing table insertion and update
- * Linus Torvalds : Rewrote bits to be sensible
- * Alan Cox : Added BSD route gw semantics
- * Alan Cox : Super /proc >4K
- * Alan Cox : MTU in route table
- * Alan Cox : MSS actually. Also added the window
- * clamper.
- * Sam Lantinga : Fixed route matching in rt_del()
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include "route.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "icmp.h"
-
-/*
- * The routing table list
- */
-
-static struct rtable *rt_base = NULL;
-
-/*
- * Pointer to the loopback route
- */
-
-static struct rtable *rt_loopback = NULL;
-
-/*
- * Remove a routing table entry.
- */
-
-static void rt_del(unsigned long dst, char *devname)
-{
- struct rtable *r, **rp;
- unsigned long flags;
-
- rp = &rt_base;
-
- /*
- * This must be done with interrupts off because we could take
- * an ICMP_REDIRECT.
- */
-
- save_flags(flags);
- cli();
- while((r = *rp) != NULL)
- {
- /* Make sure both the destination and the device match */
- if ( r->rt_dst != dst ||
- (devname != NULL && strcmp((r->rt_dev)->name,devname) != 0) )
- {
- rp = &r->rt_next;
- continue;
- }
- *rp = r->rt_next;
-
- /*
- * If we delete the loopback route update its pointer.
- */
-
- if (rt_loopback == r)
- rt_loopback = NULL;
- kfree_s(r, sizeof(struct rtable));
- }
- restore_flags(flags);
-}
-
-
-/*
- * Remove all routing table entries for a device. This is called when
- * a device is downed.
- */
-
-void ip_rt_flush(struct device *dev)
-{
- struct rtable *r;
- struct rtable **rp;
- unsigned long flags;
-
- rp = &rt_base;
- save_flags(flags);
- cli();
- while ((r = *rp) != NULL) {
- if (r->rt_dev != dev) {
- rp = &r->rt_next;
- continue;
- }
- *rp = r->rt_next;
- if (rt_loopback == r)
- rt_loopback = NULL;
- kfree_s(r, sizeof(struct rtable));
- }
- restore_flags(flags);
-}
-
-/*
- * Used by 'rt_add()' when we can't get the netmask any other way..
- *
- * If the lower byte or two are zero, we guess the mask based on the
- * number of zero 8-bit net numbers, otherwise we use the "default"
- * masks judging by the destination address and our device netmask.
- */
-
-static inline unsigned long default_mask(unsigned long dst)
-{
- dst = ntohl(dst);
- if (IN_CLASSA(dst))
- return htonl(IN_CLASSA_NET);
- if (IN_CLASSB(dst))
- return htonl(IN_CLASSB_NET);
- return htonl(IN_CLASSC_NET);
-}
-
-
-/*
- * If no mask is specified then generate a default entry.
- */
-
-static unsigned long guess_mask(unsigned long dst, struct device * dev)
-{
- unsigned long mask;
-
- if (!dst)
- return 0;
- mask = default_mask(dst);
- if ((dst ^ dev->pa_addr) & mask)
- return mask;
- return dev->pa_mask;
-}
-
-
-/*
- * Find the route entry through which our gateway will be reached
- */
-
-static inline struct device * get_gw_dev(unsigned long gw)
-{
- struct rtable * rt;
-
- for (rt = rt_base ; ; rt = rt->rt_next)
- {
- if (!rt)
- return NULL;
- if ((gw ^ rt->rt_dst) & rt->rt_mask)
- continue;
- /*
- * Gateways behind gateways are a no-no
- */
-
- if (rt->rt_flags & RTF_GATEWAY)
- return NULL;
- return rt->rt_dev;
- }
-}
-
-/*
- * Rewrote rt_add(), as the old one was weird - Linus
- *
- * This routine is used to update the IP routing table, either
- * from the kernel (ICMP_REDIRECT) or via an ioctl call issued
- * by the superuser.
- */
-
-void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
- unsigned long gw, struct device *dev, unsigned short mtu, unsigned long window)
-{
- struct rtable *r, *rt;
- struct rtable **rp;
- unsigned long cpuflags;
-
- /*
- * A host is a unique machine and has no network bits.
- */
-
- if (flags & RTF_HOST)
- {
- mask = 0xffffffff;
- }
-
- /*
- * Calculate the network mask
- */
-
- else if (!mask)
- {
- if (!((dst ^ dev->pa_addr) & dev->pa_mask))
- {
- mask = dev->pa_mask;
- flags &= ~RTF_GATEWAY;
- if (flags & RTF_DYNAMIC)
- {
- /*printk("Dynamic route to my own net rejected\n");*/
- return;
- }
- }
- else
- mask = guess_mask(dst, dev);
- dst &= mask;
- }
-
- /*
- * A gateway must be reachable and not a local address
- */
-
- if (gw == dev->pa_addr)
- flags &= ~RTF_GATEWAY;
-
- if (flags & RTF_GATEWAY)
- {
- /*
- * Don't try to add a gateway we can't reach..
- */
-
- if (dev != get_gw_dev(gw))
- return;
-
- flags |= RTF_GATEWAY;
- }
- else
- gw = 0;
-
- /*
- * Allocate an entry and fill it in.
- */
-
- rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC);
- if (rt == NULL)
- {
- return;
- }
- memset(rt, 0, sizeof(struct rtable));
- rt->rt_flags = flags | RTF_UP;
- rt->rt_dst = dst;
- rt->rt_dev = dev;
- rt->rt_gateway = gw;
- rt->rt_mask = mask;
- rt->rt_mss = dev->mtu - HEADER_SIZE;
- rt->rt_window = 0; /* Default is no clamping */
-
- /* Are the MSS/Window valid ? */
-
- if(rt->rt_flags & RTF_MSS)
- rt->rt_mss = mtu;
-
- if(rt->rt_flags & RTF_WINDOW)
- rt->rt_window = window;
-
- /*
- * What we have to do is loop though this until we have
- * found the first address which has a higher generality than
- * the one in rt. Then we can put rt in right before it.
- * The interrupts must be off for this process.
- */
-
- save_flags(cpuflags);
- cli();
-
- /*
- * Remove old route if we are getting a duplicate.
- */
-
- rp = &rt_base;
- while ((r = *rp) != NULL)
- {
- if (r->rt_dst != dst ||
- r->rt_mask != mask)
- {
- rp = &r->rt_next;
- continue;
- }
- *rp = r->rt_next;
- if (rt_loopback == r)
- rt_loopback = NULL;
- kfree_s(r, sizeof(struct rtable));
- }
-
- /*
- * Add the new route
- */
-
- rp = &rt_base;
- while ((r = *rp) != NULL) {
- if ((r->rt_mask & mask) != mask)
- break;
- rp = &r->rt_next;
- }
- rt->rt_next = r;
- *rp = rt;
-
- /*
- * Update the loopback route
- */
-
- if ((rt->rt_dev->flags & IFF_LOOPBACK) && !rt_loopback)
- rt_loopback = rt;
-
- /*
- * Restore the interrupts and return
- */
-
- restore_flags(cpuflags);
- return;
-}
-
-/*
- * Remove a routing table entry (exported version).
- */
-void ip_rt_del (unsigned long dst, struct device *dev)
-{
- /* Should probably just copy contents of rt_del and replace name
- comparison with device comparsion. */
- rt_del (dst, dev->name);
-}
-
-
-/*
- * Check if a mask is acceptable.
- */
-
-static inline int bad_mask(unsigned long mask, unsigned long addr)
-{
- if (addr & (mask = ~mask))
- return 1;
- mask = ntohl(mask);
- if (mask & (mask+1))
- return 1;
- return 0;
-}
-
-/*
- * Process a route add request from the user
- */
-
-static int rt_new(struct rtentry *r)
-{
- int err;
- char * devname;
- struct device * dev = NULL;
- unsigned long flags, daddr, mask, gw;
-
- /*
- * If a device is specified find it.
- */
-
- if ((devname = r->rt_dev) != NULL)
- {
- err = getname(devname, &devname);
- if (err)
- return err;
- dev = dev_get(devname);
- putname(devname);
- if (!dev)
- return -EINVAL;
- }
-
- /*
- * If the device isn't INET, don't allow it
- */
-
- if (r->rt_dst.sa_family != AF_INET)
- return -EAFNOSUPPORT;
-
- /*
- * Make local copies of the important bits
- */
-
- flags = r->rt_flags;
- daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
- mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
- gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
-
-
- /*
- * BSD emulation: Permits route add someroute gw one-of-my-addresses
- * to indicate which iface. Not as clean as the nice Linux dev technique
- * but people keep using it...
- */
-
- if (!dev && (flags & RTF_GATEWAY))
- {
- struct device *dev2;
- for (dev2 = dev_base ; dev2 != NULL ; dev2 = dev2->next)
- {
- if ((dev2->flags & IFF_UP) && dev2->pa_addr == gw)
- {
- flags &= ~RTF_GATEWAY;
- dev = dev2;
- break;
- }
- }
- }
-
- /*
- * Ignore faulty masks
- */
-
- if (bad_mask(mask, daddr))
- mask = 0;
-
- /*
- * Set the mask to nothing for host routes.
- */
-
- if (flags & RTF_HOST)
- mask = 0xffffffff;
- else if (mask && r->rt_genmask.sa_family != AF_INET)
- return -EAFNOSUPPORT;
-
- /*
- * You can only gateway IP via IP..
- */
-
- if (flags & RTF_GATEWAY)
- {
- if (r->rt_gateway.sa_family != AF_INET)
- return -EAFNOSUPPORT;
- if (!dev)
- dev = get_gw_dev(gw);
- }
- else if (!dev)
- dev = ip_dev_check(daddr);
-
- /*
- * Unknown device.
- */
-
- if (dev == NULL)
- return -ENETUNREACH;
-
- /*
- * Add the route
- */
-
- ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window);
- return 0;
-}
-
-
-/*
- * Remove a route, as requested by the user.
- */
-
-static int rt_kill(struct rtentry *r)
-{
- struct sockaddr_in *trg;
- char *devname;
- int err;
-
- trg = (struct sockaddr_in *) &r->rt_dst;
- if ((devname = r->rt_dev) != NULL)
- {
- err = getname(devname, &devname);
- if (err)
- return err;
- }
- rt_del(trg->sin_addr.s_addr, devname);
- if ( devname != NULL )
- putname(devname);
- return 0;
-}
-
-
-/*
- * Called from the PROCfs module. This outputs /proc/net/route.
- */
-
-int rt_get_info(char *buffer, char **start, off_t offset, int length)
-{
- struct rtable *r;
- int len=0;
- off_t pos=0;
- off_t begin=0;
- int size;
-
- len += sprintf(buffer,
- "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\n");
- pos=len;
-
- /*
- * This isn't quite right -- r->rt_dst is a struct!
- */
-
- for (r = rt_base; r != NULL; r = r->rt_next)
- {
- size = sprintf(buffer+len, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\t%d\t%lu\n",
- r->rt_dev->name, r->rt_dst, r->rt_gateway,
- r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
- r->rt_mask, (int)r->rt_mss, r->rt_window);
- len+=size;
- pos+=size;
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- }
-
- *start=buffer+(offset-begin);
- len-=(offset-begin);
- if(len>length)
- len=length;
- return len;
-}
-
-/*
- * This is hackish, but results in better code. Use "-S" to see why.
- */
-
-#define early_out ({ goto no_route; 1; })
-
-/*
- * Route a packet. This needs to be fairly quick. Florian & Co.
- * suggested a unified ARP and IP routing cache. Done right its
- * probably a brilliant idea. I'd actually suggest a unified
- * ARP/IP routing/Socket pointer cache. Volunteers welcome
- */
-
-struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr)
-{
- struct rtable *rt;
-
- for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next)
- {
- if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
- break;
- /*
- * broadcast addresses can be special cases..
- */
- if (rt->rt_flags & RTF_GATEWAY)
- continue;
- if ((rt->rt_dev->flags & IFF_BROADCAST) &&
- (rt->rt_dev->pa_brdaddr == daddr))
- break;
- }
-
- if(src_addr!=NULL)
- *src_addr= rt->rt_dev->pa_addr;
-
- if (daddr == rt->rt_dev->pa_addr) {
- if ((rt = rt_loopback) == NULL)
- goto no_route;
- }
- rt->rt_use++;
- return rt;
-no_route:
- return NULL;
-}
-
-struct rtable * ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr)
-{
- struct rtable *rt;
-
- for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next)
- {
- /*
- * No routed addressing.
- */
- if (rt->rt_flags&RTF_GATEWAY)
- continue;
-
- if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
- break;
- /*
- * broadcast addresses can be special cases..
- */
-
- if ((rt->rt_dev->flags & IFF_BROADCAST) &&
- rt->rt_dev->pa_brdaddr == daddr)
- break;
- }
-
- if(src_addr!=NULL)
- *src_addr= rt->rt_dev->pa_addr;
-
- if (daddr == rt->rt_dev->pa_addr) {
- if ((rt = rt_loopback) == NULL)
- goto no_route;
- }
- rt->rt_use++;
- return rt;
-no_route:
- return NULL;
-}
-
-/*
- * Backwards compatibility
- */
-
-static int ip_get_old_rtent(struct old_rtentry * src, struct rtentry * rt)
-{
- int err;
- struct old_rtentry tmp;
-
- err=verify_area(VERIFY_READ, src, sizeof(*src));
- if (err)
- return err;
- memcpy_fromfs(&tmp, src, sizeof(*src));
- memset(rt, 0, sizeof(*rt));
- rt->rt_dst = tmp.rt_dst;
- rt->rt_gateway = tmp.rt_gateway;
- rt->rt_genmask.sa_family = AF_INET;
- ((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask;
- rt->rt_flags = tmp.rt_flags;
- rt->rt_dev = tmp.rt_dev;
- printk("Warning: obsolete routing request made.\n");
- return 0;
-}
-
-#ifndef _HURD_
-/*
- * Handle IP routing ioctl calls. These are used to manipulate the routing tables
- */
-
-int ip_rt_ioctl(unsigned int cmd, void *arg)
-{
- int err;
- struct rtentry rt;
-
- switch(cmd)
- {
- case SIOCADDRTOLD: /* Old style add route */
- case SIOCDELRTOLD: /* Old style delete route */
- if (!suser())
- return -EPERM;
- err = ip_get_old_rtent((struct old_rtentry *) arg, &rt);
- if (err)
- return err;
- return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt);
-
- case SIOCADDRT: /* Add a route */
- case SIOCDELRT: /* Delete a route */
- if (!suser())
- return -EPERM;
- err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
- if (err)
- return err;
- memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
- return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
- }
-
- return -EINVAL;
-}
-#endif
diff --git a/pfinet/linux-inet/route.h b/pfinet/linux-inet/route.h
deleted file mode 100644
index e43efa4e..00000000
--- a/pfinet/linux-inet/route.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the IP router.
- *
- * Version: @(#)route.h 1.0.4 05/27/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Fixes:
- * Alan Cox : Reformatted. Added ip_rt_local()
- * Alan Cox : Support for TCP parameters.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _ROUTE_H
-#define _ROUTE_H
-
-
-#include <linux/route.h>
-
-
-/* This is an entry in the IP routing table. */
-struct rtable
-{
- struct rtable *rt_next;
- unsigned long rt_dst;
- unsigned long rt_mask;
- unsigned long rt_gateway;
- unsigned char rt_flags;
- unsigned char rt_metric;
- short rt_refcnt;
- unsigned long rt_use;
- unsigned short rt_mss;
- unsigned long rt_window;
- struct device *rt_dev;
-};
-
-
-extern void ip_rt_flush(struct device *dev);
-extern void ip_rt_add(short flags, unsigned long addr, unsigned long mask,
- unsigned long gw, struct device *dev, unsigned short mss, unsigned long window);
-extern void ip_rt_del(unsigned long dst, struct device *dev);
-extern struct rtable *ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr);
-extern struct rtable *ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr);
-extern int rt_get_info(char * buffer, char **start, off_t offset, int length);
-extern int ip_rt_ioctl(unsigned int cmd, void *arg);
-
-#endif /* _ROUTE_H */
diff --git a/pfinet/linux-inet/skbuff.c b/pfinet/linux-inet/skbuff.c
deleted file mode 100644
index e4e1d247..00000000
--- a/pfinet/linux-inet/skbuff.c
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * Routines having to do with the 'struct sk_buff' memory handlers.
- *
- * Authors: Alan Cox <iiitac@pyr.swan.ac.uk>
- * Florian La Roche <rzsfl@rz.uni-sb.de>
- *
- * Fixes:
- * Alan Cox : Fixed the worst of the load balancer bugs.
- * Dave Platt : Interrupt stacking fix
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-/*
- * Note: There are a load of cli()/sti() pairs protecting the net_memory type
- * variables. Without them for some reason the ++/-- operators do not come out
- * atomic. Also with gcc 2.4.5 these counts can come out wrong anyway - use 2.5.8!!
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include <linux/string.h>
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-
-
-/*
- * Resource tracking variables
- */
-
-volatile unsigned long net_memory = 0;
-volatile unsigned long net_skbcount = 0;
-volatile unsigned long net_locked = 0;
-volatile unsigned long net_allocs = 0;
-volatile unsigned long net_fails = 0;
-volatile unsigned long net_free_locked = 0;
-
-void show_net_buffers(void)
-{
- printk("Networking buffers in use : %lu\n",net_skbcount);
- printk("Memory committed to network buffers: %lu\n",net_memory);
- printk("Network buffers locked by drivers : %lu\n",net_locked);
- printk("Total network buffer allocations : %lu\n",net_allocs);
- printk("Total failed network buffer allocs : %lu\n",net_fails);
- printk("Total free while locked events : %lu\n",net_free_locked);
-}
-
-#if CONFIG_SKB_CHECK
-
-/*
- * Debugging paranoia. Can go later when this crud stack works
- */
-
-int skb_check(struct sk_buff *skb, int head, int line, char *file)
-{
- if (head) {
- if (skb->magic_debug_cookie != SK_HEAD_SKB) {
- printk("File: %s Line %d, found a bad skb-head\n",
- file,line);
- return -1;
- }
- if (!skb->next || !skb->prev) {
- printk("skb_check: head without next or prev\n");
- return -1;
- }
- if (skb->next->magic_debug_cookie != SK_HEAD_SKB
- && skb->next->magic_debug_cookie != SK_GOOD_SKB) {
- printk("File: %s Line %d, bad next head-skb member\n",
- file,line);
- return -1;
- }
- if (skb->prev->magic_debug_cookie != SK_HEAD_SKB
- && skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
- printk("File: %s Line %d, bad prev head-skb member\n",
- file,line);
- return -1;
- }
-#if 0
- {
- struct sk_buff *skb2 = skb->next;
- int i = 0;
- while (skb2 != skb && i < 5) {
- if (skb_check(skb2, 0, line, file) < 0) {
- printk("bad queue element in whole queue\n");
- return -1;
- }
- i++;
- skb2 = skb2->next;
- }
- }
-#endif
- return 0;
- }
- if (skb->next != NULL && skb->next->magic_debug_cookie != SK_HEAD_SKB
- && skb->next->magic_debug_cookie != SK_GOOD_SKB) {
- printk("File: %s Line %d, bad next skb member\n",
- file,line);
- return -1;
- }
- if (skb->prev != NULL && skb->prev->magic_debug_cookie != SK_HEAD_SKB
- && skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
- printk("File: %s Line %d, bad prev skb member\n",
- file,line);
- return -1;
- }
-
-
- if(skb->magic_debug_cookie==SK_FREED_SKB)
- {
- printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
- file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
- skb,skb->truesize,skb->mem_len,skb->free);
- return -1;
- }
- if(skb->magic_debug_cookie!=SK_GOOD_SKB)
- {
- printk("File: %s Line %d, passed a non skb!\n", file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
- skb,skb->truesize,skb->mem_len,skb->free);
- return -1;
- }
- if(skb->mem_len!=skb->truesize)
- {
- printk("File: %s Line %d, Dubious size setting!\n",file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld\n",
- skb,skb->truesize,skb->mem_len);
- return -1;
- }
- /* Guess it might be acceptable then */
- return 0;
-}
-#endif
-
-
-#ifdef CONFIG_SKB_CHECK
-void skb_queue_head_init(struct sk_buff_head *list)
-{
- list->prev = (struct sk_buff *)list;
- list->next = (struct sk_buff *)list;
- list->magic_debug_cookie = SK_HEAD_SKB;
-}
-
-
-/*
- * Insert an sk_buff at the start of a list.
- */
-void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
-{
- unsigned long flags;
- struct sk_buff *list = (struct sk_buff *)list_;
-
- save_flags(flags);
- cli();
-
- IS_SKB(newsk);
- IS_SKB_HEAD(list);
- if (newsk->next || newsk->prev)
- printk("Suspicious queue head: sk_buff on list!\n");
-
- newsk->next = list->next;
- newsk->prev = list;
-
- newsk->next->prev = newsk;
- newsk->prev->next = newsk;
-
- restore_flags(flags);
-}
-
-/*
- * Insert an sk_buff at the end of a list.
- */
-void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
-{
- unsigned long flags;
- struct sk_buff *list = (struct sk_buff *)list_;
-
- save_flags(flags);
- cli();
-
- if (newsk->next || newsk->prev)
- printk("Suspicious queue tail: sk_buff on list!\n");
- IS_SKB(newsk);
- IS_SKB_HEAD(list);
-
- newsk->next = list;
- newsk->prev = list->prev;
-
- newsk->next->prev = newsk;
- newsk->prev->next = newsk;
-
- restore_flags(flags);
-}
-
-/*
- * Remove an sk_buff from a list. This routine is also interrupt safe
- * so you can grab read and free buffers as another process adds them.
- */
-
-struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
-{
- long flags;
- struct sk_buff *result;
- struct sk_buff *list = (struct sk_buff *)list_;
-
- save_flags(flags);
- cli();
-
- IS_SKB_HEAD(list);
-
- result = list->next;
- if (result == list) {
- restore_flags(flags);
- return NULL;
- }
-
- result->next->prev = list;
- list->next = result->next;
-
- result->next = NULL;
- result->prev = NULL;
-
- restore_flags(flags);
-
- IS_SKB(result);
- return result;
-}
-
-/*
- * Insert a packet before another one in a list.
- */
-void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
-{
- unsigned long flags;
-
- IS_SKB(old);
- IS_SKB(newsk);
-
- if(!old->next || !old->prev)
- printk("insert before unlisted item!\n");
- if(newsk->next || newsk->prev)
- printk("inserted item is already on a list.\n");
-
- save_flags(flags);
- cli();
- newsk->next = old;
- newsk->prev = old->prev;
- old->prev = newsk;
- newsk->prev->next = newsk;
-
- restore_flags(flags);
-}
-
-/*
- * Place a packet after a given packet in a list.
- */
-void skb_append(struct sk_buff *old, struct sk_buff *newsk)
-{
- unsigned long flags;
-
- IS_SKB(old);
- IS_SKB(newsk);
-
- if(!old->next || !old->prev)
- printk("append before unlisted item!\n");
- if(newsk->next || newsk->prev)
- printk("append item is already on a list.\n");
-
- save_flags(flags);
- cli();
-
- newsk->prev = old;
- newsk->next = old->next;
- newsk->next->prev = newsk;
- old->next = newsk;
-
- restore_flags(flags);
-}
-
-/*
- * Remove an sk_buff from its list. Works even without knowing the list it
- * is sitting on, which can be handy at times. It also means that THE LIST
- * MUST EXIST when you unlink. Thus a list must have its contents unlinked
- * _FIRST_.
- */
-void skb_unlink(struct sk_buff *skb)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- IS_SKB(skb);
-
- if(skb->prev && skb->next)
- {
- skb->next->prev = skb->prev;
- skb->prev->next = skb->next;
- skb->next = NULL;
- skb->prev = NULL;
- }
-#ifdef PARANOID_BUGHUNT_MODE /* This is legal but we sometimes want to watch it */
- else
- printk("skb_unlink: not a linked element\n");
-#endif
- restore_flags(flags);
-}
-
-#endif
-
-/*
- * Free an sk_buff. This still knows about things it should
- * not need to like protocols and sockets.
- */
-
-void kfree_skb(struct sk_buff *skb, int rw)
-{
- if (skb == NULL)
- {
- printk("kfree_skb: skb = NULL (from %p)\n",
- __builtin_return_address(0));
- return;
- }
-#ifdef CONFIG_SKB_CHECK
- IS_SKB(skb);
-#endif
- if (skb->lock)
- {
- skb->free = 3; /* Free when unlocked */
- net_free_locked++;
- return;
- }
- if (skb->free == 2)
- printk("Warning: kfree_skb passed an skb that nobody set the free flag on! (from %p)\n",
- __builtin_return_address(0));
- if (skb->next)
- printk("Warning: kfree_skb passed an skb still on a list (from %p).\n",
- __builtin_return_address(0));
- if (skb->sk)
- {
- if(skb->sk->prot!=NULL)
- {
- if (rw)
- skb->sk->prot->rfree(skb->sk, skb, skb->mem_len);
- else
- skb->sk->prot->wfree(skb->sk, skb, skb->mem_len);
-
- }
- else
- {
- unsigned long flags;
- /* Non INET - default wmalloc/rmalloc handler */
- save_flags(flags);
- cli();
- if (rw)
- skb->sk->rmem_alloc-=skb->mem_len;
- else
- skb->sk->wmem_alloc-=skb->mem_len;
- restore_flags(flags);
- if(!skb->sk->dead)
- skb->sk->write_space(skb->sk);
- kfree_skbmem(skb,skb->mem_len);
- }
- }
- else
- kfree_skbmem(skb, skb->mem_len);
-}
-
-/*
- * Allocate a new skbuff. We do this ourselves so we can fill in a few 'private'
- * fields and also do memory statistics to find all the [BEEP] leaks.
- */
-struct sk_buff *alloc_skb(unsigned int size,int priority)
-{
- struct sk_buff *skb;
- unsigned long flags;
-
- if (intr_count && priority!=GFP_ATOMIC) {
- static int count = 0;
- if (++count < 5) {
- printk("alloc_skb called nonatomically from interrupt %p\n",
- __builtin_return_address(0));
- priority = GFP_ATOMIC;
- }
- }
-
- size+=sizeof(struct sk_buff);
- skb=(struct sk_buff *)kmalloc(size,priority);
- if (skb == NULL)
- {
- net_fails++;
- return NULL;
- }
-#ifdef PARANOID_BUGHUNT_MODE
- if(skb->magic_debug_cookie == SK_GOOD_SKB)
- printk("Kernel kmalloc handed us an existing skb (%p)\n",skb);
-#endif
-
- net_allocs++;
-
- skb->free = 2; /* Invalid so we pick up forgetful users */
- skb->lock = 0;
- skb->pkt_type = PACKET_HOST; /* Default type */
- skb->truesize = size;
- skb->mem_len = size;
- skb->mem_addr = skb;
-#ifdef CONFIG_SLAVE_BALANCING
- skb->in_dev_queue = 0;
-#endif
- skb->fraglist = NULL;
- skb->prev = skb->next = NULL;
- skb->link3 = NULL;
- skb->sk = NULL;
- skb->localroute=0;
- skb->stamp.tv_sec=0; /* No idea about time */
- skb->localroute = 0;
- save_flags(flags);
- cli();
- net_memory += size;
- net_skbcount++;
- restore_flags(flags);
-#if CONFIG_SKB_CHECK
- skb->magic_debug_cookie = SK_GOOD_SKB;
-#endif
- skb->users = 0;
- return skb;
-}
-
-/*
- * Free an skbuff by memory
- */
-
-void kfree_skbmem(struct sk_buff *skb,unsigned size)
-{
- unsigned long flags;
-#ifdef CONFIG_SLAVE_BALANCING
- save_flags(flags);
- cli();
- if(skb->in_dev_queue && skb->dev!=NULL)
- skb->dev->pkt_queue--;
- restore_flags(flags);
-#endif
-#ifdef CONFIG_SKB_CHECK
- IS_SKB(skb);
- if(size!=skb->truesize)
- printk("kfree_skbmem: size mismatch.\n");
-
- if(skb->magic_debug_cookie == SK_GOOD_SKB)
- {
- save_flags(flags);
- cli();
- IS_SKB(skb);
- skb->magic_debug_cookie = SK_FREED_SKB;
- kfree_s((void *)skb,size);
- net_skbcount--;
- net_memory -= size;
- restore_flags(flags);
- }
- else
- printk("kfree_skbmem: bad magic cookie\n");
-#else
- save_flags(flags);
- cli();
- kfree_s((void *)skb,size);
- net_skbcount--;
- net_memory -= size;
- restore_flags(flags);
-#endif
-}
-
-/*
- * Duplicate an sk_buff. The new one is not owned by a socket or locked
- * and will be freed on deletion.
- */
-
-struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
-{
- struct sk_buff *n;
- unsigned long offset;
-
- n=alloc_skb(skb->mem_len-sizeof(struct sk_buff),priority);
- if(n==NULL)
- return NULL;
-
- offset=((char *)n)-((char *)skb);
-
- memcpy(n->data,skb->data,skb->mem_len-sizeof(struct sk_buff));
- n->len=skb->len;
- n->link3=NULL;
- n->sk=NULL;
- n->when=skb->when;
- n->dev=skb->dev;
- n->h.raw=skb->h.raw+offset;
- n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
- n->fraglen=skb->fraglen;
- n->fraglist=skb->fraglist;
- n->saddr=skb->saddr;
- n->daddr=skb->daddr;
- n->raddr=skb->raddr;
- n->acked=skb->acked;
- n->used=skb->used;
- n->free=1;
- n->arp=skb->arp;
- n->tries=0;
- n->lock=0;
- n->users=0;
- n->pkt_type=skb->pkt_type;
- return n;
-}
-
-
-/*
- * Skbuff device locking
- */
-
-void skb_device_lock(struct sk_buff *skb)
-{
- if(skb->lock)
- printk("double lock on device queue!\n");
- else
- net_locked++;
- skb->lock++;
-}
-
-void skb_device_unlock(struct sk_buff *skb)
-{
- if(skb->lock==0)
- printk("double unlock on device queue!\n");
- skb->lock--;
- if(skb->lock==0)
- net_locked--;
-}
-
-void dev_kfree_skb(struct sk_buff *skb, int mode)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if(skb->lock==1)
- net_locked--;
-
- if (!--skb->lock && (skb->free == 1 || skb->free == 3))
- {
- restore_flags(flags);
- kfree_skb(skb,mode);
- }
- else
- restore_flags(flags);
-}
-
-int skb_device_locked(struct sk_buff *skb)
-{
- return skb->lock? 1 : 0;
-}
-
diff --git a/pfinet/linux-inet/snmp.h b/pfinet/linux-inet/snmp.h
deleted file mode 100644
index 552292be..00000000
--- a/pfinet/linux-inet/snmp.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *
- * SNMP MIB entries for the IP subsystem.
- *
- * Alan Cox <gw4pts@gw4pts.ampr.org>
- *
- * We don't chose to implement SNMP in the kernel (this would
- * be silly as SNMP is a pain in the backside in places). We do
- * however need to collect the MIB statistics and export them
- * out of /proc (eventually)
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#ifndef _SNMP_H
-#define _SNMP_H
-
-/*
- * We use all unsigned longs. Linux will soon be so reliable that even these
- * will rapidly get too small 8-). Seriously consider the IpInReceives count
- * on the 20Gb/s + networks people expect in a few years time!
- */
-
-struct ip_mib
-{
- unsigned long IpForwarding;
- unsigned long IpDefaultTTL;
- unsigned long IpInReceives;
- unsigned long IpInHdrErrors;
- unsigned long IpInAddrErrors;
- unsigned long IpForwDatagrams;
- unsigned long IpInUnknownProtos;
- unsigned long IpInDiscards;
- unsigned long IpInDelivers;
- unsigned long IpOutRequests;
- unsigned long IpOutDiscards;
- unsigned long IpOutNoRoutes;
- unsigned long IpReasmTimeout;
- unsigned long IpReasmReqds;
- unsigned long IpReasmOKs;
- unsigned long IpReasmFails;
- unsigned long IpFragOKs;
- unsigned long IpFragFails;
- unsigned long IpFragCreates;
-};
-
-
-struct icmp_mib
-{
- unsigned long IcmpInMsgs;
- unsigned long IcmpInErrors;
- unsigned long IcmpInDestUnreachs;
- unsigned long IcmpInTimeExcds;
- unsigned long IcmpInParmProbs;
- unsigned long IcmpInSrcQuenchs;
- unsigned long IcmpInRedirects;
- unsigned long IcmpInEchos;
- unsigned long IcmpInEchoReps;
- unsigned long IcmpInTimestamps;
- unsigned long IcmpInTimestampReps;
- unsigned long IcmpInAddrMasks;
- unsigned long IcmpInAddrMaskReps;
- unsigned long IcmpOutMsgs;
- unsigned long IcmpOutErrors;
- unsigned long IcmpOutDestUnreachs;
- unsigned long IcmpOutTimeExcds;
- unsigned long IcmpOutParmProbs;
- unsigned long IcmpOutSrcQuenchs;
- unsigned long IcmpOutRedirects;
- unsigned long IcmpOutEchos;
- unsigned long IcmpOutEchoReps;
- unsigned long IcmpOutTimestamps;
- unsigned long IcmpOutTimestampReps;
- unsigned long IcmpOutAddrMasks;
- unsigned long IcmpOutAddrMaskReps;
-};
-
-struct tcp_mib
-{
- unsigned long TcpRtoAlgorithm;
- unsigned long TcpRtoMin;
- unsigned long TcpRtoMax;
- unsigned long TcpMaxConn;
- unsigned long TcpActiveOpens;
- unsigned long TcpPassiveOpens;
- unsigned long TcpAttemptFails;
- unsigned long TcpEstabResets;
- unsigned long TcpCurrEstab;
- unsigned long TcpInSegs;
- unsigned long TcpOutSegs;
- unsigned long TcpRetransSegs;
-};
-
-struct udp_mib
-{
- unsigned long UdpInDatagrams;
- unsigned long UdpNoPorts;
- unsigned long UdpInErrors;
- unsigned long UdpOutDatagrams;
-};
-
-
-#endif
diff --git a/pfinet/linux-inet/sock.c b/pfinet/linux-inet/sock.c
deleted file mode 100644
index 40d4a8f4..00000000
--- a/pfinet/linux-inet/sock.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Generic socket support routines. Memory allocators, sk->inuse/release
- * handler for protocols to use and generic option handler.
- *
- *
- * Version: @(#)sock.c 1.0.17 06/02/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Florian La Roche, <flla@stud.uni-sb.de>
- * Alan Cox, <A.Cox@swansea.ac.uk>
- *
- * Fixes:
- * Alan Cox : Numerous verify_area() problems
- * Alan Cox : Connecting on a connecting socket
- * now returns an error for tcp.
- * Alan Cox : sock->protocol is set correctly.
- * and is not sometimes left as 0.
- * Alan Cox : connect handles icmp errors on a
- * connect properly. Unfortunately there
- * is a restart syscall nasty there. I
- * can't match BSD without hacking the C
- * library. Ideas urgently sought!
- * Alan Cox : Disallow bind() to addresses that are
- * not ours - especially broadcast ones!!
- * Alan Cox : Socket 1024 _IS_ ok for users. (fencepost)
- * Alan Cox : sock_wfree/sock_rfree don't destroy sockets,
- * instead they leave that for the DESTROY timer.
- * Alan Cox : Clean up error flag in accept
- * Alan Cox : TCP ack handling is buggy, the DESTROY timer
- * was buggy. Put a remove_sock() in the handler
- * for memory when we hit 0. Also altered the timer
- * code. The ACK stuff can wait and needs major
- * TCP layer surgery.
- * Alan Cox : Fixed TCP ack bug, removed remove sock
- * and fixed timer/inet_bh race.
- * Alan Cox : Added zapped flag for TCP
- * Alan Cox : Move kfree_skb into skbuff.c and tidied up surplus code
- * Alan Cox : for new sk_buff allocations wmalloc/rmalloc now call alloc_skb
- * Alan Cox : kfree_s calls now are kfree_skbmem so we can track skb resources
- * Alan Cox : Supports socket option broadcast now as does udp. Packet and raw need fixing.
- * Alan Cox : Added RCVBUF,SNDBUF size setting. It suddenly occurred to me how easy it was so...
- * Rick Sladkey : Relaxed UDP rules for matching packets.
- * C.E.Hawkins : IFF_PROMISC/SIOCGHWADDR support
- * Pauline Middelink : identd support
- * Alan Cox : Fixed connect() taking signals I think.
- * Alan Cox : SO_LINGER supported
- * Alan Cox : Error reporting fixes
- * Anonymous : inet_create tidied up (sk->reuse setting)
- * Alan Cox : inet sockets don't set sk->type!
- * Alan Cox : Split socket option code
- * Alan Cox : Callbacks
- * Alan Cox : Nagle flag for Charles & Johannes stuff
- * Alex : Removed restriction on inet fioctl
- * Alan Cox : Splitting INET from NET core
- * Alan Cox : Fixed bogus SO_TYPE handling in getsockopt()
- * Adam Caldwell : Missing return in SO_DONTROUTE/SO_DEBUG code
- * Alan Cox : Split IP from generic code
- * Alan Cox : New kfree_skbmem()
- * Alan Cox : Make SO_DEBUG superuser only.
- * Alan Cox : Allow anyone to clear SO_DEBUG
- * (compatibility fix)
- *
- * To Fix:
- *
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include "arp.h"
-#include "rarp.h"
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "raw.h"
-#include "icmp.h"
-
-#define min(a,b) ((a)<(b)?(a):(b))
-
-/*
- * This is meant for all protocols to use and covers goings on
- * at the socket level. Everything here is generic.
- */
-
-int sock_setsockopt(struct sock *sk, int level, int optname,
- char *optval, int optlen)
-{
- int val;
- int err;
- struct linger ling;
-
- if (optval == NULL)
- return(-EINVAL);
-
- err=verify_area(VERIFY_READ, optval, sizeof(int));
- if(err)
- return err;
-
- val = get_fs_long((unsigned long *)optval);
- switch(optname)
- {
- case SO_TYPE:
- case SO_ERROR:
- return(-ENOPROTOOPT);
-
- case SO_DEBUG:
- if(val && !suser())
- return(-EPERM);
- sk->debug=val?1:0;
- return 0;
- case SO_DONTROUTE:
- sk->localroute=val?1:0;
- return 0;
- case SO_BROADCAST:
- sk->broadcast=val?1:0;
- return 0;
- case SO_SNDBUF:
- if(val>32767)
- val=32767;
- if(val<256)
- val=256;
- sk->sndbuf=val;
- return 0;
- case SO_LINGER:
- err=verify_area(VERIFY_READ,optval,sizeof(ling));
- if(err)
- return err;
- memcpy_fromfs(&ling,optval,sizeof(ling));
- if(ling.l_onoff==0)
- sk->linger=0;
- else
- {
- sk->lingertime=ling.l_linger;
- sk->linger=1;
- }
- return 0;
- case SO_RCVBUF:
- if(val>32767)
- val=32767;
- if(val<256)
- val=256;
- sk->rcvbuf=val;
- return(0);
-
- case SO_REUSEADDR:
- if (val)
- sk->reuse = 1;
- else
- sk->reuse = 0;
- return(0);
-
- case SO_KEEPALIVE:
- if (val)
- sk->keepopen = 1;
- else
- sk->keepopen = 0;
- return(0);
-
- case SO_OOBINLINE:
- if (val)
- sk->urginline = 1;
- else
- sk->urginline = 0;
- return(0);
-
- case SO_NO_CHECK:
- if (val)
- sk->no_check = 1;
- else
- sk->no_check = 0;
- return(0);
-
- case SO_PRIORITY:
- if (val >= 0 && val < DEV_NUMBUFFS)
- {
- sk->priority = val;
- }
- else
- {
- return(-EINVAL);
- }
- return(0);
-
- default:
- return(-ENOPROTOOPT);
- }
-}
-
-
-int sock_getsockopt(struct sock *sk, int level, int optname,
- char *optval, int *optlen)
-{
- int val;
- int err;
- struct linger ling;
-
- switch(optname)
- {
- case SO_DEBUG:
- val = sk->debug;
- break;
-
- case SO_DONTROUTE:
- val = sk->localroute;
- break;
-
- case SO_BROADCAST:
- val= sk->broadcast;
- break;
-
- case SO_LINGER:
- err=verify_area(VERIFY_WRITE,optval,sizeof(ling));
- if(err)
- return err;
- err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
- if(err)
- return err;
- put_fs_long(sizeof(ling),(unsigned long *)optlen);
- ling.l_onoff=sk->linger;
- ling.l_linger=sk->lingertime;
- memcpy_tofs(optval,&ling,sizeof(ling));
- return 0;
-
- case SO_SNDBUF:
- val=sk->sndbuf;
- break;
-
- case SO_RCVBUF:
- val =sk->rcvbuf;
- break;
-
- case SO_REUSEADDR:
- val = sk->reuse;
- break;
-
- case SO_KEEPALIVE:
- val = sk->keepopen;
- break;
-
- case SO_TYPE:
-#if 0
- if (sk->prot == &tcp_prot)
- val = SOCK_STREAM;
- else
- val = SOCK_DGRAM;
-#endif
- val = sk->type;
- break;
-
- case SO_ERROR:
- val = sk->err;
- sk->err = 0;
- break;
-
- case SO_OOBINLINE:
- val = sk->urginline;
- break;
-
- case SO_NO_CHECK:
- val = sk->no_check;
- break;
-
- case SO_PRIORITY:
- val = sk->priority;
- break;
-
- default:
- return(-ENOPROTOOPT);
- }
- err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
- if(err)
- return err;
- put_fs_long(sizeof(int),(unsigned long *) optlen);
-
- err=verify_area(VERIFY_WRITE, optval, sizeof(int));
- if(err)
- return err;
- put_fs_long(val,(unsigned long *)optval);
-
- return(0);
-}
-
-
-struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
-{
- if (sk)
- {
- if (sk->wmem_alloc + size < sk->sndbuf || force)
- {
- struct sk_buff * c = alloc_skb(size, priority);
- if (c)
- {
- unsigned long flags;
- save_flags(flags);
- cli();
- sk->wmem_alloc+= c->mem_len;
- restore_flags(flags); /* was sti(); */
- }
- return c;
- }
- return(NULL);
- }
- return(alloc_skb(size, priority));
-}
-
-
-struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
-{
- if (sk)
- {
- if (sk->rmem_alloc + size < sk->rcvbuf || force)
- {
- struct sk_buff *c = alloc_skb(size, priority);
- if (c)
- {
- unsigned long flags;
- save_flags(flags);
- cli();
- sk->rmem_alloc += c->mem_len;
- restore_flags(flags); /* was sti(); */
- }
- return(c);
- }
- return(NULL);
- }
- return(alloc_skb(size, priority));
-}
-
-
-unsigned long sock_rspace(struct sock *sk)
-{
- int amt;
-
- if (sk != NULL)
- {
- if (sk->rmem_alloc >= sk->rcvbuf-2*MIN_WINDOW)
- return(0);
- amt = min((sk->rcvbuf-sk->rmem_alloc)/2-MIN_WINDOW, MAX_WINDOW);
- if (amt < 0)
- return(0);
- return(amt);
- }
- return(0);
-}
-
-
-unsigned long sock_wspace(struct sock *sk)
-{
- if (sk != NULL)
- {
- if (sk->shutdown & SEND_SHUTDOWN)
- return(0);
- if (sk->wmem_alloc >= sk->sndbuf)
- return(0);
- return(sk->sndbuf-sk->wmem_alloc );
- }
- return(0);
-}
-
-
-void sock_wfree(struct sock *sk, struct sk_buff *skb, unsigned long size)
-{
-#ifdef CONFIG_SKB_CHECK
- IS_SKB(skb);
-#endif
- kfree_skbmem(skb, size);
- if (sk)
- {
- unsigned long flags;
- save_flags(flags);
- cli();
- sk->wmem_alloc -= size;
- restore_flags(flags);
- /* In case it might be waiting for more memory. */
- if (!sk->dead)
- sk->write_space(sk);
- return;
- }
-}
-
-
-void sock_rfree(struct sock *sk, struct sk_buff *skb, unsigned long size)
-{
-#ifdef CONFIG_SKB_CHECK
- IS_SKB(skb);
-#endif
- kfree_skbmem(skb, size);
- if (sk)
- {
- unsigned long flags;
- save_flags(flags);
- cli();
- sk->rmem_alloc -= size;
- restore_flags(flags);
- }
-}
-
-/*
- * Generic send/receive buffer handlers
- */
-
-struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, int noblock, int *errcode)
-{
- struct sk_buff *skb;
- int err;
-
- sk->inuse=1;
-
- do
- {
- if(sk->err!=0)
- {
- cli();
- err= -sk->err;
- sk->err=0;
- sti();
- *errcode=err;
- return NULL;
- }
-
- if(sk->shutdown&SEND_SHUTDOWN)
- {
- *errcode=-EPIPE;
- return NULL;
- }
-
- skb = sock_wmalloc(sk, size, 0, GFP_KERNEL);
-
- if(skb==NULL)
- {
- unsigned long tmp;
-
- sk->socket->flags |= SO_NOSPACE;
- if(noblock)
- {
- *errcode=-EAGAIN;
- return NULL;
- }
- if(sk->shutdown&SEND_SHUTDOWN)
- {
- *errcode=-EPIPE;
- return NULL;
- }
- tmp = sk->wmem_alloc;
- cli();
- if(sk->shutdown&SEND_SHUTDOWN)
- {
- sti();
- *errcode=-EPIPE;
- return NULL;
- }
-
- if( tmp <= sk->wmem_alloc)
- {
- sk->socket->flags &= ~SO_NOSPACE;
- interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked)
- {
- sti();
- *errcode = -ERESTARTSYS;
- return NULL;
- }
- }
- sti();
- }
- }
- while(skb==NULL);
-
- return skb;
-}
-
-/*
- * Queue a received datagram if it will fit. Stream and sequenced protocols
- * can't normally use this as they need to fit buffers in and play with them.
- */
-
-int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
- unsigned long flags;
- if(sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
- return -ENOMEM;
- save_flags(flags);
- cli();
- sk->rmem_alloc+=skb->mem_len;
- skb->sk=sk;
- restore_flags(flags);
- skb_queue_tail(&sk->receive_queue,skb);
- if(!sk->dead)
- sk->data_ready(sk,skb->len);
- return 0;
-}
-
-void release_sock(struct sock *sk)
-{
- unsigned long flags;
-#ifdef CONFIG_INET
- struct sk_buff *skb;
-#endif
-
- if (!sk->prot)
- return;
- /*
- * Make the backlog atomic. If we don't do this there is a tiny
- * window where a packet may arrive between the sk->blog being
- * tested and then set with sk->inuse still 0 causing an extra
- * unwanted re-entry into release_sock().
- */
-
- save_flags(flags);
- cli();
- if (sk->blog)
- {
- restore_flags(flags);
- return;
- }
- sk->blog=1;
- sk->inuse = 1;
- restore_flags(flags);
-#ifdef CONFIG_INET
- /* See if we have any packets built up. */
- while((skb = skb_dequeue(&sk->back_log)) != NULL)
- {
- sk->blog = 1;
- if (sk->prot->rcv)
- sk->prot->rcv(skb, skb->dev, sk->opt,
- skb->saddr, skb->len, skb->daddr, 1,
- /* Only used for/by raw sockets. */
- (struct inet_protocol *)sk->pair);
- }
-#endif
- sk->blog = 0;
- sk->inuse = 0;
-#ifdef CONFIG_INET
- if (sk->dead && sk->state == TCP_CLOSE)
- {
- /* Should be about 2 rtt's */
- reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
- }
-#endif
-}
-
-
diff --git a/pfinet/linux-inet/sock.h b/pfinet/linux-inet/sock.h
deleted file mode 100644
index 2005745e..00000000
--- a/pfinet/linux-inet/sock.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the AF_INET socket handler.
- *
- * Version: @(#)sock.h 1.0.4 05/13/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Corey Minyard <wf-rch!minyard@relay.EU.net>
- * Florian La Roche <flla@stud.uni-sb.de>
- *
- * Fixes:
- * Alan Cox : Volatiles in skbuff pointers. See
- * skbuff comments. May be overdone,
- * better to prove they can be removed
- * than the reverse.
- * Alan Cox : Added a zapped field for tcp to note
- * a socket is reset and must stay shut up
- * Alan Cox : New fields for options
- * Pauline Middelink : identd support
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _SOCK_H
-#define _SOCK_H
-
-#include <linux/timer.h>
-#include <linux/ip.h> /* struct options */
-#include <linux/tcp.h> /* struct tcphdr */
-#include <linux/config.h>
-
-#include <linux/skbuff.h> /* struct sk_buff */
-#include "protocol.h" /* struct inet_protocol */
-#ifdef CONFIG_AX25
-#include "ax25.h"
-#endif
-#ifdef CONFIG_IPX
-#include "ipx.h"
-#endif
-#ifdef CONFIG_ATALK
-#include <linux/atalk.h>
-#endif
-
-#include <linux/igmp.h>
-
-#define SOCK_ARRAY_SIZE 256 /* Think big (also on some systems a byte is faster */
-
-
-/*
- * This structure really needs to be cleaned up.
- * Most of it is for TCP, and not used by any of
- * the other protocols.
- */
-struct sock {
- struct options *opt;
- volatile unsigned long wmem_alloc;
- volatile unsigned long rmem_alloc;
- unsigned long write_seq;
- unsigned long sent_seq;
- unsigned long acked_seq;
- unsigned long copied_seq;
- unsigned long rcv_ack_seq;
- unsigned long window_seq;
- unsigned long fin_seq;
- unsigned long urg_seq;
- unsigned long urg_data;
-
- /*
- * Not all are volatile, but some are, so we
- * might as well say they all are.
- */
- volatile char inuse,
- dead,
- urginline,
- intr,
- blog,
- done,
- reuse,
- keepopen,
- linger,
- delay_acks,
- destroy,
- ack_timed,
- no_check,
- zapped, /* In ax25 & ipx means not linked */
- broadcast,
- nonagle;
- unsigned long lingertime;
- int proc;
- struct sock *next;
- struct sock *prev; /* Doubly linked chain.. */
- struct sock *pair;
- struct sk_buff * volatile send_head;
- struct sk_buff * volatile send_tail;
- struct sk_buff_head back_log;
- struct sk_buff *partial;
- struct timer_list partial_timer;
- long retransmits;
- struct sk_buff_head write_queue,
- receive_queue;
- struct proto *prot;
- struct wait_queue **sleep;
- unsigned long daddr;
- unsigned long saddr;
- unsigned short max_unacked;
- unsigned short window;
- unsigned short bytes_rcv;
-/* mss is min(mtu, max_window) */
- unsigned short mtu; /* mss negotiated in the syn's */
- volatile unsigned short mss; /* current eff. mss - can change */
- volatile unsigned short user_mss; /* mss requested by user in ioctl */
- volatile unsigned short max_window;
- unsigned long window_clamp;
- unsigned short num;
- volatile unsigned short cong_window;
- volatile unsigned short cong_count;
- volatile unsigned short ssthresh;
- volatile unsigned short packets_out;
- volatile unsigned short shutdown;
- volatile unsigned long rtt;
- volatile unsigned long mdev;
- volatile unsigned long rto;
-/* currently backoff isn't used, but I'm maintaining it in case
- * we want to go back to a backoff formula that needs it
- */
- volatile unsigned short backoff;
- volatile error_t err; /* Note change XXX HURD */
- unsigned char protocol;
- volatile unsigned char state;
- volatile unsigned char ack_backlog;
- unsigned char max_ack_backlog;
- unsigned char priority;
- unsigned char debug;
- unsigned short rcvbuf;
- unsigned short sndbuf;
- unsigned short type;
- unsigned char localroute; /* Route locally only */
-#ifdef CONFIG_IPX
- ipx_address ipx_dest_addr;
- ipx_interface *ipx_intrfc;
- unsigned short ipx_port;
- unsigned short ipx_type;
-#endif
-#ifdef CONFIG_AX25
-/* Really we want to add a per protocol private area */
- ax25_address ax25_source_addr,ax25_dest_addr;
- struct sk_buff *volatile ax25_retxq[8];
- char ax25_state,ax25_vs,ax25_vr,ax25_lastrxnr,ax25_lasttxnr;
- char ax25_condition;
- char ax25_retxcnt;
- char ax25_xx;
- char ax25_retxqi;
- char ax25_rrtimer;
- char ax25_timer;
- unsigned char ax25_n2;
- unsigned short ax25_t1,ax25_t2,ax25_t3;
- ax25_digi *ax25_digipeat;
-#endif
-#ifdef CONFIG_ATALK
- struct atalk_sock at;
-#endif
-
-/* IP 'private area' or will be eventually */
- int ip_ttl; /* TTL setting */
- int ip_tos; /* TOS */
- struct tcphdr dummy_th;
- struct timer_list keepalive_timer; /* TCP keepalive hack */
- struct timer_list retransmit_timer; /* TCP retransmit timer */
- struct timer_list ack_timer; /* TCP delayed ack timer */
- int ip_xmit_timeout; /* Why the timeout is running */
-#ifdef CONFIG_IP_MULTICAST
- int ip_mc_ttl; /* Multicasting TTL */
- int ip_mc_loop; /* Loopback (not implemented yet) */
- char ip_mc_name[MAX_ADDR_LEN]; /* Multicast device name */
- struct ip_mc_socklist *ip_mc_list; /* Group array */
-#endif
-
- /* This part is used for the timeout functions (timer.c). */
- int timeout; /* What are we waiting for? */
- struct timer_list timer; /* This is the TIME_WAIT/receive timer when we are doing IP */
- struct timeval stamp;
-
- /* identd */
- struct socket *socket;
-
- /* Callbacks */
- void (*state_change)(struct sock *sk);
- void (*data_ready)(struct sock *sk,int bytes);
- void (*write_space)(struct sock *sk);
- void (*error_report)(struct sock *sk);
-
-};
-
-struct proto {
- struct sk_buff * (*wmalloc)(struct sock *sk,
- unsigned long size, int force,
- int priority);
- struct sk_buff * (*rmalloc)(struct sock *sk,
- unsigned long size, int force,
- int priority);
- void (*wfree)(struct sock *sk, struct sk_buff *skb,
- unsigned long size);
- void (*rfree)(struct sock *sk, struct sk_buff *skb,
- unsigned long size);
- unsigned long (*rspace)(struct sock *sk);
- unsigned long (*wspace)(struct sock *sk);
- void (*close)(struct sock *sk, int timeout);
- int (*read)(struct sock *sk, unsigned char *to,
- int len, int nonblock, unsigned flags);
- int (*write)(struct sock *sk, unsigned char *to,
- int len, int nonblock, unsigned flags);
- int (*sendto)(struct sock *sk,
- unsigned char *from, int len, int noblock,
- unsigned flags, struct sockaddr_in *usin,
- int addr_len);
- int (*recvfrom)(struct sock *sk,
- unsigned char *from, int len, int noblock,
- unsigned flags, struct sockaddr_in *usin,
- int *addr_len);
- int (*build_header)(struct sk_buff *skb,
- unsigned long saddr,
- unsigned long daddr,
- struct device **dev, int type,
- struct options *opt, int len, int tos, int ttl);
- int (*connect)(struct sock *sk,
- struct sockaddr_in *usin, int addr_len);
- struct sock * (*accept) (struct sock *sk, int flags);
- void (*queue_xmit)(struct sock *sk,
- struct device *dev, struct sk_buff *skb,
- int free);
- void (*retransmit)(struct sock *sk, int all);
- void (*write_wakeup)(struct sock *sk);
- void (*read_wakeup)(struct sock *sk);
- int (*rcv)(struct sk_buff *buff, struct device *dev,
- struct options *opt, unsigned long daddr,
- unsigned short len, unsigned long saddr,
- int redo, struct inet_protocol *protocol);
- int (*select)(struct sock *sk, int which,
- select_table *wait);
- int (*ioctl)(struct sock *sk, int cmd,
- unsigned long arg);
- int (*init)(struct sock *sk);
- void (*shutdown)(struct sock *sk, int how);
- int (*setsockopt)(struct sock *sk, int level, int optname,
- char *optval, int optlen);
- int (*getsockopt)(struct sock *sk, int level, int optname,
- char *optval, int *option);
- unsigned short max_header;
- unsigned long retransmits;
- struct sock * sock_array[SOCK_ARRAY_SIZE];
- char name[80];
- int inuse, highestinuse;
-};
-
-#define TIME_WRITE 1
-#define TIME_CLOSE 2
-#define TIME_KEEPOPEN 3
-#define TIME_DESTROY 4
-#define TIME_DONE 5 /* used to absorb those last few packets */
-#define TIME_PROBE0 6
-#define SOCK_DESTROY_TIME 1000 /* about 10 seconds */
-
-#define PROT_SOCK 1024 /* Sockets 0-1023 can't be bound too unless you are superuser */
-
-#define SHUTDOWN_MASK 3
-#define RCV_SHUTDOWN 1
-#define SEND_SHUTDOWN 2
-
-
-extern void destroy_sock(struct sock *sk);
-extern unsigned short get_new_socknum(struct proto *, unsigned short);
-extern void put_sock(unsigned short, struct sock *);
-extern void release_sock(struct sock *sk);
-extern struct sock *get_sock(struct proto *, unsigned short,
- unsigned long, unsigned short,
- unsigned long);
-extern struct sock *get_sock_mcast(struct sock *, unsigned short,
- unsigned long, unsigned short,
- unsigned long);
-extern struct sock *get_sock_raw(struct sock *, unsigned short,
- unsigned long, unsigned long);
-
-extern struct sk_buff *sock_wmalloc(struct sock *sk,
- unsigned long size, int force,
- int priority);
-extern struct sk_buff *sock_rmalloc(struct sock *sk,
- unsigned long size, int force,
- int priority);
-extern void sock_wfree(struct sock *sk, struct sk_buff *skb,
- unsigned long size);
-extern void sock_rfree(struct sock *sk, struct sk_buff *skb,
- unsigned long size);
-extern unsigned long sock_rspace(struct sock *sk);
-extern unsigned long sock_wspace(struct sock *sk);
-
-extern int sock_setsockopt(struct sock *sk,int level,int op,char *optval,int optlen);
-
-extern int sock_getsockopt(struct sock *sk,int level,int op,char *optval,int *optlen);
-extern struct sk_buff *sock_alloc_send_skb(struct sock *skb, unsigned long size, int noblock, int *errcode);
-extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
-
-/* declarations from timer.c */
-extern struct sock *timer_base;
-
-void delete_timer (struct sock *);
-void reset_timer (struct sock *, int, unsigned long);
-void net_timer (unsigned long);
-
-
-#endif /* _SOCK_H */
diff --git a/pfinet/linux-inet/tcp.c b/pfinet/linux-inet/tcp.c
deleted file mode 100644
index 3005fbfd..00000000
--- a/pfinet/linux-inet/tcp.c
+++ /dev/null
@@ -1,5121 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Implementation of the Transmission Control Protocol(TCP).
- *
- * Version: @(#)tcp.c 1.0.16 05/25/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Mark Evans, <evansmp@uhura.aston.ac.uk>
- * Corey Minyard <wf-rch!minyard@relay.EU.net>
- * Florian La Roche, <flla@stud.uni-sb.de>
- * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
- * Linus Torvalds, <torvalds@cs.helsinki.fi>
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- * Matthew Dillon, <dillon@apollo.west.oic.com>
- * Arnt Gulbrandsen, <agulbra@no.unit.nvg>
- *
- * Fixes:
- * Alan Cox : Numerous verify_area() calls
- * Alan Cox : Set the ACK bit on a reset
- * Alan Cox : Stopped it crashing if it closed while sk->inuse=1
- * and was trying to connect (tcp_err()).
- * Alan Cox : All icmp error handling was broken
- * pointers passed where wrong and the
- * socket was looked up backwards. Nobody
- * tested any icmp error code obviously.
- * Alan Cox : tcp_err() now handled properly. It wakes people
- * on errors. select behaves and the icmp error race
- * has gone by moving it into sock.c
- * Alan Cox : tcp_reset() fixed to work for everything not just
- * packets for unknown sockets.
- * Alan Cox : tcp option processing.
- * Alan Cox : Reset tweaked (still not 100%) [Had syn rule wrong]
- * Herp Rosmanith : More reset fixes
- * Alan Cox : No longer acks invalid rst frames. Acking
- * any kind of RST is right out.
- * Alan Cox : Sets an ignore me flag on an rst receive
- * otherwise odd bits of prattle escape still
- * Alan Cox : Fixed another acking RST frame bug. Should stop
- * LAN workplace lockups.
- * Alan Cox : Some tidyups using the new skb list facilities
- * Alan Cox : sk->keepopen now seems to work
- * Alan Cox : Pulls options out correctly on accepts
- * Alan Cox : Fixed assorted sk->rqueue->next errors
- * Alan Cox : PSH doesn't end a TCP read. Switched a bit to skb ops.
- * Alan Cox : Tidied tcp_data to avoid a potential nasty.
- * Alan Cox : Added some better commenting, as the tcp is hard to follow
- * Alan Cox : Removed incorrect check for 20 * psh
- * Michael O'Reilly : ack < copied bug fix.
- * Johannes Stille : Misc tcp fixes (not all in yet).
- * Alan Cox : FIN with no memory -> CRASH
- * Alan Cox : Added socket option proto entries. Also added awareness of them to accept.
- * Alan Cox : Added TCP options (SOL_TCP)
- * Alan Cox : Switched wakeup calls to callbacks, so the kernel can layer network sockets.
- * Alan Cox : Use ip_tos/ip_ttl settings.
- * Alan Cox : Handle FIN (more) properly (we hope).
- * Alan Cox : RST frames sent on unsynchronised state ack error/
- * Alan Cox : Put in missing check for SYN bit.
- * Alan Cox : Added tcp_select_window() aka NET2E
- * window non shrink trick.
- * Alan Cox : Added a couple of small NET2E timer fixes
- * Charles Hedrick : TCP fixes
- * Toomas Tamm : TCP window fixes
- * Alan Cox : Small URG fix to rlogin ^C ack fight
- * Charles Hedrick : Rewrote most of it to actually work
- * Linus : Rewrote tcp_read() and URG handling
- * completely
- * Gerhard Koerting: Fixed some missing timer handling
- * Matthew Dillon : Reworked TCP machine states as per RFC
- * Gerhard Koerting: PC/TCP workarounds
- * Adam Caldwell : Assorted timer/timing errors
- * Matthew Dillon : Fixed another RST bug
- * Alan Cox : Move to kernel side addressing changes.
- * Alan Cox : Beginning work on TCP fastpathing (not yet usable)
- * Arnt Gulbrandsen: Turbocharged tcp_check() routine.
- * Alan Cox : TCP fast path debugging
- * Alan Cox : Window clamping
- * Michael Riepe : Bug in tcp_check()
- * Matt Dillon : More TCP improvements and RST bug fixes
- * Matt Dillon : Yet more small nasties remove from the TCP code
- * (Be very nice to this man if tcp finally works 100%) 8)
- * Alan Cox : BSD accept semantics.
- * Alan Cox : Reset on closedown bug.
- * Peter De Schrijver : ENOTCONN check missing in tcp_sendto().
- * Michael Pall : Handle select() after URG properly in all cases.
- * Michael Pall : Undo the last fix in tcp_read_urg() (multi URG PUSH broke rlogin).
- * Michael Pall : Fix the multi URG PUSH problem in tcp_readable(), select() after URG works now.
- * Michael Pall : recv(...,MSG_OOB) never blocks in the BSD api.
- * Alan Cox : Changed the semantics of sk->socket to
- * fix a race and a signal problem with
- * accept() and async I/O.
- * Alan Cox : Relaxed the rules on tcp_sendto().
- * Yury Shevchuk : Really fixed accept() blocking problem.
- * Craig I. Hagan : Allow for BSD compatible TIME_WAIT for
- * clients/servers which listen in on
- * fixed ports.
- * Alan Cox : Cleaned the above up and shrank it to
- * a sensible code size.
- * Alan Cox : Self connect lockup fix.
- * Alan Cox : No connect to multicast.
- * Ross Biro : Close unaccepted children on master
- * socket close.
- * Alan Cox : Reset tracing code.
- * Alan Cox : Spurious resets on shutdown.
- * Alan Cox : Giant 15 minute/60 second timer error
- * Alan Cox : Small whoops in selecting before an accept.
- * Alan Cox : Kept the state trace facility since it's
- * handy for debugging.
- * Alan Cox : More reset handler fixes.
- * Alan Cox : Started rewriting the code based on the RFC's
- * for other useful protocol references see:
- * Comer, KA9Q NOS, and for a reference on the
- * difference between specifications and how BSD
- * works see the 4.4lite source.
- * A.N.Kuznetsov : Don't time wait on completion of tidy
- * close.
- * Linus Torvalds : Fin/Shutdown & copied_seq changes.
- * Linus Torvalds : Fixed BSD port reuse to work first syn
- * Alan Cox : Reimplemented timers as per the RFC and using multiple
- * timers for sanity.
- * Alan Cox : Small bug fixes, and a lot of new
- * comments.
- * Alan Cox : Fixed dual reader crash by locking
- * the buffers (much like datagram.c)
- * Alan Cox : Fixed stuck sockets in probe. A probe
- * now gets fed up of retrying without
- * (even a no space) answer.
- * Alan Cox : Extracted closing code better
- * Alan Cox : Fixed the closing state machine to
- * resemble the RFC.
- * Alan Cox : More 'per spec' fixes.
- * Alan Cox : tcp_data() doesn't ack illegal PSH
- * only frames. At least one pc tcp stack
- * generates them.
- *
- *
- * To Fix:
- * Fast path the code. Two things here - fix the window calculation
- * so it doesn't iterate over the queue, also spot packets with no funny
- * options arriving in order and process directly.
- *
- * Implement RFC 1191 [Path MTU discovery]
- * Look at the effect of implementing RFC 1337 suggestions and their impact.
- * Rewrite output state machine to use a single queue and do low window
- * situations as per the spec (RFC 1122)
- * Speed up input assembly algorithm.
- * RFC1323 - PAWS and window scaling. PAWS is required for IPv6 so we
- * could do with it working on IPv4
- * User settable/learned rtt/max window/mtu
- * Cope with MTU/device switches when retransmitting in tcp.
- * Fix the window handling to use PR's new code.
- *
- * Change the fundamental structure to a single send queue maintained
- * by TCP (removing the bogus ip stuff [thus fixing mtu drops on
- * active routes too]). Cut the queue off in tcp_retransmit/
- * tcp_transmit.
- * Change the receive queue to assemble as it goes. This lets us
- * dispose of most of tcp_sequence, half of tcp_ack and chunks of
- * tcp_data/tcp_read as well as the window shrink crud.
- * Separate out duplicated code - tcp_alloc_skb, tcp_build_ack
- * tcp_queue_skb seem obvious routines to extract.
- *
- * 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
- * 2 of the License, or(at your option) any later version.
- *
- * Description of States:
- *
- * TCP_SYN_SENT sent a connection request, waiting for ack
- *
- * TCP_SYN_RECV received a connection request, sent ack,
- * waiting for final ack in three-way handshake.
- *
- * TCP_ESTABLISHED connection established
- *
- * TCP_FIN_WAIT1 our side has shutdown, waiting to complete
- * transmission of remaining buffered data
- *
- * TCP_FIN_WAIT2 all buffered data sent, waiting for remote
- * to shutdown
- *
- * TCP_CLOSING both sides have shutdown but we still have
- * data we have to finish sending
- *
- * TCP_TIME_WAIT timeout to catch resent junk before entering
- * closed, can only be entered from FIN_WAIT2
- * or CLOSING. Required because the other end
- * may not have gotten our last ACK causing it
- * to retransmit the data packet (which we ignore)
- *
- * TCP_CLOSE_WAIT remote side has shutdown and is waiting for
- * us to finish writing our data and to shutdown
- * (we have to close() to move on to LAST_ACK)
- *
- * TCP_LAST_ACK out side has shutdown after remote has
- * shutdown. There may still be data in our
- * buffer that we have to finish sending
- *
- * TCP_CLOSE socket is finished
- */
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/config.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/termios.h>
-#include <linux/in.h>
-#include <linux/fcntl.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "snmp.h"
-#include "ip.h"
-#include "protocol.h"
-#include "icmp.h"
-#include "tcp.h"
-#include "arp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "route.h"
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-/*
- * The MSL timer is the 'normal' timer.
- */
-
-#define reset_msl_timer(x,y,z) reset_timer(x,y,z)
-
-#define SEQ_TICK 3
-unsigned long seq_offset;
-struct tcp_mib tcp_statistics;
-
-static void tcp_close(struct sock *sk, int timeout);
-
-
-/*
- * The less said about this the better, but it works and will do for 1.2
- */
-
-static struct wait_queue *master_select_wakeup;
-
-static __inline__ int min(unsigned int a, unsigned int b)
-{
- if (a < b)
- return(a);
- return(b);
-}
-
-#undef STATE_TRACE
-
-#ifdef STATE_TRACE
-static char *statename[]={
- "Unused","Established","Syn Sent","Syn Recv",
- "Fin Wait 1","Fin Wait 2","Time Wait", "Close",
- "Close Wait","Last ACK","Listen","Closing"
-};
-#endif
-
-static __inline__ void tcp_set_state(struct sock *sk, int state)
-{
- if(sk->state==TCP_ESTABLISHED)
- tcp_statistics.TcpCurrEstab--;
-#ifdef STATE_TRACE
- if(sk->debug)
- printk("TCP sk=%p, State %s -> %s\n",sk, statename[sk->state],statename[state]);
-#endif
- /* This is a hack but it doesn't occur often and it's going to
- be a real to fix nicely */
-
- if(state==TCP_ESTABLISHED && sk->state==TCP_SYN_RECV)
- {
- wake_up_interruptible(&master_select_wakeup);
- }
- sk->state=state;
- if(state==TCP_ESTABLISHED)
- tcp_statistics.TcpCurrEstab++;
-}
-
-/*
- * This routine picks a TCP windows for a socket based on
- * the following constraints
- *
- * 1. The window can never be shrunk once it is offered (RFC 793)
- * 2. We limit memory per socket
- *
- * For now we use NET2E3's heuristic of offering half the memory
- * we have handy. All is not as bad as this seems however because
- * of two things. Firstly we will bin packets even within the window
- * in order to get the data we are waiting for into the memory limit.
- * Secondly we bin common duplicate forms at receive time
- * Better heuristics welcome
- */
-
-int tcp_select_window(struct sock *sk)
-{
- int new_window = sk->prot->rspace(sk);
-
- if(sk->window_clamp)
- new_window=min(sk->window_clamp,new_window);
- /*
- * Two things are going on here. First, we don't ever offer a
- * window less than min(sk->mss, MAX_WINDOW/2). This is the
- * receiver side of SWS as specified in RFC1122.
- * Second, we always give them at least the window they
- * had before, in order to avoid retracting window. This
- * is technically allowed, but RFC1122 advises against it and
- * in practice it causes trouble.
- *
- * Fixme: This doesn't correctly handle the case where
- * new_window > sk->window but not by enough to allow for the
- * shift in sequence space.
- */
- if (new_window < min(sk->mss, MAX_WINDOW/2) || new_window < sk->window)
- return(sk->window);
- return(new_window);
-}
-
-/*
- * Find someone to 'accept'. Must be called with
- * sk->inuse=1 or cli()
- */
-
-static struct sk_buff *tcp_find_established(struct sock *s)
-{
- struct sk_buff *p=skb_peek(&s->receive_queue);
- if(p==NULL)
- return NULL;
- do
- {
- if(p->sk->state == TCP_ESTABLISHED || p->sk->state >= TCP_FIN_WAIT1)
- return p;
- p=p->next;
- }
- while(p!=(struct sk_buff *)&s->receive_queue);
- return NULL;
-}
-
-/*
- * Remove a completed connection and return it. This is used by
- * tcp_accept() to get connections from the queue.
- */
-
-static struct sk_buff *tcp_dequeue_established(struct sock *s)
-{
- struct sk_buff *skb;
- unsigned long flags;
- save_flags(flags);
- cli();
- skb=tcp_find_established(s);
- if(skb!=NULL)
- skb_unlink(skb); /* Take it off the queue */
- restore_flags(flags);
- return skb;
-}
-
-/*
- * This routine closes sockets which have been at least partially
- * opened, but not yet accepted. Currently it is only called by
- * tcp_close, and timeout mirrors the value there.
- */
-
-static void tcp_close_pending (struct sock *sk)
-{
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&sk->receive_queue)) != NULL)
- {
- skb->sk->dead=1;
- tcp_close(skb->sk, 0);
- kfree_skb(skb, FREE_READ);
- }
- return;
-}
-
-/*
- * Enter the time wait state.
- */
-
-static void tcp_time_wait(struct sock *sk)
-{
- tcp_set_state(sk,TCP_TIME_WAIT);
- sk->shutdown = SHUTDOWN_MASK;
- if (!sk->dead)
- sk->state_change(sk);
- reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
-}
-
-/*
- * A socket has timed out on its send queue and wants to do a
- * little retransmitting. Currently this means TCP.
- */
-
-void tcp_do_retransmit(struct sock *sk, int all)
-{
- struct sk_buff * skb;
- struct proto *prot;
- struct device *dev;
- int ct=0;
-
- prot = sk->prot;
- skb = sk->send_head;
-
- while (skb != NULL)
- {
- struct tcphdr *th;
- struct iphdr *iph;
- int size;
-
- dev = skb->dev;
- IS_SKB(skb);
- skb->when = jiffies;
-
- /*
- * In general it's OK just to use the old packet. However we
- * need to use the current ack and window fields. Urg and
- * urg_ptr could possibly stand to be updated as well, but we
- * don't keep the necessary data. That shouldn't be a problem,
- * if the other end is doing the right thing. Since we're
- * changing the packet, we have to issue a new IP identifier.
- */
-
- iph = (struct iphdr *)(skb->data + dev->hard_header_len);
- th = (struct tcphdr *)(((char *)iph) + (iph->ihl << 2));
- size = skb->len - (((unsigned char *) th) - skb->data);
-
- /*
- * Note: We ought to check for window limits here but
- * currently this is done (less efficiently) elsewhere.
- * We do need to check for a route change but can't handle
- * that until we have the new 1.3.x buffers in.
- *
- */
-
- iph->id = htons(ip_id_count++);
- ip_send_check(iph);
-
- /*
- * This is not the right way to handle this. We have to
- * issue an up to date window and ack report with this
- * retransmit to keep the odd buggy tcp that relies on
- * the fact BSD does this happy.
- * We don't however need to recalculate the entire
- * checksum, so someone wanting a small problem to play
- * with might like to implement RFC1141/RFC1624 and speed
- * this up by avoiding a full checksum.
- */
-
- th->ack_seq = ntohl(sk->acked_seq);
- th->window = ntohs(tcp_select_window(sk));
- tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
-
- /*
- * If the interface is (still) up and running, kick it.
- */
-
- if (dev->flags & IFF_UP)
- {
- /*
- * If the packet is still being sent by the device/protocol
- * below then don't retransmit. This is both needed, and good -
- * especially with connected mode AX.25 where it stops resends
- * occurring of an as yet unsent anyway frame!
- * We still add up the counts as the round trip time wants
- * adjusting.
- */
- if (sk && !skb_device_locked(skb))
- {
- /* Remove it from any existing driver queue first! */
- skb_unlink(skb);
- /* Now queue it */
- ip_statistics.IpOutRequests++;
- dev_queue_xmit(skb, dev, sk->priority);
- }
- }
-
- /*
- * Count retransmissions
- */
-
- ct++;
- sk->prot->retransmits ++;
-
- /*
- * Only one retransmit requested.
- */
-
- if (!all)
- break;
-
- /*
- * This should cut it off before we send too many packets.
- */
-
- if (ct >= sk->cong_window)
- break;
- skb = skb->link3;
- }
-}
-
-/*
- * Reset the retransmission timer
- */
-
-static void reset_xmit_timer(struct sock *sk, int why, unsigned long when)
-{
- del_timer(&sk->retransmit_timer);
- sk->ip_xmit_timeout = why;
- if((int)when < 0)
- {
- when=3;
- printk("Error: Negative timer in xmit_timer\n");
- }
- sk->retransmit_timer.expires=when;
- add_timer(&sk->retransmit_timer);
-}
-
-/*
- * This is the normal code called for timeouts. It does the retransmission
- * and then does backoff. tcp_do_retransmit is separated out because
- * tcp_ack needs to send stuff from the retransmit queue without
- * initiating a backoff.
- */
-
-
-void tcp_retransmit_time(struct sock *sk, int all)
-{
- tcp_do_retransmit(sk, all);
-
- /*
- * Increase the timeout each time we retransmit. Note that
- * we do not increase the rtt estimate. rto is initialized
- * from rtt, but increases here. Jacobson (SIGCOMM 88) suggests
- * that doubling rto each time is the least we can get away with.
- * In KA9Q, Karn uses this for the first few times, and then
- * goes to quadratic. netBSD doubles, but only goes up to *64,
- * and clamps at 1 to 64 sec afterwards. Note that 120 sec is
- * defined in the protocol as the maximum possible RTT. I guess
- * we'll have to use something other than TCP to talk to the
- * University of Mars.
- *
- * PAWS allows us longer timeouts and large windows, so once
- * implemented ftp to mars will work nicely. We will have to fix
- * the 120 second clamps though!
- */
-
- sk->retransmits++;
- sk->backoff++;
- sk->rto = min(sk->rto << 1, 120*HZ);
- reset_xmit_timer(sk, TIME_WRITE, sk->rto);
-}
-
-
-/*
- * A timer event has trigger a tcp retransmit timeout. The
- * socket xmit queue is ready and set up to send. Because
- * the ack receive code keeps the queue straight we do
- * nothing clever here.
- */
-
-static void tcp_retransmit(struct sock *sk, int all)
-{
- if (all)
- {
- tcp_retransmit_time(sk, all);
- return;
- }
-
- sk->ssthresh = sk->cong_window >> 1; /* remember window where we lost */
- /* sk->ssthresh in theory can be zero. I guess that's OK */
- sk->cong_count = 0;
-
- sk->cong_window = 1;
-
- /* Do the actual retransmit. */
- tcp_retransmit_time(sk, all);
-}
-
-/*
- * A write timeout has occurred. Process the after effects.
- */
-
-static int tcp_write_timeout(struct sock *sk)
-{
- /*
- * Look for a 'soft' timeout.
- */
- if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
- || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1))
- {
- /*
- * Attempt to recover if arp has changed (unlikely!) or
- * a route has shifted (not supported prior to 1.3).
- */
- arp_destroy (sk->daddr, 0);
- ip_route_check (sk->daddr);
- }
- /*
- * Has it gone just too far ?
- */
- if (sk->retransmits > TCP_RETR2)
- {
- sk->err = ETIMEDOUT;
- sk->error_report(sk);
- del_timer(&sk->retransmit_timer);
- /*
- * Time wait the socket
- */
- if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 || sk->state == TCP_CLOSING )
- {
- tcp_set_state(sk,TCP_TIME_WAIT);
- reset_msl_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
- }
- else
- {
- /*
- * Clean up time.
- */
- tcp_set_state(sk, TCP_CLOSE);
- return 0;
- }
- }
- return 1;
-}
-
-/*
- * The TCP retransmit timer. This lacks a few small details.
- *
- * 1. An initial rtt timeout on the probe0 should cause what we can
- * of the first write queue buffer to be split and sent.
- * 2. On a 'major timeout' as defined by RFC1122 we shouldn't report
- * ETIMEDOUT if we know an additional 'soft' error caused this.
- * tcp_err should save a 'soft error' for us.
- */
-
-static void retransmit_timer(unsigned long data)
-{
- struct sock *sk = (struct sock*)data;
- int why = sk->ip_xmit_timeout;
-
- /*
- * only process if socket is not in use
- */
-
- cli();
- if (sk->inuse || in_bh)
- {
- /* Try again in 1 second */
- sk->retransmit_timer.expires = HZ;
- add_timer(&sk->retransmit_timer);
- sti();
- return;
- }
-
- sk->inuse = 1;
- sti();
-
- /* Always see if we need to send an ack. */
-
- if (sk->ack_backlog && !sk->zapped)
- {
- sk->prot->read_wakeup (sk);
- if (! sk->dead)
- sk->data_ready(sk,0);
- }
-
- /* Now we need to figure out why the socket was on the timer. */
-
- switch (why)
- {
- /* Window probing */
- case TIME_PROBE0:
- tcp_send_probe0(sk);
- tcp_write_timeout(sk);
- break;
- /* Retransmitting */
- case TIME_WRITE:
- /* It could be we got here because we needed to send an ack.
- * So we need to check for that.
- */
- {
- struct sk_buff *skb;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- skb = sk->send_head;
- if (!skb)
- {
- restore_flags(flags);
- }
- else
- {
- /*
- * Kicked by a delayed ack. Reset timer
- * correctly now
- */
- if (jiffies < skb->when + sk->rto)
- {
- reset_xmit_timer (sk, TIME_WRITE, skb->when + sk->rto - jiffies);
- restore_flags(flags);
- break;
- }
- restore_flags(flags);
- /*
- * Retransmission
- */
- sk->prot->retransmit (sk, 0);
- tcp_write_timeout(sk);
- }
- break;
- }
- /* Sending Keepalives */
- case TIME_KEEPOPEN:
- /*
- * this reset_timer() call is a hack, this is not
- * how KEEPOPEN is supposed to work.
- */
- reset_xmit_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
-
- /* Send something to keep the connection open. */
- if (sk->prot->write_wakeup)
- sk->prot->write_wakeup (sk);
- sk->retransmits++;
- tcp_write_timeout(sk);
- break;
- default:
- printk ("rexmit_timer: timer expired - reason unknown\n");
- break;
- }
- release_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. After adjustment
- * header points to the first 8 bytes of the tcp header. We need
- * to find the appropriate port.
- */
-
-void tcp_err(int err, unsigned char *header, unsigned long daddr,
- unsigned long saddr, struct inet_protocol *protocol)
-{
- struct tcphdr *th;
- struct sock *sk;
- struct iphdr *iph=(struct iphdr *)header;
-
- header+=4*iph->ihl;
-
-
- th =(struct tcphdr *)header;
- sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr);
-
- if (sk == NULL)
- return;
-
- if(err<0)
- {
- sk->err = -err;
- sk->error_report(sk);
- return;
- }
-
- if ((err & 0xff00) == (ICMP_SOURCE_QUENCH << 8))
- {
- /*
- * FIXME:
- * For now we will just trigger a linear backoff.
- * The slow start code should cause a real backoff here.
- */
- if (sk->cong_window > 4)
- sk->cong_window--;
- return;
- }
-
-/* sk->err = icmp_err_convert[err & 0xff].errno; -- moved as TCP should hide non fatals internally (and does) */
-
- /*
- * If we've already connected we will keep trying
- * until we time out, or the user gives up.
- */
-
- if (icmp_err_convert[err & 0xff].fatal || sk->state == TCP_SYN_SENT)
- {
- if (sk->state == TCP_SYN_SENT)
- {
- tcp_statistics.TcpAttemptFails++;
- tcp_set_state(sk,TCP_CLOSE);
- sk->error_report(sk); /* Wake people up to see the error (see connect in sock.c) */
- }
- sk->err = icmp_err_convert[err & 0xff].error;
- }
- return;
-}
-
-
-/*
- * Walk down the receive queue counting readable data until we hit the end or we find a gap
- * in the received data queue (ie a frame missing that needs sending to us). Not
- * sorting using two queues as data arrives makes life so much harder.
- */
-
-#ifndef _HURD_
-static
-#endif
-int tcp_readable(struct sock *sk)
-{
- unsigned long counted;
- unsigned long amount;
- struct sk_buff *skb;
- int sum;
- unsigned long flags;
-
- if(sk && sk->debug)
- printk("tcp_readable: %p - ",sk);
-
- save_flags(flags);
- cli();
- if (sk == NULL || (skb = skb_peek(&sk->receive_queue)) == NULL)
- {
- restore_flags(flags);
- if(sk && sk->debug)
- printk("empty\n");
- return(0);
- }
-
- counted = sk->copied_seq; /* Where we are at the moment */
- amount = 0;
-
- /*
- * Do until a push or until we are out of data.
- */
-
- do
- {
- if (before(counted, skb->h.th->seq)) /* Found a hole so stops here */
- break;
- sum = skb->len -(counted - skb->h.th->seq); /* Length - header but start from where we are up to (avoid overlaps) */
- if (skb->h.th->syn)
- sum++;
- if (sum > 0)
- { /* Add it up, move on */
- amount += sum;
- if (skb->h.th->syn)
- amount--;
- counted += sum;
- }
- /*
- * Don't count urg data ... but do it in the right place!
- * Consider: "old_data (ptr is here) URG PUSH data"
- * The old code would stop at the first push because
- * it counted the urg (amount==1) and then does amount--
- * *after* the loop. This means tcp_readable() always
- * returned zero if any URG PUSH was in the queue, even
- * though there was normal data available. If we subtract
- * the urg data right here, we even get it to work for more
- * than one URG PUSH skb without normal data.
- * This means that select() finally works now with urg data
- * in the queue. Note that rlogin was never affected
- * because it doesn't use select(); it uses two processes
- * and a blocking read(). And the queue scan in tcp_read()
- * was correct. Mike <pall@rz.uni-karlsruhe.de>
- */
- if (skb->h.th->urg)
- amount--; /* don't count urg data */
- if (amount && skb->h.th->psh) break;
- skb = skb->next;
- }
- while(skb != (struct sk_buff *)&sk->receive_queue);
-
- restore_flags(flags);
- if(sk->debug)
- printk("got %lu bytes.\n",amount);
- return(amount);
-}
-
-/*
- * LISTEN is a special case for select..
- */
-static int tcp_listen_select(struct sock *sk, int sel_type, select_table *wait)
-{
- if (sel_type == SEL_IN) {
- int retval;
-
- sk->inuse = 1;
- retval = (tcp_find_established(sk) != NULL);
- release_sock(sk);
- if (!retval)
- select_wait(&master_select_wakeup,wait);
- return retval;
- }
- return 0;
-}
-
-
-/*
- * Wait for a TCP event.
- *
- * Note that we don't need to set "sk->inuse", as the upper select layers
- * take care of normal races (between the test and the event) and we don't
- * go look at any of the socket buffers directly.
- */
-static int tcp_select(struct sock *sk, int sel_type, select_table *wait)
-{
- if (sk->state == TCP_LISTEN)
- return tcp_listen_select(sk, sel_type, wait);
-
- switch(sel_type) {
- case SEL_IN:
- if (sk->err)
- return 1;
- if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
- break;
-
- if (sk->shutdown & RCV_SHUTDOWN)
- return 1;
-
- if (sk->acked_seq == sk->copied_seq)
- break;
-
- if (sk->urg_seq != sk->copied_seq ||
- sk->acked_seq != sk->copied_seq+1 ||
- sk->urginline || !sk->urg_data)
- return 1;
- break;
-
- case SEL_OUT:
- if (sk->shutdown & SEND_SHUTDOWN)
- return 0;
- if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
- break;
- /*
- * This is now right thanks to a small fix
- * by Matt Dillon.
- */
-
- if (sk->prot->wspace(sk) < sk->mtu+128+sk->prot->max_header)
- break;
- return 1;
-
- case SEL_EX:
- if (sk->err || sk->urg_data)
- return 1;
- break;
- }
- select_wait(sk->sleep, wait);
- return 0;
-}
-
-#ifndef _HURD_
-int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
-{
- int err;
- switch(cmd)
- {
-
- case TIOCINQ:
-#ifdef FIXME /* FIXME: */
- case FIONREAD:
-#endif
- {
- unsigned long amount;
-
- if (sk->state == TCP_LISTEN)
- return(-EINVAL);
-
- sk->inuse = 1;
- amount = tcp_readable(sk);
- release_sock(sk);
- err=verify_area(VERIFY_WRITE,(void *)arg,
- sizeof(unsigned long));
- if(err)
- return err;
- put_fs_long(amount,(unsigned long *)arg);
- return(0);
- }
- case SIOCATMARK:
- {
- int answ = sk->urg_data && sk->urg_seq == sk->copied_seq;
-
- err = verify_area(VERIFY_WRITE,(void *) arg,
- sizeof(unsigned long));
- if (err)
- return err;
- put_fs_long(answ,(int *) arg);
- return(0);
- }
- case TIOCOUTQ:
- {
- unsigned long amount;
-
- if (sk->state == TCP_LISTEN) return(-EINVAL);
- amount = sk->prot->wspace(sk);
- err=verify_area(VERIFY_WRITE,(void *)arg,
- sizeof(unsigned long));
- if(err)
- return err;
- put_fs_long(amount,(unsigned long *)arg);
- return(0);
- }
- default:
- return(-EINVAL);
- }
-}
-#endif
-
-
-
-void tcp_send_check(struct tcphdr *th, unsigned long saddr,
- unsigned long daddr, int len, struct sock *sk)
-{
- th->check = 0;
- th->check = tcp_check(th, len, saddr, daddr);
- return;
-}
-
-/*
- * This is the main buffer sending routine. We queue the buffer
- * having checked it is sane seeming.
- */
-
-static void tcp_send_skb(struct sock *sk, struct sk_buff *skb)
-{
- int size;
- struct tcphdr * th = skb->h.th;
-
- /*
- * length of packet (not counting length of pre-tcp headers)
- */
-
- size = skb->len - ((unsigned char *) th - skb->data);
-
- /*
- * Sanity check it..
- */
-
- if (size < sizeof(struct tcphdr) || size > skb->len)
- {
- printk("tcp_send_skb: bad skb (skb = %p, data = %p, th = %p, len = %lu)\n",
- skb, skb->data, th, skb->len);
- kfree_skb(skb, FREE_WRITE);
- return;
- }
-
- /*
- * If we have queued a header size packet.. (these crash a few
- * tcp stacks if ack is not set)
- */
-
- if (size == sizeof(struct tcphdr))
- {
- /* If it's got a syn or fin it's notionally included in the size..*/
- if(!th->syn && !th->fin)
- {
- printk("tcp_send_skb: attempt to queue a bogon.\n");
- kfree_skb(skb,FREE_WRITE);
- return;
- }
- }
-
- /*
- * Actual processing.
- */
-
- tcp_statistics.TcpOutSegs++;
- skb->h.seq = ntohl(th->seq) + size - 4*th->doff;
-
- /*
- * We must queue if
- *
- * a) The right edge of this frame exceeds the window
- * b) We are retransmitting (Nagle's rule)
- * c) We have too many packets 'in flight'
- */
-
- if (after(skb->h.seq, sk->window_seq) ||
- (sk->retransmits && sk->ip_xmit_timeout == TIME_WRITE) ||
- sk->packets_out >= sk->cong_window)
- {
- /* checksum will be supplied by tcp_write_xmit. So
- * we shouldn't need to set it at all. I'm being paranoid */
- th->check = 0;
- if (skb->next != NULL)
- {
- printk("tcp_send_partial: next != NULL\n");
- skb_unlink(skb);
- }
- skb_queue_tail(&sk->write_queue, skb);
-
- /*
- * If we don't fit we have to start the zero window
- * probes. This is broken - we really need to do a partial
- * send _first_ (This is what causes the Cisco and PC/TCP
- * grief).
- */
-
- if (before(sk->window_seq, sk->write_queue.next->h.seq) &&
- sk->send_head == NULL && sk->ack_backlog == 0)
- reset_xmit_timer(sk, TIME_PROBE0, sk->rto);
- }
- else
- {
- /*
- * This is going straight out
- */
-
- th->ack_seq = ntohl(sk->acked_seq);
- th->window = ntohs(tcp_select_window(sk));
-
- tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
-
- sk->sent_seq = sk->write_seq;
-
- /*
- * This is mad. The tcp retransmit queue is put together
- * by the ip layer. This causes half the problems with
- * unroutable FIN's and other things.
- */
-
- sk->prot->queue_xmit(sk, skb->dev, skb, 0);
-
- /*
- * Set for next retransmit based on expected ACK time.
- * FIXME: We set this every time which means our
- * retransmits are really about a window behind.
- */
-
- reset_xmit_timer(sk, TIME_WRITE, sk->rto);
- }
-}
-
-/*
- * Locking problems lead us to a messy situation where we can have
- * multiple partially complete buffers queued up. This is really bad
- * as we don't want to be sending partial buffers. Fix this with
- * a semaphore or similar to lock tcp_write per socket.
- *
- * These routines are pretty self descriptive.
- */
-
-struct sk_buff * tcp_dequeue_partial(struct sock * sk)
-{
- struct sk_buff * skb;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- skb = sk->partial;
- if (skb) {
- sk->partial = NULL;
- del_timer(&sk->partial_timer);
- }
- restore_flags(flags);
- return skb;
-}
-
-/*
- * Empty the partial queue
- */
-
-static void tcp_send_partial(struct sock *sk)
-{
- struct sk_buff *skb;
-
- if (sk == NULL)
- return;
- while ((skb = tcp_dequeue_partial(sk)) != NULL)
- tcp_send_skb(sk, skb);
-}
-
-/*
- * Queue a partial frame
- */
-
-void tcp_enqueue_partial(struct sk_buff * skb, struct sock * sk)
-{
- struct sk_buff * tmp;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- tmp = sk->partial;
- if (tmp)
- del_timer(&sk->partial_timer);
- sk->partial = skb;
- init_timer(&sk->partial_timer);
- /*
- * Wait up to 1 second for the buffer to fill.
- */
- sk->partial_timer.expires = HZ;
- sk->partial_timer.function = (void (*)(unsigned long)) tcp_send_partial;
- sk->partial_timer.data = (unsigned long) sk;
- add_timer(&sk->partial_timer);
- restore_flags(flags);
- if (tmp)
- tcp_send_skb(sk, tmp);
-}
-
-
-/*
- * This routine sends an ack and also updates the window.
- */
-
-static void tcp_send_ack(unsigned long sequence, unsigned long ack,
- struct sock *sk,
- struct tcphdr *th, unsigned long daddr)
-{
- struct sk_buff *buff;
- struct tcphdr *t1;
- struct device *dev = NULL;
- int tmp;
-
- if(sk->zapped)
- return; /* We have been reset, we may not send again */
-
- /*
- * We need to grab some memory, and put together an ack,
- * and then put it into the queue to be sent.
- */
-
- buff = sk->prot->wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC);
- if (buff == NULL)
- {
- /*
- * Force it to send an ack. We don't have to do this
- * (ACK is unreliable) but it's much better use of
- * bandwidth on slow links to send a spare ack than
- * resend packets.
- */
-
- sk->ack_backlog++;
- if (sk->ip_xmit_timeout != TIME_WRITE && tcp_connected(sk->state))
- {
- reset_xmit_timer(sk, TIME_WRITE, HZ);
- }
- return;
- }
-
- /*
- * Assemble a suitable TCP frame
- */
-
- buff->len = sizeof(struct tcphdr);
- buff->sk = sk;
- buff->localroute = sk->localroute;
- t1 =(struct tcphdr *) buff->data;
-
- /*
- * Put in the IP header and routing stuff.
- */
-
- tmp = sk->prot->build_header(buff, sk->saddr, daddr, &dev,
- IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
- if (tmp < 0)
- {
- buff->free = 1;
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
- return;
- }
- buff->len += tmp;
- t1 =(struct tcphdr *)((char *)t1 +tmp);
-
- memcpy(t1, th, sizeof(*t1));
-
- /*
- * Swap the send and the receive.
- */
-
- t1->dest = th->source;
- t1->source = th->dest;
- t1->seq = ntohl(sequence);
- t1->ack = 1;
- sk->window = tcp_select_window(sk);
- t1->window = ntohs(sk->window);
- t1->res1 = 0;
- t1->res2 = 0;
- t1->rst = 0;
- t1->urg = 0;
- t1->syn = 0;
- t1->psh = 0;
- t1->fin = 0;
-
- /*
- * If we have nothing queued for transmit and the transmit timer
- * is on we are just doing an ACK timeout and need to switch
- * to a keepalive.
- */
-
- if (ack == sk->acked_seq)
- {
- sk->ack_backlog = 0;
- sk->bytes_rcv = 0;
- sk->ack_timed = 0;
- if (sk->send_head == NULL && skb_peek(&sk->write_queue) == NULL
- && sk->ip_xmit_timeout == TIME_WRITE)
- {
- if(sk->keepopen) {
- reset_xmit_timer(sk,TIME_KEEPOPEN,TCP_TIMEOUT_LEN);
- } else {
- delete_timer(sk);
- }
- }
- }
-
- /*
- * Fill in the packet and send it
- */
-
- t1->ack_seq = ntohl(ack);
- t1->doff = sizeof(*t1)/4;
- tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), sk);
- if (sk->debug)
- printk("\rtcp_ack: seq %lx ack %lx\n", sequence, ack);
- tcp_statistics.TcpOutSegs++;
- sk->prot->queue_xmit(sk, dev, buff, 1);
-}
-
-
-/*
- * This routine builds a generic TCP header.
- */
-
-extern __inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
-{
-
- memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
- th->seq = htonl(sk->write_seq);
- th->psh =(push == 0) ? 1 : 0;
- th->doff = sizeof(*th)/4;
- th->ack = 1;
- th->fin = 0;
- sk->ack_backlog = 0;
- sk->bytes_rcv = 0;
- sk->ack_timed = 0;
- th->ack_seq = htonl(sk->acked_seq);
- sk->window = tcp_select_window(sk);
- th->window = htons(sk->window);
-
- return(sizeof(*th));
-}
-
-/*
- * This routine copies from a user buffer into a socket,
- * and starts the transmit system.
- */
-
-static int tcp_write(struct sock *sk, unsigned char *from,
- int len, int nonblock, unsigned flags)
-{
- int copied = 0;
- int copy;
- int tmp;
- struct sk_buff *skb;
- struct sk_buff *send_tmp;
- unsigned char *buff;
- struct proto *prot;
- struct device *dev = NULL;
-
- sk->inuse=1;
- prot = sk->prot;
- while(len > 0)
- {
- if (sk->err)
- { /* Stop on an error */
- release_sock(sk);
- if (copied)
- return(copied);
- tmp = -sk->err;
- sk->err = 0;
- return(tmp);
- }
-
- /*
- * First thing we do is make sure that we are established.
- */
-
- if (sk->shutdown & SEND_SHUTDOWN)
- {
- release_sock(sk);
- sk->err = EPIPE;
- if (copied)
- return(copied);
- sk->err = 0;
- return(-EPIPE);
- }
-
- /*
- * Wait for a connection to finish.
- */
-
- while(sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
- {
- if (sk->err)
- {
- release_sock(sk);
- if (copied)
- return(copied);
- tmp = -sk->err;
- sk->err = 0;
- return(tmp);
- }
-
- if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV)
- {
- release_sock(sk);
- if (copied)
- return(copied);
-
- if (sk->err)
- {
- tmp = -sk->err;
- sk->err = 0;
- return(tmp);
- }
-
- if (sk->keepopen)
- {
- send_sig(SIGPIPE, current, 0);
- }
- return(-EPIPE);
- }
-
- if (nonblock || copied)
- {
- release_sock(sk);
- if (copied)
- return(copied);
- return(-EAGAIN);
- }
-
- release_sock(sk);
- cli();
-
- if (sk->state != TCP_ESTABLISHED &&
- sk->state != TCP_CLOSE_WAIT && sk->err == 0)
- {
- interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked)
- {
- sti();
- if (copied)
- return(copied);
- return(-ERESTARTSYS);
- }
- }
- sk->inuse = 1;
- sti();
- }
-
- /*
- * The following code can result in copy <= if sk->mss is ever
- * decreased. It shouldn't be. sk->mss is min(sk->mtu, sk->max_window).
- * sk->mtu is constant once SYN processing is finished. I.e. we
- * had better not get here until we've seen his SYN and at least one
- * valid ack. (The SYN sets sk->mtu and the ack sets sk->max_window.)
- * But ESTABLISHED should guarantee that. sk->max_window is by definition
- * non-decreasing. Note that any ioctl to set user_mss must be done
- * before the exchange of SYN's. If the initial ack from the other
- * end has a window of 0, max_window and thus mss will both be 0.
- */
-
- /*
- * Now we need to check if we have a half built packet.
- */
-
- if ((skb = tcp_dequeue_partial(sk)) != NULL)
- {
- int hdrlen;
-
- /* IP header + TCP header */
- hdrlen = ((unsigned long)skb->h.th - (unsigned long)skb->data)
- + sizeof(struct tcphdr);
-
- /* Add more stuff to the end of skb->len */
- if (!(flags & MSG_OOB))
- {
- copy = min(sk->mss - (skb->len - hdrlen), len);
- /* FIXME: this is really a bug. */
- if (copy <= 0)
- {
- printk("TCP: **bug**: \"copy\" <= 0!!\n");
- copy = 0;
- }
-
- memcpy_fromfs(skb->data + skb->len, from, copy);
- skb->len += copy;
- from += copy;
- copied += copy;
- len -= copy;
- sk->write_seq += copy;
- }
- if ((skb->len - hdrlen) >= sk->mss ||
- (flags & MSG_OOB) || !sk->packets_out)
- tcp_send_skb(sk, skb);
- else
- tcp_enqueue_partial(skb, sk);
- continue;
- }
-
- /*
- * We also need to worry about the window.
- * If window < 1/2 the maximum window we've seen from this
- * host, don't use it. This is sender side
- * silly window prevention, as specified in RFC1122.
- * (Note that this is different than earlier versions of
- * SWS prevention, e.g. RFC813.). What we actually do is
- * use the whole MSS. Since the results in the right
- * edge of the packet being outside the window, it will
- * be queued for later rather than sent.
- */
-
- copy = sk->window_seq - sk->write_seq;
- if (copy <= 0 || copy < (sk->max_window >> 1) || copy > sk->mss)
- copy = sk->mss;
- if (copy > len)
- copy = len;
-
- /*
- * We should really check the window here also.
- */
-
- send_tmp = NULL;
- if (copy < sk->mss && !(flags & MSG_OOB))
- {
- /*
- * We will release the socket in case we sleep here.
- */
- release_sock(sk);
- /*
- * NB: following must be mtu, because mss can be increased.
- * mss is always <= mtu
- */
- skb = prot->wmalloc(sk, sk->mtu + 128 + prot->max_header, 0, GFP_KERNEL);
- sk->inuse = 1;
- send_tmp = skb;
- }
- else
- {
- /*
- * We will release the socket in case we sleep here.
- */
- release_sock(sk);
- skb = prot->wmalloc(sk, copy + prot->max_header , 0, GFP_KERNEL);
- sk->inuse = 1;
- }
-
- /*
- * If we didn't get any memory, we need to sleep.
- */
-
- if (skb == NULL)
- {
- sk->socket->flags |= SO_NOSPACE;
- if (nonblock)
- {
- release_sock(sk);
- if (copied)
- return(copied);
- return(-EAGAIN);
- }
-
- /*
- * FIXME: here is another race condition.
- */
-
- tmp = sk->wmem_alloc;
- release_sock(sk);
- cli();
- /*
- * Again we will try to avoid it.
- */
- if (tmp <= sk->wmem_alloc &&
- (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)
- && sk->err == 0)
- {
- sk->socket->flags &= ~SO_NOSPACE;
- interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked)
- {
- sti();
- if (copied)
- return(copied);
- return(-ERESTARTSYS);
- }
- }
- sk->inuse = 1;
- sti();
- continue;
- }
-
- skb->len = 0;
- skb->sk = sk;
- skb->free = 0;
- skb->localroute = sk->localroute|(flags&MSG_DONTROUTE);
-
- buff = skb->data;
-
- /*
- * FIXME: we need to optimize this.
- * Perhaps some hints here would be good.
- */
-
- tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
- if (tmp < 0 )
- {
- prot->wfree(sk, skb->mem_addr, skb->mem_len);
- release_sock(sk);
- if (copied)
- return(copied);
- return(tmp);
- }
- skb->len += tmp;
- skb->dev = dev;
- buff += tmp;
- skb->h.th =(struct tcphdr *) buff;
- tmp = tcp_build_header((struct tcphdr *)buff, sk, len-copy);
- if (tmp < 0)
- {
- prot->wfree(sk, skb->mem_addr, skb->mem_len);
- release_sock(sk);
- if (copied)
- return(copied);
- return(tmp);
- }
-
- if (flags & MSG_OOB)
- {
- ((struct tcphdr *)buff)->urg = 1;
- ((struct tcphdr *)buff)->urg_ptr = ntohs(copy);
- }
- skb->len += tmp;
- memcpy_fromfs(buff+tmp, from, copy);
-
- from += copy;
- copied += copy;
- len -= copy;
- skb->len += copy;
- skb->free = 0;
- sk->write_seq += copy;
-
- if (send_tmp != NULL && sk->packets_out)
- {
- tcp_enqueue_partial(send_tmp, sk);
- continue;
- }
- tcp_send_skb(sk, skb);
- }
- sk->err = 0;
-
-/*
- * Nagle's rule. Turn Nagle off with TCP_NODELAY for highly
- * interactive fast network servers. It's meant to be on and
- * it really improves the throughput though not the echo time
- * on my slow slip link - Alan
- */
-
-/*
- * Avoid possible race on send_tmp - c/o Johannes Stille
- */
-
- if(sk->partial && ((!sk->packets_out)
- /* If not nagling we can send on the before case too.. */
- || (sk->nonagle && before(sk->write_seq , sk->window_seq))
- ))
- tcp_send_partial(sk);
-
- release_sock(sk);
- return(copied);
-}
-
-/*
- * This is just a wrapper.
- */
-
-static int tcp_sendto(struct sock *sk, unsigned char *from,
- int len, int nonblock, unsigned flags,
- struct sockaddr_in *addr, int addr_len)
-{
- if (flags & ~(MSG_OOB|MSG_DONTROUTE))
- return -EINVAL;
- if (sk->state == TCP_CLOSE)
- return -ENOTCONN;
- if (addr_len < sizeof(*addr))
- return -EINVAL;
- if (addr->sin_family && addr->sin_family != AF_INET)
- return -EINVAL;
- if (addr->sin_port != sk->dummy_th.dest)
- return -EISCONN;
- if (addr->sin_addr.s_addr != sk->daddr)
- return -EISCONN;
- return tcp_write(sk, from, len, nonblock, flags);
-}
-
-
-/*
- * Send an ack if one is backlogged at this point. Ought to merge
- * this with tcp_send_ack().
- */
-
-static void tcp_read_wakeup(struct sock *sk)
-{
- int tmp;
- struct device *dev = NULL;
- struct tcphdr *t1;
- struct sk_buff *buff;
-
- if (!sk->ack_backlog)
- return;
-
- /*
- * FIXME: we need to put code here to prevent this routine from
- * being called. Being called once in a while is ok, so only check
- * if this is the second time in a row.
- */
-
- /*
- * We need to grab some memory, and put together an ack,
- * and then put it into the queue to be sent.
- */
-
- buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
- if (buff == NULL)
- {
- /* Try again real soon. */
- reset_xmit_timer(sk, TIME_WRITE, HZ);
- return;
- }
-
- buff->len = sizeof(struct tcphdr);
- buff->sk = sk;
- buff->localroute = sk->localroute;
-
- /*
- * Put in the IP header and routing stuff.
- */
-
- tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
- if (tmp < 0)
- {
- buff->free = 1;
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
- return;
- }
-
- buff->len += tmp;
- t1 =(struct tcphdr *)(buff->data +tmp);
-
- memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
- t1->seq = htonl(sk->sent_seq);
- t1->ack = 1;
- t1->res1 = 0;
- t1->res2 = 0;
- t1->rst = 0;
- t1->urg = 0;
- t1->syn = 0;
- t1->psh = 0;
- sk->ack_backlog = 0;
- sk->bytes_rcv = 0;
- sk->window = tcp_select_window(sk);
- t1->window = ntohs(sk->window);
- t1->ack_seq = ntohl(sk->acked_seq);
- t1->doff = sizeof(*t1)/4;
- tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
- sk->prot->queue_xmit(sk, dev, buff, 1);
- tcp_statistics.TcpOutSegs++;
-}
-
-
-/*
- * FIXME:
- * This routine frees used buffers.
- * It should consider sending an ACK to let the
- * other end know we now have a bigger window.
- */
-
-static void cleanup_rbuf(struct sock *sk)
-{
- unsigned long flags;
- unsigned long left;
- struct sk_buff *skb;
- unsigned long rspace;
-
- if(sk->debug)
- printk("cleaning rbuf for sk=%p\n", sk);
-
- save_flags(flags);
- cli();
-
- left = sk->prot->rspace(sk);
-
- /*
- * We have to loop through all the buffer headers,
- * and try to free up all the space we can.
- */
-
- while((skb=skb_peek(&sk->receive_queue)) != NULL)
- {
- if (!skb->used || skb->users)
- break;
- skb_unlink(skb);
- skb->sk = sk;
- kfree_skb(skb, FREE_READ);
- }
-
- restore_flags(flags);
-
- /*
- * FIXME:
- * At this point we should send an ack if the difference
- * in the window, and the amount of space is bigger than
- * TCP_WINDOW_DIFF.
- */
-
- if(sk->debug)
- printk("sk->rspace = %lu, was %lu\n", sk->prot->rspace(sk),
- left);
- if ((rspace=sk->prot->rspace(sk)) != left)
- {
- /*
- * This area has caused the most trouble. The current strategy
- * is to simply do nothing if the other end has room to send at
- * least 3 full packets, because the ack from those will auto-
- * matically update the window. If the other end doesn't think
- * we have much space left, but we have room for at least 1 more
- * complete packet than it thinks we do, we will send an ack
- * immediately. Otherwise we will wait up to .5 seconds in case
- * the user reads some more.
- */
- sk->ack_backlog++;
- /*
- * It's unclear whether to use sk->mtu or sk->mss here. They differ only
- * if the other end is offering a window smaller than the agreed on MSS
- * (called sk->mtu here). In theory there's no connection between send
- * and receive, and so no reason to think that they're going to send
- * small packets. For the moment I'm using the hack of reducing the mss
- * only on the send side, so I'm putting mtu here.
- */
-
- if (rspace > (sk->window - sk->bytes_rcv + sk->mtu))
- {
- /* Send an ack right now. */
- tcp_read_wakeup(sk);
- }
- else
- {
- /* Force it to send an ack soon. */
- int was_active = del_timer(&sk->retransmit_timer);
- if (!was_active || TCP_ACK_TIME < sk->timer.expires)
- {
- reset_xmit_timer(sk, TIME_WRITE, TCP_ACK_TIME);
- }
- else
- add_timer(&sk->retransmit_timer);
- }
- }
-}
-
-
-/*
- * Handle reading urgent data. BSD has very simple semantics for
- * this, no blocking and very strange errors 8)
- */
-
-static int tcp_read_urg(struct sock * sk, int nonblock,
- unsigned char *to, int len, unsigned flags)
-{
- /*
- * No URG data to read
- */
- if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ)
- return -EINVAL; /* Yes this is right ! */
-
- if (sk->err)
- {
- int tmp = -sk->err;
- sk->err = 0;
- return tmp;
- }
-
- if (sk->state == TCP_CLOSE || sk->done)
- {
- if (!sk->done) {
- sk->done = 1;
- return 0;
- }
- return -ENOTCONN;
- }
-
- if (sk->shutdown & RCV_SHUTDOWN)
- {
- sk->done = 1;
- return 0;
- }
- sk->inuse = 1;
- if (sk->urg_data & URG_VALID)
- {
- char c = sk->urg_data;
- if (!(flags & MSG_PEEK))
- sk->urg_data = URG_READ;
- put_fs_byte(c, to);
- release_sock(sk);
- return 1;
- }
- release_sock(sk);
-
- /*
- * Fixed the recv(..., MSG_OOB) behaviour. BSD docs and
- * the available implementations agree in this case:
- * this call should never block, independent of the
- * blocking state of the socket.
- * Mike <pall@rz.uni-karlsruhe.de>
- */
- return -EAGAIN;
-}
-
-
-/*
- * This routine copies from a sock struct into the user buffer.
- */
-
-static int tcp_read(struct sock *sk, unsigned char *to,
- int len, int nonblock, unsigned flags)
-{
-#ifndef _HURD_
- struct wait_queue wait = { current, NULL };
-#endif
- int copied = 0;
- unsigned long peek_seq;
- volatile unsigned long *seq; /* So gcc doesn't overoptimise */
- unsigned long used;
-
- /*
- * This error should be checked.
- */
-
- if (sk->state == TCP_LISTEN)
- return -ENOTCONN;
-
- /*
- * Urgent data needs to be handled specially.
- */
-
- if (flags & MSG_OOB)
- return tcp_read_urg(sk, nonblock, to, len, flags);
-
- /*
- * Copying sequence to update. This is volatile to handle
- * the multi-reader case neatly (memcpy_to/fromfs might be
- * inline and thus not flush cached variables otherwise).
- */
-
- peek_seq = sk->copied_seq;
- seq = &sk->copied_seq;
- if (flags & MSG_PEEK)
- seq = &peek_seq;
-
-#ifndef _HURD_
- add_wait_queue(sk->sleep, &wait);
-#endif
- sk->inuse = 1;
- while (len > 0)
- {
- struct sk_buff * skb;
- unsigned long offset;
-
- /*
- * Are we at urgent data? Stop if we have read anything.
- */
-
- if (copied && sk->urg_data && sk->urg_seq == *seq)
- break;
-
- /*
- * Next get a buffer.
- */
-
-#ifndef _HURD_
- current->state = TASK_INTERRUPTIBLE;
-#endif
-
- skb = skb_peek(&sk->receive_queue);
- do
- {
- if (!skb)
- break;
- if (before(*seq, skb->h.th->seq))
- break;
- offset = *seq - skb->h.th->seq;
- if (skb->h.th->syn)
- offset--;
- if (offset < skb->len)
- goto found_ok_skb;
- if (skb->h.th->fin)
- goto found_fin_ok;
- if (!(flags & MSG_PEEK))
- skb->used = 1;
- skb = skb->next;
- }
- while (skb != (struct sk_buff *)&sk->receive_queue);
-
- if (copied)
- break;
-
- if (sk->err)
- {
- copied = -sk->err;
- sk->err = 0;
- break;
- }
-
- if (sk->state == TCP_CLOSE)
- {
- if (!sk->done)
- {
- sk->done = 1;
- break;
- }
- copied = -ENOTCONN;
- break;
- }
-
- if (sk->shutdown & RCV_SHUTDOWN)
- {
- sk->done = 1;
- break;
- }
-
- if (nonblock)
- {
- copied = -EAGAIN;
- break;
- }
-
- cleanup_rbuf(sk);
- release_sock(sk);
- sk->socket->flags |= SO_WAITDATA;
-#ifdef _HURD_
- interruptible_sleep_on (sk->sleep);
-#else
- schedule();
-#endif
- sk->socket->flags &= ~SO_WAITDATA;
- sk->inuse = 1;
-
- if (current->signal & ~current->blocked)
- {
- copied = -ERESTARTSYS;
- break;
- }
- continue;
-
- found_ok_skb:
- /*
- * Lock the buffer. We can be fairly relaxed as
- * an interrupt will never steal a buffer we are
- * using unless I've missed something serious in
- * tcp_data.
- */
-
- skb->users++;
-
- /*
- * Ok so how much can we use ?
- */
-
- used = skb->len - offset;
- if (len < used)
- used = len;
- /*
- * Do we have urgent data here?
- */
-
- if (sk->urg_data)
- {
- unsigned long urg_offset = sk->urg_seq - *seq;
- if (urg_offset < used)
- {
- if (!urg_offset)
- {
- if (!sk->urginline)
- {
- ++*seq;
- offset++;
- used--;
- }
- }
- else
- used = urg_offset;
- }
- }
-
- /*
- * Copy it - We _MUST_ update *seq first so that we
- * don't ever double read when we have dual readers
- */
-
- *seq += used;
-
- /*
- * This memcpy_tofs can sleep. If it sleeps and we
- * do a second read it relies on the skb->users to avoid
- * a crash when cleanup_rbuf() gets called.
- */
-
- memcpy_tofs(to,((unsigned char *)skb->h.th) +
- skb->h.th->doff*4 + offset, used);
- copied += used;
- len -= used;
- to += used;
-
- /*
- * We now will not sleep again until we are finished
- * with skb. Sorry if you are doing the SMP port
- * but you'll just have to fix it neatly ;)
- */
-
- skb->users --;
-
- if (after(sk->copied_seq,sk->urg_seq))
- sk->urg_data = 0;
- if (used + offset < skb->len)
- continue;
-
- /*
- * Process the FIN.
- */
-
- if (skb->h.th->fin)
- goto found_fin_ok;
- if (flags & MSG_PEEK)
- continue;
- skb->used = 1;
- continue;
-
- found_fin_ok:
- ++*seq;
- if (flags & MSG_PEEK)
- break;
-
- /*
- * All is done
- */
-
- skb->used = 1;
- sk->shutdown |= RCV_SHUTDOWN;
- break;
-
- }
-#ifndef _HURD_
- remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
-#endif
-
- /* Clean up data we have read: This will do ACK frames */
- cleanup_rbuf(sk);
- release_sock(sk);
- return copied;
-}
-
-/*
- * State processing on a close. This implements the state shift for
- * sending our FIN frame. Note that we only send a FIN for some
- * states. A shutdown() may have already sent the FIN, or we may be
- * closed.
- */
-
-static int tcp_close_state(struct sock *sk, int dead)
-{
- int ns=TCP_CLOSE;
- int send_fin=0;
- switch(sk->state)
- {
- case TCP_SYN_SENT: /* No SYN back, no FIN needed */
- break;
- case TCP_SYN_RECV:
- case TCP_ESTABLISHED: /* Closedown begin */
- ns=TCP_FIN_WAIT1;
- send_fin=1;
- break;
- case TCP_FIN_WAIT1: /* Already closing, or FIN sent: no change */
- case TCP_FIN_WAIT2:
- case TCP_CLOSING:
- ns=sk->state;
- break;
- case TCP_CLOSE:
- case TCP_LISTEN:
- break;
- case TCP_CLOSE_WAIT: /* They have FIN'd us. We send our FIN and
- wait only for the ACK */
- ns=TCP_LAST_ACK;
- send_fin=1;
- }
-
- tcp_set_state(sk,ns);
-
- /*
- * This is a (useful) BSD violating of the RFC. There is a
- * problem with TCP as specified in that the other end could
- * keep a socket open forever with no application left this end.
- * We use a 3 minute timeout (about the same as BSD) then kill
- * our end. If they send after that then tough - BUT: long enough
- * that we won't make the old 4*rto = almost no time - whoops
- * reset mistake.
- */
- if(dead && ns==TCP_FIN_WAIT2)
- {
- int timer_active=del_timer(&sk->timer);
- if(timer_active)
- add_timer(&sk->timer);
- else
- reset_msl_timer(sk, TIME_CLOSE, TCP_FIN_TIMEOUT);
- }
-
- return send_fin;
-}
-
-/*
- * Send a fin.
- */
-
-static void tcp_send_fin(struct sock *sk)
-{
- struct proto *prot =(struct proto *)sk->prot;
- struct tcphdr *th =(struct tcphdr *)&sk->dummy_th;
- struct tcphdr *t1;
- struct sk_buff *buff;
- struct device *dev=NULL;
- int tmp;
-
- release_sock(sk); /* in case the malloc sleeps. */
-
- buff = prot->wmalloc(sk, MAX_RESET_SIZE,1 , GFP_KERNEL);
- sk->inuse = 1;
-
- if (buff == NULL)
- {
- /* This is a disaster if it occurs */
- printk("tcp_send_fin: Impossible malloc failure");
- return;
- }
-
- /*
- * Administrivia
- */
-
- buff->sk = sk;
- buff->len = sizeof(*t1);
- buff->localroute = sk->localroute;
- t1 =(struct tcphdr *) buff->data;
-
- /*
- * Put in the IP header and routing stuff.
- */
-
- tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, sk->opt,
- sizeof(struct tcphdr),sk->ip_tos,sk->ip_ttl);
- if (tmp < 0)
- {
- int t;
- /*
- * Finish anyway, treat this as a send that got lost.
- * (Not good).
- */
-
- buff->free = 1;
- prot->wfree(sk,buff->mem_addr, buff->mem_len);
- sk->write_seq++;
- t=del_timer(&sk->timer);
- if(t)
- add_timer(&sk->timer);
- else
- reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
- return;
- }
-
- /*
- * We ought to check if the end of the queue is a buffer and
- * if so simply add the fin to that buffer, not send it ahead.
- */
-
- t1 =(struct tcphdr *)((char *)t1 +tmp);
- buff->len += tmp;
- buff->dev = dev;
- memcpy(t1, th, sizeof(*t1));
- t1->seq = ntohl(sk->write_seq);
- sk->write_seq++;
- buff->h.seq = sk->write_seq;
- t1->ack = 1;
- t1->ack_seq = ntohl(sk->acked_seq);
- t1->window = ntohs(sk->window=tcp_select_window(sk));
- t1->fin = 1;
- t1->rst = 0;
- t1->doff = sizeof(*t1)/4;
- tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
-
- /*
- * If there is data in the write queue, the fin must be appended to
- * the write queue.
- */
-
- if (skb_peek(&sk->write_queue) != NULL)
- {
- buff->free = 0;
- if (buff->next != NULL)
- {
- printk("tcp_send_fin: next != NULL\n");
- skb_unlink(buff);
- }
- skb_queue_tail(&sk->write_queue, buff);
- }
- else
- {
- sk->sent_seq = sk->write_seq;
- sk->prot->queue_xmit(sk, dev, buff, 0);
- reset_xmit_timer(sk, TIME_WRITE, sk->rto);
- }
-}
-
-/*
- * Shutdown the sending side of a connection. Much like close except
- * that we don't receive shut down or set sk->dead=1.
- */
-
-void tcp_shutdown(struct sock *sk, int how)
-{
- /*
- * We need to grab some memory, and put together a FIN,
- * and then put it into the queue to be sent.
- * Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
- */
-
- if (!(how & SEND_SHUTDOWN))
- return;
-
- /*
- * If we've already sent a FIN, or it's a closed state
- */
-
- if (sk->state == TCP_FIN_WAIT1 ||
- sk->state == TCP_FIN_WAIT2 ||
- sk->state == TCP_CLOSING ||
- sk->state == TCP_LAST_ACK ||
- sk->state == TCP_TIME_WAIT ||
- sk->state == TCP_CLOSE ||
- sk->state == TCP_LISTEN
- )
- {
- return;
- }
- sk->inuse = 1;
-
- /*
- * flag that the sender has shutdown
- */
-
- sk->shutdown |= SEND_SHUTDOWN;
-
- /*
- * Clear out any half completed packets.
- */
-
- if (sk->partial)
- tcp_send_partial(sk);
-
- /*
- * FIN if needed
- */
-
- if(tcp_close_state(sk,0))
- tcp_send_fin(sk);
-
- release_sock(sk);
-}
-
-
-static int
-tcp_recvfrom(struct sock *sk, unsigned char *to,
- int to_len, int nonblock, unsigned flags,
- struct sockaddr_in *addr, int *addr_len)
-{
- int result;
-
- /*
- * Have to check these first unlike the old code. If
- * we check them after we lose data on an error
- * which is wrong
- */
-
- if(addr_len)
- *addr_len = sizeof(*addr);
- result=tcp_read(sk, to, to_len, nonblock, flags);
-
- if (result < 0)
- return(result);
-
- if(addr)
- {
- addr->sin_family = AF_INET;
- addr->sin_port = sk->dummy_th.dest;
- addr->sin_addr.s_addr = sk->daddr;
- }
- return(result);
-}
-
-
-/*
- * This routine will send an RST to the other tcp.
- */
-
-static void tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
- struct proto *prot, struct options *opt, struct device *dev, int tos, int ttl)
-{
- struct sk_buff *buff;
- struct tcphdr *t1;
- int tmp;
- struct device *ndev=NULL;
-
- /*
- * Cannot reset a reset (Think about it).
- */
-
- if(th->rst)
- return;
-
- /*
- * We need to grab some memory, and put together an RST,
- * and then put it into the queue to be sent.
- */
-
- buff = prot->wmalloc(NULL, MAX_RESET_SIZE, 1, GFP_ATOMIC);
- if (buff == NULL)
- return;
-
- buff->len = sizeof(*t1);
- buff->sk = NULL;
- buff->dev = dev;
- buff->localroute = 0;
-
- t1 =(struct tcphdr *) buff->data;
-
- /*
- * Put in the IP header and routing stuff.
- */
-
- tmp = prot->build_header(buff, saddr, daddr, &ndev, IPPROTO_TCP, opt,
- sizeof(struct tcphdr),tos,ttl);
- if (tmp < 0)
- {
- buff->free = 1;
- prot->wfree(NULL, buff->mem_addr, buff->mem_len);
- return;
- }
-
- t1 =(struct tcphdr *)((char *)t1 +tmp);
- buff->len += tmp;
- memcpy(t1, th, sizeof(*t1));
-
- /*
- * Swap the send and the receive.
- */
-
- t1->dest = th->source;
- t1->source = th->dest;
- t1->rst = 1;
- t1->window = 0;
-
- if(th->ack)
- {
- t1->ack = 0;
- t1->seq = th->ack_seq;
- t1->ack_seq = 0;
- }
- else
- {
- t1->ack = 1;
- if(!th->syn)
- t1->ack_seq=htonl(th->seq);
- else
- t1->ack_seq=htonl(th->seq+1);
- t1->seq=0;
- }
-
- t1->syn = 0;
- t1->urg = 0;
- t1->fin = 0;
- t1->psh = 0;
- t1->doff = sizeof(*t1)/4;
- tcp_send_check(t1, saddr, daddr, sizeof(*t1), NULL);
- prot->queue_xmit(NULL, ndev, buff, 1);
- tcp_statistics.TcpOutSegs++;
-}
-
-
-/*
- * Look for tcp options. Parses everything but only knows about MSS.
- * This routine is always called with the packet containing the SYN.
- * However it may also be called with the ack to the SYN. So you
- * can't assume this is always the SYN. It's always called after
- * we have set up sk->mtu to our own MTU.
- *
- * We need at minimum to add PAWS support here. Possibly large windows
- * as Linux gets deployed on 100Mb/sec networks.
- */
-
-static void tcp_options(struct sock *sk, struct tcphdr *th)
-{
- unsigned char *ptr;
- int length=(th->doff*4)-sizeof(struct tcphdr);
- int mss_seen = 0;
-
- ptr = (unsigned char *)(th + 1);
-
- while(length>0)
- {
- int opcode=*ptr++;
- int opsize=*ptr++;
- switch(opcode)
- {
- case TCPOPT_EOL:
- return;
- case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */
- length--;
- ptr--; /* the opsize=*ptr++ above was a mistake */
- continue;
-
- default:
- if(opsize<=2) /* Avoid silly options looping forever */
- return;
- switch(opcode)
- {
- case TCPOPT_MSS:
- if(opsize==4 && th->syn)
- {
- sk->mtu=min(sk->mtu,ntohs(*(unsigned short *)ptr));
- mss_seen = 1;
- }
- break;
- /* Add other options here as people feel the urge to implement stuff like large windows */
- }
- ptr+=opsize-2;
- length-=opsize;
- }
- }
- if (th->syn)
- {
- if (! mss_seen)
- sk->mtu=min(sk->mtu, 536); /* default MSS if none sent */
- }
-#ifdef CONFIG_INET_PCTCP
- sk->mss = min(sk->max_window >> 1, sk->mtu);
-#else
- sk->mss = min(sk->max_window, sk->mtu);
-#endif
-}
-
-static inline unsigned long default_mask(unsigned long dst)
-{
- dst = ntohl(dst);
- if (IN_CLASSA(dst))
- return htonl(IN_CLASSA_NET);
- if (IN_CLASSB(dst))
- return htonl(IN_CLASSB_NET);
- return htonl(IN_CLASSC_NET);
-}
-
-/*
- * Default sequence number picking algorithm.
- * As close as possible to RFC 793, which
- * suggests using a 250kHz clock.
- * Further reading shows this assumes 2MB/s networks.
- * For 10MB/s ethernet, a 1MHz clock is appropriate.
- * That's funny, Linux has one built in! Use it!
- */
-
-extern inline unsigned long tcp_init_seq(void)
-{
- struct timeval tv;
- do_gettimeofday(&tv);
- return tv.tv_usec+tv.tv_sec*1000000;
-}
-
-/*
- * This routine handles a connection request.
- * It should make sure we haven't already responded.
- * Because of the way BSD works, we have to send a syn/ack now.
- * This also means it will be harder to close a socket which is
- * listening.
- */
-
-static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
- unsigned long daddr, unsigned long saddr,
- struct options *opt, struct device *dev, unsigned long seq)
-{
- struct sk_buff *buff;
- struct tcphdr *t1;
- unsigned char *ptr;
- struct sock *newsk;
- struct tcphdr *th;
- struct device *ndev=NULL;
- int tmp;
- struct rtable *rt;
-
- th = skb->h.th;
-
- /* If the socket is dead, don't accept the connection. */
- if (!sk->dead)
- {
- sk->data_ready(sk,0);
- }
- else
- {
- if(sk->debug)
- printk("Reset on %p: Connect on dead socket.\n",sk);
- tcp_reset(daddr, saddr, th, sk->prot, opt, dev, sk->ip_tos,sk->ip_ttl);
- tcp_statistics.TcpAttemptFails++;
- kfree_skb(skb, FREE_READ);
- return;
- }
-
- /*
- * Make sure we can accept more. This will prevent a
- * flurry of syns from eating up all our memory.
- */
-
- if (sk->ack_backlog >= sk->max_ack_backlog)
- {
- tcp_statistics.TcpAttemptFails++;
- kfree_skb(skb, FREE_READ);
- return;
- }
-
- /*
- * We need to build a new sock struct.
- * It is sort of bad to have a socket without an inode attached
- * to it, but the wake_up's will just wake up the listening socket,
- * and if the listening socket is destroyed before this is taken
- * off of the queue, this will take care of it.
- */
-
- newsk = (struct sock *) kmalloc(sizeof(struct sock), GFP_ATOMIC);
- if (newsk == NULL)
- {
- /* just ignore the syn. It will get retransmitted. */
- tcp_statistics.TcpAttemptFails++;
- kfree_skb(skb, FREE_READ);
- return;
- }
-
- memcpy(newsk, sk, sizeof(*newsk));
- skb_queue_head_init(&newsk->write_queue);
- skb_queue_head_init(&newsk->receive_queue);
- newsk->send_head = NULL;
- newsk->send_tail = NULL;
- skb_queue_head_init(&newsk->back_log);
- newsk->rtt = 0; /*TCP_CONNECT_TIME<<3*/
- newsk->rto = TCP_TIMEOUT_INIT;
- newsk->mdev = 0;
- newsk->max_window = 0;
- newsk->cong_window = 1;
- newsk->cong_count = 0;
- newsk->ssthresh = 0;
- newsk->backoff = 0;
- newsk->blog = 0;
- newsk->intr = 0;
- newsk->proc = 0;
- newsk->done = 0;
- newsk->partial = NULL;
- newsk->pair = NULL;
- newsk->wmem_alloc = 0;
- newsk->rmem_alloc = 0;
- newsk->localroute = sk->localroute;
-
- newsk->max_unacked = MAX_WINDOW - TCP_WINDOW_DIFF;
-
- newsk->err = 0;
- newsk->shutdown = 0;
- newsk->ack_backlog = 0;
- newsk->acked_seq = skb->h.th->seq+1;
- newsk->copied_seq = skb->h.th->seq+1;
- newsk->fin_seq = skb->h.th->seq;
- newsk->state = TCP_SYN_RECV;
- newsk->timeout = 0;
- newsk->ip_xmit_timeout = 0;
- newsk->write_seq = seq;
- newsk->window_seq = newsk->write_seq;
- newsk->rcv_ack_seq = newsk->write_seq;
- newsk->urg_data = 0;
- newsk->retransmits = 0;
- newsk->linger=0;
- newsk->destroy = 0;
- init_timer(&newsk->timer);
- newsk->timer.data = (unsigned long)newsk;
- newsk->timer.function = &net_timer;
- init_timer(&newsk->retransmit_timer);
- newsk->retransmit_timer.data = (unsigned long)newsk;
- newsk->retransmit_timer.function=&retransmit_timer;
- newsk->dummy_th.source = skb->h.th->dest;
- newsk->dummy_th.dest = skb->h.th->source;
-
- /*
- * Swap these two, they are from our point of view.
- */
-
- newsk->daddr = saddr;
- newsk->saddr = daddr;
-
- put_sock(newsk->num,newsk);
- newsk->dummy_th.res1 = 0;
- newsk->dummy_th.doff = 6;
- newsk->dummy_th.fin = 0;
- newsk->dummy_th.syn = 0;
- newsk->dummy_th.rst = 0;
- newsk->dummy_th.psh = 0;
- newsk->dummy_th.ack = 0;
- newsk->dummy_th.urg = 0;
- newsk->dummy_th.res2 = 0;
- newsk->acked_seq = skb->h.th->seq + 1;
- newsk->copied_seq = skb->h.th->seq + 1;
- newsk->socket = NULL;
-
- /*
- * Grab the ttl and tos values and use them
- */
-
- newsk->ip_ttl=sk->ip_ttl;
- newsk->ip_tos=skb->ip_hdr->tos;
-
- /*
- * Use 512 or whatever user asked for
- */
-
- /*
- * Note use of sk->user_mss, since user has no direct access to newsk
- */
-
- rt=ip_rt_route(saddr, NULL,NULL);
-
- if(rt!=NULL && (rt->rt_flags&RTF_WINDOW))
- newsk->window_clamp = rt->rt_window;
- else
- newsk->window_clamp = 0;
-
- if (sk->user_mss)
- newsk->mtu = sk->user_mss;
- else if(rt!=NULL && (rt->rt_flags&RTF_MSS))
- newsk->mtu = rt->rt_mss - HEADER_SIZE;
- else
- {
-#ifdef CONFIG_INET_SNARL /* Sub Nets Are Local */
- if ((saddr ^ daddr) & default_mask(saddr))
-#else
- if ((saddr ^ daddr) & dev->pa_mask)
-#endif
- newsk->mtu = 576 - HEADER_SIZE;
- else
- newsk->mtu = MAX_WINDOW;
- }
-
- /*
- * But not bigger than device MTU
- */
-
- newsk->mtu = min(newsk->mtu, dev->mtu - HEADER_SIZE);
-
- /*
- * This will min with what arrived in the packet
- */
-
- tcp_options(newsk,skb->h.th);
-
- buff = newsk->prot->wmalloc(newsk, MAX_SYN_SIZE, 1, GFP_ATOMIC);
- if (buff == NULL)
- {
- sk->err = ENOMEM;
- newsk->dead = 1;
- newsk->state = TCP_CLOSE;
- /* And this will destroy it */
- release_sock(newsk);
- kfree_skb(skb, FREE_READ);
- tcp_statistics.TcpAttemptFails++;
- return;
- }
-
- buff->len = sizeof(struct tcphdr)+4;
- buff->sk = newsk;
- buff->localroute = newsk->localroute;
-
- t1 =(struct tcphdr *) buff->data;
-
- /*
- * Put in the IP header and routing stuff.
- */
-
- tmp = sk->prot->build_header(buff, newsk->saddr, newsk->daddr, &ndev,
- IPPROTO_TCP, NULL, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl);
-
- /*
- * Something went wrong.
- */
-
- if (tmp < 0)
- {
- sk->err = -tmp;
- buff->free = 1;
- kfree_skb(buff,FREE_WRITE);
- newsk->dead = 1;
- newsk->state = TCP_CLOSE;
- release_sock(newsk);
- skb->sk = sk;
- kfree_skb(skb, FREE_READ);
- tcp_statistics.TcpAttemptFails++;
- return;
- }
-
- buff->len += tmp;
- t1 =(struct tcphdr *)((char *)t1 +tmp);
-
- memcpy(t1, skb->h.th, sizeof(*t1));
- buff->h.seq = newsk->write_seq;
- /*
- * Swap the send and the receive.
- */
- t1->dest = skb->h.th->source;
- t1->source = newsk->dummy_th.source;
- t1->seq = ntohl(newsk->write_seq++);
- t1->ack = 1;
- newsk->window = tcp_select_window(newsk);
- newsk->sent_seq = newsk->write_seq;
- t1->window = ntohs(newsk->window);
- t1->res1 = 0;
- t1->res2 = 0;
- t1->rst = 0;
- t1->urg = 0;
- t1->psh = 0;
- t1->syn = 1;
- t1->ack_seq = ntohl(skb->h.th->seq+1);
- t1->doff = sizeof(*t1)/4+1;
- ptr =(unsigned char *)(t1+1);
- ptr[0] = 2;
- ptr[1] = 4;
- ptr[2] = ((newsk->mtu) >> 8) & 0xff;
- ptr[3] =(newsk->mtu) & 0xff;
-
- tcp_send_check(t1, daddr, saddr, sizeof(*t1)+4, newsk);
- newsk->prot->queue_xmit(newsk, ndev, buff, 0);
- reset_xmit_timer(newsk, TIME_WRITE , TCP_TIMEOUT_INIT);
- skb->sk = newsk;
-
- /*
- * Charge the sock_buff to newsk.
- */
-
- sk->rmem_alloc -= skb->mem_len;
- newsk->rmem_alloc += skb->mem_len;
-
- skb_queue_tail(&sk->receive_queue,skb);
- sk->ack_backlog++;
- release_sock(newsk);
- tcp_statistics.TcpOutSegs++;
-}
-
-
-static void tcp_close(struct sock *sk, int timeout)
-{
- /*
- * We need to grab some memory, and put together a FIN,
- * and then put it into the queue to be sent.
- */
-
- sk->inuse = 1;
-
- if(sk->state == TCP_LISTEN)
- {
- /* Special case */
- tcp_set_state(sk, TCP_CLOSE);
- tcp_close_pending(sk);
- release_sock(sk);
- return;
- }
-
- sk->keepopen = 1;
- sk->shutdown = SHUTDOWN_MASK;
-
- if (!sk->dead)
- sk->state_change(sk);
-
- if (timeout == 0)
- {
- struct sk_buff *skb;
-
- /*
- * We need to flush the recv. buffs. We do this only on the
- * descriptor close, not protocol-sourced closes, because the
- * reader process may not have drained the data yet!
- */
-
- while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
- kfree_skb(skb, FREE_READ);
- /*
- * Get rid off any half-completed packets.
- */
-
- if (sk->partial)
- tcp_send_partial(sk);
- }
-
-
- /*
- * Timeout is not the same thing - however the code likes
- * to send both the same way (sigh).
- */
-
- if(timeout)
- {
- tcp_set_state(sk, TCP_CLOSE); /* Dead */
- }
- else
- {
- if(tcp_close_state(sk,1)==1)
- {
- tcp_send_fin(sk);
- }
- }
- release_sock(sk);
-}
-
-
-/*
- * This routine takes stuff off of the write queue,
- * and puts it in the xmit queue. This happens as incoming acks
- * open up the remote window for us.
- */
-
-static void tcp_write_xmit(struct sock *sk)
-{
- struct sk_buff *skb;
-
- /*
- * The bytes will have to remain here. In time closedown will
- * empty the write queue and all will be happy
- */
-
- if(sk->zapped)
- return;
-
- /*
- * Anything on the transmit queue that fits the window can
- * be added providing we are not
- *
- * a) retransmitting (Nagle's rule)
- * b) exceeding our congestion window.
- */
-
- while((skb = skb_peek(&sk->write_queue)) != NULL &&
- before(skb->h.seq, sk->window_seq + 1) &&
- (sk->retransmits == 0 ||
- sk->ip_xmit_timeout != TIME_WRITE ||
- before(skb->h.seq, sk->rcv_ack_seq + 1))
- && sk->packets_out < sk->cong_window)
- {
- IS_SKB(skb);
- skb_unlink(skb);
-
- /*
- * See if we really need to send the packet.
- */
-
- if (before(skb->h.seq, sk->rcv_ack_seq +1))
- {
- /*
- * This is acked data. We can discard it. This
- * cannot currently occur.
- */
-
- sk->retransmits = 0;
- kfree_skb(skb, FREE_WRITE);
- if (!sk->dead)
- sk->write_space(sk);
- }
- else
- {
- struct tcphdr *th;
- struct iphdr *iph;
- int size;
-/*
- * put in the ack seq and window at this point rather than earlier,
- * in order to keep them monotonic. We really want to avoid taking
- * back window allocations. That's legal, but RFC1122 says it's frowned on.
- * Ack and window will in general have changed since this packet was put
- * on the write queue.
- */
- iph = (struct iphdr *)(skb->data +
- skb->dev->hard_header_len);
- th = (struct tcphdr *)(((char *)iph) +(iph->ihl << 2));
- size = skb->len - (((unsigned char *) th) - skb->data);
-
- th->ack_seq = ntohl(sk->acked_seq);
- th->window = ntohs(tcp_select_window(sk));
-
- tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
-
- sk->sent_seq = skb->h.seq;
-
- /*
- * IP manages our queue for some crazy reason
- */
-
- sk->prot->queue_xmit(sk, skb->dev, skb, skb->free);
-
- /*
- * Again we slide the timer wrongly
- */
-
- reset_xmit_timer(sk, TIME_WRITE, sk->rto);
- }
- }
-}
-
-
-/*
- * This routine deals with incoming acks, but not outgoing ones.
- */
-
-extern __inline__ int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int len)
-{
- unsigned long ack;
- int flag = 0;
-
- /*
- * 1 - there was data in packet as well as ack or new data is sent or
- * in shutdown state
- * 2 - data from retransmit queue was acked and removed
- * 4 - window shrunk or data from retransmit queue was acked and removed
- */
-
- if(sk->zapped)
- return(1); /* Dead, cant ack any more so why bother */
-
- /*
- * Have we discovered a larger window
- */
-
- ack = ntohl(th->ack_seq);
-
- if (ntohs(th->window) > sk->max_window)
- {
- sk->max_window = ntohs(th->window);
-#ifdef CONFIG_INET_PCTCP
- /* Hack because we don't send partial packets to non SWS
- handling hosts */
- sk->mss = min(sk->max_window>>1, sk->mtu);
-#else
- sk->mss = min(sk->max_window, sk->mtu);
-#endif
- }
-
- /*
- * We have dropped back to keepalive timeouts. Thus we have
- * no retransmits pending.
- */
-
- if (sk->retransmits && sk->ip_xmit_timeout == TIME_KEEPOPEN)
- sk->retransmits = 0;
-
- /*
- * If the ack is newer than sent or older than previous acks
- * then we can probably ignore it.
- */
-
- if (after(ack, sk->sent_seq) || before(ack, sk->rcv_ack_seq))
- {
- if(sk->debug)
- printk("Ack ignored %lu %lu\n",ack,sk->sent_seq);
-
- /*
- * Keepalive processing.
- */
-
- if (after(ack, sk->sent_seq))
- {
- return(0);
- }
-
- /*
- * Restart the keepalive timer.
- */
-
- if (sk->keepopen)
- {
- if(sk->ip_xmit_timeout==TIME_KEEPOPEN)
- reset_xmit_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
- }
- return(1);
- }
-
- /*
- * If there is data set flag 1
- */
-
- if (len != th->doff*4)
- flag |= 1;
-
- /*
- * See if our window has been shrunk.
- */
-
- if (after(sk->window_seq, ack+ntohs(th->window)))
- {
- /*
- * We may need to move packets from the send queue
- * to the write queue, if the window has been shrunk on us.
- * The RFC says you are not allowed to shrink your window
- * like this, but if the other end does, you must be able
- * to deal with it.
- */
- struct sk_buff *skb;
- struct sk_buff *skb2;
- struct sk_buff *wskb = NULL;
-
- skb2 = sk->send_head;
- sk->send_head = NULL;
- sk->send_tail = NULL;
-
- /*
- * This is an artifact of a flawed concept. We want one
- * queue and a smarter send routine when we send all.
- */
-
- flag |= 4; /* Window changed */
-
- sk->window_seq = ack + ntohs(th->window);
- cli();
- while (skb2 != NULL)
- {
- skb = skb2;
- skb2 = skb->link3;
- skb->link3 = NULL;
- if (after(skb->h.seq, sk->window_seq))
- {
- if (sk->packets_out > 0)
- sk->packets_out--;
- /* We may need to remove this from the dev send list. */
- if (skb->next != NULL)
- {
- skb_unlink(skb);
- }
- /* Now add it to the write_queue. */
- if (wskb == NULL)
- skb_queue_head(&sk->write_queue,skb);
- else
- skb_append(wskb,skb);
- wskb = skb;
- }
- else
- {
- if (sk->send_head == NULL)
- {
- sk->send_head = skb;
- sk->send_tail = skb;
- }
- else
- {
- sk->send_tail->link3 = skb;
- sk->send_tail = skb;
- }
- skb->link3 = NULL;
- }
- }
- sti();
- }
-
- /*
- * Pipe has emptied
- */
-
- if (sk->send_tail == NULL || sk->send_head == NULL)
- {
- sk->send_head = NULL;
- sk->send_tail = NULL;
- sk->packets_out= 0;
- }
-
- /*
- * Update the right hand window edge of the host
- */
-
- sk->window_seq = ack + ntohs(th->window);
-
- /*
- * We don't want too many packets out there.
- */
-
- if (sk->ip_xmit_timeout == TIME_WRITE &&
- sk->cong_window < 2048 && after(ack, sk->rcv_ack_seq))
- {
- /*
- * This is Jacobson's slow start and congestion avoidance.
- * SIGCOMM '88, p. 328. Because we keep cong_window in integral
- * mss's, we can't do cwnd += 1 / cwnd. Instead, maintain a
- * counter and increment it once every cwnd times. It's possible
- * that this should be done only if sk->retransmits == 0. I'm
- * interpreting "new data is acked" as including data that has
- * been retransmitted but is just now being acked.
- */
- if (sk->cong_window < sk->ssthresh)
- /*
- * In "safe" area, increase
- */
- sk->cong_window++;
- else
- {
- /*
- * In dangerous area, increase slowly. In theory this is
- * sk->cong_window += 1 / sk->cong_window
- */
- if (sk->cong_count >= sk->cong_window)
- {
- sk->cong_window++;
- sk->cong_count = 0;
- }
- else
- sk->cong_count++;
- }
- }
-
- /*
- * Remember the highest ack received.
- */
-
- sk->rcv_ack_seq = ack;
-
- /*
- * If this ack opens up a zero window, clear backoff. It was
- * being used to time the probes, and is probably far higher than
- * it needs to be for normal retransmission.
- */
-
- if (sk->ip_xmit_timeout == TIME_PROBE0)
- {
- sk->retransmits = 0; /* Our probe was answered */
-
- /*
- * Was it a usable window open ?
- */
-
- if (skb_peek(&sk->write_queue) != NULL && /* should always be non-null */
- ! before (sk->window_seq, sk->write_queue.next->h.seq))
- {
- sk->backoff = 0;
-
- /*
- * Recompute rto from rtt. this eliminates any backoff.
- */
-
- sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1;
- if (sk->rto > 120*HZ)
- sk->rto = 120*HZ;
- if (sk->rto < 20) /* Was 1*HZ, then 1 - turns out we must allow about
- .2 of a second because of BSD delayed acks - on a 100Mb/sec link
- .2 of a second is going to need huge windows (SIGH) */
- sk->rto = 20;
- }
- }
-
- /*
- * See if we can take anything off of the retransmit queue.
- */
-
- while(sk->send_head != NULL)
- {
- /* Check for a bug. */
- if (sk->send_head->link3 &&
- after(sk->send_head->h.seq, sk->send_head->link3->h.seq))
- printk("INET: tcp.c: *** bug send_list out of order.\n");
-
- /*
- * If our packet is before the ack sequence we can
- * discard it as it's confirmed to have arrived the other end.
- */
-
- if (before(sk->send_head->h.seq, ack+1))
- {
- struct sk_buff *oskb;
- if (sk->retransmits)
- {
- /*
- * We were retransmitting. don't count this in RTT est
- */
- flag |= 2;
-
- /*
- * even though we've gotten an ack, we're still
- * retransmitting as long as we're sending from
- * the retransmit queue. Keeping retransmits non-zero
- * prevents us from getting new data interspersed with
- * retransmissions.
- */
-
- if (sk->send_head->link3) /* Any more queued retransmits? */
- sk->retransmits = 1;
- else
- sk->retransmits = 0;
- }
- /*
- * Note that we only reset backoff and rto in the
- * rtt recomputation code. And that doesn't happen
- * if there were retransmissions in effect. So the
- * first new packet after the retransmissions is
- * sent with the backoff still in effect. Not until
- * we get an ack from a non-retransmitted packet do
- * we reset the backoff and rto. This allows us to deal
- * with a situation where the network delay has increased
- * suddenly. I.e. Karn's algorithm. (SIGCOMM '87, p5.)
- */
-
- /*
- * We have one less packet out there.
- */
-
- if (sk->packets_out > 0)
- sk->packets_out --;
- /*
- * Wake up the process, it can probably write more.
- */
- if (!sk->dead)
- sk->write_space(sk);
- oskb = sk->send_head;
-
- if (!(flag&2)) /* Not retransmitting */
- {
- long m;
-
- /*
- * The following amusing code comes from Jacobson's
- * article in SIGCOMM '88. Note that rtt and mdev
- * are scaled versions of rtt and mean deviation.
- * This is designed to be as fast as possible
- * m stands for "measurement".
- */
-
- m = jiffies - oskb->when; /* RTT */
- if(m<=0)
- m=1; /* IS THIS RIGHT FOR <0 ??? */
- m -= (sk->rtt >> 3); /* m is now error in rtt est */
- sk->rtt += m; /* rtt = 7/8 rtt + 1/8 new */
- if (m < 0)
- m = -m; /* m is now abs(error) */
- m -= (sk->mdev >> 2); /* similar update on mdev */
- sk->mdev += m; /* mdev = 3/4 mdev + 1/4 new */
-
- /*
- * Now update timeout. Note that this removes any backoff.
- */
-
- sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1;
- if (sk->rto > 120*HZ)
- sk->rto = 120*HZ;
- if (sk->rto < 20) /* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks */
- sk->rto = 20;
- sk->backoff = 0;
- }
- flag |= (2|4); /* 2 is really more like 'don't adjust the rtt
- In this case as we just set it up */
- cli();
- oskb = sk->send_head;
- IS_SKB(oskb);
- sk->send_head = oskb->link3;
- if (sk->send_head == NULL)
- {
- sk->send_tail = NULL;
- }
-
- /*
- * We may need to remove this from the dev send list.
- */
-
- if (oskb->next)
- skb_unlink(oskb);
- sti();
- kfree_skb(oskb, FREE_WRITE); /* write. */
- if (!sk->dead)
- sk->write_space(sk);
- }
- else
- {
- break;
- }
- }
-
- /*
- * XXX someone ought to look at this too.. at the moment, if skb_peek()
- * returns non-NULL, we complete ignore the timer stuff in the else
- * clause. We ought to organize the code so that else clause can
- * (should) be executed regardless, possibly moving the PROBE timer
- * reset over. The skb_peek() thing should only move stuff to the
- * write queue, NOT also manage the timer functions.
- */
-
- /*
- * Maybe we can take some stuff off of the write queue,
- * and put it onto the xmit queue.
- */
- if (skb_peek(&sk->write_queue) != NULL)
- {
- if (after (sk->window_seq+1, sk->write_queue.next->h.seq) &&
- (sk->retransmits == 0 ||
- sk->ip_xmit_timeout != TIME_WRITE ||
- before(sk->write_queue.next->h.seq, sk->rcv_ack_seq + 1))
- && sk->packets_out < sk->cong_window)
- {
- /*
- * Add more data to the send queue.
- */
- flag |= 1;
- tcp_write_xmit(sk);
- }
- else if (before(sk->window_seq, sk->write_queue.next->h.seq) &&
- sk->send_head == NULL &&
- sk->ack_backlog == 0 &&
- sk->state != TCP_TIME_WAIT)
- {
- /*
- * Data to queue but no room.
- */
- reset_xmit_timer(sk, TIME_PROBE0, sk->rto);
- }
- }
- else
- {
- /*
- * from TIME_WAIT we stay in TIME_WAIT as long as we rx packets
- * from TCP_CLOSE we don't do anything
- *
- * from anything else, if there is write data (or fin) pending,
- * we use a TIME_WRITE timeout, else if keepalive we reset to
- * a KEEPALIVE timeout, else we delete the timer.
- *
- * We do not set flag for nominal write data, otherwise we may
- * force a state where we start to write itsy bitsy tidbits
- * of data.
- */
-
- switch(sk->state) {
- case TCP_TIME_WAIT:
- /*
- * keep us in TIME_WAIT until we stop getting packets,
- * reset the timeout.
- */
- reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
- break;
- case TCP_CLOSE:
- /*
- * don't touch the timer.
- */
- break;
- default:
- /*
- * Must check send_head, write_queue, and ack_backlog
- * to determine which timeout to use.
- */
- if (sk->send_head || skb_peek(&sk->write_queue) != NULL || sk->ack_backlog) {
- reset_xmit_timer(sk, TIME_WRITE, sk->rto);
- } else if (sk->keepopen) {
- reset_xmit_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
- } else {
- del_timer(&sk->retransmit_timer);
- sk->ip_xmit_timeout = 0;
- }
- break;
- }
- }
-
- /*
- * We have nothing queued but space to send. Send any partial
- * packets immediately (end of Nagle rule application).
- */
-
- if (sk->packets_out == 0 && sk->partial != NULL &&
- skb_peek(&sk->write_queue) == NULL && sk->send_head == NULL)
- {
- flag |= 1;
- tcp_send_partial(sk);
- }
-
- /*
- * In the LAST_ACK case, the other end FIN'd us. We then FIN'd them, and
- * we are now waiting for an acknowledge to our FIN. The other end is
- * already in TIME_WAIT.
- *
- * Move to TCP_CLOSE on success.
- */
-
- if (sk->state == TCP_LAST_ACK)
- {
- if (!sk->dead)
- sk->state_change(sk);
- if(sk->debug)
- printk("rcv_ack_seq: %lX==%lX, acked_seq: %lX==%lX\n",
- sk->rcv_ack_seq,sk->write_seq,sk->acked_seq,sk->fin_seq);
- if (sk->rcv_ack_seq == sk->write_seq /*&& sk->acked_seq == sk->fin_seq*/)
- {
- flag |= 1;
- tcp_set_state(sk,TCP_CLOSE);
- sk->shutdown = SHUTDOWN_MASK;
- }
- }
-
- /*
- * Incoming ACK to a FIN we sent in the case of our initiating the close.
- *
- * Move to FIN_WAIT2 to await a FIN from the other end. Set
- * SEND_SHUTDOWN but not RCV_SHUTDOWN as data can still be coming in.
- */
-
- if (sk->state == TCP_FIN_WAIT1)
- {
-
- if (!sk->dead)
- sk->state_change(sk);
- if (sk->rcv_ack_seq == sk->write_seq)
- {
- flag |= 1;
- sk->shutdown |= SEND_SHUTDOWN;
- tcp_set_state(sk, TCP_FIN_WAIT2);
- }
- }
-
- /*
- * Incoming ACK to a FIN we sent in the case of a simultaneous close.
- *
- * Move to TIME_WAIT
- */
-
- if (sk->state == TCP_CLOSING)
- {
-
- if (!sk->dead)
- sk->state_change(sk);
- if (sk->rcv_ack_seq == sk->write_seq)
- {
- flag |= 1;
- tcp_time_wait(sk);
- }
- }
-
- /*
- * Final ack of a three way shake
- */
-
- if(sk->state==TCP_SYN_RECV)
- {
- tcp_set_state(sk, TCP_ESTABLISHED);
- tcp_options(sk,th);
- sk->dummy_th.dest=th->source;
- sk->copied_seq = sk->acked_seq;
- if(!sk->dead)
- sk->state_change(sk);
- if(sk->max_window==0)
- {
- sk->max_window=32; /* Sanity check */
- sk->mss=min(sk->max_window,sk->mtu);
- }
- }
-
- /*
- * I make no guarantees about the first clause in the following
- * test, i.e. "(!flag) || (flag&4)". I'm not entirely sure under
- * what conditions "!flag" would be true. However I think the rest
- * of the conditions would prevent that from causing any
- * unnecessary retransmission.
- * Clearly if the first packet has expired it should be
- * retransmitted. The other alternative, "flag&2 && retransmits", is
- * harder to explain: You have to look carefully at how and when the
- * timer is set and with what timeout. The most recent transmission always
- * sets the timer. So in general if the most recent thing has timed
- * out, everything before it has as well. So we want to go ahead and
- * retransmit some more. If we didn't explicitly test for this
- * condition with "flag&2 && retransmits", chances are "when + rto < jiffies"
- * would not be true. If you look at the pattern of timing, you can
- * show that rto is increased fast enough that the next packet would
- * almost never be retransmitted immediately. Then you'd end up
- * waiting for a timeout to send each packet on the retransmission
- * queue. With my implementation of the Karn sampling algorithm,
- * the timeout would double each time. The net result is that it would
- * take a hideous amount of time to recover from a single dropped packet.
- * It's possible that there should also be a test for TIME_WRITE, but
- * I think as long as "send_head != NULL" and "retransmit" is on, we've
- * got to be in real retransmission mode.
- * Note that tcp_do_retransmit is called with all==1. Setting cong_window
- * back to 1 at the timeout will cause us to send 1, then 2, etc. packets.
- * As long as no further losses occur, this seems reasonable.
- */
-
- if (((!flag) || (flag&4)) && sk->send_head != NULL &&
- (((flag&2) && sk->retransmits) ||
- (sk->send_head->when + sk->rto < jiffies)))
- {
- if(sk->send_head->when + sk->rto < jiffies)
- tcp_retransmit(sk,0);
- else
- {
- tcp_do_retransmit(sk, 1);
- reset_xmit_timer(sk, TIME_WRITE, sk->rto);
- }
- }
-
- return(1);
-}
-
-
-/*
- * Process the FIN bit. This now behaves as it is supposed to work
- * and the FIN takes effect when it is validly part of sequence
- * space. Not before when we get holes.
- *
- * If we are ESTABLISHED, a received fin moves us to CLOSE-WAIT
- * (and thence onto LAST-ACK and finally, CLOSE, we never enter
- * TIME-WAIT)
- *
- * If we are in FINWAIT-1, a received FIN indicates simultaneous
- * close and we go into CLOSING (and later onto TIME-WAIT)
- *
- * If we are in FINWAIT-2, a received FIN moves us to TIME-WAIT.
- *
- */
-
-static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
-{
- sk->fin_seq = th->seq + skb->len + th->syn + th->fin;
-
- if (!sk->dead)
- {
- sk->state_change(sk);
- sock_wake_async(sk->socket, 1);
- }
-
- switch(sk->state)
- {
- case TCP_SYN_RECV:
- case TCP_SYN_SENT:
- case TCP_ESTABLISHED:
- /*
- * move to CLOSE_WAIT, tcp_data() already handled
- * sending the ack.
- */
- tcp_set_state(sk,TCP_CLOSE_WAIT);
- if (th->rst)
- sk->shutdown = SHUTDOWN_MASK;
- break;
-
- case TCP_CLOSE_WAIT:
- case TCP_CLOSING:
- /*
- * received a retransmission of the FIN, do
- * nothing.
- */
- break;
- case TCP_TIME_WAIT:
- /*
- * received a retransmission of the FIN,
- * restart the TIME_WAIT timer.
- */
- reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
- return(0);
- case TCP_FIN_WAIT1:
- /*
- * This case occurs when a simultaneous close
- * happens, we must ack the received FIN and
- * enter the CLOSING state.
- *
- * This causes a WRITE timeout, which will either
- * move on to TIME_WAIT when we timeout, or resend
- * the FIN properly (maybe we get rid of that annoying
- * FIN lost hang). The TIME_WRITE code is already correct
- * for handling this timeout.
- */
-
- if(sk->ip_xmit_timeout != TIME_WRITE)
- reset_xmit_timer(sk, TIME_WRITE, sk->rto);
- tcp_set_state(sk,TCP_CLOSING);
- break;
- case TCP_FIN_WAIT2:
- /*
- * received a FIN -- send ACK and enter TIME_WAIT
- */
- reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
- sk->shutdown|=SHUTDOWN_MASK;
- tcp_set_state(sk,TCP_TIME_WAIT);
- break;
- case TCP_CLOSE:
- /*
- * already in CLOSE
- */
- break;
- default:
- tcp_set_state(sk,TCP_LAST_ACK);
-
- /* Start the timers. */
- reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
- return(0);
- }
-
- return(0);
-}
-
-
-
-/*
- * This routine handles the data. If there is room in the buffer,
- * it will be have already been moved into it. If there is no
- * room, then we will just have to discard the packet.
- */
-
-extern __inline__ int tcp_data(struct sk_buff *skb, struct sock *sk,
- unsigned long saddr, unsigned short len)
-{
- struct sk_buff *skb1, *skb2;
- struct tcphdr *th;
- int dup_dumped=0;
- unsigned long new_seq;
- unsigned long shut_seq;
-
- th = skb->h.th;
- skb->len = len -(th->doff*4);
-
- /*
- * The bytes in the receive read/assembly queue has increased. Needed for the
- * low memory discard algorithm
- */
-
- sk->bytes_rcv += skb->len;
-
- if (skb->len == 0 && !th->fin)
- {
- /*
- * Don't want to keep passing ack's back and forth.
- * (someone sent us dataless, boring frame)
- */
- if (!th->ack)
- tcp_send_ack(sk->sent_seq, sk->acked_seq,sk, th, saddr);
- kfree_skb(skb, FREE_READ);
- return(0);
- }
-
- /*
- * We no longer have anyone receiving data on this connection.
- */
-
-#ifndef TCP_DONT_RST_SHUTDOWN
-
- if(sk->shutdown & RCV_SHUTDOWN)
- {
- /*
- * FIXME: BSD has some magic to avoid sending resets to
- * broken 4.2 BSD keepalives. Much to my surprise a few non
- * BSD stacks still have broken keepalives so we want to
- * cope with it.
- */
-
- if(skb->len) /* We don't care if it's just an ack or
- a keepalive/window probe */
- {
- new_seq= th->seq + skb->len + th->syn; /* Right edge of _data_ part of frame */
-
- /* Do this the way 4.4BSD treats it. Not what I'd
- regard as the meaning of the spec but it's what BSD
- does and clearly they know everything 8) */
-
- /*
- * This is valid because of two things
- *
- * a) The way tcp_data behaves at the bottom.
- * b) A fin takes effect when read not when received.
- */
-
- shut_seq=sk->acked_seq+1; /* Last byte */
-
- if(after(new_seq,shut_seq))
- {
- if(sk->debug)
- printk("Data arrived on %p after close [Data right edge %lX, Socket shut on %lX] %d\n",
- sk, new_seq, shut_seq, sk->blog);
- if(sk->dead)
- {
- sk->acked_seq = new_seq + th->fin;
- tcp_reset(sk->saddr, sk->daddr, skb->h.th,
- sk->prot, NULL, skb->dev, sk->ip_tos, sk->ip_ttl);
- tcp_statistics.TcpEstabResets++;
- tcp_set_state(sk,TCP_CLOSE);
- sk->err = EPIPE;
- sk->shutdown = SHUTDOWN_MASK;
- kfree_skb(skb, FREE_READ);
- return 0;
- }
- }
- }
- }
-
-#endif
-
- /*
- * Now we have to walk the chain, and figure out where this one
- * goes into it. This is set up so that the last packet we received
- * will be the first one we look at, that way if everything comes
- * in order, there will be no performance loss, and if they come
- * out of order we will be able to fit things in nicely.
- *
- * [AC: This is wrong. We should assume in order first and then walk
- * forwards from the first hole based upon real traffic patterns.]
- *
- */
-
- if (skb_peek(&sk->receive_queue) == NULL) /* Empty queue is easy case */
- {
- skb_queue_head(&sk->receive_queue,skb);
- skb1= NULL;
- }
- else
- {
- for(skb1=sk->receive_queue.prev; ; skb1 = skb1->prev)
- {
- if(sk->debug)
- {
- printk("skb1=%p :", skb1);
- printk("skb1->h.th->seq = %ld: ", skb1->h.th->seq);
- printk("skb->h.th->seq = %ld\n",skb->h.th->seq);
- printk("copied_seq = %ld acked_seq = %ld\n", sk->copied_seq,
- sk->acked_seq);
- }
-
- /*
- * Optimisation: Duplicate frame or extension of previous frame from
- * same sequence point (lost ack case).
- * The frame contains duplicate data or replaces a previous frame
- * discard the previous frame (safe as sk->inuse is set) and put
- * the new one in its place.
- */
-
- if (th->seq==skb1->h.th->seq && skb->len>= skb1->len)
- {
- skb_append(skb1,skb);
- skb_unlink(skb1);
- kfree_skb(skb1,FREE_READ);
- dup_dumped=1;
- skb1=NULL;
- break;
- }
-
- /*
- * Found where it fits
- */
-
- if (after(th->seq+1, skb1->h.th->seq))
- {
- skb_append(skb1,skb);
- break;
- }
-
- /*
- * See if we've hit the start. If so insert.
- */
- if (skb1 == skb_peek(&sk->receive_queue))
- {
- skb_queue_head(&sk->receive_queue, skb);
- break;
- }
- }
- }
-
- /*
- * Figure out what the ack value for this frame is
- */
-
- th->ack_seq = th->seq + skb->len;
- if (th->syn)
- th->ack_seq++;
- if (th->fin)
- th->ack_seq++;
-
- if (before(sk->acked_seq, sk->copied_seq))
- {
- printk("*** tcp.c:tcp_data bug acked < copied\n");
- sk->acked_seq = sk->copied_seq;
- }
-
- /*
- * Now figure out if we can ack anything. This is very messy because we really want two
- * receive queues, a completed and an assembly queue. We also want only one transmit
- * queue.
- */
-
- if ((!dup_dumped && (skb1 == NULL || skb1->acked)) || before(th->seq, sk->acked_seq+1))
- {
- if (before(th->seq, sk->acked_seq+1))
- {
- int newwindow;
-
- if (after(th->ack_seq, sk->acked_seq))
- {
- newwindow = sk->window-(th->ack_seq - sk->acked_seq);
- if (newwindow < 0)
- newwindow = 0;
- sk->window = newwindow;
- sk->acked_seq = th->ack_seq;
- }
- skb->acked = 1;
-
- /*
- * When we ack the fin, we do the FIN
- * processing.
- */
-
- if (skb->h.th->fin)
- {
- tcp_fin(skb,sk,skb->h.th);
- }
-
- for(skb2 = skb->next;
- skb2 != (struct sk_buff *)&sk->receive_queue;
- skb2 = skb2->next)
- {
- if (before(skb2->h.th->seq, sk->acked_seq+1))
- {
- if (after(skb2->h.th->ack_seq, sk->acked_seq))
- {
- newwindow = sk->window -
- (skb2->h.th->ack_seq - sk->acked_seq);
- if (newwindow < 0)
- newwindow = 0;
- sk->window = newwindow;
- sk->acked_seq = skb2->h.th->ack_seq;
- }
- skb2->acked = 1;
- /*
- * When we ack the fin, we do
- * the fin handling.
- */
- if (skb2->h.th->fin)
- {
- tcp_fin(skb,sk,skb->h.th);
- }
-
- /*
- * Force an immediate ack.
- */
-
- sk->ack_backlog = sk->max_ack_backlog;
- }
- else
- {
- break;
- }
- }
-
- /*
- * This also takes care of updating the window.
- * This if statement needs to be simplified.
- */
- if (!sk->delay_acks ||
- sk->ack_backlog >= sk->max_ack_backlog ||
- sk->bytes_rcv > sk->max_unacked || th->fin) {
- /* tcp_send_ack(sk->sent_seq, sk->acked_seq,sk,th, saddr); */
- }
- else
- {
- sk->ack_backlog++;
- if(sk->debug)
- printk("Ack queued.\n");
- reset_xmit_timer(sk, TIME_WRITE, TCP_ACK_TIME);
- }
- }
- }
-
- /*
- * If we've missed a packet, send an ack.
- * Also start a timer to send another.
- */
-
- if (!skb->acked)
- {
-
- /*
- * This is important. If we don't have much room left,
- * we need to throw out a few packets so we have a good
- * window. Note that mtu is used, not mss, because mss is really
- * for the send side. He could be sending us stuff as large as mtu.
- */
-
- while (sk->prot->rspace(sk) < sk->mtu)
- {
- skb1 = skb_peek(&sk->receive_queue);
- if (skb1 == NULL)
- {
- printk("INET: tcp.c:tcp_data memory leak detected.\n");
- break;
- }
-
- /*
- * Don't throw out something that has been acked.
- */
-
- if (skb1->acked)
- {
- break;
- }
-
- skb_unlink(skb1);
- kfree_skb(skb1, FREE_READ);
- }
- tcp_send_ack(sk->sent_seq, sk->acked_seq, sk, th, saddr);
- sk->ack_backlog++;
- reset_xmit_timer(sk, TIME_WRITE, TCP_ACK_TIME);
- }
- else
- {
- tcp_send_ack(sk->sent_seq, sk->acked_seq, sk, th, saddr);
- }
-
- /*
- * Now tell the user we may have some data.
- */
-
- if (!sk->dead)
- {
- if(sk->debug)
- printk("Data wakeup.\n");
- sk->data_ready(sk,0);
- }
- return(0);
-}
-
-
-/*
- * This routine is only called when we have urgent data
- * signalled. Its the 'slow' part of tcp_urg. It could be
- * moved inline now as tcp_urg is only called from one
- * place. We handle URGent data wrong. We have to - as
- * BSD still doesn't use the correction from RFC961.
- */
-
-static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
-{
- unsigned long ptr = ntohs(th->urg_ptr);
-
- if (ptr)
- ptr--;
- ptr += th->seq;
-
- /* ignore urgent data that we've already seen and read */
- if (after(sk->copied_seq, ptr))
- return;
-
- /* do we already have a newer (or duplicate) urgent pointer? */
- if (sk->urg_data && !after(ptr, sk->urg_seq))
- return;
-
- /* tell the world about our new urgent pointer */
- if (sk->proc != 0) {
- if (sk->proc > 0) {
- kill_proc(sk->proc, SIGURG, 1);
- } else {
- kill_pg(-sk->proc, SIGURG, 1);
- }
- }
- sk->urg_data = URG_NOTYET;
- sk->urg_seq = ptr;
-}
-
-/*
- * This is the 'fast' part of urgent handling.
- */
-
-extern __inline__ int tcp_urg(struct sock *sk, struct tcphdr *th,
- unsigned long saddr, unsigned long len)
-{
- unsigned long ptr;
-
- /*
- * Check if we get a new urgent pointer - normally not
- */
-
- if (th->urg)
- tcp_check_urg(sk,th);
-
- /*
- * Do we wait for any urgent data? - normally not
- */
-
- if (sk->urg_data != URG_NOTYET)
- return 0;
-
- /*
- * Is the urgent pointer pointing into this packet?
- */
-
- ptr = sk->urg_seq - th->seq + th->doff*4;
- if (ptr >= len)
- return 0;
-
- /*
- * Ok, got the correct packet, update info
- */
-
- sk->urg_data = URG_VALID | *(ptr + (unsigned char *) th);
- if (!sk->dead)
- sk->data_ready(sk,0);
- return 0;
-}
-
-/*
- * This will accept the next outstanding connection.
- */
-
-static struct sock *tcp_accept(struct sock *sk, int flags)
-{
- struct sock *newsk;
- struct sk_buff *skb;
-
- /*
- * We need to make sure that this socket is listening,
- * and that it has something pending.
- */
-
- if (sk->state != TCP_LISTEN)
- {
- sk->err = EINVAL;
- return(NULL);
- }
-
- /* Avoid the race. */
- cli();
- sk->inuse = 1;
-
- while((skb = tcp_dequeue_established(sk)) == NULL)
- {
- if (flags & O_NONBLOCK)
- {
- sti();
- release_sock(sk);
- sk->err = EAGAIN;
- return(NULL);
- }
-
- release_sock(sk);
- interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked)
- {
- sti();
- sk->err = ERESTARTSYS;
- return(NULL);
- }
- sk->inuse = 1;
- }
- sti();
-
- /*
- * Now all we need to do is return skb->sk.
- */
-
- newsk = skb->sk;
-
- kfree_skb(skb, FREE_READ);
- sk->ack_backlog--;
- release_sock(sk);
- return(newsk);
-}
-
-
-/*
- * This will initiate an outgoing connection.
- */
-
-static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
-{
- struct sk_buff *buff;
- struct device *dev=NULL;
- unsigned char *ptr;
- int tmp;
- int atype;
- struct tcphdr *t1;
- struct rtable *rt;
-
- if (sk->state != TCP_CLOSE)
- {
- return(-EISCONN);
- }
-
- if (addr_len < 8)
- return(-EINVAL);
-
- if (usin->sin_family && usin->sin_family != AF_INET)
- return(-EAFNOSUPPORT);
-
- /*
- * connect() to INADDR_ANY means loopback (BSD'ism).
- */
-
- if(usin->sin_addr.s_addr==INADDR_ANY)
- usin->sin_addr.s_addr=ip_my_addr();
-
- /*
- * Don't want a TCP connection going to a broadcast address
- */
-
- if ((atype=ip_chk_addr(usin->sin_addr.s_addr)) == IS_BROADCAST || atype==IS_MULTICAST)
- return -ENETUNREACH;
-
- sk->inuse = 1;
- sk->daddr = usin->sin_addr.s_addr;
- sk->write_seq = tcp_init_seq();
- sk->window_seq = sk->write_seq;
- sk->rcv_ack_seq = sk->write_seq -1;
- sk->err = 0;
- sk->dummy_th.dest = usin->sin_port;
- release_sock(sk);
-
- buff = sk->prot->wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
- if (buff == NULL)
- {
- return(-ENOMEM);
- }
- sk->inuse = 1;
- buff->len = 24;
- buff->sk = sk;
- buff->free = 0;
- buff->localroute = sk->localroute;
-
- t1 = (struct tcphdr *) buff->data;
-
- /*
- * Put in the IP header and routing stuff.
- */
-
- rt=ip_rt_route(sk->daddr, NULL, NULL);
-
-
- /*
- * We need to build the routing stuff from the things saved in skb.
- */
-
- tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, NULL, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl);
- if (tmp < 0)
- {
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
- release_sock(sk);
- return(-ENETUNREACH);
- }
-
- buff->len += tmp;
- t1 = (struct tcphdr *)((char *)t1 +tmp);
-
- memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1));
- t1->seq = ntohl(sk->write_seq++);
- sk->sent_seq = sk->write_seq;
- buff->h.seq = sk->write_seq;
- t1->ack = 0;
- t1->window = 2;
- t1->res1=0;
- t1->res2=0;
- t1->rst = 0;
- t1->urg = 0;
- t1->psh = 0;
- t1->syn = 1;
- t1->urg_ptr = 0;
- t1->doff = 6;
- /* use 512 or whatever user asked for */
-
- if(rt!=NULL && (rt->rt_flags&RTF_WINDOW))
- sk->window_clamp=rt->rt_window;
- else
- sk->window_clamp=0;
-
- if (sk->user_mss)
- sk->mtu = sk->user_mss;
- else if(rt!=NULL && (rt->rt_flags&RTF_MTU))
- sk->mtu = rt->rt_mss;
- else
- {
-#ifdef CONFIG_INET_SNARL
- if ((sk->saddr ^ sk->daddr) & default_mask(sk->saddr))
-#else
- if ((sk->saddr ^ sk->daddr) & dev->pa_mask)
-#endif
- sk->mtu = 576 - HEADER_SIZE;
- else
- sk->mtu = MAX_WINDOW;
- }
- /*
- * but not bigger than device MTU
- */
-
- if(sk->mtu <32)
- sk->mtu = 32; /* Sanity limit */
-
- sk->mtu = min(sk->mtu, dev->mtu - HEADER_SIZE);
-
- /*
- * Put in the TCP options to say MTU.
- */
-
- ptr = (unsigned char *)(t1+1);
- ptr[0] = 2;
- ptr[1] = 4;
- ptr[2] = (sk->mtu) >> 8;
- ptr[3] = (sk->mtu) & 0xff;
- tcp_send_check(t1, sk->saddr, sk->daddr,
- sizeof(struct tcphdr) + 4, sk);
-
- /*
- * This must go first otherwise a really quick response will get reset.
- */
-
- tcp_set_state(sk,TCP_SYN_SENT);
- sk->rto = TCP_TIMEOUT_INIT;
-#if 0 /* we already did this */
- init_timer(&sk->retransmit_timer);
-#endif
- sk->retransmit_timer.function=&retransmit_timer;
- sk->retransmit_timer.data = (unsigned long)sk;
- reset_xmit_timer(sk, TIME_WRITE, sk->rto); /* Timer for repeating the SYN until an answer */
- sk->retransmits = TCP_SYN_RETRIES;
-
- sk->prot->queue_xmit(sk, dev, buff, 0);
- reset_xmit_timer(sk, TIME_WRITE, sk->rto);
- tcp_statistics.TcpActiveOpens++;
- tcp_statistics.TcpOutSegs++;
-
- release_sock(sk);
- return(0);
-}
-
-
-/* This functions checks to see if the tcp header is actually acceptable. */
-extern __inline__ int tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
- struct options *opt, unsigned long saddr, struct device *dev)
-{
- unsigned long next_seq;
-
- next_seq = len - 4*th->doff;
- if (th->fin)
- next_seq++;
- /* if we have a zero window, we can't have any data in the packet.. */
- if (next_seq && !sk->window)
- goto ignore_it;
- next_seq += th->seq;
-
- /*
- * This isn't quite right. sk->acked_seq could be more recent
- * than sk->window. This is however close enough. We will accept
- * slightly more packets than we should, but it should not cause
- * problems unless someone is trying to forge packets.
- */
-
- /* have we already seen all of this packet? */
- if (!after(next_seq+1, sk->acked_seq))
- goto ignore_it;
- /* or does it start beyond the window? */
- if (!before(th->seq, sk->acked_seq + sk->window + 1))
- goto ignore_it;
-
- /* ok, at least part of this packet would seem interesting.. */
- return 1;
-
-ignore_it:
- if (th->rst)
- return 0;
-
- /*
- * Send a reset if we get something not ours and we are
- * unsynchronized. Note: We don't do anything to our end. We
- * are just killing the bogus remote connection then we will
- * connect again and it will work (with luck).
- */
-
- if (sk->state==TCP_SYN_SENT || sk->state==TCP_SYN_RECV)
- {
- tcp_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
- return 1;
- }
-
- /* Try to resync things. */
- tcp_send_ack(sk->sent_seq, sk->acked_seq, sk, th, saddr);
- return 0;
-}
-
-/*
- * When we get a reset we do this.
- */
-
-static int tcp_std_reset(struct sock *sk, struct sk_buff *skb)
-{
- sk->zapped = 1;
- sk->err = ECONNRESET;
- if (sk->state == TCP_SYN_SENT)
- sk->err = ECONNREFUSED;
- if (sk->state == TCP_CLOSE_WAIT)
- sk->err = EPIPE;
-#ifdef TCP_DO_RFC1337
- /*
- * Time wait assassination protection [RFC1337]
- */
- if(sk->state!=TCP_TIME_WAIT)
- {
- tcp_set_state(sk,TCP_CLOSE);
- sk->shutdown = SHUTDOWN_MASK;
- }
-#else
- tcp_set_state(sk,TCP_CLOSE);
- sk->shutdown = SHUTDOWN_MASK;
-#endif
- if (!sk->dead)
- sk->state_change(sk);
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return(0);
-}
-
-/*
- * A TCP packet has arrived.
- */
-
-int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
- unsigned long daddr, unsigned short len,
- unsigned long saddr, int redo, struct inet_protocol * protocol)
-{
- struct tcphdr *th;
- struct sock *sk;
- int syn_ok=0;
-
- if (!skb)
- {
- printk("IMPOSSIBLE 1\n");
- return(0);
- }
-
- if (!dev)
- {
- printk("IMPOSSIBLE 2\n");
- return(0);
- }
-
- tcp_statistics.TcpInSegs++;
-
- if(skb->pkt_type!=PACKET_HOST)
- {
- kfree_skb(skb,FREE_READ);
- return(0);
- }
-
- th = skb->h.th;
-
- /*
- * Find the socket.
- */
-
- sk = get_sock(&tcp_prot, th->dest, saddr, th->source, daddr);
-
- /*
- * If this socket has got a reset it's to all intents and purposes
- * really dead. Count closed sockets as dead.
- *
- * Note: BSD appears to have a bug here. A 'closed' TCP in BSD
- * simply drops data. This seems incorrect as a 'closed' TCP doesn't
- * exist so should cause resets as if the port was unreachable.
- */
-
- if (sk!=NULL && (sk->zapped || sk->state==TCP_CLOSE))
- sk=NULL;
-
- if (!redo)
- {
- if (tcp_check(th, len, saddr, daddr ))
- {
- skb->sk = NULL;
- kfree_skb(skb,FREE_READ);
- /*
- * We don't release the socket because it was
- * never marked in use.
- */
- return(0);
- }
- th->seq = ntohl(th->seq);
-
- /* See if we know about the socket. */
- if (sk == NULL)
- {
- /*
- * No such TCB. If th->rst is 0 send a reset (checked in tcp_reset)
- */
- tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255);
- skb->sk = NULL;
- /*
- * Discard frame
- */
- kfree_skb(skb, FREE_READ);
- return(0);
- }
-
- skb->len = len;
- skb->acked = 0;
- skb->used = 0;
- skb->free = 0;
- skb->saddr = daddr;
- skb->daddr = saddr;
-
- /* We may need to add it to the backlog here. */
- cli();
- if (sk->inuse)
- {
- skb_queue_tail(&sk->back_log, skb);
- sti();
- return(0);
- }
- sk->inuse = 1;
- sti();
- }
- else
- {
- if (sk==NULL)
- {
- tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255);
- skb->sk = NULL;
- kfree_skb(skb, FREE_READ);
- return(0);
- }
- }
-
-
- if (!sk->prot)
- {
- printk("IMPOSSIBLE 3\n");
- return(0);
- }
-
-
- /*
- * Charge the memory to the socket.
- */
-
- if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
- {
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return(0);
- }
-
- skb->sk=sk;
- sk->rmem_alloc += skb->mem_len;
-
- /*
- * This basically follows the flow suggested by RFC793, with the corrections in RFC1122. We
- * don't implement precedence and we process URG incorrectly (deliberately so) for BSD bug
- * compatibility. We also set up variables more thoroughly [Karn notes in the
- * KA9Q code the RFC793 incoming segment rules don't initialise the variables for all paths].
- */
-
- if(sk->state!=TCP_ESTABLISHED) /* Skip this lot for normal flow */
- {
-
- /*
- * Now deal with unusual cases.
- */
-
- if(sk->state==TCP_LISTEN)
- {
- if(th->ack) /* These use the socket TOS.. might want to be the received TOS */
- tcp_reset(daddr,saddr,th,sk->prot,opt,dev,sk->ip_tos, sk->ip_ttl);
-
- /*
- * We don't care for RST, and non SYN are absorbed (old segments)
- * Broadcast/multicast SYN isn't allowed. Note - bug if you change the
- * netmask on a running connection it can go broadcast. Even Sun's have
- * this problem so I'm ignoring it
- */
-
- if(th->rst || !th->syn || th->ack || ip_chk_addr(daddr)!=IS_MYADDR)
- {
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return 0;
- }
-
- /*
- * Guess we need to make a new socket up
- */
-
- tcp_conn_request(sk, skb, daddr, saddr, opt, dev, tcp_init_seq());
-
- /*
- * Now we have several options: In theory there is nothing else
- * in the frame. KA9Q has an option to send data with the syn,
- * BSD accepts data with the syn up to the [to be] advertised window
- * and Solaris 2.1 gives you a protocol error. For now we just ignore
- * it, that fits the spec precisely and avoids incompatibilities. It
- * would be nice in future to drop through and process the data.
- */
-
- release_sock(sk);
- return 0;
- }
-
- /* retransmitted SYN? */
- if (sk->state == TCP_SYN_RECV && th->syn && th->seq+1 == sk->acked_seq)
- {
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return 0;
- }
-
- /*
- * SYN sent means we have to look for a suitable ack and either reset
- * for bad matches or go to connected
- */
-
- if(sk->state==TCP_SYN_SENT)
- {
- /* Crossed SYN or previous junk segment */
- if(th->ack)
- {
- /* We got an ack, but it's not a good ack */
- if(!tcp_ack(sk,th,saddr,len))
- {
- /* Reset the ack - its an ack from a
- different connection [ th->rst is checked in tcp_reset()] */
- tcp_statistics.TcpAttemptFails++;
- tcp_reset(daddr, saddr, th,
- sk->prot, opt,dev,sk->ip_tos,sk->ip_ttl);
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return(0);
- }
- if(th->rst)
- return tcp_std_reset(sk,skb);
- if(!th->syn)
- {
- /* A valid ack from a different connection
- start. Shouldn't happen but cover it */
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return 0;
- }
- /*
- * Ok.. it's good. Set up sequence numbers and
- * move to established.
- */
- syn_ok=1; /* Don't reset this connection for the syn */
- sk->acked_seq=th->seq+1;
- sk->fin_seq=th->seq;
- tcp_send_ack(sk->sent_seq,sk->acked_seq,sk,th,sk->daddr);
- tcp_set_state(sk, TCP_ESTABLISHED);
- tcp_options(sk,th);
- sk->dummy_th.dest=th->source;
- sk->copied_seq = sk->acked_seq;
- if(!sk->dead)
- {
- sk->state_change(sk);
- sock_wake_async(sk->socket, 0);
- }
- if(sk->max_window==0)
- {
- sk->max_window = 32;
- sk->mss = min(sk->max_window, sk->mtu);
- }
- }
- else
- {
- /* See if SYN's cross. Drop if boring */
- if(th->syn && !th->rst)
- {
- /* Crossed SYN's are fine - but talking to
- yourself is right out... */
- if(sk->saddr==saddr && sk->daddr==daddr &&
- sk->dummy_th.source==th->source &&
- sk->dummy_th.dest==th->dest)
- {
- tcp_statistics.TcpAttemptFails++;
- return tcp_std_reset(sk,skb);
- }
- tcp_set_state(sk,TCP_SYN_RECV);
-
- /*
- * FIXME:
- * Must send SYN|ACK here
- */
- }
- /* Discard junk segment */
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return 0;
- }
- /*
- * SYN_RECV with data maybe.. drop through
- */
- goto rfc_step6;
- }
-
- /*
- * BSD has a funny hack with TIME_WAIT and fast reuse of a port. There is
- * a more complex suggestion for fixing these reuse issues in RFC1644
- * but not yet ready for general use. Also see RFC1379.
- */
-
-#define BSD_TIME_WAIT
-#ifdef BSD_TIME_WAIT
- if (sk->state == TCP_TIME_WAIT && th->syn && sk->dead &&
- after(th->seq, sk->acked_seq) && !th->rst)
- {
- long seq=sk->write_seq;
- if(sk->debug)
- printk("Doing a BSD time wait\n");
- tcp_statistics.TcpEstabResets++;
- sk->rmem_alloc -= skb->mem_len;
- skb->sk = NULL;
- sk->err=ECONNRESET;
- tcp_set_state(sk, TCP_CLOSE);
- sk->shutdown = SHUTDOWN_MASK;
- release_sock(sk);
- sk=get_sock(&tcp_prot, th->dest, saddr, th->source, daddr);
- if (sk && sk->state==TCP_LISTEN)
- {
- sk->inuse=1;
- skb->sk = sk;
- sk->rmem_alloc += skb->mem_len;
- tcp_conn_request(sk, skb, daddr, saddr,opt, dev,seq+128000);
- release_sock(sk);
- return 0;
- }
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-#endif
- }
-
- /*
- * We are now in normal data flow (see the step list in the RFC)
- * Note most of these are inline now. I'll inline the lot when
- * I have time to test it hard and look at what gcc outputs
- */
-
- if(!tcp_sequence(sk,th,len,opt,saddr,dev))
- {
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return 0;
- }
-
- if(th->rst)
- return tcp_std_reset(sk,skb);
-
- /*
- * !syn_ok is effectively the state test in RFC793.
- */
-
- if(th->syn && !syn_ok)
- {
- tcp_reset(daddr,saddr,th, &tcp_prot, opt, dev, skb->ip_hdr->tos, 255);
- return tcp_std_reset(sk,skb);
- }
-
- /*
- * Process the ACK
- */
-
-
- if(th->ack && !tcp_ack(sk,th,saddr,len))
- {
- /*
- * Our three way handshake failed.
- */
-
- if(sk->state==TCP_SYN_RECV)
- {
- tcp_reset(daddr, saddr, th,sk->prot, opt, dev,sk->ip_tos,sk->ip_ttl);
- }
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return 0;
- }
-
-rfc_step6: /* I'll clean this up later */
-
- /*
- * Process urgent data
- */
-
- if(tcp_urg(sk, th, saddr, len))
- {
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return 0;
- }
-
-
- /*
- * Process the encapsulated data
- */
-
- if(tcp_data(skb,sk, saddr, len))
- {
- kfree_skb(skb, FREE_READ);
- release_sock(sk);
- return 0;
- }
-
- /*
- * And done
- */
-
- release_sock(sk);
- return 0;
-}
-
-/*
- * This routine sends a packet with an out of date sequence
- * number. It assumes the other end will try to ack it.
- */
-
-static void tcp_write_wakeup(struct sock *sk)
-{
- struct sk_buff *buff;
- struct tcphdr *t1;
- struct device *dev=NULL;
- int tmp;
-
- if (sk->zapped)
- return; /* After a valid reset we can send no more */
-
- /*
- * Write data can still be transmitted/retransmitted in the
- * following states. If any other state is encountered, return.
- * [listen/close will never occur here anyway]
- */
-
- if (sk->state != TCP_ESTABLISHED &&
- sk->state != TCP_CLOSE_WAIT &&
- sk->state != TCP_FIN_WAIT1 &&
- sk->state != TCP_LAST_ACK &&
- sk->state != TCP_CLOSING
- )
- {
- return;
- }
-
- buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
- if (buff == NULL)
- return;
-
- buff->len = sizeof(struct tcphdr);
- buff->free = 1;
- buff->sk = sk;
- buff->localroute = sk->localroute;
-
- t1 = (struct tcphdr *) buff->data;
-
- /* Put in the IP header and routing stuff. */
- tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
- if (tmp < 0)
- {
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
- return;
- }
-
- buff->len += tmp;
- t1 = (struct tcphdr *)((char *)t1 +tmp);
-
- memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
-
- /*
- * Use a previous sequence.
- * This should cause the other end to send an ack.
- */
-
- t1->seq = htonl(sk->sent_seq-1);
- t1->ack = 1;
- t1->res1= 0;
- t1->res2= 0;
- t1->rst = 0;
- t1->urg = 0;
- t1->psh = 0;
- t1->fin = 0; /* We are sending a 'previous' sequence, and 0 bytes of data - thus no FIN bit */
- t1->syn = 0;
- t1->ack_seq = ntohl(sk->acked_seq);
- t1->window = ntohs(tcp_select_window(sk));
- t1->doff = sizeof(*t1)/4;
- tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
- /*
- * Send it and free it.
- * This will prevent the timer from automatically being restarted.
- */
- sk->prot->queue_xmit(sk, dev, buff, 1);
- tcp_statistics.TcpOutSegs++;
-}
-
-/*
- * A window probe timeout has occurred.
- */
-
-void tcp_send_probe0(struct sock *sk)
-{
- if (sk->zapped)
- return; /* After a valid reset we can send no more */
-
- tcp_write_wakeup(sk);
-
- sk->backoff++;
- sk->rto = min(sk->rto << 1, 120*HZ);
- reset_xmit_timer (sk, TIME_PROBE0, sk->rto);
- sk->retransmits++;
- sk->prot->retransmits ++;
-}
-
-/*
- * Socket option code for TCP.
- */
-
-int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
-{
- int val,err;
-
- if(level!=SOL_TCP)
- return ip_setsockopt(sk,level,optname,optval,optlen);
-
- if (optval == NULL)
- return(-EINVAL);
-
- err=verify_area(VERIFY_READ, optval, sizeof(int));
- if(err)
- return err;
-
- val = get_fs_long((unsigned long *)optval);
-
- switch(optname)
- {
- case TCP_MAXSEG:
-/*
- * values greater than interface MTU won't take effect. however at
- * the point when this call is done we typically don't yet know
- * which interface is going to be used
- */
- if(val<1||val>MAX_WINDOW)
- return -EINVAL;
- sk->user_mss=val;
- return 0;
- case TCP_NODELAY:
- sk->nonagle=(val==0)?0:1;
- return 0;
- default:
- return(-ENOPROTOOPT);
- }
-}
-
-int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
-{
- int val,err;
-
- if(level!=SOL_TCP)
- return ip_getsockopt(sk,level,optname,optval,optlen);
-
- switch(optname)
- {
- case TCP_MAXSEG:
- val=sk->user_mss;
- break;
- case TCP_NODELAY:
- val=sk->nonagle;
- break;
- default:
- return(-ENOPROTOOPT);
- }
- err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
- if(err)
- return err;
- put_fs_long(sizeof(int),(unsigned long *) optlen);
-
- err=verify_area(VERIFY_WRITE, optval, sizeof(int));
- if(err)
- return err;
- put_fs_long(val,(unsigned long *)optval);
-
- return(0);
-}
-
-
-struct proto tcp_prot = {
- sock_wmalloc,
- sock_rmalloc,
- sock_wfree,
- sock_rfree,
- sock_rspace,
- sock_wspace,
- tcp_close,
- tcp_read,
- tcp_write,
- tcp_sendto,
- tcp_recvfrom,
- ip_build_header,
- tcp_connect,
- tcp_accept,
- ip_queue_xmit,
- tcp_retransmit,
- tcp_write_wakeup,
- tcp_read_wakeup,
- tcp_rcv,
- tcp_select,
-#ifdef _HURD_
- NULL,
-#else
- tcp_ioctl,
-#endif
- NULL,
- tcp_shutdown,
- tcp_setsockopt,
- tcp_getsockopt,
- 128,
- 0,
- {NULL,},
- "TCP",
- 0, 0
-};
-
-/*
- * This routine computes a TCP checksum.
- */
-
-unsigned short tcp_check(struct tcphdr *th, int len,
- unsigned long saddr, unsigned long daddr)
-{
- unsigned long sum;
-
- if (saddr == 0) saddr = ip_my_addr();
-
-/*
- * stupid, gcc complains when I use just one __asm__ block,
- * something about too many reloads, but this is just two
- * instructions longer than what I want
- */
- __asm__("
- addl %%ecx, %%ebx
- adcl %%edx, %%ebx
- adcl $0, %%ebx
- "
- : "=b"(sum)
- : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256)
- : "bx", "cx", "dx" );
- __asm__("
- movl %%ecx, %%edx
- cld
- cmpl $32, %%ecx
- jb 2f
- shrl $5, %%ecx
- clc
-1: lodsl
- adcl %%eax, %%ebx
- lodsl
- adcl %%eax, %%ebx
- lodsl
- adcl %%eax, %%ebx
- lodsl
- adcl %%eax, %%ebx
- lodsl
- adcl %%eax, %%ebx
- lodsl
- adcl %%eax, %%ebx
- lodsl
- adcl %%eax, %%ebx
- lodsl
- adcl %%eax, %%ebx
- loop 1b
- adcl $0, %%ebx
- movl %%edx, %%ecx
-2: andl $28, %%ecx
- je 4f
- shrl $2, %%ecx
- clc
-3: lodsl
- adcl %%eax, %%ebx
- loop 3b
- adcl $0, %%ebx
-4: movl $0, %%eax
- testw $2, %%dx
- je 5f
- lodsw
- addl %%eax, %%ebx
- adcl $0, %%ebx
- movw $0, %%ax
-5: test $1, %%edx
- je 6f
- lodsb
- addl %%eax, %%ebx
- adcl $0, %%ebx
-6: movl %%ebx, %%eax
- shrl $16, %%eax
- addw %%ax, %%bx
- adcw $0, %%bx
- "
- : "=b"(sum)
- : "0"(sum), "c"(len), "S"(th)
- : "ax", "bx", "cx", "dx", "si" );
-
- /* We only want the bottom 16 bits, but we never cleared the top 16. */
-
- return((~sum) & 0xffff);
-}
-
diff --git a/pfinet/linux-inet/tcp.h b/pfinet/linux-inet/tcp.h
deleted file mode 100644
index 016fa6dd..00000000
--- a/pfinet/linux-inet/tcp.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the TCP module.
- *
- * Version: @(#)tcp.h 1.0.5 05/23/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _TCP_H
-#define _TCP_H
-
-#include <linux/tcp.h>
-
-#define MAX_SYN_SIZE 44 + MAX_HEADER
-#define MAX_FIN_SIZE 40 + MAX_HEADER
-#define MAX_ACK_SIZE 40 + MAX_HEADER
-#define MAX_RESET_SIZE 40 + MAX_HEADER
-#define MAX_WINDOW 16384
-#define MIN_WINDOW 2048
-#define MAX_ACK_BACKLOG 2
-#define MIN_WRITE_SPACE 2048
-#define TCP_WINDOW_DIFF 2048
-
-/* urg_data states */
-#define URG_VALID 0x0100
-#define URG_NOTYET 0x0200
-#define URG_READ 0x0400
-
-#define TCP_RETR1 7 /*
- * This is how many retries it does before it
- * tries to figure out if the gateway is
- * down.
- */
-
-#define TCP_RETR2 15 /*
- * This should take at least
- * 90 minutes to time out.
- */
-
-#define TCP_TIMEOUT_LEN (15*60*HZ) /* should be about 15 mins */
-#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to successfully
- * close the socket, about 60 seconds */
-#define TCP_FIN_TIMEOUT (3*60*HZ) /* BSD style FIN_WAIT2 deadlock breaker */
-#define TCP_ACK_TIME (3*HZ) /* time to delay before sending an ACK */
-#define TCP_DONE_TIME 250 /* maximum time to wait before actually
- * destroying a socket */
-#define TCP_WRITE_TIME 3000 /* initial time to wait for an ACK,
- * after last transmit */
-#define TCP_TIMEOUT_INIT (3*HZ) /* RFC 1122 initial timeout value */
-#define TCP_SYN_RETRIES 5 /* number of times to retry opening a
- * connection */
-#define TCP_PROBEWAIT_LEN 100 /* time to wait between probes when
- * I've got something to write and
- * there is no window */
-
-#define TCP_NO_CHECK 0 /* turn to one if you want the default
- * to be no checksum */
-
-
-/*
- * TCP option
- */
-
-#define TCPOPT_NOP 1 /* Padding */
-#define TCPOPT_EOL 0 /* End of options */
-#define TCPOPT_MSS 2 /* Segment size negotiating */
-/*
- * We don't use these yet, but they are for PAWS and big windows
- */
-#define TCPOPT_WINDOW 3 /* Window scaling */
-#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
-
-
-/*
- * The next routines deal with comparing 32 bit unsigned ints
- * and worry about wraparound (automatic with unsigned arithmetic).
- */
-
-extern __inline int before(unsigned long seq1, unsigned long seq2)
-{
- return (long)(seq1-seq2) < 0;
-}
-
-extern __inline int after(unsigned long seq1, unsigned long seq2)
-{
- return (long)(seq1-seq2) > 0;
-}
-
-
-/* is s2<=s1<=s3 ? */
-extern __inline int between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
-{
- return (after(seq1+1, seq2) && before(seq1, seq3+1));
-}
-
-
-/*
- * List all states of a TCP socket that can be viewed as a "connected"
- * state. This now includes TCP_SYN_RECV, although I am not yet fully
- * convinced that this is the solution for the 'getpeername(2)'
- * problem. Thanks to Stephen A. Wood <saw@cebaf.gov> -FvK
- */
-extern __inline const int
-tcp_connected(const int state)
-{
- return(state == TCP_ESTABLISHED || state == TCP_CLOSE_WAIT ||
- state == TCP_FIN_WAIT1 || state == TCP_FIN_WAIT2 ||
- state == TCP_SYN_RECV);
-}
-
-
-extern struct proto tcp_prot;
-
-
-extern void tcp_err(int err, unsigned char *header, unsigned long daddr,
- unsigned long saddr, struct inet_protocol *protocol);
-extern void tcp_shutdown (struct sock *sk, int how);
-extern int tcp_rcv(struct sk_buff *skb, struct device *dev,
- struct options *opt, unsigned long daddr,
- unsigned short len, unsigned long saddr, int redo,
- struct inet_protocol *protocol);
-
-extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
-
-extern int tcp_select_window(struct sock *sk);
-extern void tcp_send_check(struct tcphdr *th, unsigned long saddr,
- unsigned long daddr, int len, struct sock *sk);
-extern void tcp_send_probe0(struct sock *sk);
-extern void tcp_enqueue_partial(struct sk_buff *, struct sock *);
-extern struct sk_buff * tcp_dequeue_partial(struct sock *);
-
-
-#endif /* _TCP_H */
diff --git a/pfinet/linux-inet/timer.c b/pfinet/linux-inet/timer.c
deleted file mode 100644
index 4fbbc74b..00000000
--- a/pfinet/linux-inet/timer.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * TIMER - implementation of software timers for IP.
- *
- * Version: @(#)timer.c 1.0.7 05/25/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Corey Minyard <wf-rch!minyard@relay.EU.net>
- * Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
- * Florian La Roche, <flla@stud.uni-sb.de>
- *
- * Fixes:
- * Alan Cox : To avoid destroying a wait queue as we use it
- * we defer destruction until the destroy timer goes
- * off.
- * Alan Cox : Destroy socket doesn't write a status value to the
- * socket buffer _AFTER_ freeing it! Also sock ensures
- * the socket will get removed BEFORE this is called
- * otherwise if the timer TIME_DESTROY occurs inside
- * of inet_bh() with this socket being handled it goes
- * BOOM! Have to stop timer going off if net_bh is
- * active or the destroy causes crashes.
- * Alan Cox : Cleaned up unused code.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <asm/system.h>
-#include <linux/interrupt.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "arp.h"
-
-void delete_timer (struct sock *t)
-{
- unsigned long flags;
-
- save_flags (flags);
- cli();
-
- t->timeout = 0;
- del_timer (&t->timer);
-
- restore_flags (flags);
-}
-
-void reset_timer (struct sock *t, int timeout, unsigned long len)
-{
- delete_timer (t);
- t->timeout = timeout;
-#if 1
- /* FIXME: ??? */
- if ((int) len < 0) /* prevent close to infinite timers. THEY _DO_ */
- len = 3; /* happen (negative values ?) - don't ask me why ! -FB */
-#endif
- t->timer.expires = len;
- add_timer (&t->timer);
-}
-
-
-/*
- * Now we will only be called whenever we need to do
- * something, but we must be sure to process all of the
- * sockets that need it.
- */
-
-void net_timer (unsigned long data)
-{
- struct sock *sk = (struct sock*)data;
- int why = sk->timeout;
-
- /*
- * only process if socket is not in use
- */
-
- cli();
- if (sk->inuse || in_bh)
- {
- sk->timer.expires = 10;
- add_timer(&sk->timer);
- sti();
- return;
- }
-
- sk->inuse = 1;
- sti();
-
- /* Always see if we need to send an ack. */
-
- if (sk->ack_backlog && !sk->zapped)
- {
- sk->prot->read_wakeup (sk);
- if (! sk->dead)
- sk->data_ready(sk,0);
- }
-
- /* Now we need to figure out why the socket was on the timer. */
-
- switch (why)
- {
- case TIME_DONE:
- if (! sk->dead || sk->state != TCP_CLOSE)
- {
- printk ("non dead socket in time_done\n");
- release_sock (sk);
- break;
- }
- destroy_sock (sk);
- break;
-
- case TIME_DESTROY:
- /*
- * We've waited for a while for all the memory associated with
- * the socket to be freed.
- */
- if(sk->wmem_alloc!=0 || sk->rmem_alloc!=0)
- {
- sk->wmem_alloc++; /* So it DOESN'T go away */
- destroy_sock (sk);
- sk->wmem_alloc--; /* Might now have hit 0 - fall through and do it again if so */
- sk->inuse = 0; /* This will be ok, the destroy won't totally work */
- }
- if(sk->wmem_alloc==0 && sk->rmem_alloc==0)
- destroy_sock(sk); /* Socket gone, DON'T update sk->inuse! */
- break;
- case TIME_CLOSE:
- /* We've waited long enough, close the socket. */
- sk->state = TCP_CLOSE;
- delete_timer (sk);
- /* Kill the ARP entry in case the hardware has changed. */
- arp_destroy (sk->daddr, 0);
- if (!sk->dead)
- sk->state_change(sk);
- sk->shutdown = SHUTDOWN_MASK;
- reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME);
- release_sock (sk);
- break;
-#if 0
- case TIME_PROBE0:
- tcp_send_probe0(sk);
- release_sock (sk);
- break;
- case TIME_WRITE: /* try to retransmit. */
- /* It could be we got here because we needed to send an ack.
- * So we need to check for that.
- */
- {
- struct sk_buff *skb;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- skb = sk->send_head;
- if (!skb)
- {
- restore_flags(flags);
- }
- else
- {
- if (jiffies < skb->when + sk->rto)
- {
- reset_timer (sk, TIME_WRITE, skb->when + sk->rto - jiffies);
- restore_flags(flags);
- release_sock (sk);
- break;
- }
- restore_flags(flags);
- /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq,
- sk->retransmits, sk->packets_out, sk->cong_window); */
- sk->prot->retransmit (sk, 0);
- if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
- || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1))
- {
- arp_destroy (sk->daddr, 0);
- ip_route_check (sk->daddr);
- }
- if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2)
- {
- sk->err = ETIMEDOUT;
- if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 || sk->state == TCP_CLOSING)
- {
- sk->state = TCP_TIME_WAIT;
- reset_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
- }
- else
- {
- sk->prot->close (sk, 1);
- break;
- }
- }
- }
- release_sock (sk);
- break;
- }
- case TIME_KEEPOPEN:
- /*
- * this reset_timer() call is a hack, this is not
- * how KEEPOPEN is supposed to work.
- */
- reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
-
- /* Send something to keep the connection open. */
- if (sk->prot->write_wakeup)
- sk->prot->write_wakeup (sk);
- sk->retransmits++;
- if (sk->shutdown == SHUTDOWN_MASK)
- {
- sk->prot->close (sk, 1);
- sk->state = TCP_CLOSE;
- }
- if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
- || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1))
- {
- arp_destroy (sk->daddr, 0);
- ip_route_check (sk->daddr);
- release_sock (sk);
- break;
- }
- if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2)
- {
- arp_destroy (sk->daddr, 0);
- sk->err = ETIMEDOUT;
- if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2)
- {
- sk->state = TCP_TIME_WAIT;
- if (!sk->dead)
- sk->state_change(sk);
- release_sock (sk);
- }
- else
- {
- sk->prot->close (sk, 1);
- }
- break;
- }
- release_sock (sk);
- break;
-#endif
- default:
- printk ("net_timer: timer expired - reason %d is unknown\n", why);
- release_sock (sk);
- break;
- }
-}
-
diff --git a/pfinet/linux-inet/udp.c b/pfinet/linux-inet/udp.c
deleted file mode 100644
index 420f24b3..00000000
--- a/pfinet/linux-inet/udp.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * The User Datagram Protocol (UDP).
- *
- * Version: @(#)udp.c 1.0.13 06/02/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Fixes:
- * Alan Cox : verify_area() calls
- * Alan Cox : stopped close while in use off icmp
- * messages. Not a fix but a botch that
- * 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
- * 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
- * Alan Cox : send to an unknown connection causes
- * an ECONNREFUSED off the icmp, but
- * does NOT close.
- * Alan Cox : Switched to new sk_buff handlers. No more backlog!
- * Alan Cox : Using generic datagram code. Even smaller and the PEEK
- * bug no longer crashes it.
- * Fred Van Kempen : Net2e support for sk->broadcast.
- * Alan Cox : Uses skb_free_datagram
- * Alan Cox : Added get/set sockopt support.
- * Alan Cox : Broadcasting without option set returns EACCES.
- * Alan Cox : No wakeup calls. Instead we now use the callbacks.
- * Alan Cox : Use ip_tos and ip_ttl
- * Alan Cox : SNMP Mibs
- * Alan Cox : MSG_DONTROUTE, and 0.0.0.0 support.
- * Matt Dillon : UDP length checks.
- * Alan Cox : Smarter af_inet used properly.
- * Alan Cox : Use new kernel side addressing.
- * Alan Cox : Incorrect return on truncated datagram receive.
- *
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/fcntl.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/termios.h>
-#include <linux/mm.h>
-#include <linux/config.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include "snmp.h"
-#include "ip.h"
-#include "protocol.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-#include "sock.h"
-#include "udp.h"
-#include "icmp.h"
-#include "route.h"
-
-/*
- * SNMP MIB for the UDP layer
- */
-
-struct udp_mib udp_statistics;
-
-
-static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len);
-
-#define min(a,b) ((a)<(b)?(a):(b))
-
-
-/*
- * 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.
- * 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
- * to find the appropriate port.
- */
-
-void udp_err(int err, unsigned char *header, unsigned long daddr,
- unsigned long saddr, struct inet_protocol *protocol)
-{
- struct udphdr *th;
- struct sock *sk;
- struct iphdr *ip=(struct iphdr *)header;
-
- header += 4*ip->ihl;
-
- /*
- * Find the 8 bytes of post IP header ICMP included for us
- */
-
- th = (struct udphdr *)header;
-
- sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
-
- if (sk == NULL)
- return; /* No socket for error */
-
- if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8))
- { /* Slow down! */
- if (sk->cong_window > 1)
- sk->cong_window = sk->cong_window/2;
- return;
- }
-
- /*
- * 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
- * client code people.
- */
-
-#ifdef CONFIG_I_AM_A_BROKEN_BSD_WEENIE
- /*
- * It's only fatal if we have connected to them. I'm not happy
- * with this code. Some BSD comparisons need doing.
- */
-
- if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED)
- {
- sk->err = icmp_err_convert[err & 0xff].errno;
- sk->error_report(sk);
- }
-#else
- if (icmp_err_convert[err & 0xff].fatal)
- {
- sk->err = icmp_err_convert[err & 0xff].error;
- sk->error_report(sk);
- }
-#endif
-}
-
-
-
-/*
- * Generate UDP checksums. These may be disabled, eg for fast NFS over ethernet
- * We default them enabled.. if you turn them off you either know what you are
- * doing or get burned...
- */
-
-static void udp_send_check(struct udphdr *uh, unsigned long saddr,
- unsigned long daddr, int len, struct sock *sk)
-{
- uh->check = 0;
- if (sk && sk->no_check)
- return;
- uh->check = udp_check(uh, len, saddr, daddr);
-
- /*
- * FFFF and 0 are the same, pick the right one as 0 in the
- * actual field means no checksum.
- */
-
- if (uh->check == 0)
- uh->check = 0xffff;
-}
-
-
-static int udp_send(struct sock *sk, struct sockaddr_in *sin,
- unsigned char *from, int len, int rt)
-{
- struct sk_buff *skb;
- struct device *dev;
- struct udphdr *uh;
- unsigned char *buff;
- unsigned long saddr;
- int size, tmp;
- int ttl;
-
- /*
- * Allocate an sk_buff copy of the packet.
- */
-
- size = sk->prot->max_header + len;
- skb = sock_alloc_send_skb(sk, size, 0, &tmp);
-
-
- if (skb == NULL)
- return tmp;
-
- skb->sk = NULL; /* to avoid changing sk->saddr */
- skb->free = 1;
- skb->localroute = sk->localroute|(rt&MSG_DONTROUTE);
-
- /*
- * Now build the IP and MAC header.
- */
-
- buff = skb->data;
- saddr = sk->saddr;
- dev = NULL;
- ttl = sk->ip_ttl;
-#ifdef CONFIG_IP_MULTICAST
- if (MULTICAST(sin->sin_addr.s_addr))
- ttl = sk->ip_mc_ttl;
-#endif
- tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
- &dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,ttl);
-
- skb->sk=sk; /* So memory is freed correctly */
-
- /*
- * Unable to put a header on the packet.
- */
-
- if (tmp < 0 )
- {
- sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
- return(tmp);
- }
-
- buff += tmp;
- saddr = skb->saddr; /*dev->pa_addr;*/
- skb->len = tmp + sizeof(struct udphdr) + len; /* len + UDP + IP + MAC */
- skb->dev = dev;
-
- /*
- * Fill in the UDP header.
- */
-
- uh = (struct udphdr *) buff;
- uh->len = htons(len + sizeof(struct udphdr));
- uh->source = sk->dummy_th.source;
- uh->dest = sin->sin_port;
- buff = (unsigned char *) (uh + 1);
-
- /*
- * Copy the user data.
- */
-
- memcpy_fromfs(buff, from, len);
-
- /*
- * Set up the UDP checksum.
- */
-
- udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
-
- /*
- * Send the datagram to the interface.
- */
-
- udp_statistics.UdpOutDatagrams++;
-
- sk->prot->queue_xmit(sk, dev, skb, 1);
- return(len);
-}
-
-
-static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
- unsigned flags, struct sockaddr_in *usin, int addr_len)
-{
- struct sockaddr_in sin;
- int tmp;
-
- /*
- * Check the flags. We support no flags for UDP sending
- */
- if (flags&~MSG_DONTROUTE)
- return(-EINVAL);
- /*
- * Get and verify the address.
- */
-
- if (usin)
- {
- if (addr_len < sizeof(sin))
- return(-EINVAL);
- memcpy(&sin,usin,sizeof(sin));
- if (sin.sin_family && sin.sin_family != AF_INET)
- return(-EINVAL);
- if (sin.sin_port == 0)
- return(-EINVAL);
- }
- else
- {
- if (sk->state != TCP_ESTABLISHED)
- return(-EINVAL);
- sin.sin_family = AF_INET;
- sin.sin_port = sk->dummy_th.dest;
- sin.sin_addr.s_addr = sk->daddr;
- }
-
- /*
- * BSD socket semantics. You must set SO_BROADCAST to permit
- * broadcasting of data.
- */
-
- if(sin.sin_addr.s_addr==INADDR_ANY)
- sin.sin_addr.s_addr=ip_my_addr();
-
- if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
- return -EACCES; /* Must turn broadcast on first */
-
- sk->inuse = 1;
-
- /* Send the packet. */
- tmp = udp_send(sk, &sin, from, len, flags);
-
- /* The datagram has been sent off. Release the socket. */
- release_sock(sk);
- return(tmp);
-}
-
-/*
- * In BSD SOCK_DGRAM a write is just like a send.
- */
-
-static int udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
- unsigned flags)
-{
- return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
-}
-
-
-#ifndef _HURD_
-/*
- * IOCTL requests applicable to the UDP protocol
- */
-
-int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
-{
- int err;
- switch(cmd)
- {
- case TIOCOUTQ:
- {
- unsigned long amount;
-
- if (sk->state == TCP_LISTEN) return(-EINVAL);
- amount = sk->prot->wspace(sk)/*/2*/;
- err=verify_area(VERIFY_WRITE,(void *)arg,
- sizeof(unsigned long));
- if(err)
- return(err);
- put_fs_long(amount,(unsigned long *)arg);
- return(0);
- }
-
- case TIOCINQ:
- {
- struct sk_buff *skb;
- unsigned long amount;
-
- if (sk->state == TCP_LISTEN) return(-EINVAL);
- amount = 0;
- skb = skb_peek(&sk->receive_queue);
- if (skb != NULL) {
- /*
- * We will only return the amount
- * of this packet since that is all
- * that will be read.
- */
- amount = skb->len;
- }
- err=verify_area(VERIFY_WRITE,(void *)arg,
- sizeof(unsigned long));
- if(err)
- return(err);
- put_fs_long(amount,(unsigned long *)arg);
- return(0);
- }
-
- default:
- return(-EINVAL);
- }
- return(0);
-}
-#endif
-
-/*
- * This should be easy, if there is something there we\
- * return it, otherwise we block.
- */
-
-int udp_recvfrom(struct sock *sk, unsigned char *to, int len,
- int noblock, unsigned flags, struct sockaddr_in *sin,
- int *addr_len)
-{
- int copied = 0;
- int truesize;
- struct sk_buff *skb;
- int er;
-
- /*
- * Check any passed addresses
- */
-
- if (addr_len)
- *addr_len=sizeof(*sin);
-
- /*
- * From here the generic datagram does a lot of the work. Come
- * the finished NET3, it will do _ALL_ the work!
- */
-
- skb=skb_recv_datagram(sk,flags,noblock,&er);
- if(skb==NULL)
- return er;
-
- truesize = skb->len;
- copied = min(len, truesize);
-
- /*
- * FIXME : should use udp header size info value
- */
-
- skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
- sk->stamp=skb->stamp;
-
- /* Copy the address. */
- if (sin)
- {
- sin->sin_family = AF_INET;
- sin->sin_port = skb->h.uh->source;
- sin->sin_addr.s_addr = skb->daddr;
- }
-
- skb_free_datagram(skb);
- release_sock(sk);
- return(truesize);
-}
-
-/*
- * Read has the same semantics as recv in SOCK_DGRAM
- */
-
-int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
- unsigned flags)
-{
- return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
-}
-
-
-int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
-{
- struct rtable *rt;
- unsigned long sa;
- if (addr_len < sizeof(*usin))
- return(-EINVAL);
-
- if (usin->sin_family && usin->sin_family != AF_INET)
- return(-EAFNOSUPPORT);
- if (usin->sin_addr.s_addr==INADDR_ANY)
- usin->sin_addr.s_addr=ip_my_addr();
-
- if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
- return -EACCES; /* Must turn broadcast on first */
-
- rt=ip_rt_route(usin->sin_addr.s_addr, NULL, &sa);
- if(rt==NULL)
- return -ENETUNREACH;
- sk->saddr = sa; /* Update source address */
- sk->daddr = usin->sin_addr.s_addr;
- sk->dummy_th.dest = usin->sin_port;
- sk->state = TCP_ESTABLISHED;
- return(0);
-}
-
-
-static void udp_close(struct sock *sk, int timeout)
-{
- sk->inuse = 1;
- sk->state = TCP_CLOSE;
- if (sk->dead)
- destroy_sock(sk);
- else
- release_sock(sk);
-}
-
-
-/*
- * All we need to do is get the socket, and then do a checksum.
- */
-
-int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
- unsigned long daddr, unsigned short len,
- unsigned long saddr, int redo, struct inet_protocol *protocol)
-{
- struct sock *sk;
- struct udphdr *uh;
- unsigned short ulen;
- int addr_type = IS_MYADDR;
-
- if(!dev || dev->pa_addr!=daddr)
- addr_type=ip_chk_addr(daddr);
-
- /*
- * Get the header.
- */
- uh = (struct udphdr *) skb->h.uh;
-
- ip_statistics.IpInDelivers++;
-
- /*
- * Validate the packet and the UDP length.
- */
-
- ulen = ntohs(uh->len);
-
- if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh))
- {
- printk("UDP: short packet: %d/%d\n", ulen, len);
- udp_statistics.UdpInErrors++;
- kfree_skb(skb, FREE_WRITE);
- return(0);
- }
-
- if (uh->check && udp_check(uh, len, saddr, daddr))
- {
- /* <mea@utu.fi> wants to know, who sent it, to
- go and stomp on the garbage sender... */
- printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
- ntohl(saddr),ntohs(uh->source),
- ntohl(daddr),ntohs(uh->dest),
- ulen);
- udp_statistics.UdpInErrors++;
- kfree_skb(skb, FREE_WRITE);
- return(0);
- }
-
-
- len=ulen;
-
-#ifdef CONFIG_IP_MULTICAST
- if (addr_type!=IS_MYADDR)
- {
- /*
- * Multicasts and broadcasts go to each listener.
- */
- struct sock *sknext=NULL;
- sk=get_sock_mcast(udp_prot.sock_array[ntohs(uh->dest)&(SOCK_ARRAY_SIZE-1)], uh->dest,
- saddr, uh->source, daddr);
- if(sk)
- {
- do
- {
- struct sk_buff *skb1;
-
- sknext=get_sock_mcast(sk->next, uh->dest, saddr, uh->source, daddr);
- if(sknext)
- skb1=skb_clone(skb,GFP_ATOMIC);
- else
- skb1=skb;
- if(skb1)
- udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);
- sk=sknext;
- }
- while(sknext!=NULL);
- }
- else
- kfree_skb(skb, FREE_READ);
- return 0;
- }
-#endif
- sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
- if (sk == NULL)
- {
- udp_statistics.UdpNoPorts++;
- if (addr_type == IS_MYADDR)
- {
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
- }
- /*
- * Hmm. We got an UDP broadcast to a port to which we
- * don't wanna listen. Ignore it.
- */
- skb->sk = NULL;
- kfree_skb(skb, FREE_WRITE);
- return(0);
- }
-
- return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);
-}
-
-static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len)
-{
- skb->sk = sk;
- skb->dev = dev;
- skb->len = len;
-
- /*
- * These are supposed to be switched.
- */
-
- skb->daddr = saddr;
- skb->saddr = daddr;
-
-
- /*
- * Charge it to the socket, dropping if the queue is full.
- */
-
- skb->len = len - sizeof(*uh);
-
- if (sock_queue_rcv_skb(sk,skb)<0)
- {
- udp_statistics.UdpInErrors++;
- ip_statistics.IpInDiscards++;
- ip_statistics.IpInDelivers--;
- skb->sk = NULL;
- kfree_skb(skb, FREE_WRITE);
- release_sock(sk);
- return(0);
- }
- udp_statistics.UdpInDatagrams++;
- release_sock(sk);
- return(0);
-}
-
-
-struct proto udp_prot = {
- sock_wmalloc,
- sock_rmalloc,
- sock_wfree,
- sock_rfree,
- sock_rspace,
- sock_wspace,
- udp_close,
- udp_read,
- udp_write,
- udp_sendto,
- udp_recvfrom,
- ip_build_header,
- udp_connect,
- NULL,
- ip_queue_xmit,
- NULL,
- NULL,
- NULL,
- udp_rcv,
- datagram_select,
-#ifdef _HURD_
- NULL,
-#else
- udp_ioctl,
-#endif
- NULL,
- NULL,
- ip_setsockopt,
- ip_getsockopt,
- 128,
- 0,
- {NULL,},
- "UDP",
- 0, 0
-};
-
-static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr)
-{
- unsigned long sum;
-
- __asm__( "\t addl %%ecx,%%ebx\n"
- "\t adcl %%edx,%%ebx\n"
- "\t adcl $0, %%ebx\n"
- : "=b"(sum)
- : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
- : "cx","bx","dx" );
-
- if (len > 3)
- {
- __asm__("\tclc\n"
- "1:\n"
- "\t lodsl\n"
- "\t adcl %%eax, %%ebx\n"
- "\t loop 1b\n"
- "\t adcl $0, %%ebx\n"
- : "=b"(sum) , "=S"(uh)
- : "0"(sum), "c"(len/4) ,"1"(uh)
- : "ax", "cx", "bx", "si" );
- }
-
- /*
- * Convert from 32 bits to 16 bits.
- */
-
- __asm__("\t movl %%ebx, %%ecx\n"
- "\t shrl $16,%%ecx\n"
- "\t addw %%cx, %%bx\n"
- "\t adcw $0, %%bx\n"
- : "=b"(sum)
- : "0"(sum)
- : "bx", "cx");
-
- /*
- * Check for an extra word.
- */
-
- if ((len & 2) != 0)
- {
- __asm__("\t lodsw\n"
- "\t addw %%ax,%%bx\n"
- "\t adcw $0, %%bx\n"
- : "=b"(sum), "=S"(uh)
- : "0"(sum) ,"1"(uh)
- : "si", "ax", "bx");
- }
-
- /*
- * Now check for the extra byte.
- */
-
- if ((len & 1) != 0)
- {
- __asm__("\t lodsb\n"
- "\t movb $0,%%ah\n"
- "\t addw %%ax,%%bx\n"
- "\t adcw $0, %%bx\n"
- : "=b"(sum)
- : "0"(sum) ,"S"(uh)
- : "si", "ax", "bx");
- }
-
- /*
- * We only want the bottom 16 bits, but we never cleared the top 16.
- */
-
- return((~sum) & 0xffff);
-}
diff --git a/pfinet/linux-inet/udp.h b/pfinet/linux-inet/udp.h
deleted file mode 100644
index 6bfbb3cb..00000000
--- a/pfinet/linux-inet/udp.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the UDP module.
- *
- * Version: @(#)udp.h 1.0.2 05/07/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Fixes:
- * Alan Cox : Turned on udp checksums. I don't want to
- * chase 'memory corruption' bugs that aren't!
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _UDP_H
-#define _UDP_H
-
-#include <linux/udp.h>
-
-
-#define UDP_NO_CHECK 0
-
-
-extern struct proto udp_prot;
-
-
-extern void udp_err(int err, unsigned char *header, unsigned long daddr,
- unsigned long saddr, struct inet_protocol *protocol);
-extern int udp_recvfrom(struct sock *sk, unsigned char *to,
- int len, int noblock, unsigned flags,
- struct sockaddr_in *sin, int *addr_len);
-extern int udp_read(struct sock *sk, unsigned char *buff,
- int len, int noblock, unsigned flags);
-extern int udp_connect(struct sock *sk,
- struct sockaddr_in *usin, int addr_len);
-extern int udp_rcv(struct sk_buff *skb, struct device *dev,
- struct options *opt, unsigned long daddr,
- unsigned short len, unsigned long saddr, int redo,
- struct inet_protocol *protocol);
-extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
-
-
-#endif /* _UDP_H */
diff --git a/pfinet/linux-inet/utils.c b/pfinet/linux-inet/utils.c
deleted file mode 100644
index 60bbb9f8..00000000
--- a/pfinet/linux-inet/utils.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Various kernel-resident INET utility functions; mainly
- * for format conversion and debugging output.
- *
- * Version: @(#)utils.c 1.0.7 05/18/93
- *
- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Fixes:
- * Alan Cox : verify_area check.
- * Alan Cox : removed old debugging.
- *
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/stat.h>
-#include <stdarg.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include "ip.h"
-#include "protocol.h"
-#include "tcp.h"
-#include <linux/skbuff.h>
-
-
-/*
- * Display an IP address in readable format.
- */
-
-char *in_ntoa(unsigned long in)
-{
- static char buff[18];
- char *p;
-
- p = (char *) &in;
- sprintf(buff, "%d.%d.%d.%d",
- (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
- return(buff);
-}
-
-
-/*
- * Convert an ASCII string to binary IP.
- */
-
-unsigned long in_aton(char *str)
-{
- unsigned long l;
- unsigned int val;
- int i;
-
- l = 0;
- for (i = 0; i < 4; i++)
- {
- l <<= 8;
- if (*str != '\0')
- {
- val = 0;
- while (*str != '\0' && *str != '.')
- {
- val *= 10;
- val += *str - '0';
- str++;
- }
- l |= val;
- if (*str != '\0')
- str++;
- }
- }
- return(htonl(l));
-}
-
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 cc9584a1..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)
@@ -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 27d2f802..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>
@@ -257,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)
@@ -419,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)
{
@@ -431,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)
@@ -544,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 ||
@@ -555,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)
@@ -622,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.
*/
@@ -633,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.
*/
@@ -781,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;
@@ -878,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.
*/
@@ -945,6 +948,7 @@ out:
rtnl_unlock();
return err;
}
+#endif
/*
* Write the contents of the ARP cache to a PROCfs file.
@@ -998,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
@@ -1015,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",
@@ -1023,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)
@@ -1049,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)
@@ -1059,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)
@@ -1133,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..ccae0c58 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,63 @@ 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);
+}
+
+#else
+
int devinet_ioctl(unsigned int cmd, void *arg)
{
struct ifreq ifr;
@@ -514,7 +556,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 +605,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 +647,8 @@ rarok:
return 0;
}
+#endif
+
static int
inet_gifconf(struct device *dev, char *buf, int len)
{
@@ -657,7 +701,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 +735,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 +769,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/linux/errno.h b/pfinet/linux/errno.h
deleted file mode 100644
index 7dab9bab..00000000
--- a/pfinet/linux/errno.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _HACK_ERRNO_H
-#define _HACK_ERRNO_H
-
-#include <errno.h>
-
-#define ERESTARTSYS EINTR
-
-#endif
diff --git a/pfinet/linux/etherdevice.h b/pfinet/linux/etherdevice.h
deleted file mode 100644
index 41073fcb..00000000
--- a/pfinet/linux/etherdevice.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. NET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the Ethernet handlers.
- *
- * Version: @(#)eth.h 1.0.4 05/13/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Relocated to include/linux where it belongs by Alan Cox
- * <gw4pts@gw4pts.ampr.org>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- *
- * WARNING: This move may well be temporary. This file will get merged with others RSN.
- *
- */
-#ifndef _LINUX_ETHERDEVICE_H
-#define _LINUX_ETHERDEVICE_H
-
-
-#include <linux/if_ether.h>
-
-#ifdef __KERNEL__
-extern int eth_header(unsigned char *buff, struct device *dev,
- unsigned short type, void *daddr,
- void *saddr, unsigned len,
- struct sk_buff *skb);
-extern int eth_rebuild_header(void *buff, struct device *dev,
- unsigned long raddr, struct sk_buff *skb);
-extern unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev);
-
-#endif
-
-#endif /* _LINUX_ETHERDEVICE_H */
diff --git a/pfinet/linux/icmp.h b/pfinet/linux/icmp.h
deleted file mode 100644
index 334c756d..00000000
--- a/pfinet/linux/icmp.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the ICMP protocol.
- *
- * Version: @(#)icmp.h 1.0.3 04/28/93
- *
- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_ICMP_H
-#define _LINUX_ICMP_H
-
-#define ICMP_ECHOREPLY 0 /* Echo Reply */
-#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
-#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
-#define ICMP_REDIRECT 5 /* Redirect (change route) */
-#define ICMP_ECHO 8 /* Echo Request */
-#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
-#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
-#define ICMP_TIMESTAMP 13 /* Timestamp Request */
-#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
-#define ICMP_INFO_REQUEST 15 /* Information Request */
-#define ICMP_INFO_REPLY 16 /* Information Reply */
-#define ICMP_ADDRESS 17 /* Address Mask Request */
-#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
-
-
-/* Codes for UNREACH. */
-#define ICMP_NET_UNREACH 0 /* Network Unreachable */
-#define ICMP_HOST_UNREACH 1 /* Host Unreachable */
-#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
-#define ICMP_PORT_UNREACH 3 /* Port Unreachable */
-#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
-#define ICMP_SR_FAILED 5 /* Source Route failed */
-#define ICMP_NET_UNKNOWN 6
-#define ICMP_HOST_UNKNOWN 7
-#define ICMP_HOST_ISOLATED 8
-#define ICMP_NET_ANO 9
-#define ICMP_HOST_ANO 10
-#define ICMP_NET_UNR_TOS 11
-#define ICMP_HOST_UNR_TOS 12
-
-/* Codes for REDIRECT. */
-#define ICMP_REDIR_NET 0 /* Redirect Net */
-#define ICMP_REDIR_HOST 1 /* Redirect Host */
-#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
-#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
-
-/* Codes for TIME_EXCEEDED. */
-#define ICMP_EXC_TTL 0 /* TTL count exceeded */
-#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */
-
-
-struct icmphdr {
- unsigned char type;
- unsigned char code;
- unsigned short checksum;
- union {
- struct {
- unsigned short id;
- unsigned short sequence;
- } echo;
- unsigned long gateway;
- } un;
-};
-
-
-struct icmp_err {
- int error;
- unsigned fatal:1;
-};
-
-
-#endif /* _LINUX_ICMP_H */
diff --git a/pfinet/linux/if.h b/pfinet/linux/if.h
deleted file mode 100644
index cb6b4e05..00000000
--- a/pfinet/linux/if.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Global definitions for the INET interface module.
- *
- * Version: @(#)if.h 1.0.2 04/18/93
- *
- * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
- * Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_IF_H
-#define _LINUX_IF_H
-
-#include <linux/types.h> /* for "caddr_t" et al */
-#include <linux/socket.h> /* for "struct sockaddr" et al */
-
-/* Standard interface flags. */
-#define IFF_UP 0x1 /* interface is up */
-#define IFF_BROADCAST 0x2 /* broadcast address valid */
-#define IFF_DEBUG 0x4 /* turn on debugging */
-#define IFF_LOOPBACK 0x8 /* is a loopback net */
-#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
-#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
-#define IFF_RUNNING 0x40 /* resources allocated */
-#define IFF_NOARP 0x80 /* no ARP protocol */
-#define IFF_PROMISC 0x100 /* receive all packets */
-/* Not supported */
-#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
-
-#define IFF_MASTER 0x400 /* master of a load balancer */
-#define IFF_SLAVE 0x800 /* slave of a load balancer */
-
-#define IFF_MULTICAST 0x1000 /* Supports multicast */
-
-/*
- * The ifaddr structure contains information about one address
- * of an interface. They are maintained by the different address
- * families, are allocated and attached when an address is set,
- * and are linked together so all addresses for an interface can
- * be located.
- */
-
-struct ifaddr
-{
- struct sockaddr ifa_addr; /* address of interface */
- union {
- struct sockaddr ifu_broadaddr;
- struct sockaddr ifu_dstaddr;
- } ifa_ifu;
- struct iface *ifa_ifp; /* back-pointer to interface */
- struct ifaddr *ifa_next; /* next address for interface */
-};
-
-#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */
-#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */
-
-/*
- * Device mapping structure. I'd just gone off and designed a
- * beautiful scheme using only loadable modules with arguments
- * for driver options and along come the PCMCIA people 8)
- *
- * Ah well. The get() side of this is good for WDSETUP, and it'll
- * be handy for debugging things. The set side is fine for now and
- * being very small might be worth keeping for clean configuration.
- */
-
-struct ifmap
-{
- unsigned long mem_start;
- unsigned long mem_end;
- unsigned short base_addr;
- unsigned char irq;
- unsigned char dma;
- unsigned char port;
- /* 3 bytes spare */
-};
-
-/*
- * Interface request structure used for socket
- * ioctl's. All interface ioctl's must have parameter
- * definitions which begin with ifr_name. The
- * remainder may be interface specific.
- */
-
-struct ifreq
-{
-#define IFHWADDRLEN 6
-#define IFNAMSIZ 16
- union
- {
- char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
- char ifrn_hwaddr[IFHWADDRLEN]; /* Obsolete */
- } ifr_ifrn;
-
- union {
- struct sockaddr ifru_addr;
- struct sockaddr ifru_dstaddr;
- struct sockaddr ifru_broadaddr;
- struct sockaddr ifru_netmask;
- struct sockaddr ifru_hwaddr;
- short ifru_flags;
- int ifru_metric;
- int ifru_mtu;
- struct ifmap ifru_map;
- char ifru_slave[IFNAMSIZ]; /* Just fits the size */
- caddr_t ifru_data;
- } ifr_ifru;
-};
-
-#define ifr_name ifr_ifrn.ifrn_name /* interface name */
-#define old_ifr_hwaddr ifr_ifrn.ifrn_hwaddr /* interface hardware */
-#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
-#define ifr_addr ifr_ifru.ifru_addr /* address */
-#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
-#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
-#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
-#define ifr_flags ifr_ifru.ifru_flags /* flags */
-#define ifr_metric ifr_ifru.ifru_metric /* metric */
-#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
-#define ifr_map ifr_ifru.ifru_map /* device map */
-#define ifr_slave ifr_ifru.ifru_slave /* slave device */
-#define ifr_data ifr_ifru.ifru_data /* for use by interface */
-
-/*
- * Structure used in SIOCGIFCONF request.
- * Used to retrieve interface configuration
- * for machine (useful for programs which
- * must know all networks accessible).
- */
-
-struct ifconf
-{
- int ifc_len; /* size of buffer */
- union
- {
- caddr_t ifcu_buf;
- struct ifreq *ifcu_req;
- } ifc_ifcu;
-};
-#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
-#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
-
-
-/* BSD UNIX expects to find these here, so here we go: */
-#include <linux/if_arp.h>
-#include <linux/route.h>
-
-#endif /* _NET_IF_H */
diff --git a/pfinet/linux/if_arp.h b/pfinet/linux/if_arp.h
deleted file mode 100644
index 75f86b61..00000000
--- a/pfinet/linux/if_arp.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Global definitions for the ARP (RFC 826) protocol.
- *
- * Version: @(#)if_arp.h 1.0.1 04/16/93
- *
- * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988
- * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source.
- * Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Florian La Roche.
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_IF_ARP_H
-#define _LINUX_IF_ARP_H
-
-/* ARP protocol HARDWARE identifiers. */
-#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
-#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
-#define ARPHRD_EETHER 2 /* Experimental Ethernet */
-#define ARPHRD_AX25 3 /* AX.25 Level 2 */
-#define ARPHRD_PRONET 4 /* PROnet token ring */
-#define ARPHRD_CHAOS 5 /* Chaosnet */
-#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet- huh? */
-#define ARPHRD_ARCNET 7 /* ARCnet */
-#define ARPHRD_APPLETLK 8 /* APPLEtalk */
-/* Dummy types for non ARP hardware */
-#define ARPHRD_SLIP 256
-#define ARPHRD_CSLIP 257
-#define ARPHRD_SLIP6 258
-#define ARPHRD_CSLIP6 259
-#define ARPHRD_RSRVD 260 /* Notional KISS type */
-#define ARPHRD_ADAPT 264
-#define ARPHRD_PPP 512
-#define ARPHRD_TUNNEL 768 /* IPIP tunnel */
-
-/* ARP protocol opcodes. */
-#define ARPOP_REQUEST 1 /* ARP request */
-#define ARPOP_REPLY 2 /* ARP reply */
-#define ARPOP_RREQUEST 3 /* RARP request */
-#define ARPOP_RREPLY 4 /* RARP reply */
-
-
-/* ARP ioctl request. */
-struct arpreq {
- struct sockaddr arp_pa; /* protocol address */
- struct sockaddr arp_ha; /* hardware address */
- int arp_flags; /* flags */
- struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
-};
-
-/* ARP Flag values. */
-#define ATF_COM 0x02 /* completed entry (ha valid) */
-#define ATF_PERM 0x04 /* permanent entry */
-#define ATF_PUBL 0x08 /* publish entry */
-#define ATF_USETRAILERS 0x10 /* has requested trailers */
-#define ATF_NETMASK 0x20 /* want to use a netmask (only
- for proxy entries) */
-
-/*
- * This structure defines an ethernet arp header.
- */
-
-struct arphdr
-{
- unsigned short ar_hrd; /* format of hardware address */
- unsigned short ar_pro; /* format of protocol address */
- unsigned char ar_hln; /* length of hardware address */
- unsigned char ar_pln; /* length of protocol address */
- unsigned short ar_op; /* ARP opcode (command) */
-
-#if 0
- /*
- * Ethernet looks like this : This bit is variable sized however...
- */
- unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
- unsigned char ar_sip[4]; /* sender IP address */
- unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
- unsigned char ar_tip[4]; /* target IP address */
-#endif
-
-};
-
-#endif /* _LINUX_IF_ARP_H */
diff --git a/pfinet/linux/if_ether.h b/pfinet/linux/if_ether.h
deleted file mode 100644
index b87b1785..00000000
--- a/pfinet/linux/if_ether.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Global definitions for the Ethernet IEEE 802.3 interface.
- *
- * Version: @(#)if_ether.h 1.0.1a 02/08/94
- *
- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Donald Becker, <becker@super.org>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_IF_ETHER_H
-#define _LINUX_IF_ETHER_H
-
-
-/* IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble
- and FCS/CRC (frame check sequence). */
-#define ETH_ALEN 6 /* Octets in one ethernet addr */
-#define ETH_HLEN 14 /* Total octets in header. */
-#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
-#define ETH_DATA_LEN 1500 /* Max. octets in payload */
-#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
-
-
-/* These are the defined Ethernet Protocol ID's. */
-#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
-#define ETH_P_ECHO 0x0200 /* Ethernet Echo packet */
-#define ETH_P_PUP 0x0400 /* Xerox PUP packet */
-#define ETH_P_IP 0x0800 /* Internet Protocol packet */
-#define ETH_P_ARP 0x0806 /* Address Resolution packet */
-#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */
-#define ETH_P_X25 0x0805 /* CCITT X.25 */
-#define ETH_P_ATALK 0x809B /* Appletalk DDP */
-#define ETH_P_IPX 0x8137 /* IPX over DIX */
-#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */
-#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */
-#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
-#define ETH_P_802_2 0x0004 /* 802.2 frames */
-#define ETH_P_SNAP 0x0005 /* Internal only */
-/* This is an Ethernet frame header. */
-struct ethhdr {
- unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
- unsigned char h_source[ETH_ALEN]; /* source ether addr */
- unsigned short h_proto; /* packet type ID field */
-};
-
-/* Ethernet statistics collection data. */
-struct enet_statistics{
- int rx_packets; /* total packets received */
- int tx_packets; /* total packets transmitted */
- int rx_errors; /* bad packets received */
- int tx_errors; /* packet transmit problems */
- int rx_dropped; /* no space in linux buffers */
- int tx_dropped; /* no space available in linux */
- int multicast; /* multicast packets received */
- int collisions;
-
- /* detailed rx_errors: */
- int rx_length_errors;
- int rx_over_errors; /* receiver ring buff overflow */
- int rx_crc_errors; /* recved pkt with crc error */
- int rx_frame_errors; /* recv'd frame alignment error */
- int rx_fifo_errors; /* recv'r fifo overrun */
- int rx_missed_errors; /* receiver missed packet */
-
- /* detailed tx_errors */
- int tx_aborted_errors;
- int tx_carrier_errors;
- int tx_fifo_errors;
- int tx_heartbeat_errors;
- int tx_window_errors;
-};
-
-#endif /* _LINUX_IF_ETHER_H */
diff --git a/pfinet/linux/igmp.h b/pfinet/linux/igmp.h
deleted file mode 100644
index 6ca7e019..00000000
--- a/pfinet/linux/igmp.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Linux NET3: Internet Gateway Management Protocol [IGMP]
- *
- * Authors:
- * Alan Cox <Alan.Cox@linux.org>
- *
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _LINUX_IGMP_H
-#define _LINUX_IGMP_H
-
-/*
- * IGMP protocol structures
- */
-
-struct igmphdr
-{
- unsigned char type;
- unsigned char unused;
- unsigned short csum;
- unsigned long group;
-};
-
-#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */
-#define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */
-#define IGMP_HOST_LEAVE_MESSAGE 0x17 /* An extra BSD seems to send */
-
- /* 224.0.0.1 */
-#define IGMP_ALL_HOSTS htonl(0xE0000001L)
-
-/*
- * struct for keeping the multicast list in
- */
-
-#ifdef __KERNEL__
-struct ip_mc_socklist
-{
- unsigned long multiaddr[IP_MAX_MEMBERSHIPS]; /* This is a speed trade off */
- struct device *multidev[IP_MAX_MEMBERSHIPS];
-};
-
-struct ip_mc_list
-{
- struct device *interface;
- unsigned long multiaddr;
- struct ip_mc_list *next;
- struct timer_list timer;
- int tm_running;
- int users;
-};
-
-extern struct ip_mc_list *ip_mc_head;
-
-
-extern int igmp_rcv(struct sk_buff *, struct device *, struct options *, unsigned long, unsigned short,
- unsigned long, int , struct inet_protocol *);
-extern void ip_mc_drop_device(struct device *dev);
-extern int ip_mc_join_group(struct sock *sk, struct device *dev, unsigned long addr);
-extern int ip_mc_leave_group(struct sock *sk, struct device *dev,unsigned long addr);
-extern void ip_mc_drop_socket(struct sock *sk);
-#endif
-#endif
diff --git a/pfinet/linux/inet.h b/pfinet/linux/inet.h
deleted file mode 100644
index 27aa5521..00000000
--- a/pfinet/linux/inet.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _HACK_INET_H_
-#define _HACK_INET_H_
-
-char *in_ntoa (u_long);
-
-#endif
diff --git a/pfinet/linux/interrupt.h b/pfinet/linux/interrupt.h
deleted file mode 100644
index 01f11a8c..00000000
--- a/pfinet/linux/interrupt.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _HACK_INTERRUPT_H_
-#define _HACK_INTERRUPT_H_
-
-#include <linux/netdevice.h>
-#include "pfinet.h"
-
-#define NET_BH 1
-
-extern void mark_bh (int);
-
-#endif
diff --git a/pfinet/linux/ip.h b/pfinet/linux/ip.h
deleted file mode 100644
index bcc1bdea..00000000
--- a/pfinet/linux/ip.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the IP protocol.
- *
- * Version: @(#)ip.h 1.0.2 04/28/93
- *
- * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_IP_H
-#define _LINUX_IP_H
-
-
-#define IPOPT_END 0
-#define IPOPT_NOOP 1
-#define IPOPT_SEC 130
-#define IPOPT_LSRR 131
-#define IPOPT_SSRR 137
-#define IPOPT_RR 7
-#define IPOPT_SID 136
-#define IPOPT_TIMESTAMP 68
-
-
-#define MAXTTL 255
-
-struct timestamp {
- __u8 len;
- __u8 ptr;
- union {
-#if defined(__i386__)
- __u8 flags:4,
- overflow:4;
-#elif defined(__mc68000__)
- __u8 overflow:4,
- flags:4;
-#elif defined(__MIPSEL__)
- __u8 flags:4,
- overflow:4;
-#elif defined(__MIPSEB__)
- __u8 overflow:4,
- flags:4;
-#elif defined(__alpha__)
- __u8 flags:4,
- overflow:4;
-#elif defined(__sparc__)
- __u8 overflow:4,
- flags:4;
-#else
-#error "Adjust this structure to match your CPU"
-#endif
- __u8 full_char;
- } x;
- __u32 data[9];
-};
-
-
-#define MAX_ROUTE 16
-
-struct route {
- char route_size;
- char pointer;
- unsigned long route[MAX_ROUTE];
-};
-
-
-struct options {
- struct route record_route;
- struct route loose_route;
- struct route strict_route;
- struct timestamp tstamp;
- unsigned short security;
- unsigned short compartment;
- unsigned short handling;
- unsigned short stream;
- unsigned tcc;
-};
-
-
-struct iphdr {
-#if defined(__i386__)
- __u8 ihl:4,
- version:4;
-#elif defined (__mc68000__)
- __u8 version:4,
- ihl:4;
-#elif defined(__MIPSEL__)
- __u8 ihl:4,
- version:4;
-#elif defined(__MIPSEB__)
- __u8 version:4,
- ihl:4;
-#elif defined(__alpha__)
- __u8 ihl:4,
- version:4;
-#elif defined (__sparc__)
- __u8 version:4,
- ihl:4;
-#else
-#error "Adjust this structure to match your CPU"
-#endif
- __u8 tos;
- __u16 tot_len;
- __u16 id;
- __u16 frag_off;
- __u8 ttl;
- __u8 protocol;
- __u16 check;
- __u32 saddr;
- __u32 daddr;
- /*The options start here. */
-};
-
-
-#endif /* _LINUX_IP_H */
diff --git a/pfinet/linux/ip_fw.h b/pfinet/linux/ip_fw.h
deleted file mode 100644
index f80cccbf..00000000
--- a/pfinet/linux/ip_fw.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * IP firewalling code. This is taken from 4.4BSD. Please note the
- * copyright message below. As per the GPL it must be maintained
- * and the licenses thus do not conflict. While this port is subject
- * to the GPL I also place my modifications under the original
- * license in recognition of the original copyright.
- *
- * Ported from BSD to Linux,
- * Alan Cox 22/Nov/1994.
- * Merged and included the FreeBSD-Current changes at Ugen's request
- * (but hey it's a lot cleaner now). Ugen would prefer in some ways
- * we waited for his final product but since Linux 1.2.0 is about to
- * appear it's not practical - Read: It works, it's not clean but please
- * don't consider it to be his standard of finished work.
- * Alan.
- *
- * All the real work was done by .....
- */
-
-/*
- * Copyright (c) 1993 Daniel Boulet
- * Copyright (c) 1994 Ugen J.S.Antsilevich
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- */
-
-/*
- * Format of an IP firewall descriptor
- *
- * src, dst, src_mask, dst_mask are always stored in network byte order.
- * flags and num_*_ports are stored in host byte order (of course).
- * Port numbers are stored in HOST byte order.
- */
-
-#ifndef _IP_FW_H
-#define _IP_FW_H
-
-struct ip_fw
-{
- struct ip_fw *fw_next; /* Next firewall on chain */
- struct in_addr fw_src, fw_dst; /* Source and destination IP addr */
- struct in_addr fw_smsk, fw_dmsk; /* Mask for src and dest IP addr */
- struct in_addr fw_via; /* IP address of interface "via" */
- unsigned short fw_flg; /* Flags word */
- unsigned short fw_nsp, fw_ndp; /* N'of src ports and # of dst ports */
- /* in ports array (dst ports follow */
- /* src ports; max of 10 ports in all; */
- /* count of 0 means match all ports) */
-#define IP_FW_MAX_PORTS 10 /* A reasonable maximum */
- unsigned short fw_pts[IP_FW_MAX_PORTS]; /* Array of port numbers to match */
- unsigned long fw_pcnt,fw_bcnt; /* Packet and byte counters */
-};
-
-/*
- * Values for "flags" field .
- */
-
-#define IP_FW_F_ALL 0x000 /* This is a universal packet firewall*/
-#define IP_FW_F_TCP 0x001 /* This is a TCP packet firewall */
-#define IP_FW_F_UDP 0x002 /* This is a UDP packet firewall */
-#define IP_FW_F_ICMP 0x003 /* This is a ICMP packet firewall */
-#define IP_FW_F_KIND 0x003 /* Mask to isolate firewall kind */
-#define IP_FW_F_ACCEPT 0x004 /* This is an accept firewall (as *
- * opposed to a deny firewall)*
- * */
-#define IP_FW_F_SRNG 0x008 /* The first two src ports are a min *
- * and max range (stored in host byte *
- * order). *
- * */
-#define IP_FW_F_DRNG 0x010 /* The first two dst ports are a min *
- * and max range (stored in host byte *
- * order). *
- * (ports[0] <= port <= ports[1]) *
- * */
-#define IP_FW_F_PRN 0x020 /* In verbose mode print this firewall*/
-#define IP_FW_F_BIDIR 0x040 /* For bidirectional firewalls */
-#define IP_FW_F_TCPSYN 0x080 /* For tcp packets-check SYN only */
-#define IP_FW_F_ICMPRPL 0x100 /* Send back icmp unreachable packet */
-#define IP_FW_F_MASK 0x1FF /* All possible flag bits mask */
-
-/*
- * New IP firewall options for [gs]etsockopt at the RAW IP level.
- * Unlike BSD Linux inherits IP options so you don't have to use
- * a raw socket for this. Instead we check rights in the calls.
- */
-
-#define IP_FW_BASE_CTL 64
-
-#define IP_FW_ADD_BLK (IP_FW_BASE_CTL)
-#define IP_FW_ADD_FWD (IP_FW_BASE_CTL+1)
-#define IP_FW_CHK_BLK (IP_FW_BASE_CTL+2)
-#define IP_FW_CHK_FWD (IP_FW_BASE_CTL+3)
-#define IP_FW_DEL_BLK (IP_FW_BASE_CTL+4)
-#define IP_FW_DEL_FWD (IP_FW_BASE_CTL+5)
-#define IP_FW_FLUSH_BLK (IP_FW_BASE_CTL+6)
-#define IP_FW_FLUSH_FWD (IP_FW_BASE_CTL+7)
-#define IP_FW_ZERO_BLK (IP_FW_BASE_CTL+8)
-#define IP_FW_ZERO_FWD (IP_FW_BASE_CTL+9)
-#define IP_FW_POLICY_BLK (IP_FW_BASE_CTL+10)
-#define IP_FW_POLICY_FWD (IP_FW_BASE_CTL+11)
-
-#define IP_ACCT_ADD (IP_FW_BASE_CTL+16)
-#define IP_ACCT_DEL (IP_FW_BASE_CTL+17)
-#define IP_ACCT_FLUSH (IP_FW_BASE_CTL+18)
-#define IP_ACCT_ZERO (IP_FW_BASE_CTL+19)
-
-struct ip_fwpkt
-{
- struct iphdr fwp_iph; /* IP header */
- union {
- struct tcphdr fwp_tcph; /* TCP header or */
- struct udphdr fwp_udph; /* UDP header */
- } fwp_protoh;
- struct in_addr fwp_via; /* interface address */
-};
-
-/*
- * Main firewall chains definitions and global var's definitions.
- */
-
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-
-#ifdef CONFIG_IP_FIREWALL
-extern struct ip_fw *ip_fw_blk_chain;
-extern struct ip_fw *ip_fw_fwd_chain;
-extern int ip_fw_blk_policy;
-extern int ip_fw_fwd_policy;
-extern int ip_fw_ctl(int, void *, int);
-#endif
-#ifdef CONFIG_IP_ACCT
-extern struct ip_fw *ip_acct_chain;
-extern void ip_acct_cnt(struct iphdr *, struct device *, struct ip_fw *);
-extern int ip_acct_ctl(int, void *, int);
-#endif
-extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int, int);
-#endif /* KERNEL */
-
-#endif /* _IP_FW_H */
diff --git a/pfinet/linux/ipx.h b/pfinet/linux/ipx.h
deleted file mode 100644
index d3bff83b..00000000
--- a/pfinet/linux/ipx.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _IPX_H_
-#define _IPX_H_
-#include <linux/sockios.h>
-#define IPX_NODE_LEN 6
-#define IPX_MTU 576
-
-struct sockaddr_ipx
-{
- short sipx_family;
- short sipx_port;
- unsigned long sipx_network;
- unsigned char sipx_node[IPX_NODE_LEN];
- unsigned char sipx_type;
- unsigned char sipx_zero; /* 16 byte fill */
-};
-
-/*
- * So we can fit the extra info for SIOCSIFADDR into the address nicely
- */
-
-#define sipx_special sipx_port
-#define sipx_action sipx_zero
-#define IPX_DLTITF 0
-#define IPX_CRTITF 1
-
-typedef struct ipx_route_definition
-{
- unsigned long ipx_network;
- unsigned long ipx_router_network;
- unsigned char ipx_router_node[IPX_NODE_LEN];
-} ipx_route_definition;
-
-typedef struct ipx_interface_definition
-{
- unsigned long ipx_network;
- unsigned char ipx_device[16];
- unsigned char ipx_dlink_type;
-#define IPX_FRAME_NONE 0
-#define IPX_FRAME_SNAP 1
-#define IPX_FRAME_8022 2
-#define IPX_FRAME_ETHERII 3
-#define IPX_FRAME_8023 4
- unsigned char ipx_special;
-#define IPX_SPECIAL_NONE 0
-#define IPX_PRIMARY 1
-#define IPX_INTERNAL 2
- unsigned char ipx_node[IPX_NODE_LEN];
-} ipx_interface_definition;
-
-typedef struct ipx_config_data
-{
- unsigned char ipxcfg_auto_select_primary;
- unsigned char ipxcfg_auto_create_interfaces;
-} ipx_config_data;
-
-/*
- * OLD Route Definition for backward compatibility.
- */
-
-struct ipx_route_def
-{
- unsigned long ipx_network;
- unsigned long ipx_router_network;
-#define IPX_ROUTE_NO_ROUTER 0
- unsigned char ipx_router_node[IPX_NODE_LEN];
- unsigned char ipx_device[16];
- unsigned short ipx_flags;
-#define IPX_RT_SNAP 8
-#define IPX_RT_8022 4
-#define IPX_RT_BLUEBOOK 2
-#define IPX_RT_ROUTED 1
-};
-
-#define SIOCAIPXITFCRT (SIOCPROTOPRIVATE)
-#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1)
-#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2)
-#endif
-
diff --git a/pfinet/linux/kernel.h b/pfinet/linux/kernel.h
deleted file mode 100644
index dcd5acf3..00000000
--- a/pfinet/linux/kernel.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _HACK_KERNEL_H
-#define _HACK_KERNEL_H
-
-#include <stdio.h>
-#include <linux/sched.h>
-#include <stdlib.h>
-#include <assert.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/linux/malloc.h b/pfinet/linux/malloc.h
deleted file mode 100644
index 06930659..00000000
--- a/pfinet/linux/malloc.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _HACK_MALLOC_H_
-#define _HACK_MALLOC_H_
-
-#include <linux/mm.h>
-
-#define kfree_s(a,b) (free (a))
-#define kfree(a) (free (a))
-#define kmalloc(a,b) (malloc (a))
-
-#endif
diff --git a/pfinet/linux/net.h b/pfinet/linux/net.h
deleted file mode 100644
index 341d0253..00000000
--- a/pfinet/linux/net.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * NET An implementation of the SOCKET network access protocol.
- * This is the master header file for the Linux NET layer,
- * or, in plain English: the networking handling part of the
- * kernel.
- *
- * Version: @(#)net.h 1.0.3 05/25/93
- *
- * Authors: Orest Zborowski, <obz@Kodak.COM>
- * Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_NET_H
-#define _LINUX_NET_H
-
-
-#include <linux/wait.h>
-#include <linux/socket.h>
-
-
-#define NSOCKETS 2000 /* Dynamic, this is MAX LIMIT */
-#define NSOCKETS_UNIX 128 /* unix domain static limit */
-#define NPROTO 16 /* should be enough for now.. */
-
-
-#define SYS_SOCKET 1 /* sys_socket(2) */
-#define SYS_BIND 2 /* sys_bind(2) */
-#define SYS_CONNECT 3 /* sys_connect(2) */
-#define SYS_LISTEN 4 /* sys_listen(2) */
-#define SYS_ACCEPT 5 /* sys_accept(2) */
-#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
-#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
-#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */
-#define SYS_SEND 9 /* sys_send(2) */
-#define SYS_RECV 10 /* sys_recv(2) */
-#define SYS_SENDTO 11 /* sys_sendto(2) */
-#define SYS_RECVFROM 12 /* sys_recvfrom(2) */
-#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */
-#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */
-#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
-
-
-typedef enum {
- SS_FREE = 0, /* not allocated */
- SS_UNCONNECTED, /* unconnected to any socket */
- SS_CONNECTING, /* in process of connecting */
- SS_CONNECTED, /* connected to socket */
- SS_DISCONNECTING /* in process of disconnecting */
-} socket_state;
-
-#define SO_ACCEPTCON (1<<16) /* performed a listen */
-#define SO_WAITDATA (1<<17) /* wait data to read */
-#define SO_NOSPACE (1<<18) /* no space to write */
-
-#ifdef __KERNEL__
-/*
- * Internal representation of a socket. not all the fields are used by
- * all configurations:
- *
- * server client
- * conn client connected to server connected to
- * iconn list of clients -unused-
- * awaiting connections
- * wait sleep for clients, sleep for connection,
- * sleep for i/o sleep for i/o
- */
-struct socket {
- short type; /* SOCK_STREAM, ... */
- socket_state state;
- long flags;
-#ifdef _HURD_
- int userflags; /* O_* */
- int refcnt;
- mach_port_t identity;
-#endif
- struct proto_ops *ops; /* protocols do most everything */
- void *data; /* protocol data */
- struct socket *conn; /* server socket connected to */
- struct socket *iconn; /* incomplete client conn.s */
- struct socket *next;
- struct wait_queue **wait; /* ptr to place to wait on */
- struct inode *inode;
- struct fasync_struct *fasync_list; /* Asynchronous wake up list */
-};
-
-#define SOCK_INODE(S) ((S)->inode)
-
-struct proto_ops {
- int family;
-
- int (*create) (struct socket *sock, int protocol);
- int (*dup) (struct socket *newsock, struct socket *oldsock);
- int (*release) (struct socket *sock, struct socket *peer);
- int (*bind) (struct socket *sock, struct sockaddr *umyaddr,
- int sockaddr_len);
- int (*connect) (struct socket *sock, struct sockaddr *uservaddr,
- int sockaddr_len, int flags);
- int (*socketpair) (struct socket *sock1, struct socket *sock2);
- int (*accept) (struct socket *sock, struct socket *newsock,
- int flags);
- int (*getname) (struct socket *sock, struct sockaddr *uaddr,
- int *usockaddr_len, int peer);
- int (*read) (struct socket *sock, char *ubuf, int size,
- int nonblock);
- int (*write) (struct socket *sock, char *ubuf, int size,
- int nonblock);
- int (*select) (struct socket *sock, int sel_type,
- select_table *wait);
- int (*ioctl) (struct socket *sock, unsigned int cmd,
- unsigned long arg);
- int (*listen) (struct socket *sock, int len);
- int (*send) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags);
- int (*recv) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags);
- int (*sendto) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags, struct sockaddr *, int addr_len);
- int (*recvfrom) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags, struct sockaddr *, int *addr_len);
- int (*shutdown) (struct socket *sock, int flags);
- int (*setsockopt) (struct socket *sock, int level, int optname,
- char *optval, int optlen);
- int (*getsockopt) (struct socket *sock, int level, int optname,
- char *optval, int *optlen);
- int (*fcntl) (struct socket *sock, unsigned int cmd,
- unsigned long arg);
-};
-
-struct net_proto {
- char *name; /* Protocol name */
- void (*init_func)(struct net_proto *); /* Bootstrap */
-};
-
-extern int sock_awaitconn(struct socket *mysock, struct socket *servsock, int flags);
-extern int sock_wake_async(struct socket *sock, int how);
-extern int sock_register(int family, struct proto_ops *ops);
-extern int sock_unregister(int family);
-extern struct socket *sock_alloc(void);
-extern void sock_release(struct socket *sock);
-#endif /* __KERNEL__ */
-#endif /* _LINUX_NET_H */
diff --git a/pfinet/linux/netdevice.h b/pfinet/linux/netdevice.h
deleted file mode 100644
index dcca542d..00000000
--- a/pfinet/linux/netdevice.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the Interfaces handler.
- *
- * Version: @(#)dev.h 1.0.10 08/12/93
- *
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Corey Minyard <wf-rch!minyard@relay.EU.net>
- * Donald J. Becker, <becker@super.org>
- * Alan Cox, <A.Cox@swansea.ac.uk>
- * Bjorn Ekwall. <bj0rn@blox.se>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- *
- * Moved to /usr/include/linux for NET3
- */
-#ifndef _LINUX_NETDEVICE_H
-#define _LINUX_NETDEVICE_H
-
-#include <linux/if.h>
-#include <linux/if_ether.h>
-#include <linux/skbuff.h>
-
-/* for future expansion when we will have different priorities. */
-#define DEV_NUMBUFFS 3
-#define MAX_ADDR_LEN 7
-#define MAX_HEADER 18
-
-#define IS_MYADDR 1 /* address is (one of) our own */
-#define IS_LOOPBACK 2 /* address is for LOOPBACK */
-#define IS_BROADCAST 3 /* address is a valid broadcast */
-#define IS_INVBCAST 4 /* Wrong netmask bcast not for us (unused)*/
-#define IS_MULTICAST 5 /* Multicast IP address */
-
-/*
- * We tag these structures with multicasts.
- */
-
-struct dev_mc_list
-{
- struct dev_mc_list *next;
- char dmi_addr[MAX_ADDR_LEN];
- unsigned short dmi_addrlen;
- unsigned short dmi_users;
-};
-
-/*
- * The DEVICE structure.
- * Actually, this whole structure is a big mistake. It mixes I/O
- * data with strictly "high-level" data, and it has to know about
- * almost every data structure used in the INET module.
- */
-struct device
-{
-
- /*
- * This is the first field of the "visible" part of this structure
- * (i.e. as seen by users in the "Space.c" file). It is the name
- * the interface.
- */
- char *name;
-
- /* I/O specific fields - FIXME: Merge these and struct ifmap into one */
- unsigned long rmem_end; /* shmem "recv" end */
- unsigned long rmem_start; /* shmem "recv" start */
- unsigned long mem_end; /* sahared mem end */
- unsigned long mem_start; /* shared mem start */
- unsigned long base_addr; /* device I/O address */
- unsigned char irq; /* device IRQ number */
-
- /* Low-level status flags. */
- volatile unsigned char start, /* start an operation */
- tbusy, /* transmitter busy */
- interrupt; /* interrupt arrived */
-
- struct device *next;
-
- /* The device initialization function. Called only once. */
- int (*init)(struct device *dev);
-
- /* Some hardware also needs these fields, but they are not part of the
- usual set specified in Space.c. */
- unsigned char if_port; /* Selectable AUI, TP,..*/
- unsigned char dma; /* DMA channel */
-
- struct enet_statistics* (*get_stats)(struct device *dev);
-
- /*
- * This marks the end of the "visible" part of the structure. All
- * fields hereafter are internal to the system, and may change at
- * will (read: may be cleaned up at will).
- */
-
- /* These may be needed for future network-power-down code. */
- unsigned long trans_start; /* Time (in jiffies) of last Tx */
- unsigned long last_rx; /* Time of last Rx */
-
- unsigned short flags; /* interface flags (a la BSD) */
- unsigned short family; /* address family ID (AF_INET) */
- unsigned short metric; /* routing metric (not used) */
- unsigned short mtu; /* interface MTU value */
- unsigned short type; /* interface hardware type */
- unsigned short hard_header_len; /* hardware hdr length */
- void *priv; /* pointer to private data */
-
- /* Interface address info. */
- unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
- unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */
- unsigned char addr_len; /* hardware address length */
- unsigned long pa_addr; /* protocol address */
- unsigned long pa_brdaddr; /* protocol broadcast addr */
- unsigned long pa_dstaddr; /* protocol P-P other side addr */
- unsigned long pa_mask; /* protocol netmask */
- unsigned short pa_alen; /* protocol address length */
-
- struct dev_mc_list *mc_list; /* Multicast mac addresses */
- int mc_count; /* Number of installed mcasts */
-
- struct ip_mc_list *ip_mc_list; /* IP multicast filter chain */
-
- /* For load balancing driver pair support */
-
- unsigned long pkt_queue; /* Packets queued */
- struct device *slave; /* Slave device */
-
-
- /* Pointer to the interface buffers. */
- struct sk_buff_head buffs[DEV_NUMBUFFS];
-
- /* Pointers to interface service routines. */
- int (*open)(struct device *dev);
- int (*stop)(struct device *dev);
- int (*hard_start_xmit) (struct sk_buff *skb,
- struct device *dev);
- int (*hard_header) (unsigned char *buff,
- struct device *dev,
- unsigned short type,
- void *daddr,
- void *saddr,
- unsigned len,
- struct sk_buff *skb);
- int (*rebuild_header)(void *eth, struct device *dev,
- unsigned long raddr, struct sk_buff *skb);
- unsigned short (*type_trans) (struct sk_buff *skb,
- struct device *dev);
-#define HAVE_MULTICAST
- void (*set_multicast_list)(struct device *dev,
- int num_addrs, void *addrs);
-#define HAVE_SET_MAC_ADDR
- int (*set_mac_address)(struct device *dev, void *addr);
-#define HAVE_PRIVATE_IOCTL
- int (*do_ioctl)(struct device *dev, struct ifreq *ifr, int cmd);
-#define HAVE_SET_CONFIG
- int (*set_config)(struct device *dev, struct ifmap *map);
-
-};
-
-
-struct packet_type {
- unsigned short type; /* This is really htons(ether_type). */
- struct device * dev;
- int (*func) (struct sk_buff *, struct device *,
- struct packet_type *);
- void *data;
- struct packet_type *next;
-};
-
-
-#ifdef __KERNEL__
-
-#include <linux/notifier.h>
-
-/* Used by dev_rint */
-#define IN_SKBUFF 1
-
-extern volatile char in_bh;
-
-extern struct device loopback_dev;
-extern struct device *dev_base;
-extern struct packet_type *ptype_base;
-
-
-extern int ip_addr_match(unsigned long addr1, unsigned long addr2);
-extern int ip_chk_addr(unsigned long addr);
-extern struct device *ip_dev_check(unsigned long daddr);
-extern unsigned long ip_my_addr(void);
-extern unsigned long ip_get_mask(unsigned long addr);
-
-extern void dev_add_pack(struct packet_type *pt);
-extern void dev_remove_pack(struct packet_type *pt);
-extern struct device *dev_get(char *name);
-extern int dev_open(struct device *dev);
-extern int dev_close(struct device *dev);
-extern void dev_queue_xmit(struct sk_buff *skb, struct device *dev,
- int pri);
-#define HAVE_NETIF_RX 1
-extern void netif_rx(struct sk_buff *skb);
-/* The old interface to netif_rx(). */
-extern int dev_rint(unsigned char *buff, long len, int flags,
- struct device * dev);
-extern void dev_transmit(void);
-extern int in_net_bh(void);
-extern void net_bh(void *tmp);
-extern void dev_tint(struct device *dev);
-extern int dev_get_info(char *buffer, char **start, off_t offset, int length);
-extern int dev_ioctl(unsigned int cmd, void *);
-
-extern void dev_init(void);
-
-/* These functions live elsewhere (drivers/net/net_init.c, but related) */
-
-extern void ether_setup(struct device *dev);
-extern int ether_config(struct device *dev, struct ifmap *map);
-/* Support for loadable net-drivers */
-extern int register_netdev(struct device *dev);
-extern void unregister_netdev(struct device *dev);
-extern int register_netdevice_notifier(struct notifier_block *nb);
-extern int unregister_netdevice_notifier(struct notifier_block *nb);
-/* Functions used for multicast support */
-extern void dev_mc_upload(struct device *dev);
-extern void dev_mc_delete(struct device *dev, void *addr, int alen, int all);
-extern void dev_mc_add(struct device *dev, void *addr, int alen, int newonly);
-extern void dev_mc_discard(struct device *dev);
-/* This is the wrong place but it'll do for the moment */
-extern void ip_mc_allhost(struct device *dev);
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_DEV_H */
diff --git a/pfinet/linux/notifier.h b/pfinet/linux/notifier.h
deleted file mode 100644
index 78a44649..00000000
--- a/pfinet/linux/notifier.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Routines to manage notifier chains for passing status changes to any
- * interested routines. We need this instead of hard coded call lists so
- * that modules can poke their nose into the innards. The network devices
- * needed them so here they are for the rest of you.
- *
- * Alan Cox <Alan.Cox@linux.org>
- */
-
-#ifndef _LINUX_NOTIFIER_H
-#define _LINUX_NOTIFIER_H
-#include <linux/errno.h>
-
-struct notifier_block
-{
- int (*notifier_call)(unsigned long, void *);
- struct notifier_block *next;
- int priority;
-};
-
-
-#ifdef __KERNEL__
-
-#define NOTIFY_DONE 0x0000 /* Don't care */
-#define NOTIFY_OK 0x0001 /* Suits me */
-#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
-#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */
-
-extern __inline__ int notifier_chain_register(struct notifier_block **list, struct notifier_block *n)
-{
- while(*list)
- {
- if(n->priority > (*list)->priority)
- break;
- list= &((*list)->next);
- }
- n->next = *list;
- *list=n;
- return 0;
-}
-
-/*
- * Warning to any non GPL module writers out there.. these functions are
- * GPL'd
- */
-
-extern __inline__ int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n)
-{
- while((*nl)!=NULL)
- {
- if((*nl)==n)
- {
- *nl=n->next;
- return 0;
- }
- nl=&((*nl)->next);
- }
- return -ENOENT;
-}
-
-/*
- * This is one of these things that is generally shorter inline
- */
-
-extern __inline__ int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
-{
- int ret=NOTIFY_DONE;
- struct notifier_block *nb = *n;
- while(nb)
- {
- ret=nb->notifier_call(val,v);
- if(ret&NOTIFY_STOP_MASK)
- return ret;
- nb=nb->next;
- }
- return ret;
-}
-
-
-/*
- * Declared notifiers so far. I can imagine quite a few more chains
- * over time (eg laptop power reset chains, reboot chain (to clean
- * device units up), device [un]mount chain, module load/unload chain,
- * low memory chain, screenblank chain (for plug in modular screenblankers)
- * VC switch chains (for loadable kernel svgalib VC switch helpers) etc...
- */
-
-/* netdevice notifier chain */
-#define NETDEV_UP 0x0001 /* For now you can't veto a device up/down */
-#define NETDEV_DOWN 0x0002
-#define NETDEV_REBOOT 0x0003 /* Tell a protocol stack a network interface
- detected a hardware crash and restarted
- - we can use this eg to kick tcp sessions
- once done */
-#endif
-#endif
diff --git a/pfinet/linux/route.h b/pfinet/linux/route.h
deleted file mode 100644
index 3cadd206..00000000
--- a/pfinet/linux/route.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Global definitions for the IP router interface.
- *
- * Version: @(#)route.h 1.0.3 05/27/93
- *
- * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_ROUTE_H
-#define _LINUX_ROUTE_H
-
-#include <linux/if.h>
-
-
-/* This structure gets passed by the SIOCADDRTOLD and SIOCDELRTOLD calls. */
-
-struct old_rtentry {
- unsigned long rt_genmask;
- struct sockaddr rt_dst;
- struct sockaddr rt_gateway;
- short rt_flags;
- short rt_refcnt;
- unsigned long rt_use;
- char *rt_dev;
-};
-
-/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */
-struct rtentry {
- unsigned long rt_hash; /* hash key for lookups */
- struct sockaddr rt_dst; /* target address */
- struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */
- struct sockaddr rt_genmask; /* target network mask (IP) */
- short rt_flags;
- short rt_refcnt;
- unsigned long rt_use;
- struct ifnet *rt_ifp;
- short rt_metric; /* +1 for binary compatibility! */
- char *rt_dev; /* forcing the device at add */
- unsigned long rt_mss; /* per route MTU/Window */
- unsigned long rt_window; /* Window clamping */
-};
-
-
-#define RTF_UP 0x0001 /* route usable */
-#define RTF_GATEWAY 0x0002 /* destination is a gateway */
-#define RTF_HOST 0x0004 /* host entry (net otherwise) */
-#define RTF_REINSTATE 0x0008 /* reinstate route after tmout */
-#define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */
-#define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */
-#define RTF_MSS 0x0040 /* specific MSS for this route */
-#define RTF_WINDOW 0x0080 /* per route window clamping */
-
-/*
- * REMOVE THESE BY 1.2.0 !!!!!!!!!!!!!!!!!
- */
-
-#define RTF_MTU RTF_MSS
-#define rt_mtu rt_mss
-
-#endif /* _LINUX_ROUTE_H */
diff --git a/pfinet/linux/sched.h b/pfinet/linux/sched.h
deleted file mode 100644
index acc60944..00000000
--- a/pfinet/linux/sched.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef _HACK_SCHED_H
-#define _HACK_SCHED_H
-
-#include <linux/wait.h>
-#include <sys/signal.h>
-#include <hurd/hurd_types.h>
-#include <linux/kernel.h>
-#include <linux/net.h>
-#include <sys/time.h>
-#include "mapped-time.h"
-#include <assert.h>
-#include <mach.h>
-#include <asm/system.h>
-
-#define jiffies (fetch_jiffies ())
-extern struct task_struct *current;
-extern struct task_struct current_contents;
-
-struct task_struct
-{
- uid_t pgrp, pid;
- int flags;
- int timeout;
- int signal;
- int blocked;
- int state;
- int isroot;
-};
-
-/* FLAGS in task_struct's. */
-#define PF_EXITING 1
-/* STATE in task_struct's. */
-#define TASK_INTERRUPTIBLE 1
-#define TASK_RUNNING 2
-
-extern inline int
-suser ()
-{
- return current->isroot;
-};
-
-void wake_up_interruptible (struct wait_queue **);
-void interruptible_sleep_on (struct wait_queue **);
-
-void select_wait (struct wait_queue **, select_table *);
-
-void schedule (void);
-
-#define SEL_IN SELECT_READ
-#define SEL_OUT SELECT_WRITE
-#define SEL_EX SELECT_URG
-
-/* 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;
-}
-
-int fetch_current_time (void);
-struct timeval fetch_xtime (void);
-
-#define xtime (fetch_xtime ())
-#define CURRENT_TIME (xtime.tv_sec)
-
-static struct timeval _xtime_buf;
-
-extern inline struct timeval
-fetch_xtime ()
-{
- maptime_read (mapped_time, &_xtime_buf);
- return _xtime_buf;
-}
-
-#endif
diff --git a/pfinet/linux/skbuff.h b/pfinet/linux/skbuff.h
deleted file mode 100644
index 817f89d7..00000000
--- a/pfinet/linux/skbuff.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Definitions for the 'struct sk_buff' memory handlers.
- *
- * Authors:
- * Alan Cox, <gw4pts@gw4pts.ampr.org>
- * Florian La Roche, <rzsfl@rz.uni-sb.de>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _LINUX_SKBUFF_H
-#define _LINUX_SKBUFF_H
-#include <linux/malloc.h>
-#include <linux/wait.h>
-#include <linux/time.h>
-#include <linux/config.h>
-
-#undef CONFIG_SKB_CHECK
-
-#define HAVE_ALLOC_SKB /* For the drivers to know */
-
-
-#define FREE_READ 1
-#define FREE_WRITE 0
-
-
-struct sk_buff_head {
- struct sk_buff * volatile next;
- struct sk_buff * volatile prev;
-#if CONFIG_SKB_CHECK
- int magic_debug_cookie;
-#endif
-};
-
-
-struct sk_buff {
- struct sk_buff * volatile next;
- struct sk_buff * volatile prev;
-#if CONFIG_SKB_CHECK
- int magic_debug_cookie;
-#endif
- struct sk_buff * volatile link3;
- struct sock *sk;
- volatile unsigned long when; /* used to compute rtt's */
- struct timeval stamp;
- struct device *dev;
- struct sk_buff *mem_addr;
- union {
- struct tcphdr *th;
- struct ethhdr *eth;
- struct iphdr *iph;
- struct udphdr *uh;
- unsigned char *raw;
- unsigned long seq;
- } h;
- struct iphdr *ip_hdr; /* For IPPROTO_RAW */
- unsigned long mem_len;
- unsigned long len;
- unsigned long fraglen;
- struct sk_buff *fraglist; /* Fragment list */
- unsigned long truesize;
- unsigned long saddr;
- unsigned long daddr;
- unsigned long raddr; /* next hop addr */
- volatile char acked,
- used,
- free,
- arp;
- unsigned char tries,lock,localroute,pkt_type;
-#define PACKET_HOST 0 /* To us */
-#define PACKET_BROADCAST 1
-#define PACKET_MULTICAST 2
-#define PACKET_OTHERHOST 3 /* Unmatched promiscuous */
- unsigned short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
- unsigned short pkt_class; /* For drivers that need to cache the packet type with the skbuff (new PPP) */
-#ifdef CONFIG_SLAVE_BALANCING
- unsigned short in_dev_queue;
-#endif
- unsigned long padding[0];
- unsigned char data[0];
-};
-
-#define SK_WMEM_MAX 32767
-#define SK_RMEM_MAX 32767
-
-#ifdef CONFIG_SKB_CHECK
-#define SK_FREED_SKB 0x0DE2C0DE
-#define SK_GOOD_SKB 0xDEC0DED1
-#define SK_HEAD_SKB 0x12231298
-#endif
-
-#ifdef __KERNEL__
-/*
- * Handling routines are only of interest to the kernel
- */
-
-#include <asm/system.h>
-
-#if 0
-extern void print_skb(struct sk_buff *);
-#endif
-extern void kfree_skb(struct sk_buff *skb, int rw);
-extern void skb_queue_head_init(struct sk_buff_head *list);
-extern void skb_queue_head(struct sk_buff_head *list,struct sk_buff *buf);
-extern void skb_queue_tail(struct sk_buff_head *list,struct sk_buff *buf);
-extern struct sk_buff * skb_dequeue(struct sk_buff_head *list);
-extern void skb_insert(struct sk_buff *old,struct sk_buff *newsk);
-extern void skb_append(struct sk_buff *old,struct sk_buff *newsk);
-extern void skb_unlink(struct sk_buff *buf);
-extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list);
-extern struct sk_buff * alloc_skb(unsigned int size, int priority);
-extern void kfree_skbmem(struct sk_buff *skb, unsigned size);
-extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
-extern void skb_device_lock(struct sk_buff *skb);
-extern void skb_device_unlock(struct sk_buff *skb);
-extern void dev_kfree_skb(struct sk_buff *skb, int mode);
-extern int skb_device_locked(struct sk_buff *skb);
-/*
- * Peek an sk_buff. Unlike most other operations you _MUST_
- * be careful with this one. A peek leaves the buffer on the
- * list and someone else may run off with it. For an interrupt
- * type system cli() peek the buffer copy the data and sti();
- */
-static __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_)
-{
- struct sk_buff *list = (struct sk_buff *)list_;
- return (list->next != list)? list->next : NULL;
-}
-
-#if CONFIG_SKB_CHECK
-extern int skb_check(struct sk_buff *skb,int,int, char *);
-#define IS_SKB(skb) skb_check((skb), 0, __LINE__,__FILE__)
-#define IS_SKB_HEAD(skb) skb_check((skb), 1, __LINE__,__FILE__)
-#else
-#define IS_SKB(skb)
-#define IS_SKB_HEAD(skb)
-
-extern __inline__ void skb_queue_head_init(struct sk_buff_head *list)
-{
- list->prev = (struct sk_buff *)list;
- list->next = (struct sk_buff *)list;
-}
-
-/*
- * Insert an sk_buff at the start of a list.
- */
-
-extern __inline__ void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
-{
- unsigned long flags;
- struct sk_buff *list = (struct sk_buff *)list_;
-
- save_flags(flags);
- cli();
- newsk->next = list->next;
- newsk->prev = list;
- newsk->next->prev = newsk;
- newsk->prev->next = newsk;
- restore_flags(flags);
-}
-
-/*
- * Insert an sk_buff at the end of a list.
- */
-
-extern __inline__ void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
-{
- unsigned long flags;
- struct sk_buff *list = (struct sk_buff *)list_;
-
- save_flags(flags);
- cli();
-
- newsk->next = list;
- newsk->prev = list->prev;
-
- newsk->next->prev = newsk;
- newsk->prev->next = newsk;
-
- restore_flags(flags);
-}
-
-/*
- * Remove an sk_buff from a list. This routine is also interrupt safe
- * so you can grab read and free buffers as another process adds them.
- */
-
-extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
-{
- long flags;
- struct sk_buff *result;
- struct sk_buff *list = (struct sk_buff *)list_;
-
- save_flags(flags);
- cli();
-
- result = list->next;
- if (result == list) {
- restore_flags(flags);
- return NULL;
- }
-
- result->next->prev = list;
- list->next = result->next;
-
- result->next = NULL;
- result->prev = NULL;
-
- restore_flags(flags);
-
- return result;
-}
-
-/*
- * Insert a packet before another one in a list.
- */
-
-extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- newsk->next = old;
- newsk->prev = old->prev;
- old->prev = newsk;
- newsk->prev->next = newsk;
-
- restore_flags(flags);
-}
-
-/*
- * Place a packet after a given packet in a list.
- */
-
-extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- newsk->prev = old;
- newsk->next = old->next;
- newsk->next->prev = newsk;
- old->next = newsk;
-
- restore_flags(flags);
-}
-
-/*
- * Remove an sk_buff from its list. Works even without knowing the list it
- * is sitting on, which can be handy at times. It also means that THE LIST
- * MUST EXIST when you unlink. Thus a list must have its contents unlinked
- * _FIRST_.
- */
-
-extern __inline__ void skb_unlink(struct sk_buff *skb)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- if(skb->prev && skb->next)
- {
- skb->next->prev = skb->prev;
- skb->prev->next = skb->next;
- skb->next = NULL;
- skb->prev = NULL;
- }
- restore_flags(flags);
-}
-
-#endif
-
-extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
-extern int datagram_select(struct sock *sk, int sel_type, select_table *wait);
-extern void skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
-extern void skb_free_datagram(struct sk_buff *skb);
-
-#endif /* __KERNEL__ */
-#endif /* _LINUX_SKBUFF_H */
diff --git a/pfinet/linux/socket.h b/pfinet/linux/socket.h
deleted file mode 100644
index 22dd05ce..00000000
--- a/pfinet/linux/socket.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _HACK_SOCKET_H_
-#define _HACK_SOCKET_H_
-
-#include <sys/socket.h>
-#include <sys/ioctl.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
-
-/* TCP options */
-#define TCP_NODELAY 1
-#define TCP_MAXSEG 2
-
-#define SO_NO_CHECK 11
-#define SO_PRIORITY 12
-
-#endif
diff --git a/pfinet/linux/tcp.h b/pfinet/linux/tcp.h
deleted file mode 100644
index 32ef0ad1..00000000
--- a/pfinet/linux/tcp.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the TCP protocol.
- *
- * Version: @(#)tcp.h 1.0.2 04/28/93
- *
- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_TCP_H
-#define _LINUX_TCP_H
-
-
-#define HEADER_SIZE 64 /* maximum header size */
-
-
-struct tcphdr {
- __u16 source;
- __u16 dest;
- __u32 seq;
- __u32 ack_seq;
-#if defined(__i386__)
- __u16 res1:4,
- doff:4,
- fin:1,
- syn:1,
- rst:1,
- psh:1,
- ack:1,
- urg:1,
- res2:2;
-#elif defined(__mc68000__)
- __u16 res2:2,
- urg:1,
- ack:1,
- psh:1,
- rst:1,
- syn:1,
- fin:1,
- doff:4,
- res1:4;
-#elif defined(__MIPSEL__)
- __u16 res1:4,
- doff:4,
- fin:1,
- syn:1,
- rst:1,
- psh:1,
- ack:1,
- urg:1,
- res2:2;
-#elif defined(__MIPSEB__)
- __u16 res2:2,
- urg:1,
- ack:1,
- psh:1,
- rst:1,
- syn:1,
- fin:1,
- doff:4,
- res1:4;
-#elif defined(__alpha__)
- __u16 res1:4,
- doff:4,
- fin:1,
- syn:1,
- rst:1,
- psh:1,
- ack:1,
- urg:1,
- res2:2;
-#elif defined(__sparc__)
- __u16 res2:2,
- urg:1,
- ack:1,
- psh:1,
- rst:1,
- syn:1,
- fin:1,
- doff:4,
- res1:4;
-#else
-#error "Adjust this structure for your cpu alignment rules"
-#endif
- __u16 window;
- __u16 check;
- __u16 urg_ptr;
-};
-
-
-enum {
- TCP_ESTABLISHED = 1,
- TCP_SYN_SENT,
- TCP_SYN_RECV,
- TCP_FIN_WAIT1,
- TCP_FIN_WAIT2,
- TCP_TIME_WAIT,
- TCP_CLOSE,
- TCP_CLOSE_WAIT,
- TCP_LAST_ACK,
- TCP_LISTEN,
- TCP_CLOSING /* now a valid state */
-};
-
-#endif /* _LINUX_TCP_H */
diff --git a/pfinet/linux/time.h b/pfinet/linux/time.h
deleted file mode 100644
index 50e13783..00000000
--- a/pfinet/linux/time.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _HACK_TIME_H_
-#define _HACK_TIME_H_
-
-#include <sys/time.h>
-#include "mapped-time.h"
-
-extern inline void
-do_gettimeofday (struct timeval *tp)
-{
- maptime_read (mapped_time, &_xtime_buf);
-}
-
-#endif
diff --git a/pfinet/linux/types.h b/pfinet/linux/types.h
deleted file mode 100644
index c978fb07..00000000
--- a/pfinet/linux/types.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _HACK_TYPES_H
-#define _HACK_TYPES_H
-
-#include <sys/types.h>
-typedef unsigned char __u8;
-typedef unsigned short __u16;
-typedef unsigned long __u32;
-
-/* Hackery */
-struct inode
-{
- uid_t i_uid;
-};
-
-
-#endif
diff --git a/pfinet/linux/udp.h b/pfinet/linux/udp.h
deleted file mode 100644
index 471301a2..00000000
--- a/pfinet/linux/udp.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Definitions for the UDP protocol.
- *
- * Version: @(#)udp.h 1.0.2 04/28/93
- *
- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * 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
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _LINUX_UDP_H
-#define _LINUX_UDP_H
-
-
-struct udphdr {
- unsigned short source;
- unsigned short dest;
- unsigned short len;
- unsigned short check;
-};
-
-
-#endif /* _LINUX_UDP_H */
diff --git a/pfinet/linux/wait.h b/pfinet/linux/wait.h
deleted file mode 100644
index 15759ad2..00000000
--- a/pfinet/linux/wait.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _HACK_WAIT_H_
-#define _HACK_WAIT_H_
-
-#include <cthreads.h>
-
-struct wait_queue
-{
- struct condition c;
-};
-
-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/loopback.c b/pfinet/loopback.c
index 0d3681fb..068cf3c8 100644
--- a/pfinet/loopback.c
+++ b/pfinet/loopback.c
@@ -1,6 +1,5 @@
/* Loopback "device" for pfinet
- Copyright (C) 1996, 1998 Free Software Foundation, Inc.
- Written by Thomas Bushnell, n/BSG.
+ Copyright (C) 1996,98,2000 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -18,79 +17,114 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
-#include <linux/netdevice.h>
+#include "pfinet.h"
#include <netinet/in.h>
#include <arpa/inet.h>
-#include "pfinet.h"
-
-struct device loopback_dev;
-
-int
-loopback_xmit (struct sk_buff *skb, struct device *dev)
+#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)
{
- int done;
-
- if (!skb || !dev)
- return 0;
-
- if (dev->tbusy)
- return 1;
-
- dev->tbusy;
-
- done = dev_rint (skb->data, skb->len, 0, dev);
- dev_kfree_skb (skb, FREE_WRITE);
-
- while (done != 1)
- done = dev_rint (0, 0, 0, dev);
-
- dev->tbusy = 0;
- return 0;
+ 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);
}
-u_int16_t
-loopback_type_trans (struct sk_buff *skb, struct device *dev)
+static struct net_device_stats *get_stats(struct device *dev)
{
- return htons (ETH_P_IP);
+ return (struct net_device_stats *)dev->priv;
}
+static int loopback_open(struct device *dev)
+{
+ dev->flags|=IFF_LOOPBACK;
+ return 0;
+}
-void
-setup_loopback_device (char *name)
+/* Initialize the rest of the LOOPBACK device. */
+static int loopback_init(struct device *dev)
{
- int i;
-
- loopback_dev.name = name;
- for (i = 0; i < DEV_NUMBUFFS; i++)
- skb_queue_head_init (&loopback_dev.buffs[i]);
-
- loopback_dev.open = 0;
- loopback_dev.stop = 0;
- loopback_dev.hard_start_xmit = loopback_xmit;
- loopback_dev.hard_header = 0;
- loopback_dev.rebuild_header = 0;
- loopback_dev.type_trans = loopback_type_trans;
- loopback_dev.get_stats = 0;
- loopback_dev.set_multicast_list = 0;
-
- loopback_dev.type = 0;
- loopback_dev.addr_len = 0;
- loopback_dev.flags = IFF_LOOPBACK | IFF_BROADCAST | IFF_UP;
- loopback_dev.family = AF_INET;
-
- loopback_dev.mtu = 2000;
-
- /* Defaults */
- loopback_dev.pa_addr = inet_addr ("127.0.0.1");
- loopback_dev.pa_brdaddr = inet_addr ("127.255.255.255");
- loopback_dev.pa_mask = inet_addr ("255.0.0.0");
- loopback_dev.pa_alen = sizeof (unsigned long);
-
- loopback_dev.next = dev_base;
- dev_base = &loopback_dev;
-
- /* Add the route */
- ip_rt_add (RTF_HOST, loopback_dev.pa_addr, 0xffffffff, 0, &loopback_dev,
- loopback_dev.mtu, 0);
+ 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
index 0232dd66..bd0c44f3 100644
--- a/pfinet/main.c
+++ b/pfinet/main.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ 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.
@@ -27,6 +27,9 @@
#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;
@@ -141,12 +144,6 @@ find_device (char *name, struct device **device)
setup_ethernet_device (name);
- /* Default mask is 255.255.255.0. XXX should be class dependent. */
- {
- char addr[4] = {255, 255, 255, 0};
- ether_dev.pa_mask = *(u_long *)addr;
- }
-
/* Turn on device. */
dev_open (&ether_dev);
@@ -168,6 +165,9 @@ enumerate_devices (error_t (*fun) (struct device *dev))
return 0;
}
+extern void sk_init (void), skb_init (void);
+extern int net_dev_init (void);
+
int
main (int argc,
char **argv)
@@ -186,19 +186,37 @@ main (int argc,
/* Generic initialization */
- init_devices ();
init_time ();
- cthread_detach (cthread_fork (input_work_thread, 0));
- inet_proto_init (0);
+ ethernet_initialize ();
+ cthread_detach (cthread_fork (net_bh_worker, 0));
- arrange_shutdown_notification ();
+ __mutex_lock (&global_lock);
- setup_loopback_device ("loopback");
+ prepare_current (1); /* Set up to call into Linux initialization. */
- /* Parse options. */
+ 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 ();
+
+ /* Parse options. When successful, this configures the interfaces
+ before returning. (And when not sucessful, it never returns.) */
argp_parse (&pfinet_argp, argc, argv, 0,0,0);
- /* Talk to parent and link us in. */
+ __mutex_unlock (&global_lock);
+
+ /* 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");
@@ -207,7 +225,7 @@ main (int argc,
trivfs_cntl_portclasses[0], pfinet_bucket,
trivfs_protid_portclasses[0], pfinet_bucket, 0);
if (err)
- error (1, errno, "contacting parent");
+ error (1, err, "contacting parent");
/* Launch */
ports_manage_port_operations_multithread (pfinet_bucket,
diff --git a/pfinet/misc.c b/pfinet/misc.c
index 6eb96b89..56611daf 100644
--- a/pfinet/misc.c
+++ b/pfinet/misc.c
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+/*
+ Copyright (C) 1995,96,2000 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -20,56 +20,45 @@
#include "pfinet.h"
#include <string.h>
+#include <stddef.h>
+
+#include <linux/socket.h>
+#include <linux/net.h>
-/* 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)
-{
- struct sock_user *user;
-
- if (noinstall)
- errno = ports_create_port_noinstall (socketport_class, pfinet_bucket,
- sizeof (struct sock_user), &user);
- else
- errno = ports_create_port (socketport_class, pfinet_bucket,
- sizeof (struct sock_user), &user);
- if (errno)
- return 0;
-
- user->isroot = isroot;
- user->sock = sock;
- sock->refcnt++;
- return user;
-}
/* 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
+ 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,
+make_sockaddr_port (struct socket *sock,
int peer,
mach_port_t *addr,
mach_msg_type_name_t *addrtype)
{
- char buf[128];
- int buflen = 128;
+ 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, (struct sockaddr *)buf, &buflen, peer);
+ err = (*sock->ops->getname) (sock, &buf.sa, &buflen, peer);
if (err)
return err;
-
+
err = ports_create_port (addrport_class, pfinet_bucket,
- sizeof (struct sock_addr) + buflen, &addrstruct);
- if (err)
- return err;
- addrstruct->len = buflen;
- bcopy (buf, addrstruct->address, buflen);
- *addr = ports_get_right (addrstruct);
- *addrtype = MACH_MSG_TYPE_MAKE_SEND;
+ (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;
}
@@ -104,86 +93,3 @@ void
clean_addrport (void *arg)
{
}
-
-/* Release the reference on the referenced socket. */
-void
-clean_socketport (void *arg)
-{
- struct sock_user *user = arg;
-
- mutex_lock (&global_lock);
-
- user->sock->refcnt--;
- if (user->sock->refcnt == 0)
- sock_release (user->sock);
-
- mutex_unlock (&global_lock);
-}
-
-struct socket *
-sock_alloc (void)
-{
- struct socket *sock;
- struct wait_queue *wait, **waitp;
-
- sock = malloc (sizeof (struct wait_queue)
- + sizeof (struct wait_queue *)
- + sizeof (struct socket));
- wait = (void *)sock + sizeof (struct socket);
- waitp = (void *)wait + sizeof (struct wait_queue);
-
- bzero (sock, sizeof (struct socket));
- sock->identity = MACH_PORT_NULL;
- sock->state = SS_UNCONNECTED;
- sock->wait = waitp;
-
- condition_init (&wait->c);
-
- *waitp = wait;
-
- return sock;
-}
-
-static inline void sock_release_peer(struct socket *peer)
-{
- peer->state = SS_DISCONNECTING;
- wake_up_interruptible(peer->wait);
- sock_wake_async(peer, 1);
-}
-
-void
-sock_release (struct socket *sock)
-{
- int oldstate;
- struct socket *peersock, *nextsock;
-
- if ((oldstate = sock->state) != SS_UNCONNECTED)
- sock->state = SS_DISCONNECTING;
-
- /*
- * Wake up anyone waiting for connections.
- */
-
- for (peersock = sock->iconn; peersock; peersock = nextsock)
- {
- nextsock = peersock->next;
- sock_release_peer(peersock);
- }
-
- /*
- * Wake up anyone we're connected to. First, we release the
- * protocol, to give it a chance to flush data, etc.
- */
-
- peersock = (oldstate == SS_CONNECTED) ? sock->conn : NULL;
- if (sock->ops)
- (*sock->ops->release) (sock, peersock);
- if (peersock)
- sock_release_peer(peersock);
-
- if (sock->identity != MACH_PORT_NULL)
- mach_port_destroy (mach_task_self (), sock->identity);
- free (sock);
-}
-
-
diff --git a/pfinet/mutations.h b/pfinet/mutations.h
index 8c0df887..f63ad9b9 100644
--- a/pfinet/mutations.h
+++ b/pfinet/mutations.h
@@ -1,4 +1,4 @@
-/*
+/*
Copyright (C) 1995 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
diff --git a/pfinet/options.c b/pfinet/options.c
index b308dc36..c565db18 100644
--- a/pfinet/options.c
+++ b/pfinet/options.c
@@ -1,8 +1,8 @@
/* Pfinet option parsing
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996,97,2000 Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Written by Miles Bader <miles@gnu.org>
This file is part of the GNU Hurd.
@@ -25,11 +25,15 @@
#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/route.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));
@@ -117,6 +121,7 @@ parse_opt (int opt, char *arg, struct argp_state *state)
/* 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); \
@@ -154,16 +159,16 @@ parse_opt (int opt, char *arg, struct argp_state *state)
break;
case 'a':
- h->curint->address = ADDR (arg, "address");
+ 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",
+ FAIL (EINVAL, 1, 0,
+ "%s: Cannot set interface address to multicast address",
arg);
- else
+ else
FAIL (EINVAL, 1, 0,
"%s: Illegal or undefined network address", arg);
}
@@ -202,52 +207,26 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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
/* Successfully finished parsing, return a result. */
for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
- {
- struct device *dev = in->device;
- if (in->address != INADDR_NONE || in->netmask != INADDR_NONE)
- {
- if (dev->pa_addr != 0)
- /* There's already an address, delete the old entry. */
- ip_rt_del (dev->pa_addr & dev->pa_mask, dev);
-
- if (in->address != INADDR_NONE)
- dev->pa_addr = in->address;
-
- if (in->netmask != INADDR_NONE)
- dev->pa_mask = in->netmask;
- else
- {
- if (IN_CLASSA (ntohl (dev->pa_addr)))
- dev->pa_mask = htonl (IN_CLASSA_NET);
- else if (IN_CLASSB (ntohl (dev->pa_addr)))
- dev->pa_mask = htonl (IN_CLASSB_NET);
- else if (IN_CLASSC (ntohl (dev->pa_addr)))
- dev->pa_mask = htonl (IN_CLASSC_NET);
- else
- abort ();
- }
-
- dev->family = AF_INET;
- dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;
-
- ip_rt_add (0, dev->pa_addr & dev->pa_mask, dev->pa_mask,
- 0, dev, 0, 0);
- }
- if (in->gateway != INADDR_NONE)
- {
- ip_rt_del (0, dev);
- ip_rt_add (RTF_GATEWAY, 0, 0, in->gateway, dev, 0, 0);
- }
- }
+ if (in->address != INADDR_NONE || in->netmask != INADDR_NONE)
+ {
+ extern error_t configure_device (struct device *dev,
+ uint32_t addr,
+ uint32_t netmask); /* devinet.c */
+ err = configure_device (in->device, in->address, in->netmask);
+ if (err)
+ error (2, err, "cannot configure interface"); /* XXX */
+ }
/* Fall through to free hook. */
case ARGP_KEY_ERROR:
@@ -287,10 +266,12 @@ trivfs_append_args (struct trivfs_control *fsys, char **argz, size_t *argz_len)
ADD_OPT ("--%s=%s", name, inet_ntoa (i)); } while (0)
ADD_OPT ("--interface=%s", dev->name);
+#if 0 /* XXX */
if (dev->pa_addr != 0)
ADD_ADDR_OPT ("address", dev->pa_addr);
if (dev->pa_mask != 0)
ADD_ADDR_OPT ("netmask", dev->pa_mask);
+#endif
/* XXX how do we figure out the default gateway? */
#undef ADD_OPT
diff --git a/pfinet/pfinet.h b/pfinet/pfinet.h
index 36756615..b5c551d8 100644
--- a/pfinet/pfinet.h
+++ b/pfinet/pfinet.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc.
+ 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.
@@ -23,16 +23,12 @@
#include <device/device.h>
#include <hurd/ports.h>
-#include <linux/netdevice.h>
#include <hurd/trivfs.h>
#include <sys/mman.h>
+#include <sys/socket.h>
-extern device_t master_device;
-
-extern struct proto_ops *proto_ops;
-
-struct mutex global_lock;
-struct mutex packet_queue_lock;
+extern struct mutex global_lock;
+extern struct mutex net_bh_lock;
struct port_bucket *pfinet_bucket;
struct port_class *addrport_class;
@@ -55,27 +51,23 @@ struct sock_user
struct sock_addr
{
struct port_info pi;
- size_t len;
- struct sockaddr address[0];
+ struct sockaddr address;
};
-void setup_loopback_device (char *);
-
+void ethernet_initialize (void);
int ethernet_demuxer (mach_msg_header_t *, mach_msg_header_t *);
void setup_ethernet_device (char *);
-void become_task_protid (struct trivfs_protid *);
-void become_task (struct sock_user *);
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 input_work_thread (any_t);
+any_t net_bh_worker (any_t);
void init_time (void);
-void inet_proto_init (struct net_proto *);
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 *);
-int tcp_readable (struct sock *);
+struct sock;
+error_t tcp_tiocinq (struct sock *sk, mach_msg_type_number_t *amount);
struct sock_user *begin_using_socket_port (socket_t);
diff --git a/pfinet/sched.c b/pfinet/sched.c
index 41059b3f..53f0cb09 100644
--- a/pfinet/sched.c
+++ b/pfinet/sched.c
@@ -1,6 +1,5 @@
-/*
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Written by Michael I. Bushnell, p/BSG.
+/*
+ Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -18,38 +17,21 @@
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 "pfinet.h"
+#include <linux/interrupt.h>
struct mutex global_lock = MUTEX_INITIALIZER;
-struct mutex packet_queue_lock = MUTEX_INITIALIZER;
-
-struct task_struct current_contents;
-struct task_struct *current = &current_contents;
-
-void
-interruptible_sleep_on (struct wait_queue **p)
-{
- int cancel;
-
- cancel = hurd_condition_wait (&(*p)->c, &global_lock);
- if (cancel)
- current->signal = 1;
-}
+struct mutex net_bh_lock = MUTEX_INITIALIZER;
+struct condition net_bh_wakeup = CONDITION_INITIALIZER;
-void
-wake_up_interruptible (struct wait_queue **p)
-{
- /* tcp.c uses an unitialized wait queue; don't bomb
- if we see it. */
- if (*p)
- condition_broadcast (&(*p)->c);
-}
+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
+ 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
@@ -60,28 +42,28 @@ sock_wake_async (struct socket *sock, int how)
}
-/* Set the contents of current appropriately for an RPC being undertaken
- by USER. */
-void
-become_task (struct sock_user *user)
-{
- /* These fields are not really used currently. */
- current->pgrp = current->pid = 0;
-
- current->flags = 0;
- current->timeout = 0;
- current->signal = current->blocked = 0;
- current->state = TASK_RUNNING;
- current->isroot = user->isroot;
-}
-
-void
-become_task_protid (struct trivfs_protid *protid)
+/* 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)
{
- current->pgrp = current->pid = 0;
- current->flags = 0;
- current->timeout = 0;
- current->signal = current->blocked = 0;
- current->state = TASK_RUNNING;
- current->isroot = protid->isroot;
+ __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
index 3db4985f..bcfa7f45 100644
--- a/pfinet/socket-ops.c
+++ b/pfinet/socket-ops.c
@@ -1,5 +1,5 @@
/* Interface functions for the socket.defs interface.
- Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ 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.
@@ -20,11 +20,18 @@
#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,
@@ -48,16 +55,15 @@ S_socket_create (struct trivfs_protid *master,
|| protocol < 0)
return EINVAL;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
become_task_protid (master);
sock = sock_alloc ();
sock->type = sock_type;
- sock->ops = proto_ops;
- err = - (*sock->ops->create) (sock, protocol);
+ err = - (*net_families[PF_INET]->create) (sock, protocol);
if (err)
sock_release (sock);
else
@@ -68,7 +74,7 @@ S_socket_create (struct trivfs_protid *master,
ports_port_deref (user);
}
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return err;
}
@@ -78,26 +84,17 @@ S_socket_create (struct trivfs_protid *master,
error_t
S_socket_listen (struct sock_user *user, int queue_limit)
{
+ error_t err;
+
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
-
+ __mutex_lock (&global_lock);
become_task (user);
+ err = - (*user->sock->ops->listen) (user->sock, queue_limit);
+ __mutex_unlock (&global_lock);
- if (user->sock->state == SS_UNCONNECTED)
- {
- if (user->sock->ops && user->sock->ops->listen)
- (*user->sock->ops->listen) (user->sock, queue_limit);
- user->sock->flags |= SO_ACCEPTCON;
- mutex_unlock (&global_lock);
- return 0;
- }
- else
- {
- mutex_unlock (&global_lock);
- return EINVAL;
- }
+ return err;
}
error_t
@@ -114,47 +111,43 @@ S_socket_accept (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
-
- become_task (user);
-
sock = user->sock;
- newsock = 0;
- err = 0;
- if ((sock->state != SS_UNCONNECTED)
- || (!(sock->flags & SO_ACCEPTCON)))
- err = EINVAL;
- else if (!(newsock = sock_alloc ()))
- err = ENOMEM;
-
- if (err)
- goto out;
+ __mutex_lock (&global_lock);
- newsock->type = sock->type;
- newsock->ops = sock->ops;
-
- err = - (*sock->ops->dup) (newsock, sock);
- if (err)
- goto out;
-
- err = - (*sock->ops->accept) (sock, newsock, sock->userflags);
- if (err)
- goto out;
+ become_task (user);
- err = make_sockaddr_port (newsock, 1, addr_port, addr_port_type);
- if (err)
- goto out;
+ 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);
+ }
- 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);
+ __mutex_unlock (&global_lock);
- out:
- if (err && newsock)
- sock_release (newsock);
- mutex_unlock (&global_lock);
return err;
}
@@ -170,25 +163,14 @@ S_socket_connect (struct sock_user *user,
sock = user->sock;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
become_task (user);
- err = 0;
-
- if (sock->state == SS_CONNECTED
- && sock->type != SOCK_DGRAM)
- err = EISCONN;
- else if (sock->state != SS_UNCONNECTED
- && sock->state != SS_CONNECTING
- && sock->state != SS_CONNECTED)
- err = EINVAL;
-
- if (!err)
- err = - (*sock->ops->connect) (sock, addr->address, addr->len,
- sock->userflags);
+ err = - (*sock->ops->connect) (sock, &addr->address, addr->address.sa_len,
+ sock->flags);
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
/* MiG should do this for us, but it doesn't. */
if (!err)
@@ -208,10 +190,11 @@ S_socket_bind (struct sock_user *user,
if (! addr)
return EADDRNOTAVAIL;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
become_task (user);
- err = - (*user->sock->ops->bind) (user->sock, addr->address, addr->len);
- mutex_unlock (&global_lock);
+ 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)
@@ -228,10 +211,10 @@ S_socket_name (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
become_task (user);
make_sockaddr_port (user->sock, 0, addr_port, addr_port_name);
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return 0;
}
@@ -245,10 +228,10 @@ S_socket_peername (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
become_task (user);
err = make_sockaddr_port (user->sock, 1, addr_port, addr_port_name);
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return err;
}
@@ -262,7 +245,7 @@ S_socket_connect2 (struct sock_user *user1,
if (!user1 || !user2)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
become_task (user1);
@@ -274,15 +257,7 @@ S_socket_connect2 (struct sock_user *user1,
else
err = - (*user1->sock->ops->socketpair) (user1->sock, user2->sock);
- if (!err)
- {
- user1->sock->conn = user2->sock;
- user2->sock->conn = user1->sock;
- user1->sock->state = SS_CONNECTED;
- user2->sock->state = SS_CONNECTED;
- }
-
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
/* MiG should do this for us, but it doesn't. */
if (!err)
@@ -299,23 +274,30 @@ S_socket_create_address (mach_port_t server,
mach_port_t *addr_port,
mach_msg_type_name_t *addr_port_type)
{
- struct sock_addr *addr;
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,
- sizeof (struct sock_addr) + data_len, &addr);
+ (offsetof (struct sock_addr, address)
+ + data_len), &addrstruct);
if (err)
return err;
- addr->len = data_len;
- bcopy (data, addr->address, data_len);
+ 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 (addr);
+ *addr_port = ports_get_right (addrstruct);
*addr_port_type = MACH_MSG_TYPE_MAKE_SEND;
- ports_port_deref (addr);
+ ports_port_deref (addrstruct);
return 0;
}
@@ -337,11 +319,12 @@ S_socket_whatis_address (struct sock_addr *addr,
if (!addr)
return EOPNOTSUPP;
- *type = AF_INET;
- if (*datalen < addr->len)
- *data = mmap (0, addr->len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
- bcopy (addr->address, *data, addr->len);
- *datalen = addr->len;
+ *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;
}
@@ -355,10 +338,10 @@ S_socket_shutdown (struct sock_user *user,
if (!user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
become_task (user);
err = - (*user->sock->ops->shutdown) (user->sock, direction);
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return err;
}
@@ -375,18 +358,17 @@ S_socket_getopt (struct sock_user *user,
if (! user)
return EOPNOTSUPP;
- /* XXX all options supported in the linux code are in fact ints. */
- *datalen = sizeof (int);
-
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
become_task (user);
- err =
- - (user->sock->ops->getsockopt)(user->sock, level, option, *data, datalen);
+ err = - (level == SOL_SOCKET ? sock_getsockopt
+ : *user->sock->ops->getsockopt)
+ (user->sock, level, option, *data, datalen);
- assert (*datalen == sizeof (int));
+ __mutex_unlock (&global_lock);
- 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;
}
@@ -403,13 +385,17 @@ S_socket_setopt (struct sock_user *user,
if (! user)
return EOPNOTSUPP;
- mutex_lock (&global_lock);
+ /* 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 =
- - (user->sock->ops->setsockopt)(user->sock, level, option, data, datalen);
+ err = - (level == SOL_SOCKET ? sock_setsockopt
+ : *user->sock->ops->setsockopt)
+ (user->sock, level, option, data, datalen);
- mutex_unlock (&global_lock);
+ __mutex_unlock (&global_lock);
return err;
}
@@ -427,6 +413,11 @@ S_socket_send (struct sock_user *user,
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;
@@ -435,19 +426,12 @@ S_socket_send (struct sock_user *user,
if (nports != 0 || controllen != 0)
return EINVAL;
- mutex_lock (&global_lock);
-
+ __mutex_lock (&global_lock);
become_task (user);
-
- if (addr)
- sent = (*user->sock->ops->sendto) (user->sock, data, datalen,
- user->sock->userflags, flags,
- addr->address, addr->len);
- else
- sent = (*user->sock->ops->send) (user->sock, data, datalen,
- user->sock->userflags, flags);
-
- mutex_unlock (&global_lock);
+ 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)
@@ -477,50 +461,53 @@ S_socket_recv (struct sock_user *user,
int *outflags,
mach_msg_type_number_t amount)
{
- int recvd;
- char addr[128];
- size_t addrlen = sizeof addr;
- int didalloc = 0;
+ 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;
- /* For unused recvmsg interface */
- *nports = 0;
- *portstype = MACH_MSG_TYPE_COPY_SEND;
- *controllen = 0;
- *outflags = 0;
-
- /* Instead of this, we should peek at the socket and only allocate
- as much as necessary. */
- if (*datalen < amount)
+ /* Instead of this, we should peek and the socket and only
+ allocate as much as necessary. */
+ if (amount > *datalen)
{
- vm_allocate (mach_task_self (), (vm_address_t *) data, amount, 1);
- didalloc = 1;
+ *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ alloced = 1;
}
- mutex_lock (&global_lock);
- become_task (user);
-
- recvd = (*user->sock->ops->recvfrom) (user->sock, *data, amount,
- user->sock->userflags, flags,
- (struct sockaddr *)addr, &addrlen);
-
- mutex_unlock (&global_lock);
-
- if (recvd < 0)
- return (error_t)-recvd;
-
- *datalen = recvd;
-
- if (didalloc && round_page (*datalen) < round_page (amount))
- vm_deallocate (mach_task_self (),
- (vm_address_t) (*data + round_page (*datalen)),
- round_page (amount) - round_page (*datalen));
+ 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);
- S_socket_create_address (0, AF_INET, addr, addrlen, addrport,
- addrporttype);
+ 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 0;
+ return err;
}
diff --git a/pfinet/socket.c b/pfinet/socket.c
index 7cbc0e9f..52bd37ff 100644
--- a/pfinet/socket.c
+++ b/pfinet/socket.c
@@ -1,6 +1,5 @@
-/*
- Copyright (C) 1995 Free Software Foundation, Inc.
- Written by Michael I. Bushnell, p/BSG.
+/*
+ Copyright (C) 1995,2000 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -18,18 +17,103 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
-#include <linux/net.h>
#include <assert.h>
#include "pfinet.h"
-struct proto_ops *proto_ops;
+#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 (int family, struct proto_ops *ops)
+sock_register (struct net_proto_family *fam)
{
- assert (family == PF_INET);
- proto_ops = ops;
+ 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/timer-emul.c b/pfinet/timer-emul.c
index d0842787..c305486e 100644
--- a/pfinet/timer-emul.c
+++ b/pfinet/timer-emul.c
@@ -41,7 +41,7 @@ timer_function (int this_is_a_pointless_variable_with_a_rather_long_name)
timer_thread = mach_thread_self ();
- mutex_lock (&global_lock);
+ __mutex_lock (&global_lock);
while (1)
{
int jiff = jiffies;
@@ -53,13 +53,13 @@ timer_function (int this_is_a_pointless_variable_with_a_rather_long_name)
else
wait = ((timers->expires - jiff) * 1000) / HZ;
- mutex_unlock (&global_lock);
+ __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);
+ __mutex_lock (&global_lock);
while (timers->expires < jiffies)
{
@@ -69,10 +69,10 @@ timer_function (int this_is_a_pointless_variable_with_a_rather_long_name)
timers = timers->next;
if (timers)
- timers->prevp = &timers;
+ timers->prev = &timers;
tp->next = 0;
- tp->prevp = 0;
+ tp->prev = 0;
(*tp->function) (tp->data);
}
@@ -91,15 +91,15 @@ add_timer (struct timer_list *timer)
if ((*tp)->expires > timer->expires)
{
timer->next = *tp;
- timer->next->prevp = &timer->next;
- timer->prevp = tp;
+ timer->next->prev = &timer->next;
+ timer->prev = tp;
*tp = timer;
break;
}
if (!*tp)
{
timer->next = 0;
- timer->prevp = tp;
+ timer->prev = tp;
*tp = timer;
}
@@ -122,14 +122,14 @@ add_timer (struct timer_list *timer)
int
del_timer (struct timer_list *timer)
{
- if (timer->prevp)
+ if (timer->prev)
{
- *timer->prevp = timer->next;
+ *timer->prev = timer->next;
if (timer->next)
- timer->next->prevp = timer->prevp;
+ timer->next->prev = timer->prev;
timer->next = 0;
- timer->prevp = 0;
+ timer->prev = 0;
return 1;
}
else
@@ -137,6 +137,16 @@ del_timer (struct timer_list *timer)
}
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));