diff options
author | Michael Gielda <mgielda@antmicro.com> | 2014-04-03 14:53:04 +0200 |
---|---|---|
committer | Michael Gielda <mgielda@antmicro.com> | 2014-04-03 14:53:04 +0200 |
commit | ae1e4e08a1005a0c487f03ba189d7536e7fdcba6 (patch) | |
tree | f1c296f8a966a9a39876b0e98e16d9c5da1776dd /ecos/packages/net/tcpip/current | |
parent | f157da5337118d3c5cd464266796de4262ac9dbd (diff) |
Added the OS files
Diffstat (limited to 'ecos/packages/net/tcpip/current')
231 files changed, 68714 insertions, 0 deletions
diff --git a/ecos/packages/net/tcpip/current/ChangeLog b/ecos/packages/net/tcpip/current/ChangeLog new file mode 100644 index 0000000..ed23142 --- /dev/null +++ b/ecos/packages/net/tcpip/current/ChangeLog @@ -0,0 +1,1759 @@ +2010-09-18 John Dallaway <john@dallaway.org.uk> + + * doc/openbsd.sgml: No longer "recent". + +2009-09-10 John Dallaway <john@dallaway.org.uk> + + * src/sys/netinet/tcp_input.c, src/sys/netinet/tcp_timer.c: Remove + lvalue casts. + +2005-10-23 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/sys/kern/kern_subr.c (uiomove): Remove lvalue cast to + keep GCC4.x happy. + +2003-12-10 Gary Thomas <gary@mlbassoc.com> + + * include/netinet/in.h: Prototype for inet_ntoa_r() + +2003-11-25 Manu Sharma <manu.sharma@ascom.com> + * src/sys/net/bridgestp.c: Code for Spanning Tree Protocol (STP). + + * cdl/openbsd_net.cdl: Changes make provisions for STP code. + * doc/openbsd.sgml: Same. + * include/net/if.h: Same. + * include/net/if_bridge.h: Same. + * include/net/if_llc.h: Same. + * include/sys/sockio.h: Same. + * src/sys/net/if_bridge.c: Same. + + * doc/openbsd-manpages-stp.sgml: Documentation for OpenBSD specific code + * doc/openbsd-manpages-netintro.sgml: Same. + * doc/openbsd-manpages-bridge.sgml: Same. + +2003-09-22 Reinhard Jessich <Reinhard.Jessich@frequentis.com> + + * include/net/if.h: Define macro IF_IS_EMPTY needed by eth_drv.c + +2003-02-24 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/openbsd_net.cdl: Improve doc links. + +2003-01-30 Jonathan Larmour <jifl@eCosCentric.com> + + * src/sys/net/if_bridge.c (bridge_input): Learn source host addr, + not dest host addr. + Fix pointed to by Daniel Néri. + +2002-12-14 Nick Garnett <nickg@ecoscentric.com> + + * src/sys/netinet/tcp_usrreq.c (tcp_usrreq): Rearranged ifndef on + PRU_SENSE case to keep the case in the switch and let it return a + sensible result. Otherwise a stat() on a socket causes a panic(). + +2002-12-03 Gary Thomas <gthomas@ecoscentric.com> + + * src/ecos/support.c (show_network_tables): New function used + to print network information (interface, routing). + +2002-05-21 Jesper Skov <jskov@redhat.com> + + * src/lib/recv.c: Fix warning. socket.h declarations are not + available to the kernel code. Added missing argument in the + recvfrom call. + +2002-05-14 Jesper Skov <jskov@redhat.com> + + * include/netinet6/in6.h: Fixed warnings. + + * src/sys/kern/uipc_socket2.c (sblock): Fixed warning. + * src/sys/netinet/tcp_input.c: Same. + * src/sys/net/if_loop.c (looutput): Same. + * src/sys/kern/sockio.c: Same. + + * include/sys/param.h: Include machine headers after the namespace + changing macros to get the desired declarations, thus fixing + compiler warnings. + +2002-04-26 Gary Thomas <gthomas@redhat.com> + + * src/sys/netinet/ip_input.c: Proper "extern" definition of 'ipstat'. + + * src/sys/netinet/raw_ip.c: + * src/sys/netinet/ip_output.c: + * include/netinet/ip_var.h: Use of ramdom IP packet id is optional. + +2002-04-22 Gary Thomas <gthomas@redhat.com> + + * src/sys/netinet/tcp_usrreq.c: + * src/sys/netinet/tcp_output.c: + * src/sys/netinet/tcp_input.c: + * src/sys/netinet/tcp_debug.c: + * include/netinet/tcp_debug.h: Fully conditionalize on TCPDEBUG. + +2002-03-27 Jonathan Larmour <jlarmour@redhat.com> + + * doc/openbsd.sgml: Manpages now live in "common" BSD package. + +2002-03-19 Gary Thomas <gthomas@redhat.com> + + * src/sys/net/route.c (cyg_route_reinit): Renamed from route_reinit. + +2002-03-11 Hugo Tyson <hmt@redhat.com> + + [Case 107110] + + * src/sys/netinet/in.c (in_control): SIOCSIFADDR switch entry + moved to before the scan for this same address being in the list + already, along with Add and Delete (SIOCAIFADDR,SIOCDIFADDR) arms. + It falls through into the same alloc-if-needed code anyway. + Thus repeatedly setting the same address does not leak store. + + * src/sys/net/route.c (route_reinit): Rewrite to delete all routes + individually rather than en-masse (leaking store). + (rt_reinit_rtdelete): New function; callback for individual + deletion. + (rtioctl): Do not pass in a "route **" to return a pointer to the + route removed or added; this results in an extra reference, by the + returned pointer, and so a storeleak. + (rtrequest): RTM_DELETE arm: do not free a gateway route if the + gateway pointer is the same as the route itself - it gets freed + *again* at the end of the routine if you do. Just dec the refcnt. + +2002-03-07 Gary Thomas <gthomas@redhat.com> + + * include/sys/param.h: Privatize route_reinit(), arc4random(). + +2002-02-28 Hugo Tyson <hmt@redhat.com> +2002-02-28 Martin Buck <martin.buck@ascom.ch> + + * src/sys/net/if_ethersubr.c (ether_input): [Bugzilla 60318] + ether_input() schedules processing by calling schednetisr(FOO) and + then queues the frame afterwards. Where we cannot be preempted + eg. in a DSR or in the original BSD kernel, this is OK. In eCos + the call to schednetisr(FOO) might cause a context switch *before* + the frame is enqueued. This "jams" one packet in the queue, + delaying it until the next packet, and so on. + + This change makes ether_input() store up the schednetisr() arg + until the end, and do the call then, much like it does with the + queue to use. Thanks Martin! + +2002-02-22 Hugo Tyson <hmt@redhat.com> + + * doc/openbsd.sgml: New file; separated stack-specific docs from + monolithic net doc, and tidied up in various ways. + +2002-02-15 Gary Thomas <gthomas@redhat.com> + + * cdl/openbsd_net.cdl: Slight changes in layout required by split + of network stacks. + +2002-02-13 Jonathan Larmour <jlarmour@redhat.com> +2002-02-13 Andrew Lunn <andrew.lunn@ascom.ch> + + * include/sys/mbuf.h: Declare variables as extern in header. + * src/sys/kern/uipc_mbuf.c: Define mbtypes[] and init it. + +2002-02-05 Hugo Tyson <hmt@redhat.com> + + * cdl/openbsd_net.cdl: Place this package below CYGPKG_NET + ie. the common networking package. Only affects the view in the + GUI CT, no big deal. + +2002-01-28 Gary Thomas <gthomas@redhat.com> + + * src/sys/netinet/ip_input.c: inet_ntoa() is now common. + + * cdl/openbsd_net.cdl: Renamed from net.cdl. This package + is now a proper sub-package, implementing a network stack. + +2002-01-28 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/net.cdl: Clarify CYGPKG_NET_ROUTING description. + +2002-01-08 Jonathan Larmour <jlarmour@redhat.com> + + * tests/server_test.c (server_test): Correct port conversion. + +2001-12-14 Hugo Tyson <hmt@redhat.com> + + * src/sys/net/if_ethersubr.c (ether_output): Never ever print + anything! It can recurse unexpectedly if debugging over net. + +2001-12-10 Andrew Lunn <andrew.lunn@ascom.ch> + + * cdl/net.cdl: Add configury to eliminate network timing stats. + * src/include/machine/param.h: Timing statistics for things like + memcpy, mbuf_alloc etc now use configury to determine if the + statistics code should be compiled. + * src/ecos/support.c: Ditto. + * tests/nc_test_slave.c: Only print timing stats when they + are enabled. + * tests/tcp_echo.c: Ditto. + * tests/nc_test_master.c: Allow building with SNMP lib which has + its own gettimeofday(). This should be fixed better a different + way but will do for now. + +2001-12-06 Hugo Tyson <hmt@redhat.com> + + * src/lib/bootp_support.c (init_net): Just re-tabbed and checked + the addition to initialize DNS from DHCP info - it had already + snuck into the file in the previous change from Andrew. Include + of netdb.h added also, from the patch in Bug 57019. Also check + CYGINT_ISO_DNS for the setup code instead of CYGPKG_ISO_DNS. + +2001-12-04 Jonathan Larmour <jlarmour@redhat.com> + + * src/lib/bootp_support.c: Check CYGINT_ISO_DNS (from + <pkgconf/isoinfra.h>) instead of CYGPKG_ISO_DNS. + +2001-12-03 Andrew Lunn <Andrew.Lunn@ascom.ch> + + * src/lib/bootp_support.c: get_bootp_option(): Take the + max length of data we want out of the bootp record. + * src/lib/dhcp_prot.c: Pass the length we expect for an option. + +2001-08-16 Anssi Pulkkinen <Anssi.Pulkkinen@ascom.ch> + + * src/lib/dhcp_prot.c: Make sure we use the newly calculated xid. + +2001-08-02 Anand Srivastava <Anand.Srivastava@ascom.ch> + + * src/lib/dhcp_prot.c do_dhcp: ID calculation must be done only + once. moved it out the loop. + +2001-11-21 Hugo Tyson <hmt@redhat.com> + + * src/lib/dhcp_support.c (dhcp_mgt_entry): If we have an + SNMPAGENT, must recycle it whenever we reinitialize all + interfaces; call SnmpdShutDown() to cause this. + Also re-initialize all loopback interfaces here too. + +2001-11-30 Hugo Tyson <hmt@redhat.com> + + * src/lib/dhcp_prot.c (set_default_dhcp_tags): New routine to + insert all the extra woffle we need neatly each time, keeping the + state machine's case arms to the real work. The new thing this + sets is TAG_DHCP_PARM_REQ_LIST, with a list that matches the + default set we get from a LINUX dhcpd. This is because M$ servers + need explicit requests for eg. TAG_GATEWAY. Note that I have + included configuration to override the set of tags requested here + in the source, but not yet backed up by CDL - we'll see whether + anyone needs this. + (set_variable_tag): New routine to insert a variable pointed-to + data item rather than an int of 1,2 or 4 bytes. + (do_dhcp): Call set_default_dhcp_tags() every time we send a + packet, rather than ad hoc additions in each state. + +2001-11-29 Jonathan Larmour <jlarmour@redhat.com> + + * include/machine/ansi.h: No longer require BSD string function + compatibility macros (in fact they confuse things). + + * cdl/net.cdl: Require BSD compatibility functions from <string.h>. + +2001-11-19 Hugo Tyson <hmt@redhat.com> + + * include/bootp.h (BP_STD_TX_MINPKTSZ): New symbol defining the + minimal DHCP packet size which we should send. + + * src/lib/dhcp_prot.c (scan_dhcp_size): New routine to scan up to + the end of the packet, for length determination and padding. + (dhcp_size): Now uses scan_dhcp_size(). + (dhcp_size_for_send): New, uses scan_dhcp_size() and pads with + zero up to the min packet size that we should send. + (do_dhcp): In every sendto() call, use dhcp_size_for_send(xmit) in + order to send padded, full size packets as needed. 5 instances. + + Credit to "Anssi Pulkkinen" <Anssi.Pulkkinen@ascom.ch> for the + original version of this patch. + +2001-11-08 Jesper Skov <jskov@redhat.com> + + * tests/server_test.c (net_test): Fix compile error. + +2001-11-02 Gary Thomas <gthomas@redhat.com> + + * src/ecos/support.c: + * include/machine/ansi.h: Add C++ support [externC]. + +2001-11-11 Andrew Lunn <andrew.lunn@ascom.ch> + + *src/lib/recv.c: Implement the recv() call. + +2001-10-29 Hugo Tyson <hmt@redhat.com> + + * src/sys/net/if_ethersubr.c (ether_output): [CASE 106613] Even if + the queue is full, and we are dropping the packet, try to start + the interface anyway, to give it a chance to empty the queue if + the device has recovered from whatever made the queue fill up in + the first place - being unplugged from the network for example. + This change is belt & braces with a similar policy in the periodic + tickle function in the logical ether driver in io/eth/... ; this + change will recover the situation immediately if the application + continues trying to send despite ENOBUFS. + +2001-10-25 Hugo Tyson <hmt@redhat.com> + + * src/sys/net/if_bridge.c (bridge_broadcast): Count if_obytes in + destination interfaces as well as the bridge interface; normally + this is done in if_ethersubr.c but here we talk directly to the + interface, bypassing that layer. Thanks to Andrew Lunn for + noticing that. + +2001-10-18 Jonathan Larmour <jlarmour@redhat.com> + + * src/sys/netinet/in.c (in_lifaddr_ioctl): Silence warnings about + trigraphs. + +2001-10-10 Hugo Tyson <hmt@redhat.com> + + * tests/ftp_test.c (net_test): This was lacking #ifdefs for + CYGHWR_NET_DRIVER_ETH0 and CYGHWR_NET_DRIVER_ETH1. Ooops. + +2001-10-05 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/net.cdl (CYGPKG_NET_CFLAGS_ADD): Define __INSIDE_NET within + this package to allow segregation of definitions only relevant for + internal consumption, and definitions allowable for external + consumption. + + * include/lib/libkern/libkern.h: Conditionalize on __INSIDE_NET. + +2001-10-04 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/net.cdl (CYGHWR_NET_DRIVER_ETH0): Make flavor bool so it isn't + defined when 0. + (CYGHWR_NET_DRIVER_ETH1): Ditto. + +2001-10-04 Hugo Tyson <hmt@redhat.com> + + * src/lib/dhcp_support.c: Some conditional compilation tags were + wrong vis a vis ETH1 versus ETH0. Thanks to "Simon" + <simoncc@ms46.url.com.tw> for spotting it. + +2001-10-04 Jesper Skov <jskov@redhat.com> + + * tests/multi_lo_select.c (cyg_user_start): Added CYG_TEST_INIT + call. + * tests/ping_lo_test.c (cyg_start): Same. + * tests/tcp_lo_test.c (cyg_start): Same. + * tests/udp_lo_test.c (cyg_start): Same. + * tests/tcp_lo_select.c (cyg_start): Same. + +2001-09-28 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/net.cdl: Tell isoinfra we support getproto* and getserv* + NS functionality. + * include/netdb.h: Move to... + * include/net/netdb.h: ...here. + +2001-09-25 Jesper Skov <jskov@redhat.com> + + * cdl/net.cdl: Don't build tests/nc_test_master as it's a host + side tool. + + * src/lib/getserv.c: Added domain service. + + * include/netdb.h: Moved getbyhost()/getbyaddr() declarations and + hostent struct definition to the DNS package. + + * src/lib/gethost.c: Removed. + + * cdl/net.cdl: Removed gethost.c (replaced by proper + implementation in CYGPKG_NS_DNS). + +2001-09-17 Hugo Tyson <hmt@redhat.com> +2001-09-17 Andrew Lunn <Andrew.Lunn@ascom.ch> + + * src/sys/net/if_bridge.c (bridge_broadcast): Fix a null pointer + deference. Supporting VLANs, it seems that during the net_init() + function, it sends a packet to the bridge with the source + interface being NULL. Stats counting assumed otherwise. + +2001-09-14 Jonathan Larmour <jlarmour@redhat.com> + + * src/sys/kern/uipc_syscalls.c: Last change to uipc_syscalls.c + wasn't right. The parts that were __ECOS__ should simply have + been completely removed. + +2001-09-13 Hugo Tyson <hmt@redhat.com> + + * cdl/net.cdl: Add configury to control whether we can tickle the + network devices if there's a lack of network traffic, and to + control the delay time before so doing. + + * src/ecos/timeout.c (alarm_thread): Use a timed wait, if so + configured, for the flag; and if it times out, tickle all the + devices via the common ether driver routine for so doing. + +2001-09-12 Jonathan Larmour <jlarmour@redhat.com> + + * include/sys/socketvar.h: Use __ECOS, not __ECOS__. + * src/sys/kern/uipc_syscalls.c: Ditto. + * src/sys/kern/uipc_socket2.c (sblock): Ditto. + +2001-08-02 Jonathan Larmour <jlarmour@redhat.com> + + * tests/linux_echo.c (echo_test): Set socket options before bind. + * tests/nc_test_slave.c (do_tcp_test): Ditto. + * tests/server_test.c (server_test): Ditto. + * tests/tcp_echo.c (echo_test): Ditto. + * tests/tcp_lo_test.c (server): Ditto. + * tests/tcp_sink.c (sink_test): Ditto. + * tests/tcp_source.c (source_test): Ditto. + +2001-07-27 Jonathan Larmour <jlarmour@redhat.com> + + * include/sys/select.h: Renamed to.... + * include/sys/bsdselect.h: New file. + * include/sys/socketvar.h: Include <sys/bsdselect.h> instead of + <sys/select.h> + * src/lib/select.c: Include <sys/bsdselect.h> + +2001-07-26 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/net.cdl (CYGPKG_NET_API_LOCAL): Implements select() + * include/sys/bsdtypes.h: No need for these select definitions. + +2001-06-20 Grant Edwards <grante@visi.com> +2001-06-20 Hugo Tyson <hmt@redhat.com> + + * src/lib/dhcp_prot.c (alarm_function): Change the lease state + before re-enabling the alarm so that if it somehow gets times of + zero (ie. right now) it quickly completes the state machine rather + than recursing to its doom. + (new_lease): Test the retcode of get_bootp_option() and use + obvious defaults if the T1 and T2 times are not provided - this is + RFC compliant! - and use "infinite lease" if the lease time is not + provided at all. + +2001-06-19 Trenton D. Adams <tadams@extremeeng.com> + + * tests/server_test.c (server_test): Null terminate read string + at right place. + +2001-06-13 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/net.cdl: Make debug output an option. Include DHCP. + + * src/lib/dhcp_prot.c: DHCP_CHATTER -> CYGDBG_NET_DHCP_CHATTER + + * src/ecos/support.c (cyg_kmem_init): Only print debug output if + requested. + + * cdl/net.cdl: Make requirements on other eCos features more + abstract. + +2001-05-09 Robin Farine <acnrf@dial.eunet.ch> +2001-05-09 Hugo Tyson <hmt@redhat.com> + + * src/lib/dhcp_prot.c (do_dhcp): In DHCPSTATE_INIT case, create a + new xid. Servers apparantly can use *only* this to distinguish + machines, even with different MAC addresses! Therefore we use + both the most sensitive randomizer available (arc4random()) which + in reality uses a finegrain clock, and salt the value further with + the MAC address itself. Thanks again Robin. + + * src/ecos/support.c (arc4random): Make arc4random not always be a + multiple of 256; stir the clock into the low bits also. + +2001-05-09 Robin Farine <acnrf@dial.eunet.ch> +2001-05-09 Hugo Tyson <hmt@redhat.com> + + * src/sys/net/if_bridge.c: Patch from Robin; the route aging + process took twice as long to timeout because an entry requires + *two* executions of bridge_rtage() to actually get removed. + Record the timeout over 2 to fix that and also define + BRIDGE_RTABLE_TIMEOUT as 300s that the standard specifies as + default aging time. + +2001-05-09 Hugo Tyson <hmt@redhat.com> + + * src/lib/getserv.c (setreturned): New routine to set up a copy of + the service data with the port converted to network order like the + API demands. It's this way to make the initialization of the + table most readable. + (services[]): Added an entry for snmp. + (getservbyname): Use setreturned() to return adjusted info. + (getservbyport): Use setreturned() to return adjusted info and + compare with host-ordered version of the port. + + * src/lib/tftp_client.c (tftp_get): + (tftp_put): Do not convert to net order from + the getserv structure; it's already net order. + + * src/lib/tftp_server.c (tftpd_server): Convert the socket into + host order; it's network order in the getserv API. + + * tests/ftp_test.c (ftp_test): Do not convert to net order from + the getserv structure; it's already net order. + + * tests/tftp_client_test.c (PUTFILE): Changed the names of the + test files to be fully qualified, this makes the test work with + more server machines. /tftpboot/tftp_get and /tftpboot/tftp_put. + +2001-04-24 Bart Veer <bartv@redhat.com> + + * cdl/net.cdl: + Prevent multiple device drivers from implementing the + same eth0/eth1 device. + +2001-03-30 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/net.cdl (CYGPKG_NET_SYSCTL): Comment out - currently unsupported. + +2001-03-28 Richard Panton <rpanton@3glab.com> + + * include/bootp.h: Define func protos with C linkage + * include/netdb.h: Ditto + * include/network.h: Ditto + * include/tftp_support.h: Ditto + + * src/lib/getserv.c: getservbynumber() -> getservbyport() + +2001-03-12 Gary Thomas <gthomas@redhat.com> + + * src/lib/network_support.c (init_all_network_interfaces): + FIx slightly broken previous attempt in abort code. + +2001-03-11 Gary Thomas <gthomas@redhat.com> + + * src/lib/network_support.c (init_all_network_interfaces): + Let initialization of PCMCIA devices abort after ~5 seconds. + +2001-02-23 Jonathan Larmour <jlarmour@redhat.com> + + * src/lib/tftp_server.c (STACK_SIZE): Align + +2001-02-20 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/net.cdl: Avoid puts to the CDL header when a CDL + define will do. + Rename CYGPKG_NET_BRIDGE_CODE -> CYGPKG_NET_BRIDGE + Rename CYGPKG_NET_NBRIDGE -> CYGNUM_NET_BRIDGES + Rename CYGPKG_NET_BRIDGE_HANDLER -> CYGINT_NET_BRIDGE_HANDLER + Make if_bridge.c compilation conditional on CYGPKG_NET_BRIDGE + + * src/sys/net/if_bridge.c: Reflect above renames. + +2001-02-20 Hugo Tyson <hmt@redhat.com> +2001-02-15 Martin Buck <martin.buck@ascom.ch> + + * cdl/net.cdl: Split up CYGPKG_NET_NBRIDGE into 2 parts: + CYGPKG_NET_NBRIDGE and CYGPKG_NET_BRIDGE_HANDLER. If + CYGPKG_NET_BRIDGE_HANDLER is nonzero, calls to an Ethernet + bridge are inserted into the stack's data path. If + CYGPKG_NET_NBRIDGE is nonzero, the standard OpenBSD bridge + code is added. This setup allows you to implement your own + bridge as a separate package which then implements + CYGPKG_NET_BRIDGE_HANDLER so it gets called by the stack. + NBRIDGE now is the same as CYGPKG_NET_BRIDGE_HANDLER instead + of CYGPKG_NET_NBRIDGE. This means it's nonzero if the bridge + is wanted, but it no longer contains the number of bridge + buffers requested. This shouldn't be a problem, because the + only place where the actual number of buffers is required is + in if_bridge.c, which now uses CYGPKG_NET_NBRIDGE instead + of NBRIDGE. + + * src/sys/net/if_bridge.c: Use CYGPKG_NET_NBRIDGE instead of + NBRIDGE, because the latter one now only means that there is + a bridge, not that we should implement it. + +2001-01-07 Gary Thomas <gthomas@redhat.com> + + * src/ecos/support.c: + * cdl/net.cdl: Add interface 'CYGPKG_NET_DRIVER_FRAMEWORK' + to describe interdependencies between network stack and driver + framework packages. + + +2001-01-03 Hugo Tyson <hmt@redhat.com> + + * tests/linux_echo.c: New file to test for network bandwidth + limitations in host side. Builds to a linux version of the + tcp_echo middleman. + + * tests/make.linux (all): Build linux_echo. + +2001-01-03 Hugo Tyson <hmt@redhat.com> + + * include/dhcp.h (struct dhcp_lease): Define the semaphore pointer + field in each lease structure. + + * src/lib/dhcp_support.c: Initialize the dhcp_lease structs to + point to the semaphore "dhcp_needs_attention". + + * src/lib/dhcp_prot.c (alarm_function): Post to the semaphore + pointed to in the lease structure, rather than one hard-coded. + This is much cleaner, in that dhcp_prot.c now uses no external + variables, all state goes through the API. + +2000-11-15 Hugo Tyson <hmt@redhat.com> + + * src/lib/bootp_support.c (init_net): Do a SIOCSIFADDR a 2nd time + after setting the netmask (SIOCSIFNETMASK) in order for the newly + set netmask to "take" - otherwise a bogus route based on the + default netmask lurks within the system. + +2000-11-10 Hugo Tyson <hmt@redhat.com> + + * src/ecos/support.c (cyg_net_get_mem_stats): New API for getting + info on the various mem pools the stack uses to enable tests to + spot store leaks. + + * include/network.h (cyg_net_get_mem_stats): Export this API for + automated network testing. + +2000-10-24 Hugo Tyson <hmt@redhat.com> + + * src/lib/tftp_server.c (tftpd_server): Cut down the chatter to + nothing (unless there's an error) if running automated testing. + +2000-10-17 Hugo Tyson <hmt@redhat.com> +2000-10-10 Andrew Lunn <Andrew.Lunn@ascom.ch> + + * src/ecos/support.c (setsoftnet,cyg_panic): Less chatter, + particularly not when we're out of MBUFs. + +2000-10-17 Hugo Tyson <hmt@redhat.com> +2000-10-10 Andrew Lunn <Andrew.Lunn@ascom.ch> + + * src/sys/net/if_bridge.c: Intergrated a more up to date version + from the OpenBSD sources. This fixes a few bugs. + +2000-10-17 Hugo Tyson <hmt@redhat.com> + + * src/ecos/support.c (cyg_ktime_init): Start time at 1 Second so + that all visible time values are valid; offset time by 1 Second + subsequently, for ever. + + * src/sys/netinet/if_ether.c (arpresolve): Undo the change below; + instead make "kernel time" be valid ie. more than 1 second into + its life. Dumb stack assumes it takes UNIX-like time to start. + +2000-10-16 Hugo Tyson <hmt@redhat.com> + + * src/sys/netinet/if_ether.c (arpresolve): Deal with the initial + case when the route timeout is zero (as initialized). Otherwise + it never actually sent out the initial ARP request packet. This + caused connect() not to work, and thus ftp_test, for example. + + * src/lib/dhcp_support.c (dhcp_start_dhcp_mgt_thread): Also + initialize the dhcp semaphore here. The other place it is init'd + [correctly] didn't fire if we use the standard support. Fixed + some absent return value warnings. + +2000-10-10 Hugo Tyson <hmt@redhat.com> + + * src/lib/tftp_server.c (tftpd_server): Modify the server to + support multiple sessions - ie. starting N servers at once. + Mainly this means closing the initial socket whilst servicing a + request, so that another server can then bind to it; tell another + server to retry that bind via a semaphore, that it waited on when + the bind failed initially, rather than just returning. + + * src/lib/tftp_dummy_file.c (dummy_open): Trivial bugfix: scan the + list of files as well as incrementing the counter. + +2000-10-05 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/ecos/support.c (cyg_ktime_func,cyg_ktime_init,cyg_net_init): + Make 'ktime' value valid. + +2000-10-05 Hugo Tyson <hmt@redhat.com> + + * src/lib/tftp_server.c (tftpd_write_file): Restructure this + function to match the loop layout of the tftpd_read_file; so that + it retries sensibly, and so that a delayed/duplicated packet does + not cause a doubling of all traffic with a less smart host. + +2000-10-05 Hugo Tyson <hmt@redhat.com> + + * include/tftp_support.h (TFTP_TIMEOUT_MAX): Change this to 50; it + refers to total timeouts for a whole session, so it should be + greater than the retry count for each packet. + +2000-10-05 Hugo Tyson <hmt@redhat.com> + + * src/lib/tftp_dummy_file.c: Make the fake file slots be a Mb + instead of 10k so that you can do meaningful timing tests with it. + (dummy_open): Allow re-write of an existing file so that you can + do repeated put tests without running out of slots. + +2000-10-05 Hugo Tyson <hmt@redhat.com> + + * src/lib/select.c (_cyg_select): Unlock the scheduler in a couple + of other places I missed. Doh. + +2000-09-28 Hugo Tyson <hmt@redhat.com> + + * src/lib/select.c (_cyg_select): Elect to wait for the flags + atomically wrt sockets possibly becoming ready - this was a race + condition that would apparently delay a packet until another + arrived, eg. a tftp retry. Then two came along all at once. + +2000-09-28 Hugo Tyson <hmt@redhat.com> + + * src/lib/tftp_server.c: Add lots of instrumentation for + debugging. It's switched off, and doesn't have a real config opt, + though it easily could have. + +2000-09-26 Hugo Tyson <hmt@redhat.com> + + * src/lib/tftp_server.c (tftpd_read_file): Doh! TFTP_TIMEOUT is an + internal API thing, not an error we can send in an ERROR packet. + + * include/tftp_support.h: Comment to this effect. + +2000-09-26 Hugo Tyson <hmt@redhat.com> +2000-09-25 Andrew Lunn <Andrew.Lunn@ascom.ch> + + * src/lib/tftp_server.c: Send an ERROR packet when giving up after + too many timeouts. This should cause the client to give up as + well. Also moved all the replicated code to send an ERROR packet + into one function. + + [Huge] I collected another point where we can use the common + function also, and used ETIMEOUT instead of EBADOP for the new + error packet returns. Thanks Andrew! + +2000-09-14 Hugo Tyson <hmt@redhat.com> + + * cdl/net.cdl (CYGOPT_NET_DHCP_DHCP_THREAD_PARAM): Set default to + 1 so that the DHCP management thread loops forever. This allows + it to recover from a DHCP renewal failure. + + * src/lib/dhcp_prot.c (next_timeout): Harden the DHCP protocol + machine against [simulated] failures - otherwise the tests with + simulated failures tend just to close down all the interfaces when + DHCP packets are lost. + +2000-09-11 Gary Thomas <gthomas@redhat.com> + + * src/lib/bootp_support.c (init_net): Set default route correctly. + +2000-09-01 Hugo Tyson <hmt@cygnus.co.uk> + + * src/ecos/support.c (cyg_net_init): You can't print things while + initializing the network! Well, not if connected to GDB over the + network anyway. The printf("Init device '%s'...); removed. + +2000-09-01 Hugo Tyson <hmt@cygnus.co.uk> + + * OVERVIEW: This is part of the change to the network stack to + greatly reduce latencies both of (other) DSRs and of thread + scheduling. All the work that the network stack *and* individual + ether drivers used to do in DSRs (including alarm callbacks and + data copies to/from the device memory) is moved into a "fast + network thread" instead. It calls a device's "deliver" function + to do the work that was previously in the DSR. This is a separate + thread so that it can be set higher priority than application + threads in order to minimize packet loss (depending on the + driver), if required (the application threads presumed to be + higher priority in turn than the network thread). A crucial + consequence of this is that we are no longer locking against DSRs, + so a plain mutex can be used rather than the global scheduler + lock, thus simplifying all the splfoo/splx() style functions. + + * src/ecos/timeout.c (alarm_thread): Addition of the "fast network + thread" which runs DSR-like activities. + (do_timeout): Timeout function morphed for calling from that. + (do_alarm, ecos_synch_eth_drv_dsr): new DSR functions to signal to + the thread. + (timeout): Race condition fixed. splinternal() used for locking + instead of scheduler. + + * src/ecos/support.c (cyg_net_init): Splfoo/splx() functions, + together with tsleep/wakeup functions, all removed to separate + them from the mixed bag of utilities in this file. What remains + is mbuf wrapper routines and the like, plus the network "netisr" + thread itself, the caller into the stack that does the slower + priority work. + + * src/ecos/synch.c: New file; implemtation of new splfoo/splx() + functions, together with tsleep/wakeup functions, since they are + related now. + + * cdl/net.cdl: Compile new file synch.c; two new options, one for + "fast thread" priority, and one for DHCP manager thread priority, + as I was adding prio configury. CYGPKG_NET_FAST_THREAD_PRIORITY + and CYGPKG_NET_DHCP_THREAD_PRIORITY resp, with suitable default + values relative to the CYGPKG_NET_THREAD_PRIORITY. + + * src/lib/dhcp_support.c (dhcp_start_dhcp_mgt_thread): Use the + configured priority rather than just "net thread - 1" + +2000-08-31 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/tcp_echo.c: Change the priorities of the main and loading + threads to accommodate the network having helper threads around at + adjacent priorities to its main thread prio. + +2000-08-24 Hugo Tyson <hmt@cygnus.co.uk> + + * src/sys/net/if.c (ifioctl): Support the two new ioctl() keys; at + this level, the struct ifreq at the head of the data area must be + filled to select an interface. + + * include/sys/sockio.h (SIOCGIFSTATSUD): Add two new eCos-only + ioctl() keys, SIOCGIFSTATSUD and SIOCGIFSTATS, for reading + statistical information out of ethernet devices, for SNMP. This + should allow SNMP (a) to not explode, (b) to get useful info out + of other device implementations than this one. + +2000-08-17 Hugo Tyson <hmt@cygnus.co.uk> + + * src/ecos/timeout.c (timeout): Rework the timeout system to + record last-time-we-set-the-alarm and whence values, so that new + timeouts being added can be set up relative to the correct + absolute time. Otherwise adding a new timeout sets them *all* + into the future by the expired portion of the previous minimum + pending timeout. Also deal better with recursion ie. timeout + handlers themselves setting new timeouts as is only natural. + Lots of asserts too. + + * src/ecos/support.c (cyg_splsoftnet): Use the new kernel facility + to lock mutex &c atomically, with the scheduler locked already. + (cyg_tsleep): Similarly, and reclaim the mutex likewise. + Also added lots of asserts to both calls the better to document + what's going on. + +2000-08-17 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/tftp_server.c: Fix contributors field. + +2000-08-16 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/tftp_server.c: Improvements to server wrt better error + messages and detection of filesystem errors eg. on close-file. + Contrib from ASCOM. I tidied up some comments and indent to + minimize the diff. [CASE 104354] + +2000-08-15 Hugo Tyson <hmt@cygnus.co.uk> + + * doc/bridge.html: New file... + * doc/bridge.doc: New file... + provided by ASCOM from the OpenBSD version. + +2000-08-15 Hugo Tyson <hmt@cygnus.co.uk> + + * src/sys/net/if_bridge.c (bridge_ioctl): SIOCBRDGSTO takes + argument in seconds not in ticks. So move around some mul/div by + hz ops to get this right. + +2000-08-14 Gary Thomas <gthomas@redhat.com> + + * src/ecos/support.c: Use new table definition mechanism. + +2000-07-27 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/dhcp_prot.c (do_dhcp): Use xmit->bp_htype = + HTYPE_ETHERNET rather than ifr.ifr_hwaddr.sa_family; sa_family is + in a different namespace, despite appearances. + + * src/lib/bootp_support.c (do_bootp): Use bp_htype = + HTYPE_ETHERNET rather than ifr.ifr_hwaddr.sa_family; sa_family is + in a different namespace, despite appearances. + +2000-07-27 Nick Garnett <nickg@cygnus.co.uk> + + * cdl/net.cdl: Require the C library STDIO package to be present + if there is more than one loopback interface. This is because it + needs sprintf() to form the interface names. + + * src/sys/net/if_loop.c (loopattach): + Only use sprintf() to form the loopback interface names when there + is more than one. The CDL ensures that this will work. + + * src/lib/network_support.c: + Added diag_printf() version of perror() for when STDIO package is + absent. + Only use sprintf() to form the loopback interface names when there + is more than one. The CDL ensures that this will work. + + * tests/multi_lo_select.c: + * tests/ping_lo_test.c: + * tests/tcp_lo_test.c: + Removed dependence on C library by adding a substitute perror() + based on diag_printf() that is enabled when the STDIO package is + absent. + +2000-07-26 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/dhcp_prot.c (do_dhcp): Set the broadcast flag where + necessary, and the client address too. This makes it talk to a + greater range of servers OK. + +2000-07-25 Nick Garnett <nickg@cygnus.co.uk> + + * tests/multi_lo_select.c: Changed definition of NLISTENERS to + work correctly with FILEIO package. + + * src/sys/net/if_loop.c (loopattach): Changed initialization of + if_xname to "lo0". + + * src/ecos/support.c (cyg_net_init): Removed redundant code to + initialize loop-back interface. + +2000-07-25 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/getserv.c: Add a list terminator record with NULLs in it + so that the search finishes (without throwing asserts about bad + strings). + +2000-07-21 Hugo Tyson <hmt@cygnus.co.uk> + + * src/sys/net/if_bridge.c: Move the include of stdio.h lower, + apparently it confuses local x86 compilers if their host tree is + malformed. Or something. + +2000-07-21 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Add a lot of description about the way the various + fields are used in interface initialization: specifically that + "server" so-called is just "someone to talk to" in the absence of + bootp - and our tests depend on it! + + * src/lib/bootp_support.c (init_net): Only set up a route if the + route address is nonzero - or all manner of confusion occurs with + multiple interfaces and route that sends to 0.0.0.0... + For setting up the default route, use + (SIOCADDRT, 0, 0, TAG_GATEWAY) + rather than the bogus + (SIOCADDRT, yiaddr & netmask, netmask, TAG_GATEWAY) + that we did before. + + * tests/ftp_test.c (ftp_test): Try it with eth1 if available also. + + * tests/ping_test.c (ping_host): If a ping fails, reset the packet + size to small just in case the huge packet size is what's causing + confusion - helps it as a debug tool. + + * tests/dhcp_test.c (net_test): It didn't compile if DHCP is + disabled! Doh. Same change as ping_test also. + +2000-07-19 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/tftp_server.c (tftpd_read_file): Deal with a) [assumed] + timeouts on the select, and b) ACKs for old packets. + [CASE 104052 and CASE 104055] + +2000-07-19 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/select.c (_cyg_select): Return 0 and do not perturb + errno when the timeout occurs. That matches the man page! + [CASE 104054] + +2000-07-19 Hugo Tyson <hmt@cygnus.co.uk> + + * include/machine/param.h: Be more defensive against warnings from + external defines such as __linux__/__bsdi__/__FreeBSD__/... + [CASE 104090] + +2000-07-19 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/multi_lo_select.c: New test program to test for proper + broadcast behaviour of select() implementation. Took some + fiddling to get it to work, but it really did fail before the + select change below. + + * cdl/net.cdl: Build the new test. + + * src/lib/select.c (_cyg_select): Don't use the CLR flag in the + flag wait because that gives unicast semantics. Flags have + producer-does-all-the-work behaviour, so setting a value then + clearing it right afterwards does the right thing, with broadcast + semantics so long as no waiter has set the CLR part. + [CASE 104058] + +2000-07-18 Hugo Tyson <hmt@cygnus.co.uk> + + All part of the bridge contribution from Andrew Lunn/ASCOM + (andrew.lunn@ascom.ch). Bridginess is controlled by NBRIDGE which + is itself controlled by CDL option CYGPKG_NET_NBRIDGE aka "Number + of bridge buffers?" + + * include/machine/param.h: Add proper definition of untimeout(). + + * include/sys/sockio.h (SIOCBRDGFRL): Add this and the other 2 + bridge ioctl() call definitions. + + * include/sys/param.h (splhigh): Added. + + * src/ecos/timeout.c (untimeout): Implement this properly, it was + never used before. + + * src/ecos/support.c: implement cyg_splhigh(), call bridgeintr() + when it is scheduled and bridgeattach() if configured. + + * tests/bridge.c: New "test" file - implements an ethernet bridge. + Contributed by Andrew Lunn/ASCOM, from the usual OpenBSD external + source original. + + * include/net/if_bridge.h: New file, contributed by Andrew Lunn/ + ASCOM, from OpenBSD original. (Actually did exist in eCos source + tree but was not released) + + * src/sys/net/if_bridge.c: New file, contributed by Andrew Lunn/ + ASCOM, from OpenBSD original. + + * cdl/net.cdl: Build the new files. + +2000-07-18 Gary Thomas <gthomas@redhat.com> + + * src/lib/tftp_client.c (tftp_get): Fix edge condition when + penultimate block is full and end of file which implies that + the last block has zero data bytes. + +2000-07-18 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/dhcp_prot.c: Ignore NAK messages from the wrong server - + we get these because the REQUEST for our chosen IP is broadcast, + so other servers think we've asked to use the wrong IP. + +2000-07-14 Hugo Tyson <hmt@cygnus.co.uk> + + * include/bootp.h: export init_loopback_interface(); + +2000-07-14 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Add option controlling whether to have a separate + DHCP lease management thread, and what its parameter is to be - + which controls whether it loops or quits if a lease fails. + + * src/lib/dhcp_support.c (dhcp_start_dhcp_mgt_thread): Provide the + DHCP management thread function and code to instantiate and start + the thread if so configured. + + * src/lib/network_support.c (init_all_network_interfaces): Call + the function that starts the DHCP management thread function. + + * include/dhcp.h: Declare the DHCP management thread function &c + if so configured. + + * tests/dhcp_test.c (net_test): Only poll for need to rebind DHCP + leases if there is no service thread to do the same. + +2000-07-14 Hugo Tyson <hmt@cygnus.co.uk> + + * include/bootp.h (build_bootp_record): Export this, no harm in + it, and some folk want to use this rather than configured + initialization or bootp/dhcp. + Also commented the other APIs somewhat better. + + * src/lib/network_support.c (build_bootp_record): Unconditionally + provide this; selective linking will look after it if unused. + +2000-07-14 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/network_support.c (build_bootp_record): [Static + configuration of interface parameters] Add the gateway into the + options section with TAG_GATEWAY so that init_net() will pick it + up and set up a route accordingly. + +2000-07-13 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/dhcp_test.c: + * tests/flood.c: + * tests/ftp_test.c: + * tests/nc_test_master.c: + * tests/nc_test_slave.c: + * tests/ping_lo_test.c: + * tests/ping_test.c: + * tests/server_test.c: + * tests/set_mac_address.c: + * tests/tcp_echo.c: + * tests/tftp_client_test.c: + * tests/tftp_server_test.c: + Up the stack size to cope with full DHCP initialization in + init_all_network_interfaces(). + +2000-07-13 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Add DHCP enable and interface-specific controls. + + * include/dhcp.h: New file: describe the DHCP APIs and behaviour, + as well as some internal APIs that are also available. + + * src/lib/dhcp_support.c: New file: the surrounding management + routines, a bit like network_support.c, which know about multiple + interfaces and so on. + + * src/lib/dhcp_prot.c: New file: the interface-independent DHCP + protocol machine, which is called from dhcp_support.c routines and + init_all_network_interfaces() in network_support.c + + * include/bootp.h (struct bootp): Make the packet bigger if DHCP + so that a mininal DHCP packet will fit. + + * src/lib/bootp_support.c (do_bootp): If no reply, fail gracefully + and tidy up so that other interfaces can be upbrung. + (show_bootp): Tell us a lot more about DHCP-specific info in the + packet structure. + (get_bootp_option): be aware of DHCP extensions to re-use file and + sname fields for options. + + * src/lib/network_support.c (init_all_network_interfaces): Call + do_dhcp() rather than do_bootp() if so configured, and initialize + the per-interface DHCP state variables accordingly. + + * tests/dhcp_test.c (net_test): New test file that diddles the + DHCP machine while doing a ping test. + +2000-07-11 Gary Thomas <gthomas@redhat.com> + + * include/netdev.h: Add single-inclusion fences. + + * include/sys/param.h: Add traced versions of splx() routines, + selectable by a configuration option. + + * src/ecos/support.c: Rework splx() emulation routines to + be more robust and realtime friendly. + + * src/lib/network_support.c (init_all_network_interfaces): + Add minimal support for PCMCIA based devices. + +2000-07-04 Hugo Tyson <hmt@cygnus.co.uk> + + * include/bootp.h: Fix namespace pollution from "#define int32 + int" - it fights against application code too much. + +2000-07-04 Jonathan Larmour <jlarmour@redhat.co.uk> + + * cdl/net.cdl: Package requires CYGPKG_MEMALLOC + +2000-06-26 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/ping_test.c (net_test): Added use of the + CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS stuff now that the test + passes (consequent on the change below); also use larger ping + packets now that that is working also. + + * tests/tcp_echo.c (echo_test): Added use of the + CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS stuff now that the test + passes (consequent on the change below). + +2000-06-26 Hugo Tyson <hmt@cygnus.co.uk> + + * src/ecos/support.c (cyg_splnet): Use the scheduler lock and a + mutex instead of disable-interrupts for SPLX type processing. A + mutex is used at splsoftnet because that is client threads - we do + not want them to pre-empt the rest of the app. This enables the + real-time response testing for the EBSA285 to succeed (interrupts + every 1mS, DSRs delayed by at most 2mS). + +2000-06-23 Hugo Tyson <hmt@cygnus.co.uk> + + * src/ecos/support.c (cyg_net_mbuf_alloc, cyg_kmem_init): Align + the mbuf pool to MSIZE [128] bytes. That way dtom() works, nasty + though it is. That's needed for ip reassembly in ip_input.c, when + dealing with large icmp-layer packets eg. ping -s 2000 ... + +2000-06-21 Hugo Tyson <hmt@cygnus.co.uk> + + * include/lib/libkern/libkern.h: Do not define assert multiple + times; guarded by __ECOS. + + * include/sys/param.h (MAX,MIN): Only define if undef. + +2000-06-21 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Build the new tests; in fact build them + unconditionally. + + * src/lib/network_support.c (init_all_network_interfaces): + Initialize loopback device[s] using init_loopback_interface(), + providing a sensible default route et al. Multiple devs: lo1 will + be 127.0.*1*.1, and so on; class C netmasks will be used. + + init_all_network_interfaces() is also made thread-safe as well as + idempotent, so other threads (or daemons) can call it to make sure + the net is up. + + * src/ecos/support.c (cyg_net_init): Add a call to loopattach() if + there are indeed loopback dev(s) configured. This does the + equivalent of the init of a device from the table, but simpler. + + * tests/udp_lo_test.c (udp_server): New testcase... + * tests/tcp_lo_select.c (tcp_server): New testcase... + * tests/tcp_lo_test.c (tcp_client): New testcase... + * tests/ping_lo_test.c (net_test): New testcase, unconditionally + built loopback device test. Will run on platforms with no network + interfaces. + +2000-06-19 Nick Garnett <nickg@cygnus.co.uk> + + * src/ecos/support.c: + * include/netdev.h: + Converted to use of new table construction mechanism. + +2000-06-16 Jonathan Larmour <jlarmour@redhat.co.uk> + + * include/bootp.h: Remove RCS id tag + * include/netinet/ip_auth.h: Ditto + * include/netinet/ip_fil.h: Ditto + * include/netinet/ip_fil_compat.h: Ditto + * include/netinet/ip_frag.h: Ditto + * include/netinet/ip_nat.h: Ditto + * include/netinet/ip_proxy.h: Ditto + * include/netinet/ip_state.h: Ditto + +2000-06-15 Nick Garnett <nickg@cygnus.co.uk> + + * src/sys/kern/sockio.c: Added cyg_selinit() calls to bad_socket() + and bsd_accept() functions. + + * src/ecos/support.c (cyg_tsleep): Changed tests on wakeup from + semaphore waits to enable return of EINTR results. + +2000-06-09 Nick Garnett <nickg@cygnus.co.uk> + + * src/sys/net/if_loop.c: Substituted sprintf() for a straight + strcpy() when initalizing if name. This currently only works for + one loopback interface. However, there seems little need to have + more than one. + + * src/sys/kern/sockio.c (bsd_select): Added select support. + + * include/sys/time.h: Moved timeval structure definition to + isoinfra time.h header since it is needed by the select() API. + + * include/sys/select.h: Added option to use fileio select + mechanism if it is present. + + * src/ecos/support.c (cyg_net_init): + Added code to bring up the loopback interface. This is to help + with testing on platforms without network hardware. + +2000-06-08 Hugo Tyson <hmt@cygnus.co.uk> + + * include/netinet/ip_var.h: Export ipforwarding as well as + ip_defttl for monitoring applications. + +2000-06-07 Nick Garnett <nickg@cygnus.co.uk> + + * tests/tcp_echo.c: + * tests/socket_test.c: + * tests/server_test.c: + * tests/ping_test.c: + * tests/nc_test_master.c: + * tests/nc_test_slave.c: + * tests/ftp_test.c: + Removed dependence of these programs on STDIO. For most this + simply required the use of a diag_printf() based perror() clone is + CYGPKG_LIBC_STDIO is not defined. For server_test is also required + the substitution of sprintf() with some more primitive string + functions. + + * src/sys/netinet/ip_input.c: Rewrote inet_ntoa() to not use + sprintf(). This was the only place in the TCP/IP stack that was + dependent on a STDIO function. We really should avoid building + this kind of casual dependency into the code. + + * src/sys/kern/sockio.c: This new file contain code to support the + fileio package. So far only a few of these functions have actually + been tested. + + * include/sys/kernel.h (time): The time variable clashes with the + C library time() function. To prevent this it is renamed ktime, + and a #define allows "kernel" code to continue accessing it as + time. + + * src/ecos/support.c: Added definition for ktime variable, as + described above. I could not find any definition for struct + timeval time. I have a nasty suspicion that it was using the + time() function - let's hope that no code that actually uses this + has been run. + + * src/lib/bootp_support.c: Another substitution of a diag_printf() + based perror() clone when STDIO is absent. + + * include/sys/bsdtypes.h: This is the original + include/sys/types.h. Renamed to avoid clashing with <sys/types.h> + defined by the isoinfra package. + + * include/sys/types.h: Renamed to bsdtypes.h. + + * include/machine/limits.h: + Various changes to make these headers play nicely with those + defined in isoinfra package. + + * include/network.h: Added include of <pkgconf/system.h>. Fixed + prototypes of functions here to match POSIX specifications. + + * cdl/net.cdl: + Split list of files to compile into the common set plus those + needed when the fileio package is present and those that are + needed when it is absent. + Added CDL to export our definitions to <sys/types.h>. + + +2000-05-31 Hugo Tyson <hmt@cygnus.co.uk> + + * src/lib/network_support.c (init_all_network_interfaces): Make + this call idempotent - this is useful for reliable initialization + of dependent subsystems. + + * include/lib/libkern/libkern.h: remove protos of random() and + srandom() for they are not in fact provided. + + * cdl/net.cdl: Turn off CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS by + default - since not all tests currently pass. + +2000-05-12 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl (CYGPKG_NET_TFTPD_THREAD_PRIORITY): New option, + control the TFTPD thread priority. These options are *all* + CYGPKG_NET. Yuk, sort 'em out later. + + * tests/tftp_server_test.c (tftp_test): Added use of the + CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS stuff, same as for the flood + ping test. This one passes (with the next change), so committed. + + * src/lib/tftp_server.c (tftpd_server): Cancelled some of the + printouts as connections come and go *iff* the tests are set up to + use the realtime-ness test harness. This needs generalizing into + proper control of the network's chattiness overall. + (tftpd_start): Also added configury of the TFTPD thread priority. + +2000-05-12 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Add flood test below. Also add option + CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS to decide whether to + "Use real-time response test harness (if available)". + Consequently moved the test build stuff forward out of the build + flags area. + + * tests/flood.c (net_test): New file; performs a flood-ping (well, + as fast as we can go) of the server(s) on the two interfaces. + Also uses the real-time interrupt response verification stuff from + the EBSA285 driver component. + +2000-05-11 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Add new utility (and harmless-by-default test) + tests/set_mac_address. You have to edit it to get anything + damaging to happen. + + * tests/set_mac_address.c: New file added. It uses SIOCSIFHWADDR + to set the MAC address of any interfaces it has been told to. + +2000-05-08 Gary Thomas <gthomas@redhat.com> + + * include/machine/cpu.h: + * include/machine/cdefs.h: Add copyright boilerplate. + +2000-05-05 Hugo Tyson <hmt@cygnus.co.uk> + + * include/arpa/tftp.h: Aargh. Turns out that removing the align + driective and retaining only the packed directive makes the + original version work. So, reverted. Apologies for the wasted + time. + + * src/lib/tftp_server.c (tftpd_read_file): Coupla warnings + reduced, and reverted to match original tftp.h + + * src/lib/tftp_dummy_file.c (dummy_open): Removed use of + undeclared malloc(). + +2000-05-04 Gary Thomas <gthomas@redhat.com> + + * src/lib/tftp_server.c: + * src/lib/tftp_client.c: Adjust for changes in header structure. + + * include/arpa/tftp.h: Continuing problems with alignment on ARM. + Recourse is very bastardized structure, but it _does_ work. + +2000-05-04 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/tftp_client_test.c (tftp_test): Print out a coupla more + things and test both interfaces if they exist - which does the + same thing twice if the same server bootp'd both. Changed the + filenames to something more obvious. + + * cdl/net.cdl (CYGPKG_NET_TESTS): Build the tftp tests + tests/tftp_client_test tests/tftp_server_test + + * src/ecos/support.c (cyg_kmem_print_stats): New function; prints + info about memory usage for some tests to come. + +2000-05-04 Gary Thomas <gthomas@redhat.com> + + * include/arpa/tftp.h: Force packed alignment - required on some + architectures. + +2000-05-01 Gary Thomas <gthomas@redhat.com> + + * src/lib/tftp_dummy_file.c: Adding very simple routines - just + enough to test TFTP server. This support will come from elsewhere + in actual application environments (e.g. a real file system). + + * tests/tftp_server_test.c: + * src/lib/tftp_server.c: + * include/tftp_support.h: Flesh out TFTP server support. + +2000-04-13 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/tcp_echo.c (calibrate_load): Import better background + thread loading algorithm with bugfix; if the initial HIGH limit + was not large enough, it never got loaded enough. + + * tests/nc_test_slave.c (calibrate_load): Import the fixed version + from above back in here. + +2000-04-12 Gary Thomas <gthomas@redhat.com> + + * src/ecos/support.c (cyg_tsleep): Use 'cyg_scheduler_safe_lock()' so + this function can be called with the scheduler locked. + + * src/sys/kern/uipc_socket2.c: + * include/sys/socketvar.h: Update sblock()/sbunlock() to be eCos safe. + +2000-04-12 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/tcp_echo.c: Include <lib/libkern/libkern.h> so that it + links - otherwise max() is not around. + +2000-04-11 Gary Thomas <gthomas@redhat.com> + + * include/lib/libkern/libkern.h: + * include/network.h (NO_LIBKERN_INLINE): Disable kernel inline + functions. + +2000-04-11 Gary Thomas <gthomas@redhat.com> + + * src/lib/getserv.c: Add TFTP protocol. + + * cdl/net.cdl: Add TFTP library functions. + + * include/tftp_support.h: + * src/lib/tftp_dummy_file.c: + * src/lib/tftp_server.c: + * src/lib/tftp_client.c: New file(s). Basic TFTP support functions. + +2000-04-10 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/tcp_echo.c (echo_test): + * tests/tcp_source.c: + * tests/tcp_sink.c: + Merge in changes from Grant Edwards <grante@visi.com> presented on + ecos-discuss "Mon, 10 Apr 2000 11:01:54 -0500" - fix some + warnings, and use ntohl() on the control data that travels netly + so that the host tools will work on otherendian machines. + +2000-04-07 Gary Thomas <gthomas@redhat.com> + + * tests/nc_test_slave.c: Update background thread loading + calibration to use a binary search (better) algorithm. + +2000-03-29 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/ftp_test.c (cyg_test_exit): + * tests/mbuf_test.c (cyg_start): + * tests/nc_test_master.c (cyg_test_exit): + * tests/nc_test_slave.c (show_net_times): + * tests/ping_test.c (cyg_test_exit): + * tests/server_test.c (cyg_test_exit): + * tests/socket_test.c (cyg_test_exit): + * tests/tcp_echo.c (cyg_test_exit): + Some eCos infrastructure changes caused, in some configurations, + cyg_test_exit() from the infrastructure to be brought in (in + tcdiag.o) even when the Test Case system was not explicitly being + invoked. That fought with the convenience copy of cyg_test_exit() + in these tests. The neatest fix is to use that provided centrally + where relevent, so that is what this change does. + + * tests/tcp_echo.c: Also now use granularity of 5% by default, + calibrate the load at 50%, and check and report the load that was + actually achieved after the test. + +2000-03-29 John Dallaway <jld@cygnus.co.uk> + + * doc/ecos_tcpip.html: + + Remove error-prone cross-reference to another eCos package. + + * doc/index.html: + + Synchronize index page title with web site. + +2000-03-28 Gary Thomas <gthomas@redhat.com> + + * src/lib/bootp_support.c (init_net): Need to start interface, + especially for manual/static IP configurations. + + * tests/nc_test_slave.c (calibrate_load): Better calibration for + slower targets. + +2000-03-18 Gary Thomas <gthomas@redhat.com> + + * src/sys/kern/sys_socket.c: + * src/sys/kern/sys_generic.c: + * include/sys/sockio.h: Add FIONBIO, FIOASYNC, FIONREAD functions. + + * include/machine/types.h: Make definitions safe for use with libc. + +2000-03-08 Gary Thomas <gthomas@redhat.com> + + * src/ecos/support.c: Remove some debug messages. + Update timed sleep functions (tsleep) to use scheduler lock + instead of brute-force interrupt locks. + +2000-03-08 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/tcp_echo.c (echo_test): Also enable, log and print out the + idle-thread activity during the test - this reassures us that + there is no [significant] spare time being wasted idling during + the test. This change has no effect on the results at all. + +2000-03-07 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/tcp_echo.c (calibrate_load): Improve the accuracy of the + calibration with some post-scaling. Change load to an array + accessor instead of register-based floating point - this is less + load, so more loops are needed, so the initial load level is upped + also. More loops means better accuracy anyway, a good thing. + +2000-03-06 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/tcp_source.c (show_results): Print results in Mbit/S also. + (source_test): Warnings reduction; add some casts to sending and + receiving the control packets. + (NUM_BUF): becomes 1024; send more data to get thro'put result. + + * tests/tcp_sink.c (show_results): Print results in Mbit/S also. + (sink_test): Warnings reduction; add some casts to sending and + receiving the control packets. + + * tests/nc_test_master.c (show_results): Reinstate tot_bytes + variable for host testing tool version. Print results in Mbit/S + also. + + * tests/nc_test_slave.c (net_test): Comment out starting multiple + threads; they fight over a wide-open socket. One thread is + enough. + +2000-03-06 Gary Thomas <gthomas@redhat.com> + + * include/netdev.h: Update structure for improved API description. + +2000-03-05 Gary Thomas <gthomas@redhat.com> + + * include/network.h: + * include/sys/syscallargs.h: + * src/lib/accept.c: + * src/lib/bootp_support.c: + * src/lib/close.c: + * src/lib/getpeername.c: + * src/lib/getsockname.c: + * src/lib/recvfrom.c: + * tests/ftp_test.c: + * tests/nc_test_framework.h: + * tests/nc_test_master.c: + * tests/nc_test_slave.c: + * tests/ping_test.c: + * tests/server_test.c: + * tests/socket_test.c: + * tests/tcp_echo.c: + Cleanup to remove compiler warnings. + +2000-03-04 Gary Thomas <gthomas@redhat.com> + + * include/machine/param.h: + * include/sys/socketvar.h: + * src/ecos/timeout.c: + * src/sys/kern/kern_subr.c: + * src/sys/kern/sys_generic.c: + * src/sys/kern/sys_socket.c: + * src/sys/kern/uipc_mbuf.c: + * src/sys/kern/uipc_socket2.c: + * src/sys/kern/uipc_syscalls.c: + * src/sys/net/if_ethersubr.c: + * src/sys/net/if_loop.c: + * src/sys/net/route.c: + * src/sys/net/rtsock.c: + * src/sys/netinet/in_cksum.c: + * src/sys/netinet/in_pcb.c: + * src/sys/netinet/ip_input.c: + * src/sys/netinet/tcp_input.c: + * src/sys/netinet/tcp_output.c: + * src/sys/netinet/tcp_subr.c: + * src/sys/netinet/udp_usrreq.c: + Cleanup to remove compiler warnings. + +2000-03-01 Gary Thomas <gthomas@cygnus.co.uk> + + * tests/ping_test.c: Reorganize test, display error info. + + * src/lib/bootp_support.c: Add support for DNS options. + +2000-02-29 Gary Thomas <gthomas@cygnus.co.uk> + + * include/sys/sockio.h (SIOCSIFHWADDR): Add function to + set hardware (MAC) address via ioctl. + +2000-02-28 John Dallaway <jld@cygnus.co.uk> + + * cdl/net.cdl: + + Reparent cdl_interface CYGHWR_NET_DRIVER_ETH0_SETUP under + cdl_component CYGHWR_NET_DRIVER_ETH0_SETUP_OPTIONS to + avoid a spurious conflict report when the latter is + inactive. + +2000-02-25 John Dallaway <jld@cygnus.co.uk> + + * cdl/net.cdl: + + Reparent cdl_interface CYGHWR_NET_DRIVER_ETH1_SETUP under + cdl_component CYGHWR_NET_DRIVER_ETH1_SETUP_OPTIONS to + avoid a spurious conflict report when the latter is + inactive. + +2000-02-22 Gary Thomas <gthomas@cygnus.co.uk> + + * include/netinet/if_ether.h: + * include/netinet/ip.h: + * include/netinet/ip_icmp.h: + * include/netinet/tcp.h: + * include/netinet/udp.h: More structure alignement fixes. + +2000-02-21 Gary Thomas <gthomas@cygnus.co.uk> + + * include/netinet/tcpip.h: + * include/netinet/udp_var.h: Force structure alignment. + +2000-02-18 Gary Thomas <gthomas@cygnus.co.uk> + + * tests/server_test.c: Target [client] address was wrong. + + * tests/tcp_source.c: + * tests/tcp_sink.c: + * tests/tcp_echo.c: New test suite. + +2000-02-17 Gary Thomas <gthomas@cygnus.co.uk> + + * tests/ping_test.c: Fix typo in startup message. + + * src/sys/net/route.c (route_reinit): New function - only here + until BOOTP problems can be found/fixed. + + * src/lib/bootp_support.c (do_bootp): Force any existing routes + to be reset since this causes a problem if BOOTP has been previously + run. Also, the BOOTP request must be zeroed or the server will + get confused. + + * src/lib/network_support.c (init_all_network_interfaces): + Rearrange initialization so that all BOOTP activity takes place + before any permanent setups are in place. + +2000-02-16 Gary Thomas <gthomas@cygnus.co.uk> + + * src/sys/net/route.c (rtioctl): Add support for deleting routes. + + * src/lib/network_support.c (init_all_network_interfaces): + Support predefined IP configurations, as well as BOOTP. + + * tests/ping_test.c: Renamed from 'bootp_test.c' + + * src/lib/inet_addr.c: + * include/arpa/ftp.h: + * include/arpa/nameser.h: + * include/arpa/telnet.h: + * include/arpa/inet.h: + * include/arpa/tftp.h: New file(s). + +2000-02-15 Gary Thomas <gthomas@cygnus.co.uk> + + * src/lib/select.c: Add 'cyg_select_with_abort()' interface which + will allow 'select()' function to be abnormally terminated. Add + new function 'cyg_select_abort()' which does this. + +2000-02-15 Hugo Tyson <hmt@cygnus.co.uk> + + * cdl/net.cdl: Fix typo; cdl_interface CYGHWR_NET_DRIVER_ETH1 was + missing, so EBSA build was conflictual. + +2000-02-14 Gary Thomas <gthomas@cygnus.co.uk> + + * tests/bootp_test.c: + * tests/ftp_test.c: + * tests/nc_test_framework.h: + * tests/nc_test_master.c: + * tests/nc_test_slave.c: + * tests/server_test.c: Rework with automatic network initialization. + Includes support for multiple interfaces. + + * src/lib/network_support.c: + * include/network.h: New file(s). + + * cdl/net.cdl: New CDL to support multiple interfaces and their + configuration. (Not complete yet). + +2000-02-11 Gary Thomas <gthomas@cygnus.co.uk> + + * src/lib/select.c (select): Add a way to abort selects (EINTR). + +2000-02-10 Gary Thomas <gthomas@cygnus.co.uk> + + * tests/nc_test_slave.c (calibrate_load): Slightly different algorithm, + which should work better on all platforms. + +2000-02-09 Gary Thomas <gthomas@cygnus.co.uk> + + * cdl/net.cdl: Add CYGPKG_NET_THREAD_PRIORITY to allow user more + control over how networking [anonymous] threads behave. + + * tests/nc_test_framework.h: + * tests/nc_test_slave.c: + * tests/nc_test_master.c: Support test mode with target CPU under + various loads. + +2000-02-09 Hugo Tyson <hmt@cygnus.co.uk> + + * src/ecos/support.c (bcmp): Fix bug. Missing pointer increments + meant that the zeroth byte only was compared. Caused stack to + reject ARP packets - depending on MAC address order for particular + platform. + +2000-02-09 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/bootp_test.c: + * tests/ftp_test.c: + * tests/nc_test_master.c: + * tests/server_test.c: + * tests/socket_test.c: + Change stacksize of test thread to TYPICAL not MINIMAL - some + drivers eat more stack than others. Generally: + -#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM + +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL + +2000-02-08 John Dallaway <jld@cygnus.co.uk> + + * cdl/net.cdl: + + Tidy display strings. + +# ####GPLCOPYRIGHTBEGIN#### +# ------------------------------------------- +# This file is part of eCos, the Embedded Configurable Operating System. +# Copyright (C) 2000, 2001, 2002, 2009, 2010 Free Software Foundation, Inc. +# +# 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 or (at your option) any +# later version. +# +# This program 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., 51 Franklin Street, +# Fifth Floor, Boston, MA 02110-1301, USA. +# ------------------------------------------- +# ####GPLCOPYRIGHTEND#### diff --git a/ecos/packages/net/tcpip/current/cdl/openbsd_net.cdl b/ecos/packages/net/tcpip/current/cdl/openbsd_net.cdl new file mode 100644 index 0000000..d28fd5d --- /dev/null +++ b/ecos/packages/net/tcpip/current/cdl/openbsd_net.cdl @@ -0,0 +1,347 @@ +# ==================================================================== +# +# openbsd_net.cdl +# +# Networking configuration data +# +# ==================================================================== +# ####ECOSPDCOPYRIGHTBEGIN#### +# ------------------------------------------- +# This file is part of eCos, the Embedded Configurable Operating System. +# Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. +# +# Permission is granted to use, copy, modify and redistribute this +# file. +# +# ------------------------------------------- +# ####ECOSPDCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): gthomas +# Original data: gthomas +# Contributors: +# Date: 1999-11-29 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_NET_OPENBSD_STACK { + display "OpenBSD TCP/IP Stack" + parent CYGPKG_NET + doc ref/tcpip-openbsd.html + include_dir . + requires CYGPKG_IO + requires CYGPKG_ISOINFRA + requires CYGINT_ISO_C_TIME_TYPES + requires CYGINT_ISO_STRERROR + requires CYGINT_ISO_ERRNO + requires CYGINT_ISO_ERRNO_CODES + requires CYGINT_ISO_MALLOC + requires CYGINT_ISO_STRING_BSD_FUNCS + description "Basic networking support, including TCP/IP." + + implements CYGPKG_NET_STACK + implements CYGPKG_NET_STACK_INET + # Note: separating the stack implementation from the common support leads + # to some rather incestious config file relationships. + define_proc { + puts $::cdl_system_header "/***** Networking stack proc output start *****/" + puts $::cdl_header "#include <pkgconf/net.h>" + puts $::cdl_system_header "#define CYGDAT_NET_STACK_CFG <pkgconf/net_openbsd_stack.h>" + puts $::cdl_system_header "/***** Networking stack proc output end *****/" + } + + + # Export our types to <sys/types.h> + implements CYGINT_ISO_BSDTYPES + requires { CYGBLD_ISO_BSDTYPES_HEADER == "<sys/bsdtypes.h>" } + + compile ecos/support.c \ + ecos/synch.c \ + ecos/timeout.c \ + ecos/init.cxx \ + sys/kern/uipc_mbuf.c \ + sys/kern/uipc_domain.c \ + sys/kern/uipc_socket.c \ + sys/kern/uipc_socket2.c \ + sys/kern/kern_subr.c \ + sys/net/if.c \ + sys/net/rtsock.c \ + sys/net/raw_cb.c \ + sys/net/raw_usrreq.c \ + sys/net/route.c \ + sys/net/radix.c \ + sys/net/if_ethersubr.c \ + sys/net/if_loop.c \ + sys/netinet/igmp.c \ + sys/netinet/raw_ip.c \ + sys/netinet/in.c \ + sys/netinet/in_cksum.c \ + sys/netinet/in_pcb.c \ + sys/netinet/in_proto.c \ + sys/netinet/ip_id.c \ + sys/netinet/ip_icmp.c \ + sys/netinet/ip_input.c \ + sys/netinet/ip_output.c \ + sys/netinet/if_ether.c \ + sys/netinet/udp_usrreq.c \ + sys/netinet/tcp_input.c \ + sys/netinet/tcp_output.c \ + sys/netinet/tcp_subr.c \ + sys/netinet/tcp_debug.c \ + sys/netinet/tcp_usrreq.c \ + sys/netinet/tcp_timer.c + + cdl_option CYGPKG_NET_API_LOCAL { + display "Implement the socket API locally" + flavor bool + active_if !CYGPKG_IO_FILEIO + default_value 1 + implements CYGINT_ISO_SELECT + + compile sys/kern/uipc_syscalls.c \ + sys/kern/sys_socket.c \ + sys/kern/sys_generic.c \ + lib/socket.c \ + lib/close.c \ + lib/read.c \ + lib/write.c \ + lib/bind.c \ + lib/connect.c \ + lib/accept.c \ + lib/listen.c \ + lib/shutdown.c \ + lib/sendto.c \ + lib/recvfrom.c \ + lib/recv.c \ + lib/getsockname.c \ + lib/getpeername.c \ + lib/getsockopt.c \ + lib/setsockopt.c \ + lib/ioctl.c \ + lib/select.c + + description " + This option controls support for the network-stack supplied + API." + } + + cdl_option CYGPKG_NET_API_FILEIO { + display "Implement the socket API via Fileio package" + active_if CYGPKG_IO_FILEIO + default_value 1 + + compile -library=libextras.a sys/kern/sockio.c + + description " + This option controls support for the fileio subsystem supplied API." + } + + cdl_component CYGPKG_NET_OPENBSD_INET { + display "INET support" + active_if CYGPKG_NET_INET + flavor bool + no_define + default_value 1 + description " + This option enables support for INET (IP) network processing." + +# Placeholder only - not implemented yet +## cdl_option CYGPKG_NET_OPENBSD_INET6 { +## display "IPv6 support" +## active_if CYGPKG_NET_INET6 +## flavor bool +## default_value 0 +## description " +## This option enables support for IPv6 networking." +## } + } + +# cdl_option CYGPKG_NET_SYSCTL { +# display "Support BSD 'sysctl()' function" +# flavor bool +# default_value 0 +# description " +# This option includes support for the 'sysctl()' functions." +# } + + cdl_option CYGPKG_NET_NBPF { + display "Number of BPF filters" + flavor data + default_value 0 +# Placeholder only - not implemented yet + legal_values 0 +# Placeholder only - not implemented yet + description " + This option controls the number of active BPF filters." + define NBPFILTER + } + + cdl_component CYGPKG_NET_BRIDGE { + display "Built-in ethernet bridge code" + default_value 0 + implements CYGINT_NET_BRIDGE_HANDLER + no_define + description " + This option controls whether to include the built-in code for + the Ethernet bridge." + compile sys/net/if_bridge.c \ + sys/net/bridgestp.c + + cdl_option CYGNUM_NET_BRIDGES { + display "Number of Ethernet bridges" + flavor data + default_value 1 + legal_values 1 to 999999 + } + + cdl_option CYGPKG_NET_BRIDGE_STP_CODE { + display "Include code for Spanning Tree Protocol" + default_value 0 + description " + This option controls whether to include the code for + the Spanning Tree Protocol on Ethernet bridge." + } + } + + cdl_interface CYGINT_NET_BRIDGE_HANDLER { + display "Support for ethernet bridges in the IP stack" + define NBRIDGE + description " + This interface controls whether calls to bridge code are made + from the IP stack; these are needed if the built-in bridge code + is used, but they can also be enabled in order to call different + bridge code from an external component." + } + + cdl_option CYGPKG_NET_NGIF { + display "Number of GIF things" + flavor data + default_value 0 +# Placeholder only - not implemented yet + legal_values 0 +# Placeholder only - not implemented yet + description " + This option controls the number of active GIF things." + define NGIF + } + + cdl_option CYGPKG_NET_NLOOP { + display "Number of loopback interfaces" + flavor data + default_value 1 + requires { (CYGPKG_NET_NLOOP > 1) ? CYGPKG_LIBC_STDIO : 1 } + description " + This option controls the number of loopback, i.e. local, interfaces. + There is seldom need for this value to be anything other than one. + If a different value is required, then the C library STDIO package + is required for sprintf()." + define NLOOP + } + + cdl_option CYGPKG_NET_MEM_USAGE { + display "Memory designated for networking buffers." + flavor data + default_value 256*1024 + description " + This option controls the amount of memory pre-allocated + for buffers used by the networking code." + } + + cdl_option CYGPKG_NET_NUM_WAKEUP_EVENTS { + display "Number of supported pending network events" + flavor data + default_value 8 + description " + This option controls the number of pending network events + used by the networking code." + } + + cdl_option CYGPKG_NET_THREAD_PRIORITY { + display "Priority level for backgound network processing." + flavor data + default_value 7 + description " + This option allows the thread priority level used by the + networking stack to be adjusted by the user. It should be set + high enough that sufficient CPU resources are available to + process network data, but may be adjusted so that application + threads can have precedence over network processing." + } + + cdl_option CYGPKG_NET_FAST_THREAD_PRIORITY { + display "Priority level for fast network processing." + flavor data + default_value CYGPKG_NET_THREAD_PRIORITY - 1 + description " + This option sets the thread priority level used by the fast + network thread. The fast network thread runs often but briefly, to + service network device interrupts and network timeout events. This + thread should have higher priority than the background network + thread. It is reasonable to set this thread's priority higher than + application threads for best network throughput, or to set it lower + than application threads for best latency for those application + threads themselves, potentially at a cost to network throughput." + } + + cdl_component CYGPKG_NET_FAST_THREAD_TICKLE_DEVS { + display "Fast network processing thread 'tickles' drivers" + default_value 1 + description " + If this is enabled, the fast network thread will tickle the + device(s) periodically, to unblock them when the hardware has + become wedged due to a lost interrupt or other hardware + race-condition type problem. + This is not necessary if a networked app is running which sends + packets itself often - or + uses TCP, or any similar protocol which exchanges keep-alive + packets periodically and often enough. + Trying to send a packet passes control into the driver; this is + sufficient to detect and unblock jammed hardware." + + cdl_option CYGNUM_NET_FAST_THREAD_TICKLE_DEVS_DELAY { + display "Delay in kernel clocks of tickle loop" + flavor data + default_value 50 + description " + The default is 50, which will usually mean a delay between + tests for 'stuck' devices of 500mS, that is half a second. + The overhead only applies if no network activity occurred, + so it may be acceptable to make this value very small, + where high CPU load does not matter during network idle + periods, or very large if your application tries often to + send packets itself." + } + } + + cdl_component CYGPKG_NET_OPENBSD_STACK_OPTIONS { + display "Networking support build options" + flavor none + no_define + + cdl_option CYGPKG_NET_OPENBSD_STACK_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS -D__INSIDE_NET" } + description " + This option modifies the set of compiler flags for + building the networking package. + These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_NET_OPENBSD_STACK_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the networking package. These flags are removed from + the set of global flags if present." + } + } +} diff --git a/ecos/packages/net/tcpip/current/doc/accept.html b/ecos/packages/net/tcpip/current/doc/accept.html new file mode 100644 index 0000000..e0c9d62 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/accept.html @@ -0,0 +1,81 @@ +<html> +<body> +<pre> +NAME + accept - accept a connection on a socket + +SYNOPSIS + #include <network.h> + + int accept(int s, struct sockaddr *addr, int *addrlen); + +DESCRIPTION + The argument s is a socket that has been created with + socket(2), bound to an address with bind(2), and is lis- + tening for connections after a listen(2). The accept + function extracts the first connection request on the + queue of pending connections, creates a new socket with + the same properties of s, and allocates a new file + descriptor for the socket. If no pending connections are + present on the queue, and the socket is not marked as non- + blocking, accept blocks the caller until a connection is + present. If the socket is marked non-blocking and no + pending connections are present on the queue, accept + returns an error as described below. The socket returned + by accept may not be used to accept more connections. The + original socket s remains open. + + The argument addr is a result parameter that is filled in + with the address of the connecting entity, as known to the + communications layer. The exact format of the addr param- + eter is determined by the domain in which the communica- + tion is occurring. addrlen is a value-result parameter: + it should initially contain the amount of space pointed to + by addr; on return it will contain the actual length (in + bytes) of the address returned. This call is used with + connection-based socket types, currently with SOCK_STREAM. + + It is possible to select(2) a socket for the purposes of + doing an accept by selecting it for read. + + For certain protocols which require an explicit confirma- + tion, such as DECNet, accept can be thought of as merely + dequeuing the next connection request and not implying + confirmation. Confirmation can be implied by a normal + read or write on the new file descriptor, and rejection + can be implied by closing the new socket. Currently only + DECNet has these semantics on Linux. + +NOTES + If you want accept to never block the listening socket + needs to have the non blocking flag set. Assuming that + there is always a connection waiting after select returned + true is not reliable, because the connection might be + removed by an asynchronous network error between the + select/poll returning and the accept call. The application + would hang then if the listen socket is not non blocking. + +RETURN VALUES + The call returns -1 on error. If it succeeds, it returns + a non-negative integer that is a descriptor for the + accepted socket. + +ERRORS + EBADF The descriptor is invalid. + + ENOTSOCK + The descriptor references a file, not a socket. + + EOPNOTSUPP + The referenced socket is not of type SOCK_STREAM. + + EAGAIN The socket is marked non-blocking and no connec- + tions are present to be accepted. + + ENOBUFS, ENOMEM + Not enough free memory. + + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/accept.man b/ecos/packages/net/tcpip/current/doc/accept.man new file mode 100644 index 0000000..0defb38 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/accept.man @@ -0,0 +1,75 @@ +NAME + accept - accept a connection on a socket + +SYNOPSIS + #include <network.h> + + int accept(int s, struct sockaddr *addr, int *addrlen); + +DESCRIPTION + The argument s is a socket that has been created with + socket(2), bound to an address with bind(2), and is lis- + tening for connections after a listen(2). The accept + function extracts the first connection request on the + queue of pending connections, creates a new socket with + the same properties of s, and allocates a new file + descriptor for the socket. If no pending connections are + present on the queue, and the socket is not marked as non- + blocking, accept blocks the caller until a connection is + present. If the socket is marked non-blocking and no + pending connections are present on the queue, accept + returns an error as described below. The socket returned + by accept may not be used to accept more connections. The + original socket s remains open. + + The argument addr is a result parameter that is filled in + with the address of the connecting entity, as known to the + communications layer. The exact format of the addr param- + eter is determined by the domain in which the communica- + tion is occurring. addrlen is a value-result parameter: + it should initially contain the amount of space pointed to + by addr; on return it will contain the actual length (in + bytes) of the address returned. This call is used with + connection-based socket types, currently with SOCK_STREAM. + + It is possible to select(2) a socket for the purposes of + doing an accept by selecting it for read. + + For certain protocols which require an explicit confirma- + tion, such as DECNet, accept can be thought of as merely + dequeuing the next connection request and not implying + confirmation. Confirmation can be implied by a normal + read or write on the new file descriptor, and rejection + can be implied by closing the new socket. Currently only + DECNet has these semantics on Linux. + +NOTES + If you want accept to never block the listening socket + needs to have the non blocking flag set. Assuming that + there is always a connection waiting after select returned + true is not reliable, because the connection might be + removed by an asynchronous network error between the + select/poll returning and the accept call. The application + would hang then if the listen socket is not non blocking. + +RETURN VALUES + The call returns -1 on error. If it succeeds, it returns + a non-negative integer that is a descriptor for the + accepted socket. + +ERRORS + EBADF The descriptor is invalid. + + ENOTSOCK + The descriptor references a file, not a socket. + + EOPNOTSUPP + The referenced socket is not of type SOCK_STREAM. + + EAGAIN The socket is marked non-blocking and no connec- + tions are present to be accepted. + + ENOBUFS, ENOMEM + Not enough free memory. + + diff --git a/ecos/packages/net/tcpip/current/doc/bind.html b/ecos/packages/net/tcpip/current/doc/bind.html new file mode 100644 index 0000000..a82971d --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/bind.html @@ -0,0 +1,64 @@ +<html> +<body> +<pre> +NAME + bind - bind a name to a socket + +SYNOPSIS + #include <network.h> + + int bind(int sockfd, struct sockaddr *my_addr, int + addrlen); + +DESCRIPTION + bind gives the socket sockfd the local address my_addr. + my_addr is addrlen bytes long. Traditionally, this is + called "assigning a name to a socket." (When a socket is + created with socket(2), it exists in a name space (address + family) but has no name assigned.) + + Before a SOCK_STREAM socket is put into the LISTEN state + to receive connections, you usually need to first assign a + local address using bind to make the socket visible. + +NOTES + Binding a name that is not in the abstract namespace in + the UNIX domain creates a socket in the file system that + must be deleted by the caller when it is no longer needed + (using unlink(2)). + + The rules used in name binding vary between communication + domains. Consult the manual entries in section 4 for + detailed information. For IP see ip(4) and for PF_UNIX see + unix(4). If you want to listen to every local interface + for IPv4 set the sin_addr member of the IP-specific sock- + addr_in to INADDR_ANY. For IP only one socket may be + bound to a specific local address/port pair. For TCP a + bound local socket endpoint (address/port pair) is + unavailable for some time after closing the socket, unless + the SO_REUSEADDR flag is set. Note that carelessly setting + SO_REUSEADDR might make TCP more unreliable unless PAWS is + used (see tcp(4)); the delay is needed to handle old pack- + ets still in the network. + + IP sockets may also bind to a broadcast or multicast + address. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF sockfd is not a valid descriptor. + + EINVAL The socket is already bound to an address. This + may change in the future: see linux/unix/sock.c + for details. + + ENOTSOCK + Argument is a descriptor for a file, not a socket. + + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/bind.man b/ecos/packages/net/tcpip/current/doc/bind.man new file mode 100644 index 0000000..e5c1fe2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/bind.man @@ -0,0 +1,58 @@ +NAME + bind - bind a name to a socket + +SYNOPSIS + #include <network.h> + + int bind(int sockfd, struct sockaddr *my_addr, int + addrlen); + +DESCRIPTION + bind gives the socket sockfd the local address my_addr. + my_addr is addrlen bytes long. Traditionally, this is + called "assigning a name to a socket." (When a socket is + created with socket(2), it exists in a name space (address + family) but has no name assigned.) + + Before a SOCK_STREAM socket is put into the LISTEN state + to receive connections, you usually need to first assign a + local address using bind to make the socket visible. + +NOTES + Binding a name that is not in the abstract namespace in + the UNIX domain creates a socket in the file system that + must be deleted by the caller when it is no longer needed + (using unlink(2)). + + The rules used in name binding vary between communication + domains. Consult the manual entries in section 4 for + detailed information. For IP see ip(4) and for PF_UNIX see + unix(4). If you want to listen to every local interface + for IPv4 set the sin_addr member of the IP-specific sock- + addr_in to INADDR_ANY. For IP only one socket may be + bound to a specific local address/port pair. For TCP a + bound local socket endpoint (address/port pair) is + unavailable for some time after closing the socket, unless + the SO_REUSEADDR flag is set. Note that carelessly setting + SO_REUSEADDR might make TCP more unreliable unless PAWS is + used (see tcp(4)); the delay is needed to handle old pack- + ets still in the network. + + IP sockets may also bind to a broadcast or multicast + address. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF sockfd is not a valid descriptor. + + EINVAL The socket is already bound to an address. This + may change in the future: see linux/unix/sock.c + for details. + + ENOTSOCK + Argument is a descriptor for a file, not a socket. + + diff --git a/ecos/packages/net/tcpip/current/doc/bridge.html b/ecos/packages/net/tcpip/current/doc/bridge.html new file mode 100644 index 0000000..7c60680 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/bridge.html @@ -0,0 +1,319 @@ +<html> +<body> +<pre> +NAME + bridge - Ethernet bridge interface + +SYNOPSIS + pseudo-device bridge 2 + +DESCRIPTION + The bridge device creates a logical link between two or more Ethernet in + terfaces. This link between the interfaces selectively forwards frames + from each interface on the bridge to every other interface on the bridge. + A bridge can serve several services, including, isolation of traffic be + tween sets of machines so that traffic local to one set of machines is + not available on the wire of another set of machines, and it can act as a + transparent filter for ip(4) datagrams. + + The bridges provided by this interface are learning bridges with IP fil + tering, see ipf(4). In general a bridge works like a hub, forwarding + traffic from one interface to another. It differs from a hub in that it + will "learn" which machines are on each of its attached segments by ac + tively listening to incoming traffic and examining the headers of each + frame. A table is built containing the MAC address and segment to which + the MAC address is attached. This allows a bridge to be more selective + about what it forwards, which can be used to reduce traffic on a set of + segments and also to provide an IP firewall without changing the topology + of the network. + + The algorithm works as follows by default, but can be modified via + ioctl(2) or the utility brconfig(8). When a frame comes in, the origin + segment and the source address are recorded. If the bridge has no knowl + edge about where the destination is to be found, the bridge will forward + the frame to all attached segments. If the destination is known to be on + a different segment from its origin, the bridge will forward the packet + only to the destination segment. If the destination is on the same seg + ment as the origin segment, the bridge will drop the packet because the + receiver has already had a chance to see the frame. Before forwarding a + frame, the bridge will check to see if the packet contains an ip(4) data + gram; if so, the datagram is run through the ipf(4) interface so that it + can be filtered. Only the ipf(4) input rules for the source interface + are checked with the datagram; output rules have no effect. + +IOCTLS + A bridge interface responds to all of the ioctl(2) calls specific to oth + er interfaces listed in netintro(4). The following ioctl(2) calls are + specific to bridge devices. They are defined in <sys/sockio.h>. + + SIOCBRDGIFS (struct ifbifconf) Retrieve member interface list from a + bridge. This request takes an ifbifconf structure (see + below) as a value-result parameter. The ifbic_len field + should be initially set to the size of the buffer point + ed to by ifbic_buf. On return it will contain the + length, in bytes, of the configuration list. Alterna + tively, if the ifbic_len passed in is set to 0, + SIOCBRDGIFS will set ifbic_len to the size that + ifbic_buf needs to be to fit the entire configuration + list, and will not fill in the other parameters. This + is useful for determining the exact size that ifbic_buf + needs to be in advance. + + The argument structure is defined as follows: + + struct ifbreq { + char ifbr_name[IFNAMSIZ]; /* brdg nam */ + char ifbr_ifsname[IFNAMSIZ]; /* if name */ + u_int32_t ifbr_ifsflags; /* if flags */ + }; + + #define IFBIF_LEARNING 0x1 /* learns addrs */ + #define IFBIF_DISCOVER 0x2 /* gets fwd'd pkts */ + + struct ifbifconf { + char ifbic_name[IFNAMSIZ]; /* brdg name */ + u_int32_t ifbic_len; /* buf size */ + union { + caddr_t ifbicu_buf; /* buffer */ + struct ifbreq *ifbicu_req; + } ifbic_ifbicu; + #define ifbic_buf ifbic_ifbicu.ifbicu_buf + #define ifbic_req ifbic_ifbicu.ifbicu_req + }; + + SIOCBRDGADD (struct ifbreq) Add the interface named in ifbr_ifsname + to the bridge named in ifbr_name. + + SIOCBRDGDEL (struct ifbreq) Delete the interface named in + ifbr_ifsname from the bridge named in ifbr_name. + + SIOCBRDGSIFFLGS (struct ifbreq) Set the bridge member interface flags + for the interface named in ifbr_ifsname attached to the + bridge ifbr_name. If the flag IFBIF_LEARNING is set on + an interface, source addresses from frames received on + the interface are recorded in the address cache. If the + flag IFBIF_DISCOVER is set, the interface will receive + packets destined for unknown destinations, otherwise a + frame that has a destination not found in the address + cache is not forwarded to this interface. The default + for newly added interfaces has both flags set. If the + flag IFBIF_BLOCKNONIP is set, packets that are one of + ip(4), ip6(4), arp(4), or Reverse ARP, will not be + bridged from and to the interface. + + SIOCBRDGGIFFLGS Retrieve the bridge member interface flags for the in + terface named in ifbr_ifsname attached to the bridge + ifbr_name. + + SIOCBRDGRTS (struct ifbaconf) Retrieve the address cache of the + bridge named in ifbac_name. This request takes an + ifbaconf structure (see below) as a value result parame + ter. The ifbac_len field should be initially set to the + size of the buffer pointed to by ifbac_buf. On return, + it will contain the length, in bytes, of the configura + tion list. Alternatively, if the ifbac_len passed in is + set to 0, SIOCBRDGRTS will set it to the size that + ifbac_buf needs to be to fit the entire configuration + list and not fill in the other parameters. As with + SIOCBRDGIFS, this is useful for determining the exact + size that ifbac_buf needs to be in advance. + + The argument structure is defined as follows: + + struct ifbareq { + char ifba_name[IFNAMSIZ]; /* brdg nam */ + char ifba_ifsname[IFNAMSIZ];/* dest ifs */ + u_int8_t ifba_age; /* addr age */ + u_int8_t ifba_flags; /* addr flag */ + struct ether_addr ifba_dst; /* dst addr */ + }; + + #define IFBAF_TYPEMASK 0x03 /* addr type mask */ + #define IFBAF_DYNAMIC 0x00 /* dynamic addr */ + #define IFBAF_STATIC 0x01 /* static address */ + + struct ifbaconf { + char ifbac_name[IFNAMSIZ]; /* brdg name */ + u_int32_t ifbac_len; /* buf size */ + union { + caddr_t ifbacu_buf; /* buf */ + struct ifbareq *ifbacu_req; + } ifbac_ifbacu; + #define ifbac_buf ifbac_ifbacu.ifbacu_buf + #define ifbac_req ifbac_ifbacu.ifbacu_req + }; + Address cache entries with the type set to IFBAF_DYNAMIC + in ifba_flags are entries learned by the bridge. En + tries with the type set to IFBAF_STATIC are manually + added entries. + + SIOCBRDGSADDR (struct ifbareq) Add an entry, manually, to the address + cache for the bridge named in ifba_name. The address and + its associated interface and flags are set in the + ifba_dst, ifba_ifsname, ifba_flags fields, respectively. + + SIOCBRDGDADDR (struct ifbareq) Delete an entry from the address cache + of the bridge named in ifba_name. Entries are deleted + strictly based on the address field ifba_dst. + + SIOCBRDGSCACHE (struct ifbcachereq) Set the maximum address cache size + for the bridge named in ifbc_name to ifbc_size entries. + + The argument structure is as follows: + + struct ifbcachereq { + char ifbc_name[IFNAMSIZ]; /* bridge */ + u_int32_t ifbc_size; /* size */ + }; + + SIOCBRDGGCACHE (struct ifbcachereq) Retrieve the maximum size of the + address cache for the bridge ifbc_name. + + SIOCBRDGSTO (struct ifbcachetoreq) Set the time, in seconds, that + addresses which have not been seen on the network + (transmitted a packet) remain in the cache. If the time + is set to zero, no aging is performed on the address + cache. The argument structure is as follows: + + struct ifbcachetoreq { + char ifbct_name[IFNAMSIZ]; /* bridge */ + u_int32_t ifbct_time; /* time */ + }; + + SIOCBRDGGTO (struct ifbcachetoreq) Retrieve the address cache expi + ration time (see above). + + SIOCBRDGFLUSH (struct ifbreq) Flush addresses from the cache. + ifbr_name contains the name of the bridge device, and + ifbr_ifsflags should be set to IFBF_FLUSHALL to flush + all addresses from the cache or IFBF_FLUSHDYN to flush + only the dynamically learned addresses from the cache. + + SIOCBRDGARL (struct ifbrlreq) Add a filtering rule to the bridge + named in ifbr_name on the interface named in + ifbr_ifsname. The argument structure is as follows: + + struct ifbrlreq { + char ifbr_name[IFNAMSIZ]; /* bridge */ + char ifbr_ifsname[IFNAMSIZ]; /* ifs */ + u_int8_t ifbr_action; /* handling */ + u_int8_t ifbr_flags; /* flags */ + struct ether_addr ifbr_src; /* src mac */ + struct ether_addr ifbr_dst; /* dst mac */ + }; + #define BRL_ACTION_BLOCK 0x01 + #define BRL_ACTION_PASS 0x02 + #define BRL_FLAG_IN 0x08 + #define BRL_FLAG_OUT 0x04 + #define BRL_FLAG_SRCVALID 0x02 + #define BRL_FLAG_DSTVALID 0x01 + + Rules are applied in the order in which they were added + to the bridge, and the first matching rule's action pa + rameter determines the fate of the packet. The + ifbr_action parameter specifies whether a frame matching + the rule is to be blocked or passed. + + If the BRL_FLAG_IN bit is set in ifbr_flags, then the + rule applies to frames received by the interface. If + the BRL_FLAG_OUT bit is set, then the rule applies to + frame transmitted by the interface. At least one of + BRL_FLAG_IN or BRL_FLAG_OUT must be set. + + The source ethernet address in ifbr_src is checked if + the BRL_FLAG_SRCVALID bit is set in ifbr_flags. The des + tination address in ifbr_dst is check if the + BRL_FLAG_DSTVALID bit is set. If neither bit is set, + the rule is matches all frames. + + SIOCBRDGFRL (struct ifbrlreq) Remove all filtering rules from a + bridge interface member. ifbr_name contains the name of + the bridge device, and ifbr_ifsname contains the name of + the bridge member interface. + + SIOCBRDGGRL (struct ifbrlconf) Retrieve all of the rules from the + bridge, ifbrl_name, for the member interface, + ifbrl_ifsname. + + This request takes an ifbrlconf structure (see below) as + a value result parameter. The ifbrl_len field should be + initially set to the size of the buffer pointed to by + ifbrl_buf. On return, it will contain the length, in + bytes, of the configuration list. Alternatively, if the + ifbrl_len passed in is set to 0, SIOCBRDGGRL will set it + to the size that ifbrl_buf needs to be to fit the entire + configuration list and not fill in the other parameters. + As with SIOCBRDGIFS, this is useful for determining the + exact size that ifbrl_buf needs to be in advance. + + The argument structure is defined as follows: + + struct ifbrlconf { + char ifbrl_name[IFNAMSIZ]; /* brdg nam */ + char ifbrl_ifsname[IFNAMSIZ];/* ifs name */ + u_int32_t ifbr_len; /* buf len */ + union { + caddr_t ifbrlu_buf; + struct ifbrlreq *ifbrlu_req; + } ifrl_ifbrlu; + #define ifbrl_buf ifbrl_ifbrlu.ifbrlu_buf + #define ifbrl_req ifbrl_ifbrlu.ifbrlu_req + }; + + +ERRORS + If the ioctl(2) call fails, errno(2) is set to one of the following val + ues: + + [ENOENT] For an add request, this means that the named interface is + not configured into the system. For delete operation, it + means that the named interface is not a member of the + bridge. For a address cache deletion, the address was not + found in the table. + + [ENOMEM] Memory could not be allocated for an interface or cache en + try to be added to the bridge. + + [EEXIST] The named interface is already a member of the bridge. + + [EBUSY] The named interface is already a member of another bridge. + + [EINVAL] The named interface is not an Ethernet interface or an in + valid ioctl was performed on the bridge. + + [ENETDOWN] Address cache operation (flush, add, delete) on a bridge + that is in the down state. + + [EPERM] Super-user privilege is required to add and delete inter + faces to and from bridges and to set the bridge interface + flags. + + [EFAULT] The buffer used in a SIOCBRDGIFS or SIOCBRDGRTS request + + points outside of the process's allocated address space. + + [ESRCH] No such member interface in the bridge. + +SEE ALSO + errno(2), ioctl(2), ip(4), ipf(4), netintro(4), bridgename.if(5), + brconfig(8) + +HISTORY + The brconfig(8) command and the bridge(4) kernel interface first appeared + in + +AUTHOR + The brconfig(8) command and the bridge(4) kernel interface were written + by Jason L. Wright <jason@thought.net> as part of an undergraduate inde + pendent study at the University of North Carolina at Greensboro. + +BUGS + There is currently no loop detection. Care must be taken to make sure + that loops are not created when a bridge is brought up. + + Only ipf(4) input rules are checked with incoming packet; there is no + easy way to handle output rules. + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/bridge.man b/ecos/packages/net/tcpip/current/doc/bridge.man new file mode 100644 index 0000000..9ee47d1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/bridge.man @@ -0,0 +1,314 @@ + +NAME + bridge - Ethernet bridge interface + +SYNOPSIS + pseudo-device bridge 2 + +DESCRIPTION + The bridge device creates a logical link between two or more Ethernet in + terfaces. This link between the interfaces selectively forwards frames + from each interface on the bridge to every other interface on the bridge. + A bridge can serve several services, including, isolation of traffic be + tween sets of machines so that traffic local to one set of machines is + not available on the wire of another set of machines, and it can act as a + transparent filter for ip(4) datagrams. + + The bridges provided by this interface are learning bridges with IP fil + tering, see ipf(4). In general a bridge works like a hub, forwarding + traffic from one interface to another. It differs from a hub in that it + will "learn" which machines are on each of its attached segments by ac + tively listening to incoming traffic and examining the headers of each + frame. A table is built containing the MAC address and segment to which + the MAC address is attached. This allows a bridge to be more selective + about what it forwards, which can be used to reduce traffic on a set of + segments and also to provide an IP firewall without changing the topology + of the network. + + The algorithm works as follows by default, but can be modified via + ioctl(2) or the utility brconfig(8). When a frame comes in, the origin + segment and the source address are recorded. If the bridge has no knowl + edge about where the destination is to be found, the bridge will forward + the frame to all attached segments. If the destination is known to be on + a different segment from its origin, the bridge will forward the packet + only to the destination segment. If the destination is on the same seg + ment as the origin segment, the bridge will drop the packet because the + receiver has already had a chance to see the frame. Before forwarding a + frame, the bridge will check to see if the packet contains an ip(4) data + gram; if so, the datagram is run through the ipf(4) interface so that it + can be filtered. Only the ipf(4) input rules for the source interface + are checked with the datagram; output rules have no effect. + +IOCTLS + A bridge interface responds to all of the ioctl(2) calls specific to oth + er interfaces listed in netintro(4). The following ioctl(2) calls are + specific to bridge devices. They are defined in <sys/sockio.h>. + + SIOCBRDGIFS (struct ifbifconf) Retrieve member interface list from a + bridge. This request takes an ifbifconf structure (see + below) as a value-result parameter. The ifbic_len field + should be initially set to the size of the buffer point + ed to by ifbic_buf. On return it will contain the + length, in bytes, of the configuration list. Alterna + tively, if the ifbic_len passed in is set to 0, + SIOCBRDGIFS will set ifbic_len to the size that + ifbic_buf needs to be to fit the entire configuration + list, and will not fill in the other parameters. This + is useful for determining the exact size that ifbic_buf + needs to be in advance. + + The argument structure is defined as follows: + + struct ifbreq { + char ifbr_name[IFNAMSIZ]; /* brdg nam */ + char ifbr_ifsname[IFNAMSIZ]; /* if name */ + u_int32_t ifbr_ifsflags; /* if flags */ + }; + + #define IFBIF_LEARNING 0x1 /* learns addrs */ + #define IFBIF_DISCOVER 0x2 /* gets fwd'd pkts */ + + struct ifbifconf { + char ifbic_name[IFNAMSIZ]; /* brdg name */ + u_int32_t ifbic_len; /* buf size */ + union { + caddr_t ifbicu_buf; /* buffer */ + struct ifbreq *ifbicu_req; + } ifbic_ifbicu; + #define ifbic_buf ifbic_ifbicu.ifbicu_buf + #define ifbic_req ifbic_ifbicu.ifbicu_req + }; + + SIOCBRDGADD (struct ifbreq) Add the interface named in ifbr_ifsname + to the bridge named in ifbr_name. + + SIOCBRDGDEL (struct ifbreq) Delete the interface named in + ifbr_ifsname from the bridge named in ifbr_name. + + SIOCBRDGSIFFLGS (struct ifbreq) Set the bridge member interface flags + for the interface named in ifbr_ifsname attached to the + bridge ifbr_name. If the flag IFBIF_LEARNING is set on + an interface, source addresses from frames received on + the interface are recorded in the address cache. If the + flag IFBIF_DISCOVER is set, the interface will receive + packets destined for unknown destinations, otherwise a + frame that has a destination not found in the address + cache is not forwarded to this interface. The default + for newly added interfaces has both flags set. If the + flag IFBIF_BLOCKNONIP is set, packets that are one of + ip(4), ip6(4), arp(4), or Reverse ARP, will not be + bridged from and to the interface. + + SIOCBRDGGIFFLGS Retrieve the bridge member interface flags for the in + terface named in ifbr_ifsname attached to the bridge + ifbr_name. + + SIOCBRDGRTS (struct ifbaconf) Retrieve the address cache of the + bridge named in ifbac_name. This request takes an + ifbaconf structure (see below) as a value result parame + ter. The ifbac_len field should be initially set to the + size of the buffer pointed to by ifbac_buf. On return, + it will contain the length, in bytes, of the configura + tion list. Alternatively, if the ifbac_len passed in is + set to 0, SIOCBRDGRTS will set it to the size that + ifbac_buf needs to be to fit the entire configuration + list and not fill in the other parameters. As with + SIOCBRDGIFS, this is useful for determining the exact + size that ifbac_buf needs to be in advance. + + The argument structure is defined as follows: + + struct ifbareq { + char ifba_name[IFNAMSIZ]; /* brdg nam */ + char ifba_ifsname[IFNAMSIZ];/* dest ifs */ + u_int8_t ifba_age; /* addr age */ + u_int8_t ifba_flags; /* addr flag */ + struct ether_addr ifba_dst; /* dst addr */ + }; + + #define IFBAF_TYPEMASK 0x03 /* addr type mask */ + #define IFBAF_DYNAMIC 0x00 /* dynamic addr */ + #define IFBAF_STATIC 0x01 /* static address */ + + struct ifbaconf { + char ifbac_name[IFNAMSIZ]; /* brdg name */ + u_int32_t ifbac_len; /* buf size */ + union { + caddr_t ifbacu_buf; /* buf */ + struct ifbareq *ifbacu_req; + } ifbac_ifbacu; + #define ifbac_buf ifbac_ifbacu.ifbacu_buf + #define ifbac_req ifbac_ifbacu.ifbacu_req + }; + Address cache entries with the type set to IFBAF_DYNAMIC + in ifba_flags are entries learned by the bridge. En + tries with the type set to IFBAF_STATIC are manually + added entries. + + SIOCBRDGSADDR (struct ifbareq) Add an entry, manually, to the address + cache for the bridge named in ifba_name. The address and + its associated interface and flags are set in the + ifba_dst, ifba_ifsname, ifba_flags fields, respectively. + + SIOCBRDGDADDR (struct ifbareq) Delete an entry from the address cache + of the bridge named in ifba_name. Entries are deleted + strictly based on the address field ifba_dst. + + SIOCBRDGSCACHE (struct ifbcachereq) Set the maximum address cache size + for the bridge named in ifbc_name to ifbc_size entries. + + The argument structure is as follows: + + struct ifbcachereq { + char ifbc_name[IFNAMSIZ]; /* bridge */ + u_int32_t ifbc_size; /* size */ + }; + + SIOCBRDGGCACHE (struct ifbcachereq) Retrieve the maximum size of the + address cache for the bridge ifbc_name. + + SIOCBRDGSTO (struct ifbcachetoreq) Set the time, in seconds, that + addresses which have not been seen on the network + (transmitted a packet) remain in the cache. If the time + is set to zero, no aging is performed on the address + cache. The argument structure is as follows: + + struct ifbcachetoreq { + char ifbct_name[IFNAMSIZ]; /* bridge */ + u_int32_t ifbct_time; /* time */ + }; + + SIOCBRDGGTO (struct ifbcachetoreq) Retrieve the address cache expi + ration time (see above). + + SIOCBRDGFLUSH (struct ifbreq) Flush addresses from the cache. + ifbr_name contains the name of the bridge device, and + ifbr_ifsflags should be set to IFBF_FLUSHALL to flush + all addresses from the cache or IFBF_FLUSHDYN to flush + only the dynamically learned addresses from the cache. + + SIOCBRDGARL (struct ifbrlreq) Add a filtering rule to the bridge + named in ifbr_name on the interface named in + ifbr_ifsname. The argument structure is as follows: + + struct ifbrlreq { + char ifbr_name[IFNAMSIZ]; /* bridge */ + char ifbr_ifsname[IFNAMSIZ]; /* ifs */ + u_int8_t ifbr_action; /* handling */ + u_int8_t ifbr_flags; /* flags */ + struct ether_addr ifbr_src; /* src mac */ + struct ether_addr ifbr_dst; /* dst mac */ + }; + #define BRL_ACTION_BLOCK 0x01 + #define BRL_ACTION_PASS 0x02 + #define BRL_FLAG_IN 0x08 + #define BRL_FLAG_OUT 0x04 + #define BRL_FLAG_SRCVALID 0x02 + #define BRL_FLAG_DSTVALID 0x01 + + Rules are applied in the order in which they were added + to the bridge, and the first matching rule's action pa + rameter determines the fate of the packet. The + ifbr_action parameter specifies whether a frame matching + the rule is to be blocked or passed. + + If the BRL_FLAG_IN bit is set in ifbr_flags, then the + rule applies to frames received by the interface. If + the BRL_FLAG_OUT bit is set, then the rule applies to + frame transmitted by the interface. At least one of + BRL_FLAG_IN or BRL_FLAG_OUT must be set. + + The source ethernet address in ifbr_src is checked if + the BRL_FLAG_SRCVALID bit is set in ifbr_flags. The des + tination address in ifbr_dst is check if the + BRL_FLAG_DSTVALID bit is set. If neither bit is set, + the rule is matches all frames. + + SIOCBRDGFRL (struct ifbrlreq) Remove all filtering rules from a + bridge interface member. ifbr_name contains the name of + the bridge device, and ifbr_ifsname contains the name of + the bridge member interface. + + SIOCBRDGGRL (struct ifbrlconf) Retrieve all of the rules from the + bridge, ifbrl_name, for the member interface, + ifbrl_ifsname. + + This request takes an ifbrlconf structure (see below) as + a value result parameter. The ifbrl_len field should be + initially set to the size of the buffer pointed to by + ifbrl_buf. On return, it will contain the length, in + bytes, of the configuration list. Alternatively, if the + ifbrl_len passed in is set to 0, SIOCBRDGGRL will set it + to the size that ifbrl_buf needs to be to fit the entire + configuration list and not fill in the other parameters. + As with SIOCBRDGIFS, this is useful for determining the + exact size that ifbrl_buf needs to be in advance. + + The argument structure is defined as follows: + + struct ifbrlconf { + char ifbrl_name[IFNAMSIZ]; /* brdg nam */ + char ifbrl_ifsname[IFNAMSIZ];/* ifs name */ + u_int32_t ifbr_len; /* buf len */ + union { + caddr_t ifbrlu_buf; + struct ifbrlreq *ifbrlu_req; + } ifrl_ifbrlu; + #define ifbrl_buf ifbrl_ifbrlu.ifbrlu_buf + #define ifbrl_req ifbrl_ifbrlu.ifbrlu_req + }; + + +ERRORS + If the ioctl(2) call fails, errno(2) is set to one of the following val + ues: + + [ENOENT] For an add request, this means that the named interface is + not configured into the system. For delete operation, it + means that the named interface is not a member of the + bridge. For a address cache deletion, the address was not + found in the table. + + [ENOMEM] Memory could not be allocated for an interface or cache en + try to be added to the bridge. + + [EEXIST] The named interface is already a member of the bridge. + + [EBUSY] The named interface is already a member of another bridge. + + [EINVAL] The named interface is not an Ethernet interface or an in + valid ioctl was performed on the bridge. + + [ENETDOWN] Address cache operation (flush, add, delete) on a bridge + that is in the down state. + + [EPERM] Super-user privilege is required to add and delete inter + faces to and from bridges and to set the bridge interface + flags. + + [EFAULT] The buffer used in a SIOCBRDGIFS or SIOCBRDGRTS request + + points outside of the process's allocated address space. + + [ESRCH] No such member interface in the bridge. + +SEE ALSO + errno(2), ioctl(2), ip(4), ipf(4), netintro(4), bridgename.if(5), + brconfig(8) + +HISTORY + The brconfig(8) command and the bridge(4) kernel interface first appeared + in + +AUTHOR + The brconfig(8) command and the bridge(4) kernel interface were written + by Jason L. Wright <jason@thought.net> as part of an undergraduate inde + pendent study at the University of North Carolina at Greensboro. + +BUGS + There is currently no loop detection. Care must be taken to make sure + that loops are not created when a bridge is brought up. + + Only ipf(4) input rules are checked with incoming packet; there is no + easy way to handle output rules. + diff --git a/ecos/packages/net/tcpip/current/doc/close.html b/ecos/packages/net/tcpip/current/doc/close.html new file mode 100644 index 0000000..346de16 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/close.html @@ -0,0 +1,27 @@ +<html> +<body> +<pre> +NAME + close - close a file descriptor + +SYNOPSIS + + int close(int fd); + +DESCRIPTION + close closes a file descriptor, so that it no longer + refers to any file and may be reused. + + If fd is the last copy of a particular file descriptor the + resources associated with it are freed. + +RETURN VALUE + close returns zero on success, or -1 if an error occurred. + +ERRORS + EBADF fd isn't a valid open file descriptor. + + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/close.man b/ecos/packages/net/tcpip/current/doc/close.man new file mode 100644 index 0000000..0c202d2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/close.man @@ -0,0 +1,21 @@ +NAME + close - close a file descriptor + +SYNOPSIS + + int close(int fd); + +DESCRIPTION + close closes a file descriptor, so that it no longer + refers to any file and may be reused. + + If fd is the last copy of a particular file descriptor the + resources associated with it are freed. + +RETURN VALUE + close returns zero on success, or -1 if an error occurred. + +ERRORS + EBADF fd isn't a valid open file descriptor. + + diff --git a/ecos/packages/net/tcpip/current/doc/connect.html b/ecos/packages/net/tcpip/current/doc/connect.html new file mode 100644 index 0000000..b239f8a --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/connect.html @@ -0,0 +1,81 @@ +<html> +<body> +<pre> +NAME + connect - initiate a connection on a socket + +SYNOPSIS + #include <network.h> + + int connect(int sockfd, struct sockaddr *serv_addr, int + addrlen); + +DESCRIPTION + The parameter sockfd is a socket. If the socket is of + type SOCK_DGRAM, this call specifies the peer with which + the socket is to be associated; this address is that to + which datagrams are to be sent, and the only address from + which datagrams are to be received. If the socket is of + type SOCK_STREAM, this call attempts to make a connection + to another socket. The other socket is specified by + serv_addr, which is an address in the communications space + of the socket. Each communications space interprets the + serv_addr parameter in its own way. Generally, stream + sockets may successfully connect only once; datagram sock- + ets may use connect multiple times to change their associ- + ation. Datagram sockets may dissolve the association by + connecting to an address with the sa_family sockaddr mem- + ber set to AF_UNSPEC. + +RETURN VALUE + If the connection or binding succeeds, zero is returned. + On error, -1 is returned, and errno is set appropriately. + +ERRORS + The following are general socket errors only. There may + be other domain-specific error codes. + + EBADF Bad descriptor. + + ENOTSOCK + The descriptor is not associated with a socket. + + EISCONN The socket is already connected. + + ECONNREFUSED + Connection refused at server. + + ETIMEDOUT + Timeout while attempting connection. + + ENETUNREACH + Network is unreachable. + + EADDRINUSE + Address is already in use. + + EINPROGRESS + The socket is non-blocking and the connection can- + not be completed immediately. It is possible to + select(2) or poll(2) for completion by selecting + the socket for writing. After select indicates + writability, use getsockopt(2) to read the + SO_ERROR option at level SOL_SOCKET to determine + whether connect completed successfully (SO_ERROR + is zero) or unsuccessfully (SO_ERROR is one of the + usual error codes listed above, explaining the + reason for the failure). + + EALREADY + The socket is non-blocking and a previous connec- + tion attempt has not yet been completed. + + EAFNOSUPPORT + The passed address didn't have the correct address + family in its sa_family field. + + EACCES The user tried to connect to a broadcast address + without having the socket broadcast flag enabled. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/connect.man b/ecos/packages/net/tcpip/current/doc/connect.man new file mode 100644 index 0000000..e7bc378 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/connect.man @@ -0,0 +1,75 @@ +NAME + connect - initiate a connection on a socket + +SYNOPSIS + #include <network.h> + + int connect(int sockfd, struct sockaddr *serv_addr, int + addrlen); + +DESCRIPTION + The parameter sockfd is a socket. If the socket is of + type SOCK_DGRAM, this call specifies the peer with which + the socket is to be associated; this address is that to + which datagrams are to be sent, and the only address from + which datagrams are to be received. If the socket is of + type SOCK_STREAM, this call attempts to make a connection + to another socket. The other socket is specified by + serv_addr, which is an address in the communications space + of the socket. Each communications space interprets the + serv_addr parameter in its own way. Generally, stream + sockets may successfully connect only once; datagram sock- + ets may use connect multiple times to change their associ- + ation. Datagram sockets may dissolve the association by + connecting to an address with the sa_family sockaddr mem- + ber set to AF_UNSPEC. + +RETURN VALUE + If the connection or binding succeeds, zero is returned. + On error, -1 is returned, and errno is set appropriately. + +ERRORS + The following are general socket errors only. There may + be other domain-specific error codes. + + EBADF Bad descriptor. + + ENOTSOCK + The descriptor is not associated with a socket. + + EISCONN The socket is already connected. + + ECONNREFUSED + Connection refused at server. + + ETIMEDOUT + Timeout while attempting connection. + + ENETUNREACH + Network is unreachable. + + EADDRINUSE + Address is already in use. + + EINPROGRESS + The socket is non-blocking and the connection can- + not be completed immediately. It is possible to + select(2) or poll(2) for completion by selecting + the socket for writing. After select indicates + writability, use getsockopt(2) to read the + SO_ERROR option at level SOL_SOCKET to determine + whether connect completed successfully (SO_ERROR + is zero) or unsuccessfully (SO_ERROR is one of the + usual error codes listed above, explaining the + reason for the failure). + + EALREADY + The socket is non-blocking and a previous connec- + tion attempt has not yet been completed. + + EAFNOSUPPORT + The passed address didn't have the correct address + family in its sa_family field. + + EACCES The user tried to connect to a broadcast address + without having the socket broadcast flag enabled. diff --git a/ecos/packages/net/tcpip/current/doc/ecos_tcpip.html b/ecos/packages/net/tcpip/current/doc/ecos_tcpip.html new file mode 100644 index 0000000..f260dc8 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/ecos_tcpip.html @@ -0,0 +1,88 @@ +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; U; Linux 2.2.10 i686) [Netscape]"> +</head> +<body> + +<center> +<h1> +TCP/IP Networking for eCos</h1></center> +eCos now provides a complete TCP/IP networking stack. This package +was derived from the latest stable release of <a href="http://www.openbsd.org/">OpenBSD</a>. +At this time, the networking support is considered "beta" quality although +it is already fully featured and well tested within the eCos environment. +<p>Ethernet drivers are provided for these standard supported platforms: +<blockquote> +<li> +Motorola PowerPC MBX/860</li> + +<li> +Cirrus Logic EDB72xx</li> +</blockquote> +Other drivers for supported platforms are planned or underway. +<h4> +Networking Stack Features</h4> +Since this networking package is based on the venerable BSD code, it is +very complete and robust. The eCos implementation includes support +for these protocols: +<blockquote> +<li> +IPv4</li> + +<li> +UDP</li> + +<li> +TCP</li> + +<li> +ICMP</li> + +<li> +raw packet interface</li> +</blockquote> +These additional features are also present in the package. However +they are not yet supported: +<blockquote> +<li> +Berkeley Packet Filter</li> + +<li> +Multi-cast and uni-cast support, including multi-casting routing</li> + +<li> +IPv6</li> +</blockquote> + +<h4> +Provided Documentation</h4> +Since the networking package is "beta", documentation is still a bit thin. +However, you will find a complete set of pages documenting the supported +networking functions (user code API) <a href="tcpip_library.html">here</a>. +<h4> +Ethernet Driver Design</h4> +Note: Currently, the networking stack only supports ethernet based networking. +<p>The network drivers use a two-layer design. One layer is hardware +independent but contains all the stack specific code. The other layer +is platform dependent and communicates with the hardware independent layer +via a very simple API. In this way, hardware device drivers can actually +be used with other stacks, if the same API can be provided by that stack. +We designed the drivers this way to encourage the development of other +stacks in eCos while allowing reuse of the actual hardware specific code. +<p>Complete documentation of the ethernet device driver and the associated +API can be found in the file <tt>net/drivers/eth/common/<i>version</i>/doc/driver_doc</tt>. +<h4> +Sample Code</h4> +Many examples using the networking support are provided. These are +arranged as eCos test programs, primarily for us to verify the package, +but also can serve as useful frameworks for program design. We have +taken a <i>KISS </i>approach to building programs which use the network. +A single include file <tt><network.h></tt> is all that is required to +access the stack. A complete, annotated test program can be found +<a href="sample_program.html">here</a>. +<br> +<br> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/gethost.html b/ecos/packages/net/tcpip/current/doc/gethost.html new file mode 100644 index 0000000..4fd252b --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/gethost.html @@ -0,0 +1,110 @@ +<html> +<body> +<pre> +NAME + gethostbyname, gethostbyaddr, herror, hstrerror - get network host entry + +SYNOPSIS + #include <network.h> + + struct hostent *gethostbyname(const char *name); + + struct hostent *gethostbyaddr(const char *addr, int len, int type); + + void herror(const char *s); + + const char * hstrerror(int err); + +DESCRIPTION + The gethostbyname() function returns a structure of type + hostent for the given host name. Here name is either a + host name, or an IPv4 address in standard dot notation, or + an IPv6 address in colon (and possibly dot) notation. (See + RFC 1884 for the description of IPv6 addresses.) If name + is an IPv4 or IPv6 address, no lookup is performed and + gethostbyname() simply copies name into the h_name field + and its struct in_addr equivalent into the h_addr_list[0] + field of the returned hostent structure. If name doesn't + end in a dot and the environment variable HOSTALIASES is + set, the alias file pointed to by HOSTALIASES will first + be searched for name. (See hostname(7) for the file for + mat.) The current domain and its parents are searched + unless name ends in a dot. + + The gethostbyaddr() function returns a structure of type + hostent for the given host address addr of length len and + address type type. The only valid address type is cur + rently AF_INET. + + The (obsolete) herror() function prints the error message + associated with the current value of h_errno on stderr. + + The (obsolete) hstrerror() function takes an error number + (typically h_errno) and returns the corresponding message + string. + + The domain name queries carried out by gethostbyname() and + gethostbyaddr() use a combination of any or all of the + name server named(8), a broken out line from /etc/hosts, + and the Network Information Service (NIS or YP), depending + upon the contents of the order line in /etc/host.conf. + (See resolv+(8)). The default action is to query + named(8), followed by /etc/hosts. + + The hostent structure is defined in <netdb.h> as follows: + + struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses */ + } + #define h_addr h_addr_list[0] /* for backward compatibility */ + + The members of the hostent structure are: + + h_name The official name of the host. + + h_aliases + A zero-terminated array of alternative names for + the host. + + h_addrtype + The type of address; always AF_INET at present. + + h_length + The length of the address in bytes. + + h_addr_list + A zero-terminated array of network addresses for + the host in network byte order. + + h_addr The first address in h_addr_list for backward com + patibility. + +RETURN VALUE + The gethostbyname() and gethostbyaddr() functions return + the hostent structure or a NULL pointer if an error + occurs. On error, the h_errno variable holds an error + number. + +ERRORS + The variable h_errno can have the following values: + + HOST_NOT_FOUND + The specified host is unknown. + + NO_ADDRESS or NO_DATA + The requested name is valid but does not have an IP + address. + + NO_RECOVERY + A non-recoverable name server error occurred. + + TRY_AGAIN + A temporary error occurred on an authoritative name + server. Try again later. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/gethost.man b/ecos/packages/net/tcpip/current/doc/gethost.man new file mode 100644 index 0000000..1de98b9 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/gethost.man @@ -0,0 +1,104 @@ +NAME + gethostbyname, gethostbyaddr, herror, hstrerror - get network host entry + +SYNOPSIS + #include <network.h> + + struct hostent *gethostbyname(const char *name); + + struct hostent *gethostbyaddr(const char *addr, int len, int type); + + void herror(const char *s); + + const char * hstrerror(int err); + +DESCRIPTION + The gethostbyname() function returns a structure of type + hostent for the given host name. Here name is either a + host name, or an IPv4 address in standard dot notation, or + an IPv6 address in colon (and possibly dot) notation. (See + RFC 1884 for the description of IPv6 addresses.) If name + is an IPv4 or IPv6 address, no lookup is performed and + gethostbyname() simply copies name into the h_name field + and its struct in_addr equivalent into the h_addr_list[0] + field of the returned hostent structure. If name doesn't + end in a dot and the environment variable HOSTALIASES is + set, the alias file pointed to by HOSTALIASES will first + be searched for name. (See hostname(7) for the file for + mat.) The current domain and its parents are searched + unless name ends in a dot. + + The gethostbyaddr() function returns a structure of type + hostent for the given host address addr of length len and + address type type. The only valid address type is cur + rently AF_INET. + + The (obsolete) herror() function prints the error message + associated with the current value of h_errno on stderr. + + The (obsolete) hstrerror() function takes an error number + (typically h_errno) and returns the corresponding message + string. + + The domain name queries carried out by gethostbyname() and + gethostbyaddr() use a combination of any or all of the + name server named(8), a broken out line from /etc/hosts, + and the Network Information Service (NIS or YP), depending + upon the contents of the order line in /etc/host.conf. + (See resolv+(8)). The default action is to query + named(8), followed by /etc/hosts. + + The hostent structure is defined in <netdb.h> as follows: + + struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses */ + } + #define h_addr h_addr_list[0] /* for backward compatibility */ + + The members of the hostent structure are: + + h_name The official name of the host. + + h_aliases + A zero-terminated array of alternative names for + the host. + + h_addrtype + The type of address; always AF_INET at present. + + h_length + The length of the address in bytes. + + h_addr_list + A zero-terminated array of network addresses for + the host in network byte order. + + h_addr The first address in h_addr_list for backward com + patibility. + +RETURN VALUE + The gethostbyname() and gethostbyaddr() functions return + the hostent structure or a NULL pointer if an error + occurs. On error, the h_errno variable holds an error + number. + +ERRORS + The variable h_errno can have the following values: + + HOST_NOT_FOUND + The specified host is unknown. + + NO_ADDRESS or NO_DATA + The requested name is valid but does not have an IP + address. + + NO_RECOVERY + A non-recoverable name server error occurred. + + TRY_AGAIN + A temporary error occurred on an authoritative name + server. Try again later. diff --git a/ecos/packages/net/tcpip/current/doc/getpeername.html b/ecos/packages/net/tcpip/current/doc/getpeername.html new file mode 100644 index 0000000..325b75d --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getpeername.html @@ -0,0 +1,40 @@ +<html> +<body> +<pre> +NAME + getpeername - get name of connected peer + +SYNOPSIS + #include <network.h> + + int getpeername(int s, struct sockaddr *name, socklen_t + *namelen); + +DESCRIPTION + Getpeername returns the name of the peer connected to + socket s. The namelen parameter should be initialized to + indicate the amount of space pointed to by name. On + return it contains the actual size of the name returned + (in bytes). The name is truncated if the buffer provided + is too small. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is a file, not a socket. + + ENOTCONN + The socket is not connected. + + ENOBUFS Insufficient resources were available in the sys- + tem to perform the operation. + + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/getpeername.man b/ecos/packages/net/tcpip/current/doc/getpeername.man new file mode 100644 index 0000000..4973dc3 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getpeername.man @@ -0,0 +1,34 @@ +NAME + getpeername - get name of connected peer + +SYNOPSIS + #include <network.h> + + int getpeername(int s, struct sockaddr *name, socklen_t + *namelen); + +DESCRIPTION + Getpeername returns the name of the peer connected to + socket s. The namelen parameter should be initialized to + indicate the amount of space pointed to by name. On + return it contains the actual size of the name returned + (in bytes). The name is truncated if the buffer provided + is too small. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is a file, not a socket. + + ENOTCONN + The socket is not connected. + + ENOBUFS Insufficient resources were available in the sys- + tem to perform the operation. + + diff --git a/ecos/packages/net/tcpip/current/doc/getproto.html b/ecos/packages/net/tcpip/current/doc/getproto.html new file mode 100644 index 0000000..61eaf65 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getproto.html @@ -0,0 +1,48 @@ +<html> +<body> +<pre> +NAME + getprotobyname, getprotobynumber - get protocol entry + +SYNOPSIS + #include <network.h> + + struct protoent *getprotobyname(const char *name); + + struct protoent *getprotobynumber(int proto); + +DESCRIPTION + The getprotobyname() function returns a protoent structure + for the line from /etc/protocols that matches the protocol + name name. + + The getprotobynumber() function returns a protoent struc + ture for the line that matches the protocol number number. + + The protoent structure is defined in <netdb.h> as follows: + + struct protoent { + char *p_name; /* official protocol name */ + char **p_aliases; /* alias list */ + int p_proto; /* protocol number */ + } + + The members of the protoent structure are: + + p_name The official name of the protocol. + + p_aliases + A zero terminated list of alternative names for the + protocol. + p_proto + The protocol number. + +RETURN VALUE + The getprotobyname() and getprotobynumber() + functions return the protoent structure, or a NULL pointer + if an error occurs. + + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/getproto.man b/ecos/packages/net/tcpip/current/doc/getproto.man new file mode 100644 index 0000000..4286b88 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getproto.man @@ -0,0 +1,42 @@ +NAME + getprotobyname, getprotobynumber - get protocol entry + +SYNOPSIS + #include <network.h> + + struct protoent *getprotobyname(const char *name); + + struct protoent *getprotobynumber(int proto); + +DESCRIPTION + The getprotobyname() function returns a protoent structure + for the line from /etc/protocols that matches the protocol + name name. + + The getprotobynumber() function returns a protoent struc + ture for the line that matches the protocol number number. + + The protoent structure is defined in <netdb.h> as follows: + + struct protoent { + char *p_name; /* official protocol name */ + char **p_aliases; /* alias list */ + int p_proto; /* protocol number */ + } + + The members of the protoent structure are: + + p_name The official name of the protocol. + + p_aliases + A zero terminated list of alternative names for the + protocol. + p_proto + The protocol number. + +RETURN VALUE + The getprotobyname() and getprotobynumber() + functions return the protoent structure, or a NULL pointer + if an error occurs. + + diff --git a/ecos/packages/net/tcpip/current/doc/getserv.html b/ecos/packages/net/tcpip/current/doc/getserv.html new file mode 100644 index 0000000..68562ee --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getserv.html @@ -0,0 +1,54 @@ +<html> +<body> +<pre> +NAME + getservent, getservbyname, getservbyport - get service entry + +SYNOPSIS + #include <network.h> + + struct servent *getservbyname(const char *name, const char *proto); + + struct servent *getservbyport(int port, const char *proto); + +DESCRIPTION + The getservbyname() function returns a servent structure + for the line from /etc/services that matches the service + name using protocol proto. + + The getservbyport() function returns a servent structure + for the line that matches the port port given in network + byte order using protocol proto. + + The servent structure is defined in <netdb.h> as follows: + + struct servent { + char *s_name; /* official service name */ + char **s_aliases; /* alias list */ + int s_port; /* port number */ + char *s_proto; /* protocol to use */ + } + + The members of the servent structure are: + + s_name The official name of the service. + + s_aliases + A zero terminated list of alternative names for the + service. + + s_port The port number for the service given in network + byte order. + + s_proto + The name of the protocol to use with this service. + +RETURN VALUE + The getservbyname() and getservbyport() + functions return the servent structure, or a NULL pointer + if an error occurs. + + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/getserv.man b/ecos/packages/net/tcpip/current/doc/getserv.man new file mode 100644 index 0000000..3c32189 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getserv.man @@ -0,0 +1,48 @@ +NAME + getservent, getservbyname, getservbyport - get service entry + +SYNOPSIS + #include <network.h> + + struct servent *getservbyname(const char *name, const char *proto); + + struct servent *getservbyport(int port, const char *proto); + +DESCRIPTION + The getservbyname() function returns a servent structure + for the line from /etc/services that matches the service + name using protocol proto. + + The getservbyport() function returns a servent structure + for the line that matches the port port given in network + byte order using protocol proto. + + The servent structure is defined in <netdb.h> as follows: + + struct servent { + char *s_name; /* official service name */ + char **s_aliases; /* alias list */ + int s_port; /* port number */ + char *s_proto; /* protocol to use */ + } + + The members of the servent structure are: + + s_name The official name of the service. + + s_aliases + A zero terminated list of alternative names for the + service. + + s_port The port number for the service given in network + byte order. + + s_proto + The name of the protocol to use with this service. + +RETURN VALUE + The getservbyname() and getservbyport() + functions return the servent structure, or a NULL pointer + if an error occurs. + + diff --git a/ecos/packages/net/tcpip/current/doc/getsockname.html b/ecos/packages/net/tcpip/current/doc/getsockname.html new file mode 100644 index 0000000..1aa848b --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getsockname.html @@ -0,0 +1,37 @@ +<html> +<body> +<pre> +NAME + getsockname - get socket name + +SYNOPSIS + #include <network.h> + + int getsockname(int s , struct sockaddr * name , + socklen_t * namelen ) + +DESCRIPTION + Getsockname returns the current name for the specified + socket. The namelen parameter should be initialized to + indicate the amount of space pointed to by name. On + return it contains the actual size of the name returned + (in bytes). + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. A 0 is returned if the + call succeeds, -1 if it fails. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is a file, not a socket. + + ENOBUFS Insufficient resources were available in the sys- + tem to perform the operation. + + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/getsockname.man b/ecos/packages/net/tcpip/current/doc/getsockname.man new file mode 100644 index 0000000..b281313 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getsockname.man @@ -0,0 +1,31 @@ +NAME + getsockname - get socket name + +SYNOPSIS + #include <network.h> + + int getsockname(int s , struct sockaddr * name , + socklen_t * namelen ) + +DESCRIPTION + Getsockname returns the current name for the specified + socket. The namelen parameter should be initialized to + indicate the amount of space pointed to by name. On + return it contains the actual size of the name returned + (in bytes). + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. A 0 is returned if the + call succeeds, -1 if it fails. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is a file, not a socket. + + ENOBUFS Insufficient resources were available in the sys- + tem to perform the operation. + + diff --git a/ecos/packages/net/tcpip/current/doc/getsockopt.html b/ecos/packages/net/tcpip/current/doc/getsockopt.html new file mode 100644 index 0000000..39bfdaa --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getsockopt.html @@ -0,0 +1,70 @@ +<html> +<body> +<pre> +NAME + getsockopt, setsockopt - get and set options on sockets + +SYNOPSIS + #include <network.h> + + int getsockopt(int s, int level, int optname, void *opt + val, socklen_t *optlen); + + int setsockopt(int s, int level, int optname, const void + *optval, socklen_t optlen); + +DESCRIPTION + Getsockopt and setsockopt manipulate the options associ + ated with a socket. Options may exist at multiple proto + col levels; they are always present at the uppermost + socket level. + + When manipulating socket options the level at which the + option resides and the name of the option must be speci + fied. To manipulate options at the socket level, level is + specified as SOL_SOCKET. To manipulate options at any + other level the protocol number of the appropriate proto + col controlling the option is supplied. For example, to + indicate that an option is to be interpreted by the TCP + protocol, level should be set to the protocol number of + TCP; see getprotoent(3). + + The parameters optval and optlen are used to access option + values for setsockopt. For getsockopt they identify a + buffer in which the value for the requested option(s) are + to be returned. For getsockopt, optlen is a value-result + parameter, initially containing the size of the buffer + pointed to by optval, and modified on return to indicate + the actual size of the value returned. If no option value + is to be supplied or returned, optval may be NULL. + + Optname and any specified options are passed uninterpreted + to the appropriate protocol module for interpretation. + The include file <network.h> contains definitions for + socket level options, described below. Options at other + protocol levels vary in format and name; consult the + appropriate entries in section 4 of the manual. + + Most socket-level options utilize an int parameter for + optval. For setsockopt, the parameter should be non-zero + to enable a boolean option, or zero if the option is to be + disabled. + + For a description of the available socket options see + socket(7) and the appropriate protocol man pages. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is a file, not a socket. + + ENOPROTOOPT + The option is unknown at the level indicated. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/getsockopt.man b/ecos/packages/net/tcpip/current/doc/getsockopt.man new file mode 100644 index 0000000..e2c7173 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/getsockopt.man @@ -0,0 +1,65 @@ +NAME + getsockopt, setsockopt - get and set options on sockets + +SYNOPSIS + #include <network.h> + + + int getsockopt(int s, int level, int optname, void *opt + val, socklen_t *optlen); + + int setsockopt(int s, int level, int optname, const void + *optval, socklen_t optlen); + +DESCRIPTION + Getsockopt and setsockopt manipulate the options associ + ated with a socket. Options may exist at multiple proto + col levels; they are always present at the uppermost + socket level. + + When manipulating socket options the level at which the + option resides and the name of the option must be speci + fied. To manipulate options at the socket level, level is + specified as SOL_SOCKET. To manipulate options at any + other level the protocol number of the appropriate proto + col controlling the option is supplied. For example, to + indicate that an option is to be interpreted by the TCP + protocol, level should be set to the protocol number of + TCP; see getprotoent(3). + + The parameters optval and optlen are used to access option + values for setsockopt. For getsockopt they identify a + buffer in which the value for the requested option(s) are + to be returned. For getsockopt, optlen is a value-result + parameter, initially containing the size of the buffer + pointed to by optval, and modified on return to indicate + the actual size of the value returned. If no option value + is to be supplied or returned, optval may be NULL. + + Optname and any specified options are passed uninterpreted + to the appropriate protocol module for interpretation. + The include file <sys/socket.h> contains definitions for + socket level options, described below. Options at other + protocol levels vary in format and name; consult the + appropriate entries in section 4 of the manual. + + Most socket-level options utilize an int parameter for + optval. For setsockopt, the parameter should be non-zero + to enable a boolean option, or zero if the option is to be + disabled. + + For a description of the available socket options see + socket(7) and the appropriate protocol man pages. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is a file, not a socket. + + ENOPROTOOPT + The option is unknown at the level indicated. diff --git a/ecos/packages/net/tcpip/current/doc/index.html b/ecos/packages/net/tcpip/current/doc/index.html new file mode 100644 index 0000000..a51cc9f --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/index.html @@ -0,0 +1,27 @@ +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; I; Linux 2.2.14 ppc) [Netscape]"> +</head> +<body> + +<center> +<h1> +eCos TCP/IP Networking Documentation (beta)</h1></center> + +<li> +<a href="ecos_tcpip.html">Introduction</a></li> + +<li> +<a href="tcpip_library.html">Library Reference</a></li> + +<li> +<a href="tcpip_config.html">Configuration</a></li> + +<li> +<a href="tcpip_tests.html">Tests and Examples</a></li> + +<br> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/inet_addr.html b/ecos/packages/net/tcpip/current/doc/inet_addr.html new file mode 100644 index 0000000..b8cca4e --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/inet_addr.html @@ -0,0 +1,40 @@ +<html> +<body> +<pre> +NAME + inet_aton, inet_addr, inet_ntoa - Internet address + manipulation routines + +SYNOPSIS + #include <network.h> + + int inet_aton(const char *cp, struct in_addr *inp); + + unsigned long int inet_addr(const char *cp); + + char *inet_ntoa(struct in_addr in); + +DESCRIPTION + inet_aton() converts the Internet host address cp from the + standard numbers-and-dots notation into binary data and + stores it in the structure that inp points to. inet_aton + returns nonzero if the address is valid, zero if not. + + The inet_addr() function converts the Internet host + address cp from numbers-and-dots notation into binary data + in network byte order. If the input is invalid, + INADDR_NONE (usually -1) is returned. This is an obsolete + interface to inet_aton, described immediately above; it is + obsolete because -1 is a valid address (255.255.255.255), + and inet_aton provides a cleaner way to indicate error + return. + + The inet_ntoa() function converts the Internet host + address in given in network byte order to a string in + standard numbers-and-dots notation. The string is + returned in a statically allocated buffer, which subse + quent calls will overwrite. + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/inet_addr.man b/ecos/packages/net/tcpip/current/doc/inet_addr.man new file mode 100644 index 0000000..ddfd725 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/inet_addr.man @@ -0,0 +1,34 @@ +NAME + inet_aton, inet_addr, inet_ntoa - Internet address + manipulation routines + +SYNOPSIS + #include <network.h> + + int inet_aton(const char *cp, struct in_addr *inp); + + unsigned long int inet_addr(const char *cp); + + char *inet_ntoa(struct in_addr in); + +DESCRIPTION + inet_aton() converts the Internet host address cp from the + standard numbers-and-dots notation into binary data and + stores it in the structure that inp points to. inet_aton + returns nonzero if the address is valid, zero if not. + + The inet_addr() function converts the Internet host + address cp from numbers-and-dots notation into binary data + in network byte order. If the input is invalid, + INADDR_NONE (usually -1) is returned. This is an obsolete + interface to inet_aton, described immediately above; it is + obsolete because -1 is a valid address (255.255.255.255), + and inet_aton provides a cleaner way to indicate error + return. + + The inet_ntoa() function converts the Internet host + address in given in network byte order to a string in + standard numbers-and-dots notation. The string is + returned in a statically allocated buffer, which subse + quent calls will overwrite. + diff --git a/ecos/packages/net/tcpip/current/doc/ioctl.html b/ecos/packages/net/tcpip/current/doc/ioctl.html new file mode 100644 index 0000000..216b8c1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/ioctl.html @@ -0,0 +1,46 @@ +<html> +<body> +<pre> +NAME + ioctl - control device + +SYNOPSIS + #include <sys/ioctl.h> + + int ioctl(int d, int request, ...) + + [The "third" argument is traditionally char *argp, and + will be so named for this discussion.] + +DESCRIPTION + The ioctl function manipulates the underlying device + parameters of special files. In particular, many operat- + ing characteristics of sockets and network devices + may be controlled with ioctl requests. The argu- + ment d must be an open file descriptor. + + An ioctl request has encoded in it whether the argument is + an in parameter or out parameter, and the size of the + argument argp in bytes. Macros and defines used in speci- + fying an ioctl request are located in the file + <sys/ioctl.h>. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF d is not a valid descriptor. + + EFAULT argp references an inaccessible memory area. + + ENOTTY d is not associated with a character special + device. + + ENOTTY The specified request does not apply to the kind of + object that the descriptor d references. + + EINVAL Request or argp is not valid. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/ioctl.man b/ecos/packages/net/tcpip/current/doc/ioctl.man new file mode 100644 index 0000000..eac5cdf --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/ioctl.man @@ -0,0 +1,40 @@ +NAME + ioctl - control device + +SYNOPSIS + #include <sys/ioctl.h> + + int ioctl(int d, int request, ...) + + [The "third" argument is traditionally char *argp, and + will be so named for this discussion.] + +DESCRIPTION + The ioctl function manipulates the underlying device + parameters of special files. In particular, many operat- + ing characteristics of sockets and network devices + may be controlled with ioctl requests. The argu- + ment d must be an open file descriptor. + + An ioctl request has encoded in it whether the argument is + an in parameter or out parameter, and the size of the + argument argp in bytes. Macros and defines used in speci- + fying an ioctl request are located in the file + <sys/ioctl.h>. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF d is not a valid descriptor. + + EFAULT argp references an inaccessible memory area. + + ENOTTY d is not associated with a character special + device. + + ENOTTY The specified request does not apply to the kind of + object that the descriptor d references. + + EINVAL Request or argp is not valid. diff --git a/ecos/packages/net/tcpip/current/doc/listen.html b/ecos/packages/net/tcpip/current/doc/listen.html new file mode 100644 index 0000000..1e83775 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/listen.html @@ -0,0 +1,42 @@ +<html> +<body> +<pre> +NAME + listen - listen for connections on a socket + +SYNOPSIS + #include <network.h> + + int listen(int s, int backlog); + +DESCRIPTION + To accept connections, a socket is first created with + socket(2), a willingness to accept incoming connections + and a queue limit for incoming connections are specified + with listen, and then the connections are accepted with + accept(2). The listen call applies only to sockets of + type SOCK_STREAM or SOCK_SEQPACKET. + + The backlog parameter defines the maximum length the queue + of pending connections may grow to. If a connection + request arrives with the queue full the client may receive + an error with an indication of ECONNREFUSED or, if the + underlying protocol supports retransmission, the request + may be ignored so that retries may succeed. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is not a socket. + + EOPNOTSUPP + The socket is not of a type that supports the lis- + ten operation. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/listen.man b/ecos/packages/net/tcpip/current/doc/listen.man new file mode 100644 index 0000000..3068ce3 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/listen.man @@ -0,0 +1,36 @@ +NAME + listen - listen for connections on a socket + +SYNOPSIS + #include <network.h> + + int listen(int s, int backlog); + +DESCRIPTION + To accept connections, a socket is first created with + socket(2), a willingness to accept incoming connections + and a queue limit for incoming connections are specified + with listen, and then the connections are accepted with + accept(2). The listen call applies only to sockets of + type SOCK_STREAM or SOCK_SEQPACKET. + + The backlog parameter defines the maximum length the queue + of pending connections may grow to. If a connection + request arrives with the queue full the client may receive + an error with an indication of ECONNREFUSED or, if the + underlying protocol supports retransmission, the request + may be ignored so that retries may succeed. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is not a socket. + + EOPNOTSUPP + The socket is not of a type that supports the lis- + ten operation. diff --git a/ecos/packages/net/tcpip/current/doc/openbsd-manpages-bridge.sgml b/ecos/packages/net/tcpip/current/doc/openbsd-manpages-bridge.sgml new file mode 100644 index 0000000..2db2cb2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/openbsd-manpages-bridge.sgml @@ -0,0 +1,450 @@ +<!-- {{{ Banner --> +<!-- All of the documentation and software included in the second BSD Networking --> +<!-- Software Release is copyrighted by The Regents of the University of California. --> + +<!-- Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991 The Regents of the --> +<!-- University of California. --> +<!-- All rights reserved. --> + +<!-- Redistribution and use in source and binary forms, with or without --> +<!-- modification, are permitted provided that the following conditions --> +<!-- are met: --> +<!-- 1. Redistributions of source code must retain the above copyright --> +<!-- notice, this list of conditions and the following disclaimer. --> +<!-- 2. Redistributions in binary form must reproduce the above copyright --> +<!-- notice, this list of conditions and the following disclaimer in the --> +<!-- documentation and/or other materials provided with the distribution. --> +<!-- 3. Neither the name of the University nor the names of its contributors --> +<!-- may be used to endorse or promote products derived from this software --> +<!-- without specific prior written permission. --> + +<!-- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND --> +<!-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE --> +<!-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE --> +<!-- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE --> +<!-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL --> +<!-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS --> +<!-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) --> +<!-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT --> +<!-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY --> +<!-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF --> +<!-- SUCH DAMAGE. --> + +<!-- =============================================================== --> +<!-- --> +<!-- openbsd_bridge.sgml --> +<!-- --> +<!-- eCos TCP/IP Stacks --> +<!-- --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTBEGIN#### --> +<!-- =============================================================== --> +<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<SECT1 id="openbsd-manpages-bridge"> +<TITLE>Bridging</TITLE> +<SCREEN> + +NAME + bridge - Ethernet bridge interface + +SYNOPSIS + pseudo-device bridge + +DESCRIPTION + The bridge device creates a logical link between two or more Ethernet + interfaces. This link between the interfaces selectively forwards + frames from each interface on the bridge to every other interface on + the bridge. A bridge can serve several services, including isolation + of traffic between sets of machines so that traffic local to one set of + machines is not available on the wire of another set of machines, and + it can act as a transparent filter for ip4 datagrams. + + The bridges provided by this interface are learning bridges with filter- + ing. In general a bridge works like a hub, forwarding traffic from one + interface to another. It differs from a hub in that it will "learn" which + machines are on each of its attached segments by actively listening to + incoming traffic and examining the headers of each frame. A table is + built containing the MAC address and segment to which the MAC address is + attached. This allows a bridge to be more selective about what it + forwards, which can be used to reduce traffic on a set of segments and + also to provide an IP firewall without changing the topology of the + network. + + The algorithm works as follows by default, but can be modified via ioctl. + When a frame comes in, the origin segment and the source address are + recorded. If the bridge has no knowledge about where the destination is + to be found, the bridge will forward the frame to all attached segments. + If the destination is known to be on a different segment from its origin, + the bridge will forward the packet only to the destination segment. If the + destination is on the same segment as the origin segment, the bridge will + drop the packet because the receiver has already had a chance to see the + frame. + +IOCTLS + A bridge interface responds to all of the ioctl calls specific to oth- + er interfaces listed in <link linkend="openbsd-manpages-netintro">netintro</link>. The following ioctl calls are + specific to bridge devices. They are defined in <sys/sockio.h>. + + SIOCBRDGIFS (struct ifbifconf) Retrieve member interface list from a + bridge. This request takes an ifbifconf structure (see + below) as a value-result parameter. The ifbic_len field + should be initially set to the size of the buffer point- + ed to by ifbic_buf. On return it will contain the + length, in bytes, of the configuration list. Alterna- + tively, if the ifbic_len passed in is set to 0, + SIOCBRDGIFS will set ifbic_len to the size that + ifbic_buf needs to be to fit the entire configuration + list, and will not fill in the other parameters. This + is useful for determining the exact size that ifbic_buf + needs to be in advance. + + The argument structure is defined as follows: + + struct ifbreq { + char ifbr_name[IFNAMSIZ]; /* brdg nam */ + char ifbr_ifsname[IFNAMSIZ]; /* if name */ + u_int32_t ifbr_ifsflags; /* if flags */ + u_int8_t ifbr_state; /* member stp state */ + u_int8_t ifbr_priority; /* member stp priority */ + u_int8_t ifbr_portno; /* member port number */ + u_int32_t ifbr_path_cost; /* member stp path cost */ + }; + /* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */ + #define IFBIF_LEARNING 0x0001 /* ifs can learn */ + #define IFBIF_DISCOVER 0x0002 /* ifs sends packets w/unknown dest */ + #define IFBIF_BLOCKNONIP 0x0004 /* ifs blocks non-IP/ARP in/out */ + #define IFBIF_STP 0x0008 /* ifs participates in spanning tree */ + #define IFBIF_SPAN 0x0100 /* ifs is a span port (ro) */ + #define IFBIF_RO_MASK 0xff00 /* read only bits */ + + struct ifbifconf { + char ifbic_name[IFNAMSIZ]; /* brdg name */ + u_int32_t ifbic_len; /* buf size */ + union { + caddr_t ifbicu_buf; /* buffer */ + struct ifbreq *ifbicu_req; + } ifbic_ifbicu; + #define ifbic_buf ifbic_ifbicu.ifbicu_buf + #define ifbic_req ifbic_ifbicu.ifbicu_req + }; + + SIOCBRDGADD (struct ifbreq) Add the interface named in ifbr_ifsname + to the bridge named in ifbr_name. + + SIOCBRDGDEL (struct ifbreq) Delete the interface named in + ifbr_ifsname from the bridge named in ifbr_name. + + SIOCBRDGADDS (struct ifbreq) Add the interface named in ifbr_ifsname + as a span port to the bridge named in ifbr_name. + + SIOCBRDGDELS (struct ifbreq) Delete the interface named in + ifbr_ifsname from the list of span ports of the bridge + named in ifbr_name. + + SIOCBRDGSIFFLGS (struct ifbreq) Set the bridge member interface flags + for the interface named in ifbr_ifsname attached to the + bridge ifbr_name. If the flag IFBIF_LEARNING is set on + an interface, source addresses from frames received on + the interface are recorded in the address cache. If the + flag IFBIF_DISCOVER is set, the interface will receive + packets destined for unknown destinations, otherwise a + frame that has a destination not found in the address + cache is not forwarded to this interface. The default + for newly added interfaces has both flags set. If the + flag IFBIF_BLOCKNONIP is set, packets that are one of + ip(4), ip6(4), arp(4), or Reverse ARP, will not be + bridged from and to the interface. + + SIOCBRDGGIFFLGS Retrieve the bridge member interface flags for the in- + terface named in ifbr_ifsname attached to the bridge + ifbr_name. + + SIOCBRDGRTS (struct ifbaconf) Retrieve the address cache of the + bridge named in ifbac_name. This request takes an + ifbaconf structure (see below) as a value result parame- + ter. The ifbac_len field should be initially set to the + size of the buffer pointed to by ifbac_buf. On return, + it will contain the length, in bytes, of the configura- + tion list. Alternatively, if the ifbac_len passed in is + set to 0, SIOCBRDGRTS will set it to the size that + ifbac_buf needs to be to fit the entire configuration + list and not fill in the other parameters. As with + SIOCBRDGIFS, this is useful for determining the exact + size that ifbac_buf needs to be in advance. + + The argument structure is defined as follows: + + struct ifbareq { + char ifba_name[IFNAMSIZ]; /* brdg nam */ + char ifba_ifsname[IFNAMSIZ];/* dest ifs */ + u_int8_t ifba_age; /* addr age */ + u_int8_t ifba_flags; /* addr flag */ + struct ether_addr ifba_dst; /* dst addr */ + }; + + #define IFBAF_TYPEMASK 0x03 /* addr type mask */ + #define IFBAF_DYNAMIC 0x00 /* dynamic addr */ + #define IFBAF_STATIC 0x01 /* static address */ + + struct ifbaconf { + char ifbac_name[IFNAMSIZ]; /* brdg name */ + u_int32_t ifbac_len; /* buf size */ + union { + caddr_t ifbacu_buf; /* buf */ + struct ifbareq *ifbacu_req; + } ifbac_ifbacu; + #define ifbac_buf ifbac_ifbacu.ifbacu_buf + #define ifbac_req ifbac_ifbacu.ifbacu_req + }; + Address cache entries with the type set to IFBAF_DYNAMIC + in ifba_flags are entries learned by the bridge. En- + tries with the type set to IFBAF_STATIC are manually + added entries. + + SIOCBRDGSADDR (struct ifbareq) Add an entry, manually, to the address + cache for the bridge named in ifba_name. The address + and its associated interface and flags are set in the + ifba_dst, ifba_ifsname, and ifba_flags fields, respec- + tively. + + SIOCBRDGDADDR (struct ifbareq) Delete an entry from the address cache + of the bridge named in ifba_name. Entries are deleted + strictly based on the address field ifba_dst. + + SIOCBRDGSCACHE (struct ifbcachereq) Set the maximum address cache size + for the bridge named in ifbc_name to ifbc_size entries. + + The argument structure is as follows: + + struct ifbcachereq { + char ifbc_name[IFNAMSIZ]; /* bridge */ + u_int32_t ifbc_size; /* size */ + }; + + SIOCBRDGGCACHE (struct ifbcachereq) Retrieve the maximum size of the + address cache for the bridge ifbc_name. + + SIOCBRDGSTO (struct ifbcachetoreq) Set the time, in seconds, that + addresses which have not been seen on the network + (transmitted a packet) remain in the cache. If the time + is set to zero, no aging is performed on the address + cache. The argument structure is as follows: + + struct ifbcachetoreq { + char ifbct_name[IFNAMSIZ]; /* bridge */ + u_int32_t ifbct_time; /* time */ + }; + + SIOCBRDGGTO (struct ifbcachetoreq) Retrieve the address cache expi- + ration time (see above). + + SIOCBRDGFLUSH (struct ifbreq) Flush addresses from the cache. + ifbr_name contains the name of the bridge device, and + ifbr_ifsflags should be set to IFBF_FLUSHALL to flush + all addresses from the cache or IFBF_FLUSHDYN to flush + only the dynamically learned addresses from the cache. + + SIOCBRDGARL (struct ifbrlreq) Add an Ethernet address filtering rule + to the bridge on a specific interface. ifbr_name con- + tains the name of the bridge device, and ifbr_ifsname + contains the name of the bridge member interface. The + ifbr_action field is one of BRL_ACTION_PASS or + BRL_ACTION_BLOCK, to pass or block matching frames re- + spectively. The ifbr_flags specifies whether the rule + should match on input, output, or both be using the + flags BRL_FLAG_IN and BRL_FLAG_OUT. It also specifies + whether either (or both) of the source and destination + addresses should be matched by using the + BRL_FLAG_SRCVALID and BRL_FLAG_DSTVALID flags. The + ifbr_src field is the source address that triggers the + rule (only considered if ifbr_flags has the + BRL_FLAG_SRCVALID bit set). The ifbr_src field is the + destination address that triggers the rule (only consid- + ered if ifbr_flags has the BRL_FLAG_DSTVALID bit set). + + The argument structure is as follows: + + struct ifbrlreq { + char ifbr_name[IFNAMSIZ]; + char ifbr_ifsname[IFNAMSIZ]; + u_int8_t ifbr_action; + u_int8_t ifbr_flags; + struct ether_addr ifbr_src; + struct ether_addr ifbr_dst; + char ifbr_tagname[PF_TAG_NAME_SIZE]; + }; + #define BRL_ACTION_BLOCK 0x01 + #define BRL_ACTION_PASS 0x02 + #define BRL_FLAG_IN 0x08 + #define BRL_FLAG_OUT 0x04 + + SIOCBRDGFRL (struct ifbrlreq) Remove all filtering rules from a + bridge interface member. ifbr_name contains the name of + the bridge device, and ifbr_ifsname contains the name of + the bridge member interface. + + SIOCBRDGGRL (struct ifbrlconf) Retrieve all of the rules from the + bridge, ifbrl_name, for the member interface, + ifbrl_ifsname. This request takes an ifbrlconf struc- + ture (see below) as a value result parameter. The + ifbrl_len field should be initially set to the size of + the buffer pointed to by ifbrl_buf. On return, it will + contain the length, in bytes, of the configuration list. + Alternatively, if the ifbrl_len passed in is set to 0, + SIOCBRDGGRL will set it to the size that ifbrl_buf needs + to be to fit the entire configuration list and not fill + in the other parameters. As with SIOCBRDGIFS, this is + useful for determining the exact size that ifbrl_buf + needs to be in advance. + + The argument structure is defined as follows: + + struct ifbrlconf { + char ifbrl_name[IFNAMSIZ]; /* brdg nam */ + char ifbrl_ifsname[IFNAMSIZ];/* ifs name */ + u_int32_t ifbr_len; /* buf len */ + union { + caddr_t ifbrlu_buf; + struct ifbrlreq *ifbrlu_req; + } ifrl_ifbrlu; + #define ifbrl_buf ifbrl_ifbrlu.ifbrlu_buf + #define ifbrl_req ifbrl_ifbrlu.ifbrlu_req + }; + + SIOCBRDGARL (struct ifbrlreq) Add a filtering rule to the bridge + named in ifbr_name on the interface named in + ifbr_ifsname. The argument structure is as follows: + + struct ifbrlreq { + char ifbr_name[IFNAMSIZ]; /* bridge */ + char ifbr_ifsname[IFNAMSIZ]; /* ifs */ + u_int8_t ifbr_action; /* handling */ + u_int8_t ifbr_flags; /* flags */ + struct ether_addr ifbr_src; /* src mac */ + struct ether_addr ifbr_dst; /* dst mac */ + }; + #define BRL_ACTION_BLOCK 0x01 + #define BRL_ACTION_PASS 0x02 + #define BRL_FLAG_IN 0x08 + #define BRL_FLAG_OUT 0x04 + #define BRL_FLAG_SRCVALID 0x02 + #define BRL_FLAG_DSTVALID 0x01 + + Rules are applied in the order in which they were added + to the bridge, and the first matching rule's action pa- + rameter determines the fate of the packet. The + ifbr_action parameter specifies whether a frame matching + the rule is to be blocked or passed. + + If the BRL_FLAG_IN bit is set in ifbr_flags, then the + rule applies to frames received by the interface. If + the BRL_FLAG_OUT bit is set, then the rule applies to + frame transmitted by the interface. At least one of + BRL_FLAG_IN or BRL_FLAG_OUT must be set. + + The source Ethernet address in ifbr_src is checked if + the BRL_FLAG_SRCVALID bit is set in ifbr_flags. The + destination address in ifbr_dst is checked if the + BRL_FLAG_DSTVALID bit is set. If neither bit is set, + the rule matches all frames. + + SIOCBRDGFRL (struct ifbrlreq) Flush rules from the bridge ifbr_name + on the interface ifbr_ifsname. + + SIOCBRDGGRL (struct ifbrlconf) Retrieve an array of rules from the + bridge for a particular interface. This request takes + an ifbrlconf structure (see below) as a value-result pa- + rameter. The ifbrl_len field should be initially set to + the size of the buffer pointed to by ifbrl_buf. On re- + turn it will contain the length, in bytes, of the rule + list. Alternatively, if the ifbrl_len passed in is set + to 0, SIOCBRDGGRL will set ifbrl_len to the size that + ifbrl_buf needs to be to fit the entire configuration + list, and will not fill in the other parameters. This + is useful for determining the exact size that ifbrl_buf + needs to be in advance. + + The argument structure is as follows: + + struct ifbrlconf { + char ifbrl_name[IFNAMSIZ]; /* bridge */ + char ifbrl_ifsname[IFNAMSIZ];/* member */ + u_int32_t ifbrl_len; /* buflen */ + union { + caddr_t ifbrlu_buf; + struct ifbrlreq *ifbrlu_req; + } ifbrl_ifbrlu; + #define ifbrl_buf ifbrl_ifbrlu.ifbrlu_buf + #define ifbrl_req ifbrl_ifbrlu.ifbrlu_req + }; + +ERRORS + If the ioctl call fails, errno is set to one of the following values: + + [ENOENT] For an add request, this means that the named interface is + not configured into the system. For a delete operation, it + means that the named interface is not a member of the + bridge. For an address cache deletion, the address was not + found in the table. + + [ENOMEM] Memory could not be allocated for an interface or cache en- + try to be added to the bridge. + + [EEXIST] The named interface is already a member of the bridge. + + [EBUSY] The named interface is already a member of another bridge. + + [EINVAL] The named interface is not an Ethernet interface or an in- + valid ioctl was performed on the bridge. + + [ENETDOWN] Address cache operation (flush, add, delete) on a bridge + that is in the down state. + + [ESRCH] No such member interface in the bridge. + +SEE ALSO + <link linkend="openbsd-manpages-netintro">netintro</link>, <link linkend="openbsd-manpages-stp">spanning-tree</link> + +AUTHORS + The bridge kernel interface was written by Jason L. Wright + <jason@thought.net> as part of an undergraduate independent study at + the University of North Carolina at Greensboro. + +</SCREEN> +</SECT1> + +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:nil +sgml-shorttag:t +sgml-namecase-general:t +sgml-general-insert-case:lower +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:2 +sgml-indent-data:t +sgml-parent-document:("tcpip.sgml" "book" "chapter") +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +sgml-doctype:"book" +End: +--> diff --git a/ecos/packages/net/tcpip/current/doc/openbsd-manpages-netintro.sgml b/ecos/packages/net/tcpip/current/doc/openbsd-manpages-netintro.sgml new file mode 100644 index 0000000..b1e3173 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/openbsd-manpages-netintro.sgml @@ -0,0 +1,308 @@ +<!-- {{{ Banner --> + +<!-- All of the documentation and software included in the second BSD Networking --> +<!-- Software Release is copyrighted by The Regents of the University of California. --> + +<!-- Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991 The Regents of the --> +<!-- University of California. --> +<!-- All rights reserved. --> + +<!-- Redistribution and use in source and binary forms, with or without --> +<!-- modification, are permitted provided that the following conditions --> +<!-- are met: --> +<!-- 1. Redistributions of source code must retain the above copyright --> +<!-- notice, this list of conditions and the following disclaimer. --> +<!-- 2. Redistributions in binary form must reproduce the above copyright --> +<!-- notice, this list of conditions and the following disclaimer in the --> +<!-- documentation and/or other materials provided with the distribution. --> +<!-- 3. Neither the name of the University nor the names of its contributors --> +<!-- may be used to endorse or promote products derived from this software --> +<!-- without specific prior written permission. --> + +<!-- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND --> +<!-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE --> +<!-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE --> +<!-- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE --> +<!-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL --> +<!-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS --> +<!-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) --> +<!-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT --> +<!-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY --> +<!-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF --> +<!-- SUCH DAMAGE. --> + +<!-- =============================================================== --> +<!-- --> +<!-- openbsd_netintro.sgml --> +<!-- --> +<!-- eCos TCP/IP Stacks --> +<!-- --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTBEGIN#### --> +<!-- =============================================================== --> +<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<SECT1 id="openbsd-manpages-netintro"> +<TITLE>OpenBSD networking facilities</TITLE> +<SCREEN> + +NAME + networking - introduction to networking facilities + +SYNOPSIS + #include <sys/socket.h> + #include <net/route.h> + #include <net/if.h> + +DESCRIPTION + This section is a general introduction to the networking facilities + available in the system. The general introduction on this page is + broken up into three areas: protocol families (domains), protocols, + and network interfaces. + + All network protocols are associated with a specific protocol family. A + protocol family provides basic services to the protocol implementation + to allow it to function within a specific network environment. These + services may include packet fragmentation and reassembly, routing, + addressing, and basic transport. A protocol family may support multiple + methods of addressing, though the current protocol implementations do not. + A protocol family is normally comprised of a number of protocols, one per + <link linkend="net-common-tcpip-manpages-socket">socket</link> type. It is not required that a protocol family support all + socket types. A protocol family may contain multiple protocols support- + ing the same socket abstraction. + + A protocol supports one of the socket abstractions detailed in <link linkend="net-common-tcpip-manpages-socket">socket</link>. + A specific protocol may be accessed either by creating a socket of the + appropriate type and protocol family, or by requesting the protocol ex- + plicitly when creating a socket. Protocols normally accept only one type + of address format, usually determined by the addressing structure inher- + ent in the design of the protocol family/network architecture. Certain + semantics of the basic socket abstractions are protocol specific. All + protocols are expected to support the basic model for their particular + socket type, but may, in addition, provide non-standard facilities or ex- + tensions to a mechanism. For example, a protocol supporting the + SOCK_STREAM abstraction may allow more than one byte of out-of-band data + to be transmitted per out-of-band message. + + A network interface is similar to a device interface. Network interfaces + comprise the lowest layer of the networking subsystem, interacting with + the actual transport hardware. An interface may support one or more pro- + tocol families and/or address formats. + +PROTOCOL + The system currently supports the Internet protocols. Raw socket interfaces + are provided to the IP protocol layer of the Internet. + +ADDRESSING + Associated with each protocol family is an address format. All network + addresses adhere to a general structure, called a sockaddr, described be- + low. However, each protocol imposes a finer, more specific structure, + generally renaming the variant, which is discussed in the protocol family + manual page alluded to above. + + struct sockaddr { + u_int8_t sa_len; + sa_family_t sa_family; + char sa_data[14]; + }; + + The field sa_len contains the total length of the structure, which may + exceed 16 bytes. The following address values for sa_family are known to + the system (and additional formats are defined for possible future imple- + mentation): + + #define AF_UNIX 1 /* local to host (pipes, portals) */ + #define AF_INET 2 /* internetwork: UDP, TCP, etc. */ + #define AF_NS 6 /* Xerox NS protocols */ + #define AF_CCITT 10 /* CCITT protocols, X.25 etc */ + #define AF_HYLINK 15 /* NSC Hyperchannel */ + #define AF_APPLETALK 16 /* AppleTalk */ + #define AF_ISO 18 /* ISO protocols */ + #define AF_IPX 23 /* Novell Internet Protocol */ + #define AF_INET6 24 /* IPv6 */ + #define AF_NATM 27 /* native ATM access */ + +ROUTING + OpenBSD provides some packet routing facilities. The kernel maintains a + routing information database, which is used in selecting the appropriate + network interface when transmitting packets. + + This facility is however, untested in eCos ports. + +INTERFACES + Each network interface in a system corresponds to a path through which + messages may be sent and received. A network interface usually has a + hardware device associated with it, though certain interfaces such as the + loopback interface, lo, do not. + + The following ioctl calls may be used to manipulate network interfaces + The ioctl is made on a socket (typically of type SOCK_DGRAM) in the desired + domain. Most of the requests supported in earlier releases take an ifreq + structure as its parameter. This structure has the form + + struct ifreq { + #define IFNAMSIZ 16 + char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + short ifru_flags; + int ifru_metric; + caddr_t ifru_data; + } ifr_ifru; + #define ifr_addr ifr_ifru.ifru_addr /* address */ + #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ + #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ + #define ifr_flags ifr_ifru.ifru_flags /* flags */ + #define ifr_metric ifr_ifru.ifru_metric /* metric */ + #define ifr_media ifr_ifru.ifru_metric /* media options (overload) */ + #define ifr_data ifr_ifru.ifru_data /* for use by interface */ + }; + + Calls which are now deprecated are: + + SIOCSIFADDR Set interface address for protocol family. Following the + address assignment, the ``initialization'' routine for + the interface is called. + + SIOCSIFDSTADDR Set point to point address for protocol family and inter- + face. + + SIOCSIFBRDADDR Set broadcast address for protocol family and interface. + + ioctl requests to obtain addresses and requests both to set and retrieve + other data are still fully supported and use the ifreq structure: + + SIOCGIFADDR Get interface address for protocol family. + + SIOCGIFDSTADDR Get point to point address for protocol family and inter- + face. + + SIOCGIFBRDADDR Get broadcast address for protocol family and interface. + + SIOCSIFFLAGS Set interface flags field. If the interface is marked + down, any processes currently routing packets through the + interface are notified; some interfaces may be reset so + that incoming packets are no longer received. When + marked up again, the interface is reinitialized. + + SIOCGIFFLAGS Get interface flags. + + SIOCSIFMEDIA Set interface media. See ifmedia(4) for possible values. + + SIOCGIFMEDIA Get interface media. See ifmedia(4) for interpreting + this value. + + SIOCSIFMETRIC Set interface routing metric. The metric is used only by + user-level routers. + + SIOCGIFMETRIC Get interface metric. + + There are two requests that make use of a new structure: + + SIOCAIFADDR An interface may have more than one address associated + with it in some protocols. This request provides a means + to add additional addresses (or modify characteristics of + the primary address if the default address for the ad- + dress family is specified). Rather than making separate + calls to set destination or broadcast addresses, or net- + work masks (now an integral feature of multiple proto- + cols) a separate structure is used to specify all three + facets simultaneously (see below). One would use a + slightly tailored version of this struct specific to each + family (replacing each sockaddr by one of the family-spe- + cific type). Where the sockaddr itself is larger than + the default size, one needs to modify the ioctl(2) iden- + tifier itself to include the total size, as described in + ioctl(2). + + SIOCDIFADDR This request deletes the specified address from the list + associated with an interface. It also uses the + if_aliasreq structure to allow for the possibility of + protocols allowing multiple masks or destination address- + es, and also adopts the convention that specification of + the default address means to delete the first address for + the interface belonging to the address family in which + the original socket was opened. + + SIOCGIFCONF Get interface configuration list. This request takes an + ifconf structure (see below) as a value-result parameter. + The ifc_len field should be initially set to the size of + the buffer pointed to by ifc_buf. On return it will con- + tain the length, in bytes, of the configuration list. + Alternately, if the ifc_len passed in is set to 0, + SIOCGIFCONF will set ifc_len to the size that ifc_buf + needs to be to fit the entire configuration list and not + fill in the other parameters. This is useful for deter- + mining the exact size that ifc_buf needs to be in ad- + vance. Note, however, that this is an extension that not + all operating systems support. + + /* + * Structure used in SIOCAIFADDR request. + */ + struct ifaliasreq { + char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + struct sockaddr ifra_addr; + struct sockaddr ifra_broadaddr; + struct sockaddr ifra_mask; + }; + + /* + * 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 associated 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 returned */ + }; + +SEE ALSO + <link linkend="openbsd-manpages-bridge">bridge</link>, <link linkend="openbsd-manpages-stp">spanning-tree</link> + +</SCREEN> +</SECT1> + +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:nil +sgml-shorttag:t +sgml-namecase-general:t +sgml-general-insert-case:lower +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:2 +sgml-indent-data:t +sgml-parent-document:("tcpip.sgml" "book" "chapter") +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +sgml-doctype:"book" +End: +--> + diff --git a/ecos/packages/net/tcpip/current/doc/openbsd-manpages-stp.sgml b/ecos/packages/net/tcpip/current/doc/openbsd-manpages-stp.sgml new file mode 100644 index 0000000..7483563 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/openbsd-manpages-stp.sgml @@ -0,0 +1,135 @@ +<!-- {{{ Banner --> + +<!-- =============================================================== --> +<!-- --> +<!-- openbsd-manpages-stp.sgml --> +<!-- --> +<!-- eCos TCP/IP Stacks --> +<!-- --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTBEGIN#### --> +<!-- =============================================================== --> +<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<SECT1 id="openbsd-manpages-stp"> +<TITLE>Spanning Tree Protocol</TITLE> +<SCREEN> +NAME + stp - Spanning Tree Protocol + +SYNOPSIS + + +DESCRIPTION + Spanning Tree (STP) is a layer 2 protocol designed to run on bridges. The + main purpose of STP is to ensure that there are no loop situations when + redundant paths are provisioned in the network. STP detects and disables + creation of network loops by blocking certain ports on some of the bridges + in the network. The process of selection of blocking ports (on occurance + of redundant paths) is governed by the following three parameters : + + - Relative priority of each bridge. A higher value means lower priority. + - Relative priority of each port within a bridge. A higher value means + lower priority. + - Path cost (based on physical media type) associated with each port. + + A given port/interface participates in STP if the flag IFBIF_STP is + set for the interface. A possible time for setting this flag is at the + time when the interface in context is added to bridge. + +IOCTLS + The STP code is invoked for all ioctl calls specified in <link linkend="openbsd-manpages-bridge">bridge</link> section. + The following ioctl calls are specific to STP functionality. They are + defined in <sys/sockio.h>. + + SIOCBRDGGPRI (struct ifbrparam) Get the configured priority of this + bridge. The priority value could vary from 0 to 65535. + 0 being the highest priority and 65535 the lowest. The + configured value is returned in field ifbrp_prio. + + SIOCBRDGSPRI (struct ifbrparam) Set priority of this bridge to the + value specified in field ifbrp_prio. + + SIOCBRDGGHT (struct ifbrparam) Get the configured frequency of + transmission of hello packets from non-blocking + interfaces on this bridge. The configured frequency is + returned in field ifbrp_hellotime. + + SIOCBRDGSHT (struct ifbrparam) Set the frequency of transmission + of hello packets to the value specified in field + ifbrp_hellotime. The specified value should be greater + than 0, else EINVAL is returned. + + SIOCBRDGGFD (struct ifbrparam) Get the forwarding delay time + associated with ports/interfaces on this bridge. The + forwarding delay time is the time taken by a port + to transit from one state to other (for eg. from + LEARNING state to FORWARDING state). The configured + value if returned in field ifbrp_fwddelay. + + SIOCBRDGSFD (struct ifbrparam) Set the forwarding delay for ports + attached to this bridge to a value specified in + field ifbrp_fwddelay. The specified value should be + greater than 0, else EINVAL is returned. + + SIOCBRDGGMA (struct ifbrparam) Get aging timeout values of + spanning data. The timeout value is returned in field + ifbrp_maxage. + + SIOCBRDGSMA (struct ifbrparam) Set the aging timeout value of + BPDUs to the value specified in ifbrp_maxage. The + specified value should be greater than 0, else + EINVAL is returned. + + SIOCBRDGSIFPRIO (struct ifbreq) Set the priority of specified + interface to the value given in field ifbr_priority. + + SIOCBRDGSIFCOST (struct ifbreq) Set the cost associated with the + given interface to the value specified in field + ifbr_path_cost. + + +ERRORS + Same as the ones specified for <link linkend="openbsd-manpages-bridge">bridge</link>. + +SEE ALSO + <link linkend="openbsd-manpages-netintro">netintro</link>, <link linkend="openbsd-manpages-bridge">bridge</link> + +</SCREEN> +</SECT1> + +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:nil +sgml-shorttag:t +sgml-namecase-general:t +sgml-general-insert-case:lower +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:2 +sgml-indent-data:t +sgml-parent-document:("tcpip.sgml" "book" "chapter") +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +sgml-doctype:"book" +End: +--> + diff --git a/ecos/packages/net/tcpip/current/doc/openbsd.sgml b/ecos/packages/net/tcpip/current/doc/openbsd.sgml new file mode 100755 index 0000000..b63ae8a --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/openbsd.sgml @@ -0,0 +1,219 @@ +<!-- {{{ Banner --> + +<!-- =============================================================== --> +<!-- --> +<!-- openbsd.sgml --> +<!-- --> +<!-- eCos TCP/IP Stacks --> +<!-- --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTBEGIN#### --> +<!-- =============================================================== --> +<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2010 Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<PART id="tcpip-openbsd"> +<TITLE>OpenBSD TCP/IP Stack port for eCos</TITLE> +<PARTINTRO> +<PARA> <productname>TCP/IP Networking for eCos</productname> + now provides a complete + TCP/IP networking stack, which is derived from a + stable release of OpenBSD. The networking support is + fully featured and well tested within the eCos environment. + </PARA> +</PARTINTRO> + +<CHAPTER id="tcpip-openbsd-networking-stack-features"> +<TITLE>Networking Stack Features</TITLE> +<SECT1 id="tcpip-openbsd-tcpip-features"> +<TITLE>Introduction</TITLE> +<PARA>Since this networking package is based on BSD code, it is +very complete and robust. The eCos implementation includes support +for the following protocols: </PARA> +<itemizedlist> +<LISTITEM><PARA>IPv4</para></listitem> +<LISTITEM><PARA>UDP</para></listitem> +<LISTITEM><PARA>TCP</para></listitem> +<LISTITEM><PARA>ICMP</para></listitem> +<LISTITEM><PARA>raw packet interface</para></listitem> +</itemizedlist> +<PARA>Along with support for the above mentioned protocols, the OpenBSD +stack also supports ethernet bridging. +</PARA> +<PARA>The following additional features are also present in the package, + but are not supported:</PARA> +<itemizedlist> +<LISTITEM><PARA>Berkeley Packet Filter </PARA></LISTITEM> +<LISTITEM><PARA>Multi-cast and uni-cast support, including multi-cast +routing </PARA></LISTITEM> +<LISTITEM><PARA>IPv6 </PARA></LISTITEM> + </itemizedlist> +</SECT1> +</CHAPTER> +<CHAPTER id="tcpip-openbsd-stack-port"> +<TITLE>OpenBSD TCP/IP stack port</TITLE> +<PARA>This document describes how to get started with the OpenBSD +TCP/IP network stack. </PARA> +<SECT1 id="tcpip-openbsd-tcpip-targets"> +<TITLE>Targets</TITLE> +<PARA>A number of ethernet devices may be supported. The default configuration +supports two instances of the interface by default, +and you will need to write your own driver instantiation code, +and supplemental startup and initialization code, +if you should add additional ones.</PARA> +<PARA>The target for your board will normally be supplied with an +ethernet driver, in which case including the network stack and +generic ethernet driver package to your build will automatically +enable usage of the ethernet device driver. +If your target is not supplied with an ethernet +driver, you will need to use loopback (see +<xref linkend="net-common-loopback-tests">).</PARA> +</SECT1> +<SECT1 id="tcpip-openbsd-building-the-network-stack"> +<TITLE><!--<conditionaltext>-->Building the Network Stack</TITLE> +<PARA>Using the <EMPHASIS>Build->Packages</EMPHASIS> dialog, +add the packages “Networking”, +“OpenBSD TCP/IP Stack” +and “Common Ethernet Support” +to your configuration. Their package names +are CYGPKG_NET, CYGPKG_NET_OPENBSD_STACK and CYGPKG_NET_ETH_DRIVERS +respectively.</PARA> +<para>A short-cut way to do this is by +using the “net” <emphasis>template</emphasis> +if it is available for your platform.</para> +<PARA>The platform-specific ethernet device driver for your platform +will be added as part of the target selection (in the +<EMPHASIS>Build->Templates</EMPHASIS> “Hardware” item), +along with the +PCI I/O subsystem (if relevent) and the appropriate serial device driver. +</para><para> +For example, the PowerPC MBX target selection adds the package +PKG_NET_QUICC_ETH_DRIVERS, +and the Cirrus Logic EDB7xxx target selection adds the package +CYGPKG_NET_EDB7XXX_ETH_DRIVERS. +After this, eCos and its tests can be built exactly as usual.</PARA> +<NOTE> +<PARA>By default, most of the network tests are not built. This +is because some of them require manual intervention, i.e. they are +to be run “by hand”, and are not suitable for +automated testing. To build the full set of network tests, set +the configuration option CYGPKG_NET_BUILD_TESTS “Build +networking tests (demo programs)” within “Networking +support build options”.</PARA> +</NOTE> +</SECT1> +<SECT1 id="tcpip-openbsd-building-the-bridge-code"> +<TITLE>Inclusion of bridge code</TITLE> + +<PARA>The OpenBSD stack does not by default result in the inclusion of +the bridge code. To include bridging functionality the CDL option +CYGPKG_NET_BRIDGE must be enable . It is also possible to enable more +than one concurrent bridge. The number of bridges active in a device +is configured by the CDL option CYGNUM_NET_BRIDGES, which has a +default value of 1.</PARA> + +<PARA>The default behavior of a bridge is to operate without the +spanning tree protocol. When devices are operated in this default mode +it must be ensured the network topology is loop-free. Any loops will +cause broadcast storms and general mayhem on the network. Including +spanning tree code during the build process will allow the bridge to +communicate with other bridges. They can then detect such loops and by +disabling selected interfaces break the loop. To enable spanning tree enable +the CDL option CYGPKG_NET_BRIDGE_STP_CODE.</PARA> +</SECT1> +</CHAPTER> +<CHAPTER id="tcpip-openbsd-tcpip-apis"> +<TITLE>APIs</TITLE> +<SECT1 id="tcpip-openbsd-standard-networking-api"> +<TITLE>Standard networking</TITLE> +<PARA>The APIs for the standard networking calls such as +<FUNCTION>socket()</FUNCTION>, <FUNCTION>recv()</FUNCTION> and so on, are +in header files relative to the top-level +include directory, within the standard subdirectories as conventionally +found in <FILENAME>/usr/include</FILENAME>. For example: +<PROGRAMLISTING> + install/include/arpa/tftp.h + install/include/netinet/tcpip.h + install/include/sys/socket.h + install/include/sys/socketvar.h + install/include/sys/sockio.h +</PROGRAMLISTING> +</PARA><PARA> +<filename>network.h</filename> at the top level +defines various extensions, for example the API +<function>init_all_network_interfaces(void)</function> +described +above. We advise including <filename>network.h</filename> whether +you use these features or not.</PARA> +<PARA>In general, using the networking code may require definition +of two symbols: _KERNEL and __ECOS. _KERNEL +is not normally required; __ECOS is normally required. +So add this to your compile lines for files which use the network +stack:</PARA> +<PROGRAMLISTING> -D__ECOS</PROGRAMLISTING> +<PARA>To expand a little, it’s like this because this is +a port of a standard distribution external to Red Hat. One goal +is to perturb the sources as little as possible, so that upgrading +and maintenance from the external distribution is simplified. The __ECOS +symbol marks out Red Hat’s additions in making the port. +The _KERNEL symbol is traditional UNIX practice: it distinguishes +a compilation which is to be linked into the kernel from one which +is part of an application. eCos applications are fully linked, +so this distinction does not apply. _KERNEL can however +be used to control the visibility of the internals of the stack, +so depending on what features your application uses, it may or may +not be necessary.</PARA> +<PARA>The include file <filename>network.h</filename> undefines _KERNEL +unconditionally, to provide an application-like compilation environment. +If you were writing code which, for example, +enumerates the stack’s internal +structures, that is a kernel-like compilation environment, so you +would need to define _KERNEL (in addition to __ECOS) +and avoid including <filename>network.h</filename>.</PARA> +</SECT1> +<SECT1 id="tcpip-openbsd-enhanced-select"> +<TITLE>Enhanced Select()</TITLE> +<PARA>The network stack supports an extension to the standard select +semantics which allows all threads that are waiting to be restarted +even if the select conditions are not satisfied.</PARA> +<PARA>The standard select() API: </PARA> +<PROGRAMLISTING>int +<function>select</function>(int nfd, + fd_set *in, fd_set *out, fd_set *ex, + struct timeval *tv); </PROGRAMLISTING> +<PARA>does not support the restart.</PARA> +<PARA>The additional API: </PARA> +<PROGRAMLISTING>int +<function>cyg_select_with_abort</function>(int nfd, + fd_set *in, fd_set *out, fd_set *ex, + struct timeval *tv) +</PROGRAMLISTING> +<PARA>behaves exactly as select() with the additional feature that +a call to</PARA> +<PROGRAMLISTING> +void <function>cyg_select_abort</function>(void) +</PROGRAMLISTING> +<PARA>will cause all threads waiting in any +<function>cyg_select_with_abort()</function> call +to cease waiting and continue execution.</PARA> +</SECT1> +&net-tcpip-openbsd-manpages-netintro-sgml +&net-tcpip-openbsd-manpages-bridge-sgml +&net-tcpip-openbsd-manpages-stp-sgml +</CHAPTER> +</PART> diff --git a/ecos/packages/net/tcpip/current/doc/read.html b/ecos/packages/net/tcpip/current/doc/read.html new file mode 100644 index 0000000..1e4bf7d --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/read.html @@ -0,0 +1,61 @@ +<html> +<body> +<pre> +NAME + read - read from a file descriptor + +SYNOPSIS + ssize_t read(int fd, void *buf, size_t count); + +DESCRIPTION + read() attempts to read up to count bytes from file + descriptor fd into the buffer starting at buf. + + If count is zero, read() returns zero and has no other + results. + + +RETURN VALUE + On success, the number of bytes read is returned (zero + indicates end of file), and the file position is advanced + by this number. It is not an error if this number is + smaller than the number of bytes requested; this may hap- + pen for example because fewer bytes are actually available + right now (maybe because we were close to end-of-file, or + because we are reading from a pipe, or from a terminal), + or because read() was interrupted by a signal. On error, + -1 is returned, and errno is set appropriately. In this + case it is left unspecified whether the file position (if + any) changes. + +ERRORS + EINTR The call was interrupted by a signal before any + data was read. + + EAGAIN Non-blocking I/O has been selected using O_NON- + BLOCK and no data was immediately available for + reading. + + EIO I/O error. This will happen for example when the + process is in a background process group, tries to + read from its controlling tty, and either it is + ignoring or blocking SIGTTIN or its process group + is orphaned. It may also occur when there is a + low-level I/O error while reading from a disk or + tape. + + EISDIR fd refers to a directory. + + EBADF fd is not a valid file descriptor or is not open + for reading. + + EINVAL fd is attached to an object which is unsuitable + for reading. + + Other errors may occur, depending on the object connected + to fd. POSIX allows a read that is interrupted after + reading some data to return -1 (with errno set to EINTR) + or to return the number of bytes already read. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/read.man b/ecos/packages/net/tcpip/current/doc/read.man new file mode 100644 index 0000000..7f861bb --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/read.man @@ -0,0 +1,55 @@ +NAME + read - read from a file descriptor + +SYNOPSIS + ssize_t read(int fd, void *buf, size_t count); + +DESCRIPTION + read() attempts to read up to count bytes from file + descriptor fd into the buffer starting at buf. + + If count is zero, read() returns zero and has no other + results. + + +RETURN VALUE + On success, the number of bytes read is returned (zero + indicates end of file), and the file position is advanced + by this number. It is not an error if this number is + smaller than the number of bytes requested; this may hap- + pen for example because fewer bytes are actually available + right now (maybe because we were close to end-of-file, or + because we are reading from a pipe, or from a terminal), + or because read() was interrupted by a signal. On error, + -1 is returned, and errno is set appropriately. In this + case it is left unspecified whether the file position (if + any) changes. + +ERRORS + EINTR The call was interrupted by a signal before any + data was read. + + EAGAIN Non-blocking I/O has been selected using O_NON- + BLOCK and no data was immediately available for + reading. + + EIO I/O error. This will happen for example when the + process is in a background process group, tries to + read from its controlling tty, and either it is + ignoring or blocking SIGTTIN or its process group + is orphaned. It may also occur when there is a + low-level I/O error while reading from a disk or + tape. + + EISDIR fd refers to a directory. + + EBADF fd is not a valid file descriptor or is not open + for reading. + + EINVAL fd is attached to an object which is unsuitable + for reading. + + Other errors may occur, depending on the object connected + to fd. POSIX allows a read that is interrupted after + reading some data to return -1 (with errno set to EINTR) + or to return the number of bytes already read. diff --git a/ecos/packages/net/tcpip/current/doc/recvfrom.html b/ecos/packages/net/tcpip/current/doc/recvfrom.html new file mode 100644 index 0000000..cdb0dba --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/recvfrom.html @@ -0,0 +1,159 @@ +<html> +<body> +<pre> +NAME + recvfrom - receive a message from a socket + +SYNOPSIS + #include <network.h> + + int recvfrom(int s, void *buf, int len, unsigned int flags + struct sockaddr *from, int *fromlen); + +DESCRIPTION + The recvfrom call is used to receive messages from a socket, + and may be used to receive data on a socket whether or not it + is connection-oriented. + + + If from is not NULL, and the socket is not connection-ori + ented, the source address of the message is filled in. + Fromlen is a value-result parameter, initialized to the + size of the buffer associated with from, and modified on + return to indicate the actual size of the address stored + there. + + The routine returns the length of the message on + successful completion. If a message is too long to fit in + the supplied buffer, excess bytes may be discarded depend + ing on the type of socket the message is received from + (see socket(2)). + + If no messages are available at the socket, the receive + calls wait for a message to arrive, unless the socket is + nonblocking (see fcntl(2)) in which case the value -1 is + returned and the external variable errno set to EAGAIN. + The receive calls normally return any data available, up + to the requested amount, rather than waiting for receipt + of the full amount requested. + + The select(2) call may be used to determine + when more data arrives. + + The flags argument to a recvfrom call is formed by OR'ing one + or more of the following values: + + MSG_OOB + This flag requests receipt of out-of-band data that + would not be received in the normal data stream. + Some protocols place expedited data at the head of + the normal data queue, and thus this flag cannot be + used with such protocols. + + MSG_PEEK + This flag causes the receive operation to return + data from the beginning of the receive queue with + out removing that data from the queue. Thus, a + subsequent receive call will return the same data. + + MSG_WAITALL + This flag requests that the operation block until + the full request is satisfied. However, the call + may still return less data than requested if a sig + nal is caught, an error or disconnect occurs, or + the next data to be received is of a different type + than that returned. + + MSG_ERRQUEUE + Receive packet from the error queue + + MSG_NOSIGNAL + This flag turns off raising of SIGPIPE on stream + sockets when the other end disappears. + + MSG_ERRQUEUE + This flag specifies that queued errors should be + received from the socket error queue. The error is + passed in a ancilliary message with a type depen + dent on the protocol (for IP IP_RECVERR). The + error is supplied in a sock_extended_error struc + ture: + + #define SO_EE_ORIGIN_NONE 0 + #define SO_EE_ORIGIN_LOCAL 1 + #define SO_EE_ORIGIN_ICMP 2 + #define SO_EE_ORIGIN_ICMP6 3 + + struct sock_extended_err + { + __u32 ee_errno; /* error number */ + __u8 ee_origin; /* where the error originated */ + __u8 ee_type; /* type */ + __u8 ee_code; /* code */ + __u8 ee_pad; + __u32 ee_info; /* additional information */ + __u32 ee_data; /* other data */ + }; + + struct sockaddr *SOCK_EE_OFFENDER(struct sock_extended_err *); + + ee_errno contains the errno number of the queued + error. ee_origin is the origin code of where the + error originated. The other fields are protocol + specific. SOCK_EE_OFFENDER returns a pointer to + the address of the network object where the error + originated from. If this address is not known, the + sa_family member of the sockaddr contains AF_UNSPEC + and the other fields of the sockaddr are undefined. + The payload of the packet that caused the error is + passed as normal data. + + For local errors, no address is passed (this can be + checked with the cmsg_len member of the cmsghdr). + For error receives, the MSG_ERRQUEUE is set in the + msghdr. After a error has been passed, the pending + socket error is regenerated based on the next + queued error and will be passed on the next socket + operation. + + + The msg_flags field is set on return according to the mes + sage received. MSG_EOR indicates end-of-record; the data + returned completed a record (generally used with sockets + of type SOCK_SEQPACKET). MSG_TRUNC indicates that the + trailing portion of a datagram was discarded because the + datagram was larger than the buffer supplied. MSG_CTRUNC + indicates that some control data were discarded due to + lack of space in the buffer for ancillary data. MSG_OOB + is returned to indicate that expedited or out-of-band data + were received. MSG_ERRQUEUE indicates that no data was + received but an extended error from the socket error + queue. + +RETURN VALUES + These calls return the number of bytes received, or -1 if + an error occurred. + +ERRORS + These are some standard errors generated by the socket + layer. Additional errors may be generated and returned + from the underlying protocol modules; see their manual + pages. + + EBADF The argument s is an invalid descriptor. + + ENOTSOCK + The argument s does not refer to a socket. + + EAGAIN The socket is marked non-blocking and the receive + operation would block, or a receive timeout had + been set and the timeout expired before data was + received. + + EINTR The receive was interrupted by delivery of a sig + nal before any data were available. + + EINVAL Invalid argument passed. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/recvfrom.man b/ecos/packages/net/tcpip/current/doc/recvfrom.man new file mode 100644 index 0000000..a92871d --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/recvfrom.man @@ -0,0 +1,152 @@ +NAME + recvfrom - receive a message from a socket + +SYNOPSIS + #include <network.h> + + int recvfrom(int s, void *buf, int len, unsigned int flags + struct sockaddr *from, int *fromlen); + +DESCRIPTION + The recvfrom call is used to receive messages from a socket, + and may be used to receive data on a socket whether or not it + is connection-oriented. + + If from is not NULL, and the socket is not connection-ori + ented, the source address of the message is filled in. + Fromlen is a value-result parameter, initialized to the + size of the buffer associated with from, and modified on + return to indicate the actual size of the address stored + there. + + The routine returns the length of the message on + successful completion. If a message is too long to fit in + the supplied buffer, excess bytes may be discarded depend + ing on the type of socket the message is received from + (see socket(2)). + + If no messages are available at the socket, the receive + calls wait for a message to arrive, unless the socket is + nonblocking (see fcntl(2)) in which case the value -1 is + returned and the external variable errno set to EAGAIN. + The receive calls normally return any data available, up + to the requested amount, rather than waiting for receipt + of the full amount requested. + + The select(2) call may be used to determine + when more data arrives. + + The flags argument to a recvfrom call is formed by OR'ing one + or more of the following values: + + MSG_OOB + This flag requests receipt of out-of-band data that + would not be received in the normal data stream. + Some protocols place expedited data at the head of + the normal data queue, and thus this flag cannot be + used with such protocols. + + MSG_PEEK + This flag causes the receive operation to return + data from the beginning of the receive queue with + out removing that data from the queue. Thus, a + subsequent receive call will return the same data. + + MSG_WAITALL + This flag requests that the operation block until + the full request is satisfied. However, the call + may still return less data than requested if a sig + nal is caught, an error or disconnect occurs, or + the next data to be received is of a different type + than that returned. + + MSG_ERRQUEUE + Receive packet from the error queue + + MSG_NOSIGNAL + This flag turns off raising of SIGPIPE on stream + sockets when the other end disappears. + + MSG_ERRQUEUE + This flag specifies that queued errors should be + received from the socket error queue. The error is + passed in a ancilliary message with a type depen + dent on the protocol (for IP IP_RECVERR). The + error is supplied in a sock_extended_error struc + ture: + + #define SO_EE_ORIGIN_NONE 0 + #define SO_EE_ORIGIN_LOCAL 1 + #define SO_EE_ORIGIN_ICMP 2 + #define SO_EE_ORIGIN_ICMP6 3 + + struct sock_extended_err + { + __u32 ee_errno; /* error number */ + __u8 ee_origin; /* where the error originated */ + __u8 ee_type; /* type */ + __u8 ee_code; /* code */ + __u8 ee_pad; + __u32 ee_info; /* additional information */ + __u32 ee_data; /* other data */ + }; + + struct sockaddr *SOCK_EE_OFFENDER(struct sock_extended_err *); + + ee_errno contains the errno number of the queued + error. ee_origin is the origin code of where the + error originated. The other fields are protocol + specific. SOCK_EE_OFFENDER returns a pointer to + the address of the network object where the error + originated from. If this address is not known, the + sa_family member of the sockaddr contains AF_UNSPEC + and the other fields of the sockaddr are undefined. + The payload of the packet that caused the error is + passed as normal data. + + For local errors, no address is passed (this can be + checked with the cmsg_len member of the cmsghdr). + For error receives, the MSG_ERRQUEUE is set in the + msghdr. After a error has been passed, the pending + socket error is regenerated based on the next + queued error and will be passed on the next socket + operation. + + + The msg_flags field is set on return according to the mes + sage received. MSG_EOR indicates end-of-record; the data + returned completed a record (generally used with sockets + of type SOCK_SEQPACKET). MSG_TRUNC indicates that the + trailing portion of a datagram was discarded because the + datagram was larger than the buffer supplied. MSG_CTRUNC + indicates that some control data were discarded due to + lack of space in the buffer for ancillary data. MSG_OOB + is returned to indicate that expedited or out-of-band data + were received. MSG_ERRQUEUE indicates that no data was + received but an extended error from the socket error + queue. + +RETURN VALUES + These calls return the number of bytes received, or -1 if + an error occurred. + +ERRORS + These are some standard errors generated by the socket + layer. Additional errors may be generated and returned + from the underlying protocol modules; see their manual + pages. + + EBADF The argument s is an invalid descriptor. + + ENOTSOCK + The argument s does not refer to a socket. + + EAGAIN The socket is marked non-blocking and the receive + operation would block, or a receive timeout had + been set and the timeout expired before data was + received. + + EINTR The receive was interrupted by delivery of a sig + nal before any data were available. + + EINVAL Invalid argument passed. diff --git a/ecos/packages/net/tcpip/current/doc/sample_program.html b/ecos/packages/net/tcpip/current/doc/sample_program.html new file mode 100644 index 0000000..cd00253 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/sample_program.html @@ -0,0 +1,359 @@ +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; I; Linux 2.2.14 ppc) [Netscape]"> +</head> +<body> + +<center> +<h1> +Sample Networking Program</h1></center> + +<p><br>This example is derived from the test program <tt>".../net/tcpip/v1_3_1/tests/ping_test.c"</tt>. +<br> +<blockquote><tt><font size=-1>//==========================================================================</font></tt> +<br><tt><font size=-1>//</font></tt> +<br><tt><font size=-1>// tests/ping_test.c</font></tt> +<br><tt><font size=-1>//</font></tt> +<br><tt><font size=-1>// Simple test of PING +(ICMP) and networking support</font></tt> +<br><tt><font size=-1>//</font></tt> +<br><tt><font size=-1>//==========================================================================</font></tt> +<br><tt><font size=-1>//==========================================================================</font></tt> +<br><tt><font size=-1>//#####DESCRIPTIONBEGIN####</font></tt> +<br><tt><font size=-1>//</font></tt> +<br><tt><font size=-1>// Author(s): gthomas</font></tt> +<br><tt><font size=-1>// Contributors: gthomas</font></tt> +<br><tt><font size=-1>// Date: +2000-01-10</font></tt> +<br><tt><font size=-1>// Purpose:</font></tt> +<br><tt><font size=-1>// Description:</font></tt> +<br><tt><font size=-1>//</font></tt> +<br><tt><font size=-1>//</font></tt> +<br><tt><font size=-1>//####DESCRIPTIONEND####</font></tt> +<br><tt><font size=-1>//</font></tt> +<br><tt><font size=-1>//==========================================================================</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>// PING test code</font></tt><b><tt><font size=-1></font></tt></b> +<p><b><tt><font size=-1>#include <network.h></font></tt></b></blockquote> +This single include directive is all that is required to pick up the networking +support, including complete configuration information. +<blockquote><tt><font size=-1>#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL</font></tt> +<br><tt><font size=-1>static char stack[STACK_SIZE];</font></tt> +<br><tt><font size=-1>static cyg_thread thread_data;</font></tt> +<br><tt><font size=-1>static cyg_handle_t thread_handle;</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>#define NUM_PINGS 16</font></tt> +<br><tt><font size=-1>#define MAX_PACKET 4096</font></tt> +<br><tt><font size=-1>static unsigned char pkt1[MAX_PACKET], pkt2[MAX_PACKET];</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>#define UNIQUEID 0x1234</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>void</font></tt> +<br><tt><font size=-1>cyg_test_exit(void)</font></tt> +<br><tt><font size=-1>{</font></tt> +<br><tt><font size=-1> diag_printf("... Done\n");</font></tt> +<br><tt><font size=-1> while (1) ;</font></tt> +<br><tt><font size=-1>}</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>void</font></tt> +<br><tt><font size=-1>pexit(char *s)</font></tt> +<br><tt><font size=-1>{</font></tt> +<br><tt><font size=-1> perror(s);</font></tt> +<br><tt><font size=-1> cyg_test_exit();</font></tt> +<br><tt><font size=-1>}</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>// Compute INET checksum</font></tt> +<br><tt><font size=-1>int</font></tt> +<br><tt><font size=-1>inet_cksum(u_short *addr, int len)</font></tt> +<br><tt><font size=-1>{</font></tt> +<br><tt><font size=-1> register int nleft = len;</font></tt> +<br><tt><font size=-1> register u_short *w = addr;</font></tt> +<br><tt><font size=-1> register u_short answer;</font></tt> +<br><tt><font size=-1> register u_int sum = 0;</font></tt> +<br><tt><font size=-1> u_short odd_byte = 0;</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1> /*</font></tt> +<br><tt><font size=-1> * Our algorithm is +simple, using a 32 bit accumulator (sum),</font></tt> +<br><tt><font size=-1> * we add sequential +16 bit words to it, and at the end, fold</font></tt> +<br><tt><font size=-1> * back all the carry +bits from the top 16 bits into the lower</font></tt> +<br><tt><font size=-1> * 16 bits.</font></tt> +<br><tt><font size=-1> */</font></tt> +<br><tt><font size=-1> while( nleft > 1 ) {</font></tt> +<br><tt><font size=-1> sum += +*w++;</font></tt> +<br><tt><font size=-1> nleft +-= 2;</font></tt> +<br><tt><font size=-1> }</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1> /* mop up an odd byte, if necessary +*/</font></tt> +<br><tt><font size=-1> if( nleft == 1 ) {</font></tt> +<br><tt><font size=-1> *(u_char +*)(&odd_byte) = *(u_char *)w;</font></tt> +<br><tt><font size=-1> sum += +odd_byte;</font></tt> +<br><tt><font size=-1> }</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1> /*</font></tt> +<br><tt><font size=-1> * add back carry outs from +top 16 bits to low 16 bits</font></tt> +<br><tt><font size=-1> */</font></tt> +<br><tt><font size=-1> sum = (sum >> 16) + (sum & +0x0000ffff); /* add hi 16 to low 16 */</font></tt> +<br><tt><font size=-1> sum += (sum >> 16); +/* add carry */</font></tt> +<br><tt><font size=-1> answer = ~sum; +/* truncate to 16 bits */</font></tt> +<br><tt><font size=-1> return (answer);</font></tt> +<br><tt><font size=-1>}</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>static int</font></tt> +<br><tt><font size=-1>show_icmp(unsigned char *pkt, int len,</font></tt> +<br><tt><font size=-1> +struct sockaddr_in *from, struct sockaddr_in *to)</font></tt> +<br><tt><font size=-1>{</font></tt> +<br><tt><font size=-1> cyg_tick_count_t *tp, tv;</font></tt> +<br><tt><font size=-1> struct ip *ip;</font></tt> +<br><tt><font size=-1> struct icmp *icmp;</font></tt> +<br><tt><font size=-1> tv = cyg_current_time();</font></tt> +<br><tt><font size=-1> ip = (struct ip *)pkt;</font></tt> +<br><tt><font size=-1> if ((len < sizeof(*ip)) || +ip->ip_v != IPVERSION) {</font></tt> +<br><tt><font size=-1> diag_printf("%s: +Short packet or not IP! - Len: %d, Version: %d\n",</font></tt> +<br><tt><font size=-1> +inet_ntoa(from->sin_addr), len, ip->ip_v);</font></tt> +<br><tt><font size=-1> return +0;</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> icmp = (struct icmp *)(pkt + sizeof(*ip));</font></tt> +<br><tt><font size=-1> len -= (sizeof(*ip) + 8);</font></tt> +<br><tt><font size=-1> tp = (cyg_tick_count_t *)&icmp->icmp_data;</font></tt> +<br><tt><font size=-1> if (icmp->icmp_type != ICMP_ECHOREPLY) +{</font></tt> +<br><tt><font size=-1> diag_printf("%s: +Invalid ICMP - type: %d\n",</font></tt> +<br><tt><font size=-1> +inet_ntoa(from->sin_addr), icmp->icmp_type);</font></tt> +<br><tt><font size=-1> return +0;</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> if (icmp->icmp_id != UNIQUEID) +{</font></tt> +<br><tt><font size=-1> diag_printf("%s: +ICMP received for wrong id - sent: %x, recvd: %x\n",</font></tt> +<br><tt><font size=-1> +inet_ntoa(from->sin_addr), UNIQUEID, icmp->icmp_id);</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> diag_printf("%d bytes from %s: +", len, inet_ntoa(from->sin_addr));</font></tt> +<br><tt><font size=-1> diag_printf("icmp_seq=%d", icmp->icmp_seq);</font></tt> +<br><tt><font size=-1> diag_printf(", time=%dms\n", (int)(tv +- *tp)*10);</font></tt> +<br><tt><font size=-1> return (from->sin_addr.s_addr +== to->sin_addr.s_addr);</font></tt> +<br><tt><font size=-1>}</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>static void</font></tt> +<br><tt><font size=-1>ping_host(int s, struct sockaddr_in *host)</font></tt> +<br><tt><font size=-1>{</font></tt> +<br><tt><font size=-1> struct icmp *icmp = (struct icmp +*)pkt1;</font></tt> +<br><tt><font size=-1> int icmp_len = 64;</font></tt> +<br><tt><font size=-1> int seq, ok_recv, bogus_recv;</font></tt> +<br><tt><font size=-1> cyg_tick_count_t *tp;</font></tt> +<br><tt><font size=-1> long *dp;</font></tt> +<br><tt><font size=-1> struct sockaddr_in from;</font></tt> +<br><tt><font size=-1> int i, len, fromlen;</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1> ok_recv = 0;</font></tt> +<br><tt><font size=-1> bogus_recv = 0;</font></tt> +<br><tt><font size=-1> diag_printf("PING server %s\n", +<b>inet_ntoa(host->sin_addr)</b>);</font></tt></blockquote> +This function takes an IP address and returns a string representation. +Useful for printing the address. +<blockquote><tt><font size=-1> for (seq = 0; seq +< NUM_PINGS; seq++) {</font></tt> +<br><tt><font size=-1> // Build +ICMP packet</font></tt> +<br><tt><font size=-1> icmp->icmp_type += ICMP_ECHO;</font></tt> +<br><tt><font size=-1> icmp->icmp_code += 0;</font></tt> +<br><tt><font size=-1> icmp->icmp_cksum += 0;</font></tt> +<br><tt><font size=-1> icmp->icmp_seq += seq;</font></tt> +<br><tt><font size=-1> icmp->icmp_id += 0x1234;</font></tt> +<br><tt><font size=-1> // Set +up ping data</font></tt> +<br><tt><font size=-1> tp = (cyg_tick_count_t +*)&icmp->icmp_data;</font></tt> +<br><tt><font size=-1> *tp++ += cyg_current_time();</font></tt> +<br><tt><font size=-1> dp = (long +*)tp;</font></tt> +<br><tt><font size=-1> for (i += sizeof(*tp); i < icmp_len; i += sizeof(*dp)) {</font></tt> +<br><tt><font size=-1> +*dp++ = i;</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> // Add +checksum</font></tt> +<br><tt><font size=-1> icmp->icmp_cksum += inet_cksum( (u_short *)icmp, icmp_len+8);</font></tt> +<br><tt><font size=-1> // Send +it off</font></tt> +<br><tt><font size=-1> <b>if +(sendto(s, icmp, icmp_len+8, 0, (struct sockaddr *)host, sizeof(*host)) +< 0) {</b></font></tt></blockquote> +This function sends a single packet, in this case via the ICMP protocol. +The destination address is specified by the <tt>host</tt> argument. +<blockquote><tt><font size=-1> +perror("sendto");</font></tt> +<br><tt><font size=-1> +continue;</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> // Wait +for a response</font></tt> +<br><tt><font size=-1> fromlen += sizeof(from);</font></tt> +<br><tt><font size=-1> <b>len += recvfrom(s, pkt2, sizeof(pkt2), 0, (struct sockaddr *)&from, &fromlen);</b></font></tt></blockquote> +This function waits for a packet to be sent to this interface. Note: +this operation can fail if no packet is received with a given amount of +time (this timeout value is setup in the <tt>ping_test()</tt> routine below). +<blockquote><tt><font size=-1> +if (len < 0) {</font></tt> +<br><tt><font size=-1> +perror("recvfrom");</font></tt> +<br><tt><font size=-1> } else +{</font></tt> +<br><tt><font size=-1> +if (show_icmp(pkt2, len, &from, host)) {</font></tt> +<br><tt><font size=-1> +ok_recv++;</font></tt> +<br><tt><font size=-1> +} else {</font></tt> +<br><tt><font size=-1> +bogus_recv++;</font></tt> +<br><tt><font size=-1> +}</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> diag_printf("Sent %d packets, +received %d OK, %d bad\n", NUM_PINGS, ok_recv, bogus_recv);</font></tt> +<br><tt><font size=-1>}</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1>static void</font></tt> +<br><tt><font size=-1>ping_test(struct bootp *bp)</font></tt> +<br><tt><font size=-1>{</font></tt> +<br><tt><font size=-1> struct protoent *p;</font></tt> +<br><tt><font size=-1> struct timeval tv;</font></tt> +<br><tt><font size=-1> struct sockaddr_in host;</font></tt> +<br><tt><font size=-1> int s;</font></tt><tt><font size=-1></font></tt> +<p><tt><font size=-1> <b>if ((p = getprotobyname("icmp")) +== (struct protoent *)0) {</b></font></tt></blockquote> +This function gets information about the ICMP protocol. This will +be used below to set up the "socket" (the handle to a network connection). +<blockquote><tt><font size=-1> +perror("getprotobyname");</font></tt> +<br><tt><font size=-1> return;</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> <b>s = socket(AF_INET, SOCK_RAW, +p->p_proto);</b></font></tt></blockquote> +Create the socket "s". A socket is an abstract object (sometimes +called a handle or endpoint). Sockets come in many flavors, RAW sockets +are used for communicating with non-structured protocols. DATAGRAM +sockets are used for packet oriented protocols, such as UDP. STREAM +sockets are used for reliable, sequenced byte streams, such as those provided +by TCP. +<blockquote><tt><font size=-1> if (s < 0) {</font></tt> +<br><tt><font size=-1> perror("socket");</font></tt> +<br><tt><font size=-1> return;</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1> tv.tv_sec = 1;</font></tt> +<br><tt><font size=-1> tv.tv_usec = 0;</font></tt> +<br><tt><font size=-1> <b>setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, +&tv, sizeof(tv));</b></font></tt></blockquote> +This function instructs the system that receive operations (see <tt>ping_host()</tt> +above) must complete within 1 second or issue a timed out error condition. +<blockquote><tt><font size=-1> // Set up host address</font></tt> +<br><tt><font size=-1> host.sin_family = AF_INET;</font></tt> +<br><tt><font size=-1> host.sin_addr = bp->bp_siaddr;</font></tt> +<br><tt><font size=-1> host.sin_port = 0;</font></tt> +<br><tt><font size=-1> ping_host(s, &host);</font></tt> +<br><tt><font size=-1> // Now try a bogus host</font></tt> +<br><tt><font size=-1> host.sin_addr.s_addr = htonl(ntohl(host.sin_addr.s_addr) ++ 32);</font></tt> +<br><tt><font size=-1> ping_host(s, &host);</font></tt> +<br><tt><font size=-1>}</font></tt> +<br><tt><font size=-1></font></tt> </blockquote> +This function drives the test. +<blockquote><tt><font size=-1>void</font></tt> +<br><tt><font size=-1>net_test(cyg_addrword_t p)</font></tt> +<br><tt><font size=-1>{</font></tt> +<br><tt><font size=-1> diag_printf("Start PING test\n");</font></tt> +<br><tt><font size=-1> <b>init_all_network_interfaces();</b></font></tt></blockquote> +This is a call to the network initialization code. Note that it must +be executed from a thread context, thus we can't put it in the <tt>cyg_start() +</tt>function which follows. The <tt>init_all_network_interfaces()</tt> +routine will cause the networking system to be initialized and any hardware +interfaces will be set up. Using the system configuration information, +an interface can be started using either <b>BOOTP</b>, or a predefined +configuration with static IP information. It is also possible to +indicate that an interface will be configured by the user code, outside +of "<tt>init_all_network_interfaces()</tt>". +<br><tt><font size=-1> </font></tt> +<br><tt><font size=-1> #ifdef CYGHWR_NET_DRIVER_ETH0</font></tt> +<br><tt><font size=-1> if (eth0_up) +{</font></tt> +<blockquote><tt><font size=-1> +ping_test(&eth0_bootp_data);</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1>#endif</font></tt></blockquote> +Notice that there is a BOOTP information structure kept about all hardware +interfaces. This is created and initialized by the call to <tt>init_all_network_interfaces()</tt>, +unless manual configuration is selected. This information can be +used by the application to learn things such as the local IP address, server +name, etc. +<blockquote><tt><font size=-1>#ifdef CYGHWR_NET_DRIVER_ETH1</font></tt> +<br><tt><font size=-1> if (eth1_up) {</font></tt> +<br><tt><font size=-1> ping_test(&eth1_bootp_data);</font></tt> +<br><tt><font size=-1> }</font></tt> +<br><tt><font size=-1>#endif</font></tt></blockquote> +Multiple hardware interfaces can be supported, depending on the hardware +platform. If the platform provides a single ethernet device then +<b><tt>CYGHWR_NET_DRIVER_ETH0 </tt></b>will be defined. If there +is a second interface, then will <b><tt>CYGHWR_NET_DRIVER_ETH1 </tt></b>be +defined. +<blockquote><tt><font size=-1> cyg_test_exit();</font></tt> +<br><tt><font size=-1>}</font></tt> +<br><tt><font size=-1></font></tt> </blockquote> +The following function creates an initial thread which runs the program. +This could just as easily be done by naming the <tt>net_test()</tt> function +<tt>main()</tt>. +<blockquote><tt><font size=-1>void</font></tt> +<br><tt><font size=-1>cyg_start(void)</font></tt> +<br><tt><font size=-1>{</font></tt> +<br><tt><font size=-1> // Create a main thread, so we +can run the scheduler and have time 'pass'</font></tt> +<br><tt><font size=-1> cyg_thread_create(10, +// Priority - just a number</font></tt> +<br><tt><font size=-1> +net_test, // entry</font></tt> +<br><tt><font size=-1> +0, +// entry parameter</font></tt> +<br><tt><font size=-1> +"Network test", // Name</font></tt> +<br><tt><font size=-1> +&stack[0], // Stack</font></tt> +<br><tt><font size=-1> +STACK_SIZE, // Size</font></tt> +<br><tt><font size=-1> +&thread_handle, // Handle</font></tt> +<br><tt><font size=-1> +&thread_data // Thread data structure</font></tt> +<br><tt><font size=-1> +);</font></tt> +<br><tt><font size=-1> cyg_thread_resume(thread_handle); +// Start it</font></tt> +<br><tt><font size=-1> cyg_scheduler_start();</font></tt> +<br><tt><font size=-1>}</font></tt></blockquote> + +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/select.html b/ecos/packages/net/tcpip/current/doc/select.html new file mode 100644 index 0000000..25a3d94 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/select.html @@ -0,0 +1,108 @@ +<html> +<body> +<pre> +NAME + select, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous + I/O multiplexing + +SYNOPSIS + #include <network.h> + + int select(int n, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout); + + FD_CLR(int fd, fd_set *set); + FD_ISSET(int fd, fd_set *set); + FD_SET(int fd, fd_set *set); + FD_ZERO(fd_set *set); + +DESCRIPTION + select waits for a number of file descriptors to change + status. + + Three independent sets of descriptors are watched. Those + listed in readfds will be watched to see if characters + become available for reading, those in writefds will be + watched to see if it is ok to immediately write on them, + and those in exceptfds will be watched for exceptions. On + exit, the sets are modified in place to indicate which + descriptors actually changed status. + + Four macros are provided to manipulate the sets. FD_ZERO + will clear a set. FD_SET and FD_CLR add or remove a given + descriptor from a set. FD_ISSET tests to see if a + descriptor is part of the set; this is useful after select + returns. + + n is the highest-numbered descriptor in any of the three + sets, plus 1. + + timeout is an upper bound on the amount of time elapsed + before select returns. It may be zero, causing select to + return immediately. If timeout is NULL (no timeout), + select can block indefinitely. + +RETURN VALUE + On success, select returns the number of descriptors con- + tained in the descriptor sets, which may be zero if the + timeout expires before anything interesting happens. On + error, -1 is returned, and errno is set appropriately; the + sets and timeout become undefined, so do not rely on their + contents after an error. + +ERRORS + EBADF An invalid file descriptor was given in one of the + sets. + + EINTR A non blocked signal was caught. + + EINVAL n is negative. + + ENOMEM select was unable to allocate memory for internal + tables. + +NOTES + Some code calls select with all three sets empty, n zero, + and a non-null timeout as a fairly portable way to sleep + with subsecond precision. + +EXAMPLE + #include <stdio.h> + #include <sys/time.h> + #include <sys/types.h> + #include <unistd.h> + + int + main(void) + { + fd_set rfds; + struct timeval tv; + int retval; + + /* Watch stdin (fd 0) to see when it has input. */ + FD_ZERO(&rfds); + FD_SET(0, &rfds); + /* Wait up to five seconds. */ + tv.tv_sec = 5; + tv.tv_usec = 0; + + retval = select(1, &rfds, NULL, NULL, &tv); + /* Don't rely on the value of tv now! */ + + if (retval) + printf("Data is available now.\n"); + /* FD_ISSET(0, &rfds) will be true. */ + else + printf("No data within five seconds.\n"); + + exit(0); + } + + Generally portable to/from non-BSD systems supporting + clones of the BSD socket layer (including System V vari- + ants). However, note that the System V variant typically + sets the timeout variable before exit, but the BSD variant + does not. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/select.man b/ecos/packages/net/tcpip/current/doc/select.man new file mode 100644 index 0000000..d92c026 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/select.man @@ -0,0 +1,102 @@ +NAME + select, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous + I/O multiplexing + +SYNOPSIS + #include <network.h> + + int select(int n, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout); + + FD_CLR(int fd, fd_set *set); + FD_ISSET(int fd, fd_set *set); + FD_SET(int fd, fd_set *set); + FD_ZERO(fd_set *set); + +DESCRIPTION + select waits for a number of file descriptors to change + status. + + Three independent sets of descriptors are watched. Those + listed in readfds will be watched to see if characters + become available for reading, those in writefds will be + watched to see if it is ok to immediately write on them, + and those in exceptfds will be watched for exceptions. On + exit, the sets are modified in place to indicate which + descriptors actually changed status. + + Four macros are provided to manipulate the sets. FD_ZERO + will clear a set. FD_SET and FD_CLR add or remove a given + descriptor from a set. FD_ISSET tests to see if a + descriptor is part of the set; this is useful after select + returns. + + n is the highest-numbered descriptor in any of the three + sets, plus 1. + + timeout is an upper bound on the amount of time elapsed + before select returns. It may be zero, causing select to + return immediately. If timeout is NULL (no timeout), + select can block indefinitely. + +RETURN VALUE + On success, select returns the number of descriptors con- + tained in the descriptor sets, which may be zero if the + timeout expires before anything interesting happens. On + error, -1 is returned, and errno is set appropriately; the + sets and timeout become undefined, so do not rely on their + contents after an error. + +ERRORS + EBADF An invalid file descriptor was given in one of the + sets. + + EINTR A non blocked signal was caught. + + EINVAL n is negative. + + ENOMEM select was unable to allocate memory for internal + tables. + +NOTES + Some code calls select with all three sets empty, n zero, + and a non-null timeout as a fairly portable way to sleep + with subsecond precision. + +EXAMPLE + #include <stdio.h> + #include <sys/time.h> + #include <sys/types.h> + #include <unistd.h> + + int + main(void) + { + fd_set rfds; + struct timeval tv; + int retval; + + /* Watch stdin (fd 0) to see when it has input. */ + FD_ZERO(&rfds); + FD_SET(0, &rfds); + /* Wait up to five seconds. */ + tv.tv_sec = 5; + tv.tv_usec = 0; + + retval = select(1, &rfds, NULL, NULL, &tv); + /* Don't rely on the value of tv now! */ + + if (retval) + printf("Data is available now.\n"); + /* FD_ISSET(0, &rfds) will be true. */ + else + printf("No data within five seconds.\n"); + + exit(0); + } + + Generally portable to/from non-BSD systems supporting + clones of the BSD socket layer (including System V vari- + ants). However, note that the System V variant typically + sets the timeout variable before exit, but the BSD variant + does not. diff --git a/ecos/packages/net/tcpip/current/doc/sendto.html b/ecos/packages/net/tcpip/current/doc/sendto.html new file mode 100644 index 0000000..c24db85 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/sendto.html @@ -0,0 +1,106 @@ +<html> +<body> +<pre> +NAME + sendto - send a message from a socket + +SYNOPSIS + #include <network.h> + + int sendto(int s, const void *msg, int len, unsigned int + flags, const struct sockaddr *to, int tolen); + +DESCRIPTION + Sendto is used to transmit a message + to another socket. + + The address of the target is given by to with tolen speci + fying its size. The length of the message is given by + len. If the message is too long to pass atomically + through the underlying protocol, the error EMSGSIZE is + returned, and the message is not transmitted. + + No indication of failure to deliver is implicit in a send. + Locally detected errors are indicated by a return value of + -1. + + When the message does not fit into the send buffer of the + socket, send normally blocks, unless the socket has been + placed in non-blocking I/O mode. In non-blocking mode it + would return EAGAIN in this case. The select(2) call may + be used to determine when it is possible to send more + data. + + The flags parameter may include one or more of the follow + ing: + + #define MSG_OOB 0x1 /* process out-of-band data */ + #define MSG_DONTROUTE 0x4 /* bypass routing, use direct interface */ + #define MSG_DONTWAIT 0x40 /* don't block */ + #define MSG_NOSIGNAL 0x2000 /* don't raise SIGPIPE */ + + MSG_OOB + Sends out-of-band data on sockets that support this + notion (e.g. SOCK_STREAM); the underlying protocol + must also support out-of-band data. + + MSG_DONTROUTE + Bypasses the usual routing table lookup and sends + the packet directly to the interface described by + the destination address. This is usually used only + by diagnostic or routing programs. + + MSG_DONTWAIT + Enables non-blocking operation; if the operation + would block, EAGAIN is returned. + + MSG_NOSIGNAL + Requests not to send SIGPIPE on errors on stream + oriented sockets when the other end breaks the con + nection. The EPIPE error is still returned. + + See recv(2) for a description of the msghdr structure. You + may send control information using the msg_control and + msg_controllen members. The maximum control buffer length + the kernel can process is limited by the net.core.opt + mem_max sysctl; see socket(4). + +RETURN VALUES + The calls return the number of characters sent, or -1 if + an error occurred. + +ERRORS + These are some standard errors generated by the socket + layer. Additional errors may be generated and returned + from the underlying protocol modules; see their respective + manual pages. + + EBADF An invalid descriptor was specified. + + ENOTSOCK + The argument s is not a socket. + + EMSGSIZE + The socket requires that message be sent atomi + cally, and the size of the message to be sent made + this impossible. + + EAGAIN The socket is marked non-blocking and the + requested operation would block. + + ENOBUFS The system was unable to allocate an internal mem + ory block. The operation may succeed when buffers + become available. + + EINTR A signal occurred. + + ENOMEM No memory available. + + EINVAL Invalid argument passed. + + EPIPE The local end has been shut down on a connection + oriented socket. In this case the process will + also receive a SIGPIPE unless MSG_NOSIGNAL is set. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/sendto.man b/ecos/packages/net/tcpip/current/doc/sendto.man new file mode 100644 index 0000000..a694f2c --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/sendto.man @@ -0,0 +1,100 @@ +NAME + sendto - send a message from a socket + +SYNOPSIS + #include <network.h> + + int sendto(int s, const void *msg, int len, unsigned int + flags, const struct sockaddr *to, int tolen); + +DESCRIPTION + Sendto is used to transmit a message + to another socket. + + The address of the target is given by to with tolen speci + fying its size. The length of the message is given by + len. If the message is too long to pass atomically + through the underlying protocol, the error EMSGSIZE is + returned, and the message is not transmitted. + + No indication of failure to deliver is implicit in a send. + Locally detected errors are indicated by a return value of + -1. + + When the message does not fit into the send buffer of the + socket, send normally blocks, unless the socket has been + placed in non-blocking I/O mode. In non-blocking mode it + would return EAGAIN in this case. The select(2) call may + be used to determine when it is possible to send more + data. + + The flags parameter may include one or more of the follow + ing: + + #define MSG_OOB 0x1 /* process out-of-band data */ + #define MSG_DONTROUTE 0x4 /* bypass routing, use direct interface */ + #define MSG_DONTWAIT 0x40 /* don't block */ + #define MSG_NOSIGNAL 0x2000 /* don't raise SIGPIPE */ + + MSG_OOB + Sends out-of-band data on sockets that support this + notion (e.g. SOCK_STREAM); the underlying protocol + must also support out-of-band data. + + MSG_DONTROUTE + Bypasses the usual routing table lookup and sends + the packet directly to the interface described by + the destination address. This is usually used only + by diagnostic or routing programs. + + MSG_DONTWAIT + Enables non-blocking operation; if the operation + would block, EAGAIN is returned. + + MSG_NOSIGNAL + Requests not to send SIGPIPE on errors on stream + oriented sockets when the other end breaks the con + nection. The EPIPE error is still returned. + + See recv(2) for a description of the msghdr structure. You + may send control information using the msg_control and + msg_controllen members. The maximum control buffer length + the kernel can process is limited by the net.core.opt + mem_max sysctl; see socket(4). + +RETURN VALUES + The calls return the number of characters sent, or -1 if + an error occurred. + +ERRORS + These are some standard errors generated by the socket + layer. Additional errors may be generated and returned + from the underlying protocol modules; see their respective + manual pages. + + EBADF An invalid descriptor was specified. + + ENOTSOCK + The argument s is not a socket. + + EMSGSIZE + The socket requires that message be sent atomi + cally, and the size of the message to be sent made + this impossible. + + EAGAIN The socket is marked non-blocking and the + requested operation would block. + + ENOBUFS The system was unable to allocate an internal mem + ory block. The operation may succeed when buffers + become available. + + EINTR A signal occurred. + + ENOMEM No memory available. + + EINVAL Invalid argument passed. + + EPIPE The local end has been shut down on a connection + oriented socket. In this case the process will + also receive a SIGPIPE unless MSG_NOSIGNAL is set. diff --git a/ecos/packages/net/tcpip/current/doc/setsockopt.html b/ecos/packages/net/tcpip/current/doc/setsockopt.html new file mode 100644 index 0000000..80015f3 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/setsockopt.html @@ -0,0 +1,72 @@ +<html> +<body> +<pre> +NAME + getsockopt, setsockopt - get and set options on sockets + +SYNOPSIS + #include <network.h> + + int getsockopt(int s, int level, int optname, void *opt + val, socklen_t *optlen); + + int setsockopt(int s, int level, int optname, const void + *optval, socklen_t optlen); + +DESCRIPTION + Getsockopt and setsockopt manipulate the options associ + ated with a socket. Options may exist at multiple proto + col levels; they are always present at the uppermost + socket level. + + When manipulating socket options the level at which the + option resides and the name of the option must be speci + fied. To manipulate options at the socket level, level is + specified as SOL_SOCKET. To manipulate options at any + other level the protocol number of the appropriate proto + col controlling the option is supplied. For example, to + indicate that an option is to be interpreted by the TCP + protocol, level should be set to the protocol number of + TCP; see getprotoent(3). + + The parameters optval and optlen are used to access option + values for setsockopt. For getsockopt they identify a + buffer in which the value for the requested option(s) are + to be returned. For getsockopt, optlen is a value-result + parameter, initially containing the size of the buffer + pointed to by optval, and modified on return to indicate + the actual size of the value returned. If no option value + is to be supplied or returned, optval may be NULL. + + Optname and any specified options are passed uninterpreted + to the appropriate protocol module for interpretation. + The include file <network.h> contains definitions for + socket level options, described below. Options at other + protocol levels vary in format and name; consult the + appropriate entries in section 4 of the manual. + + Most socket-level options utilize an int parameter for + optval. For setsockopt, the parameter should be non-zero + to enable a boolean option, or zero if the option is to be + disabled. + + For a description of the available socket options see + socket(7) and the appropriate protocol man pages. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is a file, not a socket. + + ENOPROTOOPT + The option is unknown at the level indicated. + + +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/setsockopt.man b/ecos/packages/net/tcpip/current/doc/setsockopt.man new file mode 100644 index 0000000..0427e15 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/setsockopt.man @@ -0,0 +1,66 @@ +NAME + getsockopt, setsockopt - get and set options on sockets + +SYNOPSIS + #include <network.h> + + int getsockopt(int s, int level, int optname, void *opt + val, socklen_t *optlen); + + int setsockopt(int s, int level, int optname, const void + *optval, socklen_t optlen); + +DESCRIPTION + Getsockopt and setsockopt manipulate the options associ + ated with a socket. Options may exist at multiple proto + col levels; they are always present at the uppermost + socket level. + + When manipulating socket options the level at which the + option resides and the name of the option must be speci + fied. To manipulate options at the socket level, level is + specified as SOL_SOCKET. To manipulate options at any + other level the protocol number of the appropriate proto + col controlling the option is supplied. For example, to + indicate that an option is to be interpreted by the TCP + protocol, level should be set to the protocol number of + TCP; see getprotoent(3). + + The parameters optval and optlen are used to access option + values for setsockopt. For getsockopt they identify a + buffer in which the value for the requested option(s) are + to be returned. For getsockopt, optlen is a value-result + parameter, initially containing the size of the buffer + pointed to by optval, and modified on return to indicate + the actual size of the value returned. If no option value + is to be supplied or returned, optval may be NULL. + + Optname and any specified options are passed uninterpreted + to the appropriate protocol module for interpretation. + The include file <sys/socket.h> contains definitions for + socket level options, described below. Options at other + protocol levels vary in format and name; consult the + appropriate entries in section 4 of the manual. + + Most socket-level options utilize an int parameter for + optval. For setsockopt, the parameter should be non-zero + to enable a boolean option, or zero if the option is to be + disabled. + + For a description of the available socket options see + socket(7) and the appropriate protocol man pages. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF The argument s is not a valid descriptor. + + ENOTSOCK + The argument s is a file, not a socket. + + ENOPROTOOPT + The option is unknown at the level indicated. + + diff --git a/ecos/packages/net/tcpip/current/doc/shutdown.html b/ecos/packages/net/tcpip/current/doc/shutdown.html new file mode 100644 index 0000000..919ebd4 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/shutdown.html @@ -0,0 +1,33 @@ +<html> +<body> +<pre> +NAME + shutdown - shut down part of a full-duplex connection + +SYNOPSIS + #include <network.h> + + int shutdown(int s, int how); + +DESCRIPTION + The shutdown call causes all or part of a full-duplex con- + nection on the socket associated with s to be shut down. + If how is 0, further receives will be disallowed. If how + is 1, further sends will be disallowed. If how is 2, fur- + ther sends and receives will be disallowed. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF s is not a valid descriptor. + + ENOTSOCK + s is a file, not a socket. + + ENOTCONN + The specified socket is not connected. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/shutdown.man b/ecos/packages/net/tcpip/current/doc/shutdown.man new file mode 100644 index 0000000..668f55f --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/shutdown.man @@ -0,0 +1,27 @@ +NAME + shutdown - shut down part of a full-duplex connection + +SYNOPSIS + #include <network.h> + + int shutdown(int s, int how); + +DESCRIPTION + The shutdown call causes all or part of a full-duplex con- + nection on the socket associated with s to be shut down. + If how is 0, further receives will be disallowed. If how + is 1, further sends will be disallowed. If how is 2, fur- + ther sends and receives will be disallowed. + +RETURN VALUE + On success, zero is returned. On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF s is not a valid descriptor. + + ENOTSOCK + s is a file, not a socket. + + ENOTCONN + The specified socket is not connected. diff --git a/ecos/packages/net/tcpip/current/doc/socket.html b/ecos/packages/net/tcpip/current/doc/socket.html new file mode 100644 index 0000000..f560bd6 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/socket.html @@ -0,0 +1,117 @@ +<html> +<body> +<pre> +NAME + socket - create an endpoint for communication + +SYNOPSIS + #include <network.h> + + int socket(int domain, int type, int protocol); + +DESCRIPTION + Socket creates an endpoint for communication and returns a + descriptor. + + The domain parameter specifies a communications domain + within which communication will take place; this selects + the protocol family which should be used. These families + are defined in <network.h>. The currently understood + formats include: + + PF_INET + IPv4 Internet protocols; see ip(4) + + The socket has the indicated type, which specifies the + semantics of communication. Currently defined types are: + + SOCK_STREAM + Provides sequenced, reliable, two-way connection- + based byte streams. An out-of-band data transmis- + sion mechanism may be supported. + + SOCK_DGRAM + Supports datagrams (connectionless, unreliable mes- + sages of a fixed maximum length). + + SOCK_SEQPACKET + Provides a sequenced, reliable, two-way connection- + based data transmission path for datagrams of fixed + maximum length; a consumer is required to read an + entire packet with each read system call. + + SOCK_RAW + Provides raw network protocol access. + + The protocol specifies a particular protocol to be used + with the socket. Normally only a single protocol exists + to support a particular socket type within a given proto- + col family. However, it is possible that many protocols + may exist, in which case a particular protocol must be + specified in this manner. The protocol number to use is + particular to the "communication domain" in which communi- + cation is to take place; see protocols(5). See getpro- + toent(3) on how to map protocol name strings to protocol + numbers. + + Sockets of type SOCK_STREAM are full-duplex byte streams, + similar to pipes. A stream socket must be in a connected + state before any data may be sent or received on it. A + connection to another socket is created with a connect(2) + call. Once connected, data may be transferred using + read(2) and write(2) calls or some variant of the send(2) + and recv(2) calls. When a session has been completed a + close(2) may be performed. Out-of-band data may also be + transmitted as described in send(2) and received as + described in recv(2). + + The communications protocols which implement a SOCK_STREAM + ensure that data is not lost or duplicated. If a piece of + data for which the peer protocol has buffer space cannot + be successfully transmitted within a reasonable length of + time, then the connection is considered When SO_KEEPALIVE + is enabled on the socket the protocol checks in a proto- + col-specific manner if the other end is still alive. + + SOCK_DGRAM and SOCK_RAW sockets allow sending of datagrams + to correspondents named in send(2) calls. Datagrams are + generally received with recvfrom(2), which returns the + next datagram with its return address. + + When the network signals an error condition to the proto- + col module (e.g. using a ICMP message for IP) the pending + error flag is set for the socket. The next operation on + this socket will return the error code of the pending + error. For some protocols it is possible to enable a per- + socket error queue to retrieve detailed information about + the error; see IP_RECVERR in ip(4). + + The operation of sockets is controlled by socket level + options. These options are defined in <sys/socket.h>. + Setsockopt(2) and getsockopt(2) are used to set and get + options, respectively. + +RETURN VALUES + -1 is returned if an error occurs; otherwise the return + value is a descriptor referencing the socket. + +ERRORS + EPROTONOSUPPORT + The protocol type or the specified protocol is not + supported within this domain. + + EMFILE There are too many open files. + + EACCES Permission to create a socket of the specified + type and/or protocol is denied. + + ENOBUFS or ENOMEM + Insufficient memory is available. The socket can- + not be created until sufficient resources are + freed. + + EINVAL Unknown protocol, or protocol family not avail- + able. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/socket.man b/ecos/packages/net/tcpip/current/doc/socket.man new file mode 100644 index 0000000..cc5f18a --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/socket.man @@ -0,0 +1,111 @@ +NAME + socket - create an endpoint for communication + +SYNOPSIS + #include <network.h> + + int socket(int domain, int type, int protocol); + +DESCRIPTION + Socket creates an endpoint for communication and returns a + descriptor. + + The domain parameter specifies a communications domain + within which communication will take place; this selects + the protocol family which should be used. These families + are defined in <sys/socket.h>. The currently understood + formats include: + + PF_INET + IPv4 Internet protocols; see ip(4) + + The socket has the indicated type, which specifies the + semantics of communication. Currently defined types are: + + SOCK_STREAM + Provides sequenced, reliable, two-way connection- + based byte streams. An out-of-band data transmis- + sion mechanism may be supported. + + SOCK_DGRAM + Supports datagrams (connectionless, unreliable mes- + sages of a fixed maximum length). + + SOCK_SEQPACKET + Provides a sequenced, reliable, two-way connection- + based data transmission path for datagrams of fixed + maximum length; a consumer is required to read an + entire packet with each read system call. + + SOCK_RAW + Provides raw network protocol access. + + The protocol specifies a particular protocol to be used + with the socket. Normally only a single protocol exists + to support a particular socket type within a given proto- + col family. However, it is possible that many protocols + may exist, in which case a particular protocol must be + specified in this manner. The protocol number to use is + particular to the "communication domain" in which communi- + cation is to take place; see protocols(5). See getpro- + toent(3) on how to map protocol name strings to protocol + numbers. + + Sockets of type SOCK_STREAM are full-duplex byte streams, + similar to pipes. A stream socket must be in a connected + state before any data may be sent or received on it. A + connection to another socket is created with a connect(2) + call. Once connected, data may be transferred using + read(2) and write(2) calls or some variant of the send(2) + and recv(2) calls. When a session has been completed a + close(2) may be performed. Out-of-band data may also be + transmitted as described in send(2) and received as + described in recv(2). + + The communications protocols which implement a SOCK_STREAM + ensure that data is not lost or duplicated. If a piece of + data for which the peer protocol has buffer space cannot + be successfully transmitted within a reasonable length of + time, then the connection is considered When SO_KEEPALIVE + is enabled on the socket the protocol checks in a proto- + col-specific manner if the other end is still alive. + + SOCK_DGRAM and SOCK_RAW sockets allow sending of datagrams + to correspondents named in send(2) calls. Datagrams are + generally received with recvfrom(2), which returns the + next datagram with its return address. + + When the network signals an error condition to the proto- + col module (e.g. using a ICMP message for IP) the pending + error flag is set for the socket. The next operation on + this socket will return the error code of the pending + error. For some protocols it is possible to enable a per- + socket error queue to retrieve detailed information about + the error; see IP_RECVERR in ip(4). + + The operation of sockets is controlled by socket level + options. These options are defined in <sys/socket.h>. + Setsockopt(2) and getsockopt(2) are used to set and get + options, respectively. + +RETURN VALUES + -1 is returned if an error occurs; otherwise the return + value is a descriptor referencing the socket. + +ERRORS + EPROTONOSUPPORT + The protocol type or the specified protocol is not + supported within this domain. + + EMFILE There are too many open files. + + EACCES Permission to create a socket of the specified + type and/or protocol is denied. + + ENOBUFS or ENOMEM + Insufficient memory is available. The socket can- + not be created until sufficient resources are + freed. + + EINVAL Unknown protocol, or protocol family not avail- + able. diff --git a/ecos/packages/net/tcpip/current/doc/tcpip_config.html b/ecos/packages/net/tcpip/current/doc/tcpip_config.html new file mode 100644 index 0000000..d9253c1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/tcpip_config.html @@ -0,0 +1,22 @@ +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; U; Linux 2.2.10 i686) [Netscape]"> +</head> +<body> + +<center> +<h1> +eCos TCP/IP Package Configuration</h1></center> + Follow these steps to enable networking: +<blockquote><tt>% ecosconfig add CYGPKG_NET</tt> +<br><tt>% ecosconfig add CYGPKG_NET_ETH_DRIVERS</tt></blockquote> +For the Motorola PowerPC (MBX/860) board: +<blockquote><tt>% ecosconfig add CYGPKG_NET_QUICC_ETH_DRIVERS</tt></blockquote> +For the Cirrus Logic EDB7xxx board: +<blockquote><tt>% ecosconfig add CYGPKG_NET_EDB7XXX_ETH_DRIVERS</tt></blockquote> + +<br> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/tcpip_library.html b/ecos/packages/net/tcpip/current/doc/tcpip_library.html new file mode 100644 index 0000000..b51177c --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/tcpip_library.html @@ -0,0 +1,77 @@ +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; I; Linux 2.2.14 ppc) [Netscape]"> +</head> +<body> + +<center> +<h1> +TCP/IP Library Reference</h1></center> + +<li> +<a href="accept.html">accept</a></li> + +<li> +<a href="bind.html">bind</a></li> + +<li> +<a href="close.html">close</a></li> + +<li> +<a href="connect.html">connect</a></li> + +<li> +<a href="gethost.html">gethostbyname, gethostbyaddr</a></li> + +<li> +<a href="getpeername.html">getpeername</a></li> + +<li> +<a href="getproto.html">getprotobyname, getprotobynumber</a></li> + +<li> +<a href="getserv.html">getservbyname, getservbyport</a></li> + +<li> +<a href="getsockname.html">getsockname</a></li> + +<li> +<a href="getsockopt.html">getsockopt</a></li> + +<li> +<a href="inet_addr.html">inet_aton, inet_addr, inet_addr</a></li> + +<li> +<a href="ioctl.html">ioctl</a></li> + +<li> +<a href="listen.html">listen</a></li> + +<li> +<a href="read.html">read</a></li> + +<li> +<a href="recvfrom.html">recvfrom</a></li> + +<li> +<a href="select.html">select</a></li> + +<li> +<a href="sendto.html">sendto</a></li> + +<li> +<a href="setsockopt.html">setsockopt</a></li> + +<li> +<a href="shutdown.html">shutdown</a></li> + +<li> +<a href="socket.html">socket</a></li> + +<li> +<a href="write.html">write</a></li> + +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/tcpip_tests.html b/ecos/packages/net/tcpip/current/doc/tcpip_tests.html new file mode 100644 index 0000000..cc258f3 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/tcpip_tests.html @@ -0,0 +1,98 @@ +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; I; Linux 2.2.14 ppc) [Netscape]"> +</head> +<body> + +<center> +<h1> +eCos TCP/IP Networking Tests and Examples</h1></center> +A number of test/example programs are currently provided with the TCP/IP +networking package. These are not "tests" in the traditional eCos +test suite sense, but rather simple programs which exercise various parts +of the networking stack. Also included are a set of performance tests, +used to measure throughput and latency in an embedded eCos system. +<p>The following paragraphs list the various tests and how they might be +used. They are enumerated in the order in which they should +be run to verify a system configuration. +<p>Note: none of these tests are built by default. The user must +enable the <b><tt>CYGPKG_NET_BUILD_TESTS </tt></b>option and then "<tt>make +tests</tt>" to create them for the target environment. Also, these +tests require that the hardware interfaces be configured to use either +BOOTP or static initialization methods. +<h3> +mbuf_test.c</h3> +This should be the first test run on a new system. It simply tests +that the networking system can be initialized and that the internal memory +management (used by the stack) is functioning. +<h3> +socket_test.c</h3> +This test exercises some of the basic library interfaces. +<h3> +server_test.c</h3> +This test creates a server process on the target hardware which listens +on port TCP/7734. To verify that it is working, try to connect to +this port from some other [host] system. E.g. on Linux, use the command +"<tt>telnet <i>eCos</i> 7734</tt>", where "<i><tt>eCos</tt></i>" is the +name associated with the target hardware. Once connected, the eCos +application will respond with a "Hello" message and wait for a single line +of input text, which will be displayed on the diagnostic channel of the +target system. +<h3> +ping_test.c</h3> +This tests attempts to issue an ICMP "echo" request to the "server" host +(provided as part of the BOOTP or static configuration information). +The output will be similar to the analogous Linux program, "<tt>ping</tt>". +The test program also attempts to ping an additional host whose IP address +is the server IP+32. This second test is present to verify that the +ICMP (actually <tt>receive</tt>) time-out mechanism is working (assuming +that the second host is non-existent). +<h3> +ftp_test.c</h3> +This test attempts to make a connection to an FTP server, assuming the +default server host. This is an additional test which verifies that +the basic TCP functionality is working. +<h3> +nc_test_master.c</h3> + +<h3> +nc_test_slave.c</h3> +This pair of programs can be used to measure throughput and latencies in +the target system. While both programs have been written in such +a way that they can be built and used on either Linux or eCos, the primary +use will be to run the "<tt>nc_test_master</tt>" program on a Linux host +and the "<tt>nc_test_slave</tt>" on the target hardware. If run in +this configuration, the master program will attempt to connect to the slave +and make various measurements using both UDP and TCP protocols. Additionally, +measurements will be made on an eCos slave of the actual CPU utilization +by the networking stack. +<p>To build the Linux versions, simply execute (in the eCos source tree, +not the install tree): +<blockquote><tt>make -f make.linux</tt></blockquote> + +<h3> +tcp_echo.c</h3> + +<h3> +tcp_sink.c</h3> + +<h3> +tcp_source.c</h3> +This set of programs is similar to the <i><tt>nc_test_XXX</tt></i> programs +described above. However, they are designed to measure overall throughput +of the eCos system. The setup allows for one Linux host to run "<tt>tcp_source +<i>eCos</i></tt>" and another Linux host to run "<tt>tcp_sink <i>eCos</i></tt>". +The "<tt>tcp_echo</tt>" program is run on the target hardware. The +tests then measure the throughput and latency of sending TCP data from +one host, though the eCos target system and on to another host. Note: +the two Linux host systems may be the same computer in which case this +becomes a single wire echo test. This test suite is unique in that +it attempts to load the target system down with additional background processing +at various levels. This is done to simulate a real world environment +where the networking is ancillary to the main processing on the target +system. +<br> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/write.html b/ecos/packages/net/tcpip/current/doc/write.html new file mode 100644 index 0000000..a130784 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/write.html @@ -0,0 +1,42 @@ +<html> +<body> +<pre> +NAME + write - write to a file descriptor + +SYNOPSIS + ssize_t write(int fd, const void *buf, size_t count); + +DESCRIPTION + write writes up to count bytes to the file referenced by + the file descriptor fd from the buffer starting at buf. + +RETURN VALUE + On success, the number of bytes written are returned (zero + indicates nothing was written). On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF fd is not a valid file descriptor or is not open + for writing. + + EINVAL fd is attached to an object which is unsuitable for + writing. + + EPIPE fd is connected to a socket whose reading + end is closed. + + EAGAIN Non-blocking I/O has been selected using O_NONBLOCK + and there was no room in the pipe or socket con + nected to fd to write the data immediately. + + EINTR The call was interrupted before any + data was written. + + ENOSPC The device containing the file referred to by fd + has no room for the data. + + EIO A low-level I/O error occurred. +</pre> +</body> +</html> diff --git a/ecos/packages/net/tcpip/current/doc/write.man b/ecos/packages/net/tcpip/current/doc/write.man new file mode 100644 index 0000000..b0861f3 --- /dev/null +++ b/ecos/packages/net/tcpip/current/doc/write.man @@ -0,0 +1,36 @@ +NAME + write - write to a file descriptor + +SYNOPSIS + ssize_t write(int fd, const void *buf, size_t count); + +DESCRIPTION + write writes up to count bytes to the file referenced by + the file descriptor fd from the buffer starting at buf. + +RETURN VALUE + On success, the number of bytes written are returned (zero + indicates nothing was written). On error, -1 is returned, + and errno is set appropriately. + +ERRORS + EBADF fd is not a valid file descriptor or is not open + for writing. + + EINVAL fd is attached to an object which is unsuitable for + writing. + + EPIPE fd is connected to a socket whose reading + end is closed. + + EAGAIN Non-blocking I/O has been selected using O_NONBLOCK + and there was no room in the pipe or socket con + nected to fd to write the data immediately. + + EINTR The call was interrupted before any + data was written. + + ENOSPC The device containing the file referred to by fd + has no room for the data. + + EIO A low-level I/O error occurred. diff --git a/ecos/packages/net/tcpip/current/include/lib/libkern/libkern.h b/ecos/packages/net/tcpip/current/include/lib/libkern/libkern.h new file mode 100644 index 0000000..25c0245 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/lib/libkern/libkern.h @@ -0,0 +1,217 @@ +//========================================================================== +// +// include/lib/libkern/libkern.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: libkern.h,v 1.14 1997/11/30 21:47:45 mickey Exp $ */ +/* $NetBSD: libkern.h,v 1.7 1996/03/14 18:52:08 christos Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)libkern.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef __LIBKERN_H__ +#define __LIBKERN_H__ + +#ifdef __INSIDE_NET + +#include <sys/types.h> + +#ifndef LIBKERN_INLINE +#ifndef NO_LIBKERN_INLINE +#define LIBKERN_INLINE static __inline +#define LIBKERN_BODY +#else +#define LIBKERN_INLINE +#endif +#endif + + +LIBKERN_INLINE int imax __P((int, int)); +LIBKERN_INLINE int imin __P((int, int)); +LIBKERN_INLINE u_int max __P((u_int, u_int)); +LIBKERN_INLINE u_int min __P((u_int, u_int)); +LIBKERN_INLINE long lmax __P((long, long)); +LIBKERN_INLINE long lmin __P((long, long)); +LIBKERN_INLINE u_long ulmax __P((u_long, u_long)); +LIBKERN_INLINE u_long ulmin __P((u_long, u_long)); +LIBKERN_INLINE int abs __P((int)); + +#ifdef LIBKERN_BODY +LIBKERN_INLINE int +imax(a, b) + int a, b; +{ + return (a > b ? a : b); +} +LIBKERN_INLINE int +imin(a, b) + int a, b; +{ + return (a < b ? a : b); +} +LIBKERN_INLINE long +lmax(a, b) + long a, b; +{ + return (a > b ? a : b); +} +LIBKERN_INLINE long +lmin(a, b) + long a, b; +{ + return (a < b ? a : b); +} +LIBKERN_INLINE u_int +max(a, b) + u_int a, b; +{ + return (a > b ? a : b); +} +LIBKERN_INLINE u_int +min(a, b) + u_int a, b; +{ + return (a < b ? a : b); +} +LIBKERN_INLINE u_long +ulmax(a, b) + u_long a, b; +{ + return (a > b ? a : b); +} +LIBKERN_INLINE u_long +ulmin(a, b) + u_long a, b; +{ + return (a < b ? a : b); +} + +LIBKERN_INLINE int +abs(j) + int j; +{ + return(j < 0 ? -j : j); +} +#endif + +#ifndef __ECOS +#ifdef NDEBUG /* tradition! */ +#define assert(e) ((void)0) +#else +#ifdef __STDC__ +#define assert(e) ((e) ? (void)0 : \ + __assert("", __FILE__, __LINE__, #e)) +#else +#define assert(e) ((e) ? (void)0 : \ + __assert("", __FILE__, __LINE__, "e")) +#endif +#endif + +#ifndef DIAGNOSTIC +#define KASSERT(e) ((void)0) +#else +#ifdef __STDC__ +#define KASSERT(e) ((e) ? (void)0 : \ + __assert("diagnostic ", __FILE__, __LINE__, #e)) +#else +#define KASSERT(e) ((e) ? (void)0 : \ + __assert("diagnostic ", __FILE__, __LINE__, "e")) +#endif +#endif + +#ifndef DEBUG +#define KDASSERT(e) ((void)0) +#else +#ifdef __STDC__ +#define KDASSERT(e) ((e) ? (void)0 : \ + __assert("debugging ", __FILE__, __LINE__, #e)) +#else +#define KDASSERT(e) ((e) ? (void)0 : \ + __assert("debugging ", __FILE__, __LINE__, "e")) +#endif +#endif +#endif + +/* Prototypes for non-quad routines. */ +#ifndef __ECOS +void __assert __P((const char *, const char *, int, const char *)) + __attribute__ ((__noreturn__)); +#endif +int bcmp __P((const void *, const void *, size_t)); +int ffs __P((int)); +int locc __P((int, char *, u_int)); +void *memchr __P((const void *, int, size_t)); +int scanc __P((u_int, const u_char *, const u_char *, int)); +int skpc __P((int, size_t, u_char *)); +size_t strlen __P((const char *)); +char *strcat __P((char *, const char *)); +char *strcpy __P((char *, const char *)); +char *strncpy __P((char *, const char *, size_t)); +int strcmp __P((const char *, const char *)); +int strncmp __P((const char *, const char *, size_t)); +int strncasecmp __P((const char *, const char *, size_t)); +int getsn __P((char *, int)); + +extern u_int8_t const __bcd2bin[], __bin2bcd[]; +#define bcd2bin(b) (__bcd2bin[(b)&0xff]) +#define bin2bcd(b) (__bin2bcd[(b)&0xff]) + +#endif /* __INSIDE_NET */ + +#endif /* __LIBKERN_H__ */ diff --git a/ecos/packages/net/tcpip/current/include/machine/cdefs.h b/ecos/packages/net/tcpip/current/include/machine/cdefs.h new file mode 100644 index 0000000..fe027bf --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/machine/cdefs.h @@ -0,0 +1,33 @@ +//========================================================================== +// +// include/machine/cdefs.h +// +// Architecture/platform specific parameters +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#endif // _MACHINE_CDEFS_H_ diff --git a/ecos/packages/net/tcpip/current/include/machine/cpu.h b/ecos/packages/net/tcpip/current/include/machine/cpu.h new file mode 100644 index 0000000..cd0c166 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/machine/cpu.h @@ -0,0 +1,33 @@ +//========================================================================== +// +// include/machine/cpu.h +// +// Architecture/platform specific parameters +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +#endif // _MACHINE_CPU_H_ diff --git a/ecos/packages/net/tcpip/current/include/machine/limits.h b/ecos/packages/net/tcpip/current/include/machine/limits.h new file mode 100644 index 0000000..516be12 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/machine/limits.h @@ -0,0 +1,35 @@ +//========================================================================== +// +// include/machine/limits.h +// +// Architecture/platform specific limits +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include <limits.h> // Compiler provided + +#endif /* _MACHINE_LIMITS_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/machine/param.h b/ecos/packages/net/tcpip/current/include/machine/param.h new file mode 100644 index 0000000..5f41b25 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/machine/param.h @@ -0,0 +1,138 @@ +//========================================================================== +// +// include/machine/param.h +// +// Architecture/platform specific parameters +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#include <pkgconf/net.h> + +/* + * Constants related to network buffer management. + * MCLBYTES must be no larger than CLBYTES (the software page size), and, + * on machines that exchange pages of input or output buffers with mbuf + * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple + * of the hardware page size. + */ +#define MSIZE 128 /* size of an mbuf */ +#define MCLSHIFT 11 /* convert bytes to m_buf clusters */ +#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */ +#define MCLOFSET (MCLBYTES - 1) /* offset within a m_buf cluster */ +#define CLBYTES 4096 /* size of actual cluster */ + +/* + * Round p (pointer or byte index) up to a correctly-aligned value + * for all data types (int, long, ...). The result is u_int and + * must be cast to any desired pointer type. + */ +#define ALIGNBYTES (sizeof(int) - 1) +#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES) + +// These symbols are used in the IPV6 stuff +// (be more defensive about external setup) +#ifdef __linux__ +#undef __linux__ +#endif +#ifdef __bsdi__ +#undef __bsdi__ +#endif +#ifdef __FreeBSD__ +#undef __FreeBSD__ +#endif +#ifdef __OpenBSD__ +#undef __OpenBSD__ +#endif +#ifdef __NetBSD__ +#undef __NetBSD__ +#endif + + +#define __linux__ 0 +#define __bsdi__ 0 +#define __FreeBSD__ 0 +#define __OpenBSD__ 1 +#define __NetBSD__ 0 + +// These definitions here to avoid needing <sys/systm.h> +// This probably doesn't belong here, but we need these definitions +#include <lib/libkern/libkern.h> +#define SCARG(p,k) ((p)->k.datum) /* get arg from args pointer */ +#include <stdarg.h> + +// TEMP + +#include <cyg/infra/diag.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/kernel/kapi.h> +#include <cyg/io/file.h> + +struct net_stats { + int count; + cyg_uint32 min_time, max_time, total_time; +}; + +#ifdef CYGDBG_NET_TIMING_STATS +#define START_STATS() \ + cyg_uint32 start_time, end_time, elapsed_time; \ + HAL_CLOCK_READ(&start_time); +#define FINISH_STATS(stats) \ + HAL_CLOCK_READ(&end_time); \ + if (end_time < start_time) { \ + elapsed_time = (end_time+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - start_time; \ + } else { \ + elapsed_time = end_time - start_time; \ + } \ + if (stats.min_time == 0) { \ + stats.min_time = 0x7FFFFFFF; \ + } \ + if (elapsed_time < stats.min_time) \ + stats.min_time = elapsed_time; \ + if (elapsed_time > stats.max_time) \ + stats.max_time = elapsed_time; \ + stats.total_time += elapsed_time; \ + stats.count++; +#else +#define START_STATS() +#define FINISH_STATS(X) +#endif + +// timeout support +typedef void (timeout_fun)(void *); +extern cyg_uint32 timeout(timeout_fun *fun, void *arg, cyg_int32 delta); +extern void untimeout(timeout_fun *fun, void *arg); +extern int uiomove(caddr_t cp, int n, struct uio *uio); +extern int copyout(const void *s, void *d, size_t len); +extern int copyin(const void *s, void *d, size_t len); +extern void ovbcopy(const void *s, void *d, size_t len); +extern void get_mono_time(void); +extern int arc4random(void); +extern void get_random_bytes(void *buf, size_t len); + +extern void *hashinit(int elements, int type, int flags, u_long *hashmask); + +#endif // _MACHINE_PARAM_H_ diff --git a/ecos/packages/net/tcpip/current/include/machine/signal.h b/ecos/packages/net/tcpip/current/include/machine/signal.h new file mode 100644 index 0000000..713237f --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/machine/signal.h @@ -0,0 +1,30 @@ +//========================================================================== +// +// include/machine/signal.h +// +// Architecture specific 'signal' support +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +// None defined diff --git a/ecos/packages/net/tcpip/current/include/machine/stdarg.h b/ecos/packages/net/tcpip/current/include/machine/stdarg.h new file mode 100644 index 0000000..e691eb3 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/machine/stdarg.h @@ -0,0 +1,31 @@ +//========================================================================== +// +// include/machine/stdarg.h +// +// Architecture/compiler specifics +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +// Get this from the compiler +#include <stdarg.h> diff --git a/ecos/packages/net/tcpip/current/include/machine/types.h b/ecos/packages/net/tcpip/current/include/machine/types.h new file mode 100644 index 0000000..255d94d --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/machine/types.h @@ -0,0 +1,84 @@ +//========================================================================== +// +// include/machine/types.h +// +// Architecture/platform specific support for data types +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#ifndef _MACHINE_TYPES_H_ +#define _MACHINE_TYPES_H_ + +#include <sys/cdefs.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/hal/hal_arch.h> + +#define __BIT_TYPES_DEFINED__ +typedef __signed char int8_t; +typedef unsigned char u_int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short u_int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int u_int32_t; +typedef unsigned int uint32_t; +typedef long long int64_t; +typedef unsigned long long u_int64_t; +typedef unsigned long long uint64_t; + +// Types inherited from HAL + +typedef CYG_ADDRESS vaddr_t; +typedef CYG_ADDRWORD vsize_t; +typedef CYG_ADDRESS paddr_t; +typedef CYG_ADDRWORD psize_t; + +typedef CYG_ADDRESS vm_offset_t; +typedef CYG_ADDRWORD vm_size_t; + +// No good HAL definition for this + +typedef CYG_ADDRWORD register_t; + + +// From <arch/ansi.h> +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _BSD_SIZE_T_ + * typedef _BSD_SIZE_T_ size_t; + * #undef _BSD_SIZE_T_ + * #endif + */ +#define _BSD_SSIZE_T_ int /* byte count or error */ +#define _BSD_CLOCKID_T_ int +#define _BSD_TIMER_T_ int +#ifndef __time_t_defined // As defined/used by eCos libc +#define _BSD_CLOCK_T_ cyg_int64 /* clock() */ +#define _BSD_TIME_T_ cyg_count32 /* time() */ +#endif + +#endif // _MACHINE_TYPES_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/bpf.h b/ecos/packages/net/tcpip/current/include/net/bpf.h new file mode 100644 index 0000000..47665ba --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/bpf.h @@ -0,0 +1,307 @@ +//========================================================================== +// +// include/net/bpf.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: bpf.h,v 1.12 1999/08/08 00:43:00 niklas Exp $ */ +/* $NetBSD: bpf.h,v 1.15 1996/12/13 07:57:33 mikel Exp $ */ + +/* + * Copyright (c) 1990, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_BPF_H_ +#define _NET_BPF_H_ + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +typedef int32_t bpf_int32; +typedef u_int32_t bpf_u_int32; +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next even multiple of + * BPF_ALIGNMENT (which is at least as much as what a timeval needs). + */ +#define BPF_ALIGNMENT sizeof(long) +#define BPF_WORDALIGN(x) (((x) + (BPF_ALIGNMENT - 1)) & ~(BPF_ALIGNMENT - 1)) + +#define BPF_MAXINSNS 512 +#define BPF_MAXBUFSIZE 0x80000 +#define BPF_MINBUFSIZE 32 + +/* + * Structure for BIOCSETF. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct returned by BIOCGSTATS. + */ +struct bpf_stat { + u_int bs_recv; /* number of packets received */ + u_int bs_drop; /* number of packets dropped */ +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * BPF ioctls + * + * The first set is for compatibility with Sun's pcc style + * header files. If you're using gcc, we assume that you + * have run fixincludes so the latter set should work. + */ +#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__) +#define BIOCGBLEN _IOR(B,102, u_int) +#define BIOCSBLEN _IOWR(B,102, u_int) +#define BIOCSETF _IOW(B,103, struct bpf_program) +#define BIOCFLUSH _IO(B,104) +#define BIOCPROMISC _IO(B,105) +#define BIOCGDLT _IOR(B,106, u_int) +#define BIOCGETIF _IOR(B,107, struct ifreq) +#define BIOCSETIF _IOW(B,108, struct ifreq) +#define BIOCSRTIMEOUT _IOW(B,109, struct timeval) +#define BIOCGRTIMEOUT _IOR(B,110, struct timeval) +#define BIOCGSTATS _IOR(B,111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW(B,112, u_int) +#define BIOCVERSION _IOR(B,113, struct bpf_version) +#define BIOCSRSIG _IOW(B,114, u_int) +#define BIOCGRSIG _IOR(B,115, u_int) +#else +#define BIOCGBLEN _IOR('B',102, u_int) +#define BIOCSBLEN _IOWR('B',102, u_int) +#define BIOCSETF _IOW('B',103, struct bpf_program) +#define BIOCFLUSH _IO('B',104) +#define BIOCPROMISC _IO('B',105) +#define BIOCGDLT _IOR('B',106, u_int) +#define BIOCGETIF _IOR('B',107, struct ifreq) +#define BIOCSETIF _IOW('B',108, struct ifreq) +#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) +#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) +#define BIOCGSTATS _IOR('B',111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW('B',112, u_int) +#define BIOCVERSION _IOR('B',113, struct bpf_version) +#define BIOCSRSIG _IOW('B',114, u_int) +#define BIOCGRSIG _IOR('B',115, u_int) +#endif + +/* + * Structure prepended to each packet. + */ +struct bpf_hdr { + struct timeval bh_tstamp; /* time stamp */ + u_int32_t bh_caplen; /* length of captured portion */ + u_int32_t bh_datalen; /* original length of packet */ + u_int16_t bh_hdrlen; /* length of bpf header (this struct + plus alignment padding) */ +}; +/* + * Because the structure above is not a multiple of 4 bytes, some compilers + * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. + * Only the kernel needs to know about it; applications use bh_hdrlen. + * XXX To save a few bytes on 32-bit machines, we avoid end-of-struct + * XXX padding by using the size of the header data elements. This is + * XXX fail-safe: on new machines, we just use the 'safe' sizeof. + */ +#ifdef _KERNEL +#if defined(__arm32__) || defined(__i386__) || defined(__m68k__) || \ + defined(__mips__) || defined(__ns32k__) || defined(__sparc__) || \ + defined(__vax__) +#define SIZEOF_BPF_HDR 18 +#else +#define SIZEOF_BPF_HDR sizeof(struct bpf_hdr) +#endif +#endif + +/* + * Data-link level type codes. + */ +#define DLT_NULL 0 /* no link-layer encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* IEEE 802 Networks */ +#define DLT_ARCNET 7 /* ARCNET */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_LOOP 12 /* loopback type (af header) */ +#define DLT_ENC 13 /* IPSEC enc type (af header, spi, flags) */ +#define DLT_RAW 14 /* raw IP */ +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_int16_t code; + u_char jt; + u_char jf; + int32_t k; +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_int16_t)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_int16_t)(code), jt, jf, k } + +#ifdef _KERNEL +int bpf_validate __P((struct bpf_insn *, int)); +void bpf_tap __P((caddr_t, u_char *, u_int)); +void bpf_mtap __P((caddr_t, struct mbuf *)); +void bpfattach __P((caddr_t *, struct ifnet *, u_int, u_int)); +void bpfdetach __P((struct ifnet *)); +void bpfilterattach __P((int)); +u_int bpf_filter __P((struct bpf_insn *, u_char *, u_int, u_int)); +#endif + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +extern int ticks; /* from kern/kern_clock.c; incremented each */ + /* clock tick. */ + +#endif /* _NET_BPF_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/net/bpfdesc.h b/ecos/packages/net/tcpip/current/include/net/bpfdesc.h new file mode 100644 index 0000000..5ab584f --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/bpfdesc.h @@ -0,0 +1,141 @@ +//========================================================================== +// +// include/net/bpfdesc.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: bpfdesc.h,v 1.5 1999/08/08 00:43:00 niklas Exp $ */ +/* $NetBSD: bpfdesc.h,v 1.11 1995/09/27 18:30:42 thorpej Exp $ */ + +/* + * Copyright (c) 1990, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpfdesc.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_BPFDESC_H_ +#define _NET_BPFDESC_H_ + +#include <sys/select.h> + +/* + * Descriptor associated with each open bpf file. + */ +struct bpf_d { + struct bpf_d *bd_next; /* Linked list of descriptors */ + /* + * Buffer slots: two mbuf clusters buffer the incoming packets. + * The model has three slots. Sbuf is always occupied. + * sbuf (store) - Receive interrupt puts packets here. + * hbuf (hold) - When sbuf is full, put cluster here and + * wakeup read (replace sbuf with fbuf). + * fbuf (free) - When read is done, put cluster here. + * On receiving, if sbuf is full and fbuf is 0, packet is dropped. + */ + caddr_t bd_sbuf; /* store slot */ + caddr_t bd_hbuf; /* hold slot */ + caddr_t bd_fbuf; /* free slot */ + int bd_slen; /* current length of store buffer */ + int bd_hlen; /* current length of hold buffer */ + + int bd_bufsize; /* absolute length of buffers */ + + struct bpf_if * bd_bif; /* interface descriptor */ + u_long bd_rtout; /* Read timeout in 'ticks' */ + u_long bd_rdStart; /* when the read started */ + struct bpf_insn *bd_filter; /* filter code */ + u_long bd_rcount; /* number of packets received */ + u_long bd_dcount; /* number of packets dropped */ + + u_char bd_promisc; /* true if listening promiscuously */ + u_char bd_state; /* idle, waiting, or timed out */ + u_char bd_immediate; /* true to return on packet arrival */ + int bd_async; /* non-zero if packet reception should generate signal */ + int bd_sig; /* signal to send upon packet reception */ + pid_t bd_pgid; /* process or group id for signal */ + uid_t bd_siguid; /* uid for process that set pgid */ + uid_t bd_sigeuid; /* euid for process that set pgid */ +#if BSD < 199103 + u_char bd_selcoll; /* true if selects collide */ + int bd_timedout; + struct proc * bd_selproc; /* process that last selected us */ +#else + u_char bd_pad; /* explicit alignment */ + struct selinfo bd_sel; /* bsd select info */ +#endif +}; + +/* + * Descriptor associated with each attached hardware interface. + */ +struct bpf_if { + struct bpf_if *bif_next; /* list of all interfaces */ + struct bpf_d *bif_dlist; /* descriptor list */ + struct bpf_if **bif_driverp; /* pointer into softc */ + u_int bif_dlt; /* link layer type */ + u_int bif_hdrlen; /* length of header (with padding) */ + struct ifnet *bif_ifp; /* correspoding interface */ +}; + +#ifdef _KERNEL +int bpf_setf __P((struct bpf_d *, struct bpf_program *)); +#endif + +#endif // _NET_BPFDESC_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/if.h b/ecos/packages/net/tcpip/current/include/net/if.h new file mode 100644 index 0000000..cc8b060 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if.h @@ -0,0 +1,481 @@ +//========================================================================== +// +// include/net/if.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if.h,v 1.14 1999/12/08 06:50:17 itojun Exp $ */ +/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_IF_H_ +#define _NET_IF_H_ + +#include <sys/queue.h> + +/* + * Structures defining a network interface, providing a packet + * transport mechanism (ala level 0 of the PUP protocols). + * + * Each interface accepts output datagrams of a specified maximum + * length, and provides higher level routines with input datagrams + * received from its medium. + * + * Output occurs when the routine if_output is called, with four parameters: + * (*ifp->if_output)(ifp, m, dst, rt) + * Here m is the mbuf chain to be sent and dst is the destination address. + * The output routine encapsulates the supplied datagram if necessary, + * and then transmits it on its medium. + * + * On input, each interface unwraps the data received by it, and either + * places it on the input queue of a internetwork datagram routine + * and posts the associated software interrupt, or passes the datagram to a raw + * packet input routine. + * + * Routines exist for locating interfaces by their addresses + * or for locating a interface on a certain network, as well as more general + * routing and gateway routines maintaining information used to locate + * interfaces. These routines live in the files if.c and route.c + */ +#include <sys/time.h> + +struct mbuf; +struct proc; +struct rtentry; +struct socket; +struct ether_header; +struct arpcom; + +/* + * Structure defining statistics and other data kept regarding a network + * interface. + */ +struct if_data { + /* generic interface information */ + u_char ifi_type; /* ethernet, tokenring, etc. */ + u_char ifi_addrlen; /* media address length */ + u_char ifi_hdrlen; /* media header length */ + u_long ifi_mtu; /* maximum transmission unit */ + u_long ifi_metric; /* routing metric (external only) */ + u_long ifi_baudrate; /* linespeed */ + /* volatile statistics */ + u_long ifi_ipackets; /* packets received on interface */ + u_long ifi_ierrors; /* input errors on interface */ + u_long ifi_opackets; /* packets sent on interface */ + u_long ifi_oerrors; /* output errors on interface */ + u_long ifi_collisions; /* collisions on csma interfaces */ + u_long ifi_ibytes; /* total number of octets received */ + u_long ifi_obytes; /* total number of octets sent */ + u_long ifi_imcasts; /* packets received via multicast */ + u_long ifi_omcasts; /* packets sent via multicast */ + u_long ifi_iqdrops; /* dropped on input, this interface */ + u_long ifi_noproto; /* destined for unsupported protocol */ + struct timeval ifi_lastchange; /* last updated */ +}; + +/* + * Structure defining a queue for a network interface. + * + * (Would like to call this struct ``if'', but C isn't PL/1.) + */ +TAILQ_HEAD(ifnet_head, ifnet); /* the actual queue head */ + +/* + * Length of interface external name, including terminating '\0'. + * Note: this is the same size as a generic device's external name. + */ +#define IFNAMSIZ 16 +#define IF_NAMESIZE IFNAMSIZ + +struct ifnet { /* and the entries */ + void *if_softc; /* lower-level data for this if */ + TAILQ_ENTRY(ifnet) if_list; /* all struct ifnets are chained */ + TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */ + char if_xname[IFNAMSIZ]; /* external name (name + unit) */ + int if_pcount; /* number of promiscuous listeners */ + caddr_t if_bpf; /* packet filter structure */ + caddr_t if_bridge; /* bridge structure */ + u_short if_index; /* numeric abbreviation for this if */ + short if_timer; /* time 'til if_watchdog called */ + short if_flags; /* up/down, broadcast, etc. */ + struct if_data if_data; /* statistics and other data about if */ +/* procedure handles */ + int (*if_output) /* output routine (enqueue) */ + __P((struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *)); + void (*if_start) /* initiate output routine */ + __P((struct ifnet *)); + int (*if_ioctl) /* ioctl routine */ + __P((struct ifnet *, u_long, caddr_t)); + int (*if_reset) /* XXX bus reset routine */ + __P((struct ifnet *)); + void (*if_watchdog) /* timer routine */ + __P((struct ifnet *)); + struct ifqueue { + struct mbuf *ifq_head; + struct mbuf *ifq_tail; + int ifq_len; + int ifq_maxlen; + int ifq_drops; + } if_snd; /* output queue */ + struct ifprefix *if_prefixlist; /* linked list of prefixes per if */ +}; +#define if_mtu if_data.ifi_mtu +#define if_type if_data.ifi_type +#define if_addrlen if_data.ifi_addrlen +#define if_hdrlen if_data.ifi_hdrlen +#define if_metric if_data.ifi_metric +#define if_baudrate if_data.ifi_baudrate +#define if_ipackets if_data.ifi_ipackets +#define if_ierrors if_data.ifi_ierrors +#define if_opackets if_data.ifi_opackets +#define if_oerrors if_data.ifi_oerrors +#define if_collisions if_data.ifi_collisions +#define if_ibytes if_data.ifi_ibytes +#define if_obytes if_data.ifi_obytes +#define if_imcasts if_data.ifi_imcasts +#define if_omcasts if_data.ifi_omcasts +#define if_iqdrops if_data.ifi_iqdrops +#define if_noproto if_data.ifi_noproto +#define if_lastchange if_data.ifi_lastchange + +#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 point-to-point link */ +#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ +#define IFF_RUNNING 0x40 /* resources allocated */ +#define IFF_NOARP 0x80 /* no address resolution protocol */ +#define IFF_PROMISC 0x100 /* receive all packets */ +#define IFF_ALLMULTI 0x200 /* receive all multicast packets */ +#define IFF_OACTIVE 0x400 /* transmission in progress */ +#define IFF_SIMPLEX 0x800 /* can't hear own transmissions */ +#define IFF_LINK0 0x1000 /* per link layer defined bit */ +#define IFF_LINK1 0x2000 /* per link layer defined bit */ +#define IFF_LINK2 0x4000 /* per link layer defined bit */ +#define IFF_MULTICAST 0x8000 /* supports multicast */ + +/* flags set internally only: */ +#define IFF_CANTCHANGE \ + (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\ + IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI) + +/* + * Output queues (ifp->if_snd) and internetwork datagram level (pup level 1) + * input routines have queues of messages stored on ifqueue structures + * (defined above). Entries are added to and deleted from these structures + * by these macros, which should be called with ipl raised to splimp(). + */ +#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) +#define IF_DROP(ifq) ((ifq)->ifq_drops++) +#define IF_ENQUEUE(ifq, m) { \ + (m)->m_nextpkt = 0; \ + if ((ifq)->ifq_tail == 0) \ + (ifq)->ifq_head = m; \ + else \ + (ifq)->ifq_tail->m_nextpkt = m; \ + (ifq)->ifq_tail = m; \ + (ifq)->ifq_len++; \ +} +#define IF_PREPEND(ifq, m) { \ + (m)->m_nextpkt = (ifq)->ifq_head; \ + if ((ifq)->ifq_tail == 0) \ + (ifq)->ifq_tail = (m); \ + (ifq)->ifq_head = (m); \ + (ifq)->ifq_len++; \ +} +#define IF_DEQUEUE(ifq, m) { \ + (m) = (ifq)->ifq_head; \ + if (m) { \ + if (((ifq)->ifq_head = (m)->m_nextpkt) == 0) \ + (ifq)->ifq_tail = 0; \ + (m)->m_nextpkt = 0; \ + (ifq)->ifq_len--; \ + } \ +} +#define IF_IS_EMPTY(ifq) ((ifq)->ifq_len == 0) + +#define IFQ_ENQUEUE(ifq, m, pattr, err) \ +do { \ + if (IF_QFULL((ifq))) { \ + m_freem((m)); \ + (err) = ENOBUFS; \ + } else { \ + IF_ENQUEUE((ifq), (m)); \ + (err) = 0; \ + } \ + if ((err)) \ + (ifq)->ifq_drops++; \ +} while (0) + +#define IFQ_MAXLEN 50 +#define IFNET_SLOWHZ 1 /* granularity is 1 second */ + +/* + * 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 */ + struct sockaddr *ifa_dstaddr; /* other end of p-to-p link */ +#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ + struct sockaddr *ifa_netmask; /* used to determine subnet */ + struct ifnet *ifa_ifp; /* back-pointer to interface */ + TAILQ_ENTRY(ifaddr) ifa_list; /* list of addresses for interface */ + void (*ifa_rtrequest) /* check or clean routes (+ or -)'d */ + __P((int, struct rtentry *, struct sockaddr *)); + u_short ifa_flags; /* mostly rt_flags for cloning */ + u_int ifa_refcnt; /* count of references */ + int ifa_metric; /* cost of going out this interface */ +}; +#define IFA_ROUTE RTF_UP /* route installed */ + +/* + * The prefix structure contains information about one prefix + * of an interface. They are maintained by the different address families, + * are allocated and attached when an prefix or an address is set, + * and are linked together so all prfefixes for an interface can be located. + */ +struct ifprefix { + struct sockaddr *ifpr_prefix; /* prefix of interface */ + struct ifnet *ifpr_ifp; /* back-pointer to interface */ + struct ifprefix *ifpr_next; + u_char ifpr_plen; /* prefix length in bits */ + u_char ifpr_type; /* protocol dependent prefix type */ +}; + +/* + * Message format for use in obtaining information about interfaces + * from sysctl and the routing socket. + */ +struct if_msghdr { + u_short ifm_msglen; /* to skip over non-understood messages */ + u_char ifm_version; /* future binary compatability */ + u_char ifm_type; /* message type */ + int ifm_addrs; /* like rtm_addrs */ + int ifm_flags; /* value of if_flags */ + u_short ifm_index; /* index for associated ifp */ + struct if_data ifm_data;/* statistics and other data about if */ +}; + +/* + * Message format for use in obtaining information about interface addresses + * from sysctl and the routing socket. + */ +struct ifa_msghdr { + u_short ifam_msglen; /* to skip over non-understood messages */ + u_char ifam_version; /* future binary compatability */ + u_char ifam_type; /* message type */ + int ifam_addrs; /* like rtm_addrs */ + int ifam_flags; /* value of ifa_flags */ + u_short ifam_index; /* index for associated ifp */ + int ifam_metric; /* value of ifa_metric */ +}; + +/* + * 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 + char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_metric; + caddr_t ifru_data; + } ifr_ifru; +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_media ifr_ifru.ifru_metric /* media options (overload) */ +#define ifr_data ifr_ifru.ifru_data /* for use by interface */ +}; + +struct ifaliasreq { + char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + struct sockaddr ifra_addr; + struct sockaddr ifra_dstaddr; +#define ifra_broadaddr ifra_dstaddr + struct sockaddr ifra_mask; +}; + +struct ifmediareq { + char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + int ifm_current; /* current media options */ + int ifm_mask; /* don't care mask */ + int ifm_status; /* media status */ + int ifm_active; /* active options */ + int ifm_count; /* # entries in ifm_ulist + array */ + int *ifm_ulist; /* media words */ +}; + +/* + * 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 associated 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 returned */ +}; + +/* + * Structure for SIOC[AGD]LIFADDR + */ +struct if_laddrreq { + char iflr_name[IFNAMSIZ]; + unsigned int flags; +#define IFLR_PREFIX 0x8000 /* in: prefix given out: kernel fills id */ + unsigned int prefixlen; /* in/out */ + struct sockaddr_storage addr; /* in/out */ + struct sockaddr_storage dstaddr; /* out */ +}; + +struct if_nameindex { + unsigned int if_index; + char *if_name; +}; + +#ifndef _KERNEL +__BEGIN_DECLS +unsigned int if_nametoindex __P((const char *)); +char *if_indextoname __P((unsigned int, char *)); +struct if_nameindex *if_nameindex __P((void)); +__END_DECLS +#define if_freenameindex(x) free(x) +#endif + +#include <net/if_arp.h> + +#ifdef _KERNEL +#define IFAFREE(ifa) { \ + if ((ifa)->ifa_refcnt <= 0) \ + ifafree(ifa); \ + else \ + (ifa)->ifa_refcnt--; \ + } + +struct ifnet_head ifnet; +struct ifnet **ifindex2ifnet; +#if 0 +struct ifnet loif[]; +#endif +int if_index; + +void ether_ifattach __P((struct ifnet *)); +void ether_ifdetach __P((struct ifnet *)); +int ether_ioctl __P((struct ifnet *, struct arpcom *, u_long, caddr_t)); +void ether_input __P((struct ifnet *, struct ether_header *, struct mbuf *)); +int ether_output __P((struct ifnet *, + struct mbuf *, struct sockaddr *, struct rtentry *)); +char *ether_sprintf __P((u_char *)); + +void if_attach __P((struct ifnet *)); +void if_attachtail __P((struct ifnet *)); +void if_attachhead __P((struct ifnet *)); +void if_detach __P((struct ifnet *)); +void if_down __P((struct ifnet *)); +void if_qflush __P((struct ifqueue *)); +void if_slowtimo __P((void *)); +void if_up __P((struct ifnet *)); +int ifconf __P((u_long, caddr_t)); +void ifinit __P((void)); +int ifioctl __P((struct socket *, u_long, caddr_t, struct proc *)); +int ifpromisc __P((struct ifnet *, int)); +struct ifnet *ifunit __P((char *)); +struct ifnet *if_withname __P((struct sockaddr *)); + +struct ifaddr *ifa_ifwithaddr __P((struct sockaddr *)); +struct ifaddr *ifa_ifwithaf __P((int)); +struct ifaddr *ifa_ifwithdstaddr __P((struct sockaddr *)); +struct ifaddr *ifa_ifwithnet __P((struct sockaddr *)); +struct ifaddr *ifa_ifwithroute __P((int, struct sockaddr *, + struct sockaddr *)); +struct ifaddr *ifaof_ifpforaddr __P((struct sockaddr *, struct ifnet *)); +void ifafree __P((struct ifaddr *)); +void link_rtrequest __P((int, struct rtentry *, struct sockaddr *)); + +int loioctl __P((struct ifnet *, u_long, caddr_t)); +void loopattach __P((int)); +int looutput __P((struct ifnet *, + struct mbuf *, struct sockaddr *, struct rtentry *)); +void lortrequest __P((int, struct rtentry *, struct sockaddr *)); +#endif /* _KERNEL */ + +#endif // _NET_IF_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/if_arp.h b/ecos/packages/net/tcpip/current/include/net/if_arp.h new file mode 100644 index 0000000..cf9f4db --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if_arp.h @@ -0,0 +1,123 @@ +//========================================================================== +// +// include/net/if_arp.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_arp.h,v 1.3 1999/07/30 22:22:19 fgsch Exp $ */ +/* $NetBSD: if_arp.h,v 1.8 1995/03/08 02:56:52 cgd Exp $ */ + +/* + * Copyright (c) 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_arp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_IF_ARP_H_ +#define _NET_IF_ARP_H_ + +/* + * Address Resolution Protocol. + * + * See RFC 826 for protocol description. ARP packets are variable + * in size; the arphdr structure defines the fixed-length portion. + * Protocol type values are the same as those for 10 Mb/s Ethernet. + * It is followed by the variable-sized fields ar_sha, arp_spa, + * arp_tha and arp_tpa in that order, according to the lengths + * specified. Field names used correspond to RFC 826. + */ +struct arphdr { + u_int16_t ar_hrd; /* format of hardware address */ +#define ARPHRD_ETHER 1 /* ethernet hardware format */ +#define ARPHRD_IEEE802 6 /* IEEE 802 hardware format */ +#define ARPHRD_FRELAY 15 /* frame relay hardware format */ + u_int16_t ar_pro; /* format of protocol address */ + u_int8_t ar_hln; /* length of hardware address */ + u_int8_t ar_pln; /* length of protocol address */ + u_int16_t ar_op; /* one of: */ +#define ARPOP_REQUEST 1 /* request to resolve address */ +#define ARPOP_REPLY 2 /* response to previous request */ +#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */ +#define ARPOP_REVREPLY 4 /* response giving protocol address */ +#define ARPOP_INVREQUEST 8 /* request to identify peer */ +#define ARPOP_INVREPLY 9 /* response identifying peer */ +/* + * The remaining fields are variable in size, + * according to the sizes above. + */ +#ifdef COMMENT_ONLY + u_int8_t ar_sha[]; /* sender hardware address */ + u_int8_t ar_spa[]; /* sender protocol address */ + u_int8_t ar_tha[]; /* target hardware address */ + u_int8_t ar_tpa[]; /* target protocol address */ +#endif +}; + +/* + * ARP ioctl request + */ +struct arpreq { + struct sockaddr arp_pa; /* protocol address */ + struct sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ +}; +/* arp_flags and at_flags field values */ +#define ATF_INUSE 0x01 /* entry in use */ +#define ATF_COM 0x02 /* completed entry (enaddr valid) */ +#define ATF_PERM 0x04 /* permanent entry */ +#define ATF_PUBL 0x08 /* publish entry (respond for other host) */ +#define ATF_USETRAILERS 0x10 /* has requested trailers */ + +#endif // _NET_IF_ARP_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/if_bridge.h b/ecos/packages/net/tcpip/current/include/net/if_bridge.h new file mode 100644 index 0000000..7fcb33e --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if_bridge.h @@ -0,0 +1,319 @@ +//========================================================================== +// +// include/net/if_bridge.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jason L. Wright (jason@thought.net) +// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt, manu.sharma@ascom.ch +// Date: 2000-07-18 +// Purpose: Ethernet bridge +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* $OpenBSD: if_bridge.h,v 1.25 2003/07/15 03:41:15 jason Exp $ */ + +/* + * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Effort sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F30602-01-2-0537. + * + */ + +/* + * Bridge control request: add/delete member interfaces. + */ +struct ifbreq { + char ifbr_name[IFNAMSIZ]; /* bridge ifs name */ + char ifbr_ifsname[IFNAMSIZ]; /* member ifs name */ + u_int32_t ifbr_ifsflags; /* member ifs flags */ + u_int8_t ifbr_state; /* member stp state */ + u_int8_t ifbr_priority; /* member stp priority */ + u_int8_t ifbr_portno; /* member port number */ + u_int32_t ifbr_path_cost; /* member stp path cost */ +}; +/* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */ +#define IFBIF_LEARNING 0x0001 /* ifs can learn */ +#define IFBIF_DISCOVER 0x0002 /* ifs sends packets w/unknown dest */ +#define IFBIF_BLOCKNONIP 0x0004 /* ifs blocks non-IP/ARP in/out */ +#define IFBIF_STP 0x0008 /* ifs participates in spanning tree */ +#define IFBIF_SPAN 0x0100 /* ifs is a span port (ro) */ +#define IFBIF_RO_MASK 0xff00 /* read only bits */ +/* SIOCBRDGFLUSH */ +#define IFBF_FLUSHDYN 0x0 /* flush dynamic addresses only */ +#define IFBF_FLUSHALL 0x1 /* flush all addresses from cache */ + +/* port states */ +#define BSTP_IFSTATE_DISABLED 0 +#define BSTP_IFSTATE_LISTENING 1 +#define BSTP_IFSTATE_LEARNING 2 +#define BSTP_IFSTATE_FORWARDING 3 +#define BSTP_IFSTATE_BLOCKING 4 + +/* + * Interface list structure + */ +struct ifbifconf { + char ifbic_name[IFNAMSIZ]; /* bridge ifs name */ + u_int32_t ifbic_len; /* buffer size */ + union { + caddr_t ifbicu_buf; + struct ifbreq *ifbicu_req; + } ifbic_ifbicu; +#define ifbic_buf ifbic_ifbicu.ifbicu_buf +#define ifbic_req ifbic_ifbicu.ifbicu_req +}; + +/* + * Bridge address request + */ +struct ifbareq { + char ifba_name[IFNAMSIZ]; /* bridge name */ + char ifba_ifsname[IFNAMSIZ]; /* destination ifs */ + u_int8_t ifba_age; /* address age */ + u_int8_t ifba_flags; /* address flags */ + struct ether_addr ifba_dst; /* destination addr */ +}; + +#define IFBAF_TYPEMASK 0x03 /* address type mask */ +#define IFBAF_DYNAMIC 0x00 /* dynamically learned */ +#define IFBAF_STATIC 0x01 /* static address */ + +struct ifbaconf { + char ifbac_name[IFNAMSIZ]; /* bridge ifs name */ + u_int32_t ifbac_len; /* buffer size */ + union { + caddr_t ifbacu_buf; /* buffer */ + struct ifbareq *ifbacu_req; /* request pointer */ + } ifbac_ifbacu; +#define ifbac_buf ifbac_ifbacu.ifbacu_buf +#define ifbac_req ifbac_ifbacu.ifbacu_req +}; + +struct ifbrparam { + char ifbrp_name[IFNAMSIZ]; + union { + u_int32_t ifbrpu_csize; /* cache size */ + int ifbrpu_ctime; /* cache time (sec) */ + u_int16_t ifbrpu_prio; /* bridge priority */ + u_int8_t ifbrpu_hellotime; /* hello time (sec) */ + u_int8_t ifbrpu_fwddelay; /* fwd delay (sec) */ + u_int8_t ifbrpu_maxage; /* max age (sec) */ + } ifbrp_ifbrpu; +}; +#define ifbrp_csize ifbrp_ifbrpu.ifbrpu_csize +#define ifbrp_ctime ifbrp_ifbrpu.ifbrpu_ctime +#define ifbrp_prio ifbrp_ifbrpu.ifbrpu_prio +#define ifbrp_hellotime ifbrp_ifbrpu.ifbrpu_hellotime +#define ifbrp_fwddelay ifbrp_ifbrpu.ifbrpu_fwddelay +#define ifbrp_maxage ifbrp_ifbrpu.ifbrpu_maxage + +/* + * Bridge cache size get/set + */ +struct ifbcachereq { + char ifbc_name[IFNAMSIZ]; /* bridge ifs name */ + u_int32_t ifbc_size; /* cache size */ +}; + +/* + * Bridge cache timeout get/set + */ +struct ifbcachetoreq { + char ifbct_name[IFNAMSIZ]; /* bridge ifs name */ + u_int32_t ifbct_time; /* cache time (sec) */ +}; + +/* + * Bridge mac rules + */ +struct ifbrlreq { + char ifbr_name[IFNAMSIZ]; /* bridge ifs name */ + char ifbr_ifsname[IFNAMSIZ]; /* member ifs name */ + u_int8_t ifbr_action; /* disposition */ + u_int8_t ifbr_flags; /* flags */ + struct ether_addr ifbr_src; /* source mac */ + struct ether_addr ifbr_dst; /* destination mac */ +}; +#define BRL_ACTION_BLOCK 0x01 /* block frame */ +#define BRL_ACTION_PASS 0x02 /* pass frame */ +#define BRL_FLAG_IN 0x08 /* input rule */ +#define BRL_FLAG_OUT 0x04 /* output rule */ +#define BRL_FLAG_SRCVALID 0x02 /* src valid */ +#define BRL_FLAG_DSTVALID 0x01 /* dst valid */ + +struct ifbrlconf { + char ifbrl_name[IFNAMSIZ]; /* bridge ifs name */ + char ifbrl_ifsname[IFNAMSIZ]; /* member ifs name */ + u_int32_t ifbrl_len; /* buffer size */ + union { + caddr_t ifbrlu_buf; + struct ifbrlreq *ifbrlu_req; + } ifbrl_ifbrlu; +#define ifbrl_buf ifbrl_ifbrlu.ifbrlu_buf +#define ifbrl_req ifbrl_ifbrlu.ifbrlu_req +}; + +/* + * Bridge filtering rules + */ +SIMPLEQ_HEAD(brl_head, brl_node); + +struct brl_node { + SIMPLEQ_ENTRY(brl_node) brl_next; /* next rule */ + struct ether_addr brl_src; /* source mac address */ + struct ether_addr brl_dst; /* destination mac address */ + u_int16_t brl_tag; /* pf tag ID */ + u_int8_t brl_action; /* what to do with match */ + u_int8_t brl_flags; /* comparision flags */ +}; + +struct bridge_timer { + u_int16_t active; + u_int16_t value; +}; + +struct bstp_config_unit { + u_int64_t cu_rootid; + u_int64_t cu_bridge_id; + u_int32_t cu_root_path_cost; + u_int16_t cu_message_age; + u_int16_t cu_max_age; + u_int16_t cu_hello_time; + u_int16_t cu_forward_delay; + u_int16_t cu_port_id; + u_int8_t cu_message_type; + u_int8_t cu_topology_change_acknowledgment; + u_int8_t cu_topology_change; +}; + +struct bstp_tcn_unit { + u_int8_t tu_message_type; +}; + +/* + * Bridge interface list + */ +struct bridge_iflist { + LIST_ENTRY(bridge_iflist) next; /* next in list */ + u_int64_t bif_designated_root; + u_int64_t bif_designated_bridge; + u_int32_t bif_path_cost; + u_int32_t bif_designated_cost; + struct bridge_timer bif_hold_timer; + struct bridge_timer bif_message_age_timer; + struct bridge_timer bif_forward_delay_timer; + struct bstp_config_unit bif_config_bpdu; + u_int16_t bif_port_id; + u_int16_t bif_designated_port; + u_int8_t bif_state; + u_int8_t bif_topology_change_acknowledge; + u_int8_t bif_config_pending; + u_int8_t bif_change_detection_enabled; + u_int8_t bif_priority; + struct brl_head bif_brlin; /* input rules */ + struct brl_head bif_brlout; /* output rules */ + struct ifnet *ifp; /* member interface */ + u_int32_t bif_flags; /* member flags */ +}; + +/* + * Bridge route node + */ +struct bridge_rtnode { + LIST_ENTRY(bridge_rtnode) brt_next; /* next in list */ + struct ifnet *brt_if; /* destination ifs */ + u_int8_t brt_flags; /* address flags */ + u_int8_t brt_age; /* age counter */ + struct ether_addr brt_addr; /* dst addr */ +}; + +/* + * Software state for each bridge + */ +struct bridge_softc { + struct ifnet sc_if; /* the interface */ + u_int64_t sc_designated_root; + u_int64_t sc_bridge_id; + struct bridge_iflist *sc_root_port; + u_int32_t sc_root_path_cost; + u_int16_t sc_max_age; + u_int16_t sc_hello_time; + u_int16_t sc_forward_delay; + u_int16_t sc_bridge_max_age; + u_int16_t sc_bridge_hello_time; + u_int16_t sc_bridge_forward_delay; + u_int16_t sc_topology_change_time; + u_int16_t sc_hold_time; + u_int16_t sc_bridge_priority; + u_int8_t sc_topology_change_detected; + u_int8_t sc_topology_change; + struct bridge_timer sc_hello_timer; + struct bridge_timer sc_topology_change_timer; + struct bridge_timer sc_tcn_timer; + u_int32_t sc_brtmax; /* max # addresses */ + u_int32_t sc_brtcnt; /* current # addrs */ + int sc_brttimeout; /* timeout ticks */ + u_int32_t sc_hashkey; /* hash key */ +#ifndef __ECOS + struct timeout sc_brtimeout; /* timeout state */ + struct timeout sc_bstptimeout; /* stp timeout */ +#endif + LIST_HEAD(, bridge_iflist) sc_iflist; /* interface list */ + LIST_HEAD(bridge_rthead, bridge_rtnode) *sc_rts;/* hash table */ + LIST_HEAD(, bridge_iflist) sc_spanlist; /* span ports */ +}; + +#ifdef _KERNEL +extern u_int8_t bstp_etheraddr[]; + +void bridge_ifdetach(struct ifnet *); +struct mbuf *bridge_input(struct ifnet *, struct ether_header *, + struct mbuf *); +int bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +struct mbuf *bstp_input(struct bridge_softc *, struct ifnet *, + struct ether_header *, struct mbuf *); +void bstp_initialization(struct bridge_softc *); +int bstp_ioctl(struct ifnet *, u_long, caddr_t); +void bridge_rtdelete(struct bridge_softc *, struct ifnet *, int); +#endif /* _KERNEL */ diff --git a/ecos/packages/net/tcpip/current/include/net/if_dl.h b/ecos/packages/net/tcpip/current/include/net/if_dl.h new file mode 100644 index 0000000..2dba2a0 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if_dl.h @@ -0,0 +1,117 @@ +//========================================================================== +// +// include/net/if_dl.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_dl.h,v 1.2 1997/02/24 13:33:58 niklas Exp $ */ +/* $NetBSD: if_dl.h,v 1.8 1995/03/26 20:30:13 jtc Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_dl.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_IF_DL_H_ +#define _NET_IF_DL_H_ + +/* + * A Link-Level Sockaddr may specify the interface in one of two + * ways: either by means of a system-provided index number (computed + * anew and possibly differently on every reboot), or by a human-readable + * string such as "il0" (for managerial convenience). + * + * Census taking actions, such as something akin to SIOCGCONF would return + * both the index and the human name. + * + * High volume transactions (such as giving a link-level ``from'' address + * in a recvfrom or recvmsg call) may be likely only to provide the indexed + * form, (which requires fewer copy operations and less space). + * + * The form and interpretation of the link-level address is purely a matter + * of convention between the device driver and its consumers; however, it is + * expected that all drivers for an interface of a given if_type will agree. + */ + +/* + * Structure of a Link-Level sockaddr: + */ +struct sockaddr_dl { + u_char sdl_len; /* Total length of sockaddr */ + u_char sdl_family; /* AF_DLI */ + u_int16_t sdl_index; /* if != 0, system given index for interface */ + u_char sdl_type; /* interface type */ + u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */ + u_char sdl_alen; /* link level address length */ + u_char sdl_slen; /* link layer selector length */ + char sdl_data[12]; /* minimum work area, can be larger; + contains both if name and ll address */ +}; + +#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen)) + +#ifndef _KERNEL + +#include <sys/cdefs.h> + +__BEGIN_DECLS +void link_addr __P((const char *, struct sockaddr_dl *)); +char *link_ntoa __P((const struct sockaddr_dl *)); +__END_DECLS + +#endif /* !_KERNEL */ + +#endif // _NET_IF_DL_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/if_gif.h b/ecos/packages/net/tcpip/current/include/net/if_gif.h new file mode 100644 index 0000000..52c8d5d --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if_gif.h @@ -0,0 +1,115 @@ +//========================================================================== +// +// include/net/if_gif.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_gif.h,v 1.1 1999/12/08 06:50:18 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * if_gif.h + */ + +#ifndef _NET_IF_GIF_H_ +#define _NET_IF_GIF_H_ + + +#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__) +#if defined(_KERNEL) && !defined(_LKM) +#include "opt_inet.h" +#endif +#endif + +#include <netinet/in.h> +/* xxx sigh, why route have struct route instead of pointer? */ + +struct gif_softc { + struct ifnet gif_if; /* common area */ + struct sockaddr *gif_psrc; /* Physical src addr */ + struct sockaddr *gif_pdst; /* Physical dst addr */ + union { + struct route gifscr_ro; /* xxx */ +#ifdef INET6 + struct route_in6 gifscr_ro6; /* xxx */ +#endif + } gifsc_gifscr; + int gif_flags; +}; + +#define gif_ro gifsc_gifscr.gifscr_ro +#ifdef INET6 +#define gif_ro6 gifsc_gifscr.gifscr_ro6 +#endif + +#define GIFF_INUSE 0x1 /* gif is in use */ + +#define GIF_MTU (1280) /* Default MTU */ +#define GIF_MTU_MIN (1280) /* Minimum MTU */ +#define GIF_MTU_MAX (8192) /* Maximum MTU */ + +extern int ngif; +extern struct gif_softc *gif; + +/* Prototypes */ +void gif_input __P((struct mbuf *, int, struct ifnet *)); +int gif_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *)); +#if defined(__FreeBSD__) && __FreeBSD__ < 3 +int gif_ioctl __P((struct ifnet *, int, caddr_t)); +#else +int gif_ioctl __P((struct ifnet *, u_long, caddr_t)); +#endif + +#endif /* _NET_IF_GIF_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/net/if_llc.h b/ecos/packages/net/tcpip/current/include/net/if_llc.h new file mode 100644 index 0000000..a4e5adc --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if_llc.h @@ -0,0 +1,178 @@ +//========================================================================== +// +// include/net/if_llc.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_llc.h,v 1.3 1999/07/28 20:02:41 fgsch Exp $ */ +/* $NetBSD: if_llc.h,v 1.6 1995/03/08 02:56:57 cgd Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_llc.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_IF_LLC_H_ +#define _NET_IF_LLC_H_ + +/* + * IEEE 802.2 Link Level Control headers, for use in conjunction with + * 802.{3,4,5} media access control methods. + * + * Headers here do not use bit fields due to shortcommings in many + * compilers. + */ + +struct llc { + u_int8_t llc_dsap; + u_int8_t llc_ssap; + union { + struct { + u_int8_t control; + u_int8_t format_id; + u_int8_t class; + u_int8_t window_x2; + } type_u; + struct { + u_int8_t num_snd_x2; + u_int8_t num_rcv_x2; + } type_i; + struct { + u_int8_t control; + u_int8_t num_rcv_x2; + } type_s; + struct { + u_int8_t control; + struct frmrinfo { + u_int8_t rej_pdu_0; + u_int8_t rej_pdu_1; + u_int8_t frmr_control; + u_int8_t frmr_control_ext; + u_int8_t frmr_cause; + } frmrinfo; + } type_frmr; + struct { + u_int8_t control; + u_int8_t org_code[3]; + u_int16_t ether_type; + } type_snap; + struct { + u_int8_t control; + u_int8_t control_ext; + } type_raw; + } llc_un; +}; +#define llc_control llc_un.type_u.control +#define llc_control_ext llc_un.type_raw.control_ext +#define llc_fid llc_un.type_u.format_id +#define llc_class llc_un.type_u.class +#define llc_window llc_un.type_u.window_x2 +#define llc_frmrinfo llc_un.type_frmr.frmrinfo +#define llc_frmr_pdu0 llc_un.type_frmr.frmrinfo.rej_pdu0 +#define llc_frmr_pdu1 llc_un.type_frmr.frmrinfo.rej_pdu1 +#define llc_frmr_control llc_un.type_frmr.frmrinfo.frmr_control +#define llc_frmr_control_ext llc_un.type_frmr.frmrinfo.frmr_control_ext +#define llc_frmr_cause llc_un.type_frmr.frmrinfo.frmr_control_ext + +/* + * Don't use sizeof(struct llc_un) for LLC header sizes + */ +#define LLC_UFRAMELEN 3 +#define LLC_ISFRAMELEN 4 +#define LLC_FRMRLEN 7 +#define LLC_SNAPFRAMELEN 8 + +/* + * Unnumbered LLC format commands + */ +#define LLC_UI 0x3 +#define LLC_UI_P 0x13 +#define LLC_DISC 0x43 +#define LLC_DISC_P 0x53 +#define LLC_UA 0x63 +#define LLC_UA_P 0x73 +#define LLC_TEST 0xe3 +#define LLC_TEST_P 0xf3 +#define LLC_FRMR 0x87 +#define LLC_FRMR_P 0x97 +#define LLC_DM 0x0f +#define LLC_DM_P 0x1f +#define LLC_XID 0xaf +#define LLC_XID_P 0xbf +#define LLC_SABME 0x6f +#define LLC_SABME_P 0x7f + +/* + * Supervisory LLC commands + */ +#define LLC_RR 0x01 +#define LLC_RNR 0x05 +#define LLC_REJ 0x09 + +/* + * Info format - dummy only + */ +#define LLC_INFO 0x00 + +/* + * ISO PDTR 10178 contains among others + */ +#define LLC_8021D_LSAP 0x42 +#define LLC_X25_LSAP 0x7e +#define LLC_SNAP_LSAP 0xaa +#define LLC_ISO_LSAP 0xfe + +#endif // _NET_IF_LLC_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/if_slvar.h b/ecos/packages/net/tcpip/current/include/net/if_slvar.h new file mode 100644 index 0000000..55e87f8 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if_slvar.h @@ -0,0 +1,88 @@ +/* $OpenBSD: if_slvar.h,v 1.4 1997/02/24 13:34:01 niklas Exp $ */ +/* $NetBSD: if_slvar.h,v 1.16 1996/05/07 02:40:46 thorpej Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_slvar.h 8.3 (Berkeley) 2/1/94 + */ + +/* + * Definitions for SLIP interface data structures + * + * (This exists so programs like slstats can get at the definition + * of sl_softc.) + */ +struct sl_softc { + struct ifnet sc_if; /* network-visible interface */ + int sc_unit; /* XXX unit number */ + struct ifqueue sc_fastq; /* interactive output queue */ + struct tty *sc_ttyp; /* pointer to tty structure */ + u_char *sc_mp; /* pointer to next available buf char */ + u_char *sc_ep; /* pointer to last available buf char */ + u_char *sc_buf; /* input buffer */ + u_int sc_flags; /* see below */ + u_int sc_escape; /* =1 if last char input was FRAME_ESCAPE */ + long sc_lasttime; /* last time a char arrived */ + long sc_abortcount; /* number of abort esacpe chars */ + long sc_starttime; /* time of first abort in window */ + long sc_oqlen; /* previous output queue size */ + long sc_otimeout; /* number of times output's stalled */ +#if defined(__NetBSD__) || defined(__OpenBSD__) + int sc_oldbufsize; /* previous output buffer size */ + int sc_oldbufquot; /* previous output buffer quoting */ +#endif +#ifdef INET /* XXX */ + struct slcompress sc_comp; /* tcp compression data */ +#endif + caddr_t sc_bpf; /* BPF data */ +}; + +/* internal flags */ +#define SC_ERROR 0x0001 /* had an input error */ + +/* visible flags */ +#define SC_COMPRESS IFF_LINK0 /* compress TCP traffic */ +#define SC_NOICMP IFF_LINK1 /* supress ICMP traffic */ +#define SC_AUTOCOMP IFF_LINK2 /* auto-enable TCP compression */ + +#ifdef _KERNEL +void slattach __P((void)); +void slclose __P((struct tty *)); +void slinput __P((int, struct tty *)); +int slioctl __P((struct ifnet *, u_long, caddr_t)); +int slopen __P((dev_t, struct tty *)); +int sloutput __P((struct ifnet *, + struct mbuf *, struct sockaddr *, struct rtentry *)); +void slstart __P((struct tty *)); +int sltioctl __P((struct tty *, u_long, caddr_t, int)); +#endif /* _KERNEL */ diff --git a/ecos/packages/net/tcpip/current/include/net/if_tun.h b/ecos/packages/net/tcpip/current/include/net/if_tun.h new file mode 100644 index 0000000..b1e754a --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if_tun.h @@ -0,0 +1,86 @@ +//========================================================================== +// +// include/net/if_tun.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_tun.h,v 1.8 1998/08/02 07:17:44 brian Exp $ */ + +/* + * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> + * Nottingham University 1987. + * + * This source may be freely distributed, however I would be interested + * in any changes that are made. + * + * This driver takes packets off the IP i/f and hands them up to a + * user process to have it's wicked way with. This driver has it's + * roots in a similar driver written by Phil Cockcroft (formerly) at + * UCL. This driver is based much more on read/write/select mode of + * operation though. + * + * from: @Header: if_tnreg.h,v 1.1.2.1 1992/07/16 22:39:16 friedl Exp + */ + +#ifndef _NET_IF_TUN_H_ +#define _NET_IF_TUN_H_ + +#include <sys/ioccom.h> + +#define TUN_OPEN 0x0001 +#define TUN_INITED 0x0002 +#define TUN_RCOLL 0x0004 +#define TUN_IASET 0x0008 +#define TUN_DSTADDR 0x0010 +#define TUN_RWAIT 0x0040 +#define TUN_ASYNC 0x0080 +#define TUN_NBIO 0x0100 +#define TUN_BRDADDR 0x0200 +#define TUN_STAYUP 0x0400 + +#define TUN_READY (TUN_OPEN | TUN_INITED | TUN_IASET) + +/* Maximum packet size */ +#define TUNMTU 3000 + +/* Maximum receive packet size (hard limit) */ +#define TUNMRU 16384 + +/* ioctl's for get/set debug */ +#define TUNSDEBUG _IOW('t', 89, int) +#define TUNGDEBUG _IOR('t', 90, int) + +/* iface info */ +struct tuninfo { + u_int mtu; + u_short type; + u_short flags; + u_int baudrate; +}; +#define TUNSIFINFO _IOW('t', 91, struct tuninfo) +#define TUNGIFINFO _IOR('t', 92, struct tuninfo) + +#endif /* !_NET_IF_TUN_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/net/if_types.h b/ecos/packages/net/tcpip/current/include/net/if_types.h new file mode 100644 index 0000000..60e10aa --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/if_types.h @@ -0,0 +1,139 @@ +//========================================================================== +// +// include/net/if_types.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_types.h,v 1.4 1999/12/08 06:50:18 itojun Exp $ */ +/* $NetBSD: if_types.h,v 1.7 1995/02/27 09:10:24 glass Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_types.h 8.2 (Berkeley) 4/20/94 + */ + +#ifndef _NET_IF_TYPES_H_ +#define _NET_IF_TYPES_H_ + +/* + * Interface types for benefit of parsing media address headers. + * This list is derived from the SNMP list of ifTypes, currently + * documented in RFC1573. + */ + +#define IFT_OTHER 0x1 /* none of the following */ +#define IFT_1822 0x2 /* old-style arpanet imp */ +#define IFT_HDH1822 0x3 /* HDH arpanet imp */ +#define IFT_X25DDN 0x4 /* x25 to imp */ +#define IFT_X25 0x5 /* PDN X25 interface (RFC877) */ +#define IFT_ETHER 0x6 /* Ethernet CSMACD */ +#define IFT_ISO88023 0x7 /* CMSA CD */ +#define IFT_ISO88024 0x8 /* Token Bus */ +#define IFT_ISO88025 0x9 /* Token Ring */ +#define IFT_ISO88026 0xa /* MAN */ +#define IFT_STARLAN 0xb +#define IFT_P10 0xc /* Proteon 10MBit ring */ +#define IFT_P80 0xd /* Proteon 80MBit ring */ +#define IFT_HY 0xe /* Hyperchannel */ +#define IFT_FDDI 0xf +#define IFT_LAPB 0x10 +#define IFT_SDLC 0x11 +#define IFT_T1 0x12 +#define IFT_CEPT 0x13 /* E1 - european T1 */ +#define IFT_ISDNBASIC 0x14 +#define IFT_ISDNPRIMARY 0x15 +#define IFT_PTPSERIAL 0x16 /* Proprietary PTP serial */ +#define IFT_PPP 0x17 /* RFC 1331 */ +#define IFT_LOOP 0x18 /* loopback */ +#define IFT_EON 0x19 /* ISO over IP */ +#define IFT_XETHER 0x1a /* obsolete 3MB experimental ethernet */ +#define IFT_NSIP 0x1b /* XNS over IP */ +#define IFT_SLIP 0x1c /* IP over generic TTY */ +#define IFT_ULTRA 0x1d /* Ultra Technologies */ +#define IFT_DS3 0x1e /* Generic T3 */ +#define IFT_SIP 0x1f /* SMDS */ +#define IFT_FRELAY 0x20 /* Frame Relay DTE only */ +#define IFT_RS232 0x21 +#define IFT_PARA 0x22 /* parallel-port */ +#define IFT_ARCNET 0x23 +#define IFT_ARCNETPLUS 0x24 +#define IFT_ATM 0x25 /* ATM cells */ +#define IFT_MIOX25 0x26 +#define IFT_SONET 0x27 /* SONET or SDH */ +#define IFT_X25PLE 0x28 +#define IFT_ISO88022LLC 0x29 +#define IFT_LOCALTALK 0x2a +#define IFT_SMDSDXI 0x2b +#define IFT_FRELAYDCE 0x2c /* Frame Relay DCE */ +#define IFT_V35 0x2d +#define IFT_HSSI 0x2e +#define IFT_HIPPI 0x2f +#define IFT_MODEM 0x30 /* Generic Modem */ +#define IFT_AAL5 0x31 /* AAL5 over ATM */ +#define IFT_SONETPATH 0x32 +#define IFT_SONETVT 0x33 +#define IFT_SMDSICIP 0x34 /* SMDS InterCarrier Interface */ +#define IFT_PROPVIRTUAL 0x35 /* Proprietary Virtual/internal */ +#define IFT_PROPMUX 0x36 /* Proprietary Multiplexing */ +#define IFT_ENC 0x37 /* Encapsulation */ + +/* private usage... how should we define these? */ +#define IFT_GIF 0xf0 +#define IFT_DUMMY 0xf1 +#define IFT_PVC 0xf2 +#define IFT_FAITH 0xf3 + +#endif // _NET_IF_TYPES_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/netisr.h b/ecos/packages/net/tcpip/current/include/net/netisr.h new file mode 100644 index 0000000..6c37e33 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/netisr.h @@ -0,0 +1,137 @@ +//========================================================================== +// +// include/net/netisr.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: netisr.h,v 1.14 1999/12/08 15:58:30 itojun Exp $ */ +/* $NetBSD: netisr.h,v 1.12 1995/08/12 23:59:24 mycroft Exp $ */ + +/* + * Copyright (c) 1980, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)netisr.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_NETISR_H_ +#define _NET_NETISR_H_ + +/* + * The networking code runs off software interrupts. + * + * You can switch into the network by doing splsoftnet() and return by splx(). + * The software interrupt level for the network is higher than the software + * level for the clock (so you can enter the network in routines called + * at timeout time). + * + * The routine to request a network software interrupt, setsoftnet(), + * is defined in the machine-specific include files. + */ + +/* + * Each ``pup-level-1'' input queue has a bit in a ``netisr'' status + * word which is used to de-multiplex a single software + * interrupt used for scheduling the network code to calls + * on the lowest level routine of each protocol. + */ +#ifdef __ECOS +#define NETISR_SOFTNET 1 // Just used to force an interrupt +#endif +#define NETISR_IP 2 /* same as AF_INET */ +#define NETISR_IMP 3 /* same as AF_IMPLINK */ +#define NETISR_NS 6 /* same as AF_NS */ +#define NETISR_ISO 7 /* same as AF_ISO */ +#define NETISR_CCITT 10 /* same as AF_CCITT */ +#define NETISR_ATALK 16 /* same as AF_APPLETALK */ +#define NETISR_ARP 18 /* same as AF_LINK */ +#define NETISR_IPX 23 /* same as AF_IPX */ +#define NETISR_IPV6 24 /* same as AF_INET6 */ +#define NETISR_ISDN 26 /* same as AF_E164 */ +#define NETISR_NATM 27 /* same as AF_ATM */ +#define NETISR_PPP 28 /* for PPP processing */ +#define NETISR_BRIDGE 29 /* for bridge processing */ + +#ifndef _LOCORE +#ifdef _KERNEL +#ifdef __ECOS +#include <cyg/kernel/kapi.h> +extern cyg_flag_t netint_flags; +#else +int netisr; /* scheduling bits for network */ +#endif + +void arpintr __P((void)); +void ipintr __P((void)); +void ip6intr __P((void)); +void atintr __P((void)); +void nsintr __P((void)); +void clnlintr __P((void)); +void natmintr __P((void)); +void pppintr __P((void)); +void ccittintr __P((void)); +void bridgeintr __P((void)); + +#ifdef __ECOS +#define schednetisr(anisr) cyg_flag_setbits(&netint_flags, 1<<(anisr)); +#else +#include <dev/rndvar.h> + +#define schednetisr(anisr) \ + { netisr |= 1<<(anisr); add_net_randomness(anisr); setsoftnet(); } +#endif +#endif +#endif + +#endif // _NET_NETISR_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/radix.h b/ecos/packages/net/tcpip/current/include/net/radix.h new file mode 100644 index 0000000..a176186 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/radix.h @@ -0,0 +1,199 @@ +//========================================================================== +// +// include/net/radix.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: radix.h,v 1.3 1996/09/05 08:42:34 mickey Exp $ */ +/* $NetBSD: radix.h,v 1.8 1996/02/13 22:00:37 christos Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)radix.h 8.2 (Berkeley) 10/31/94 + */ + +#ifndef _NET_RADIX_H_ +#define _NET_RADIX_H_ + +/* + * Radix search tree node layout. + */ + +struct radix_node { + struct radix_mask *rn_mklist; /* list of masks contained in subtree */ + struct radix_node *rn_p; /* parent */ + short rn_b; /* bit offset; -1-index(netmask) */ + char rn_bmask; /* node: mask for bit test*/ + u_char rn_flags; /* enumerated next */ +#define RNF_NORMAL 1 /* leaf contains normal route */ +#define RNF_ROOT 2 /* leaf is root leaf for tree */ +#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */ + union { + struct { /* leaf only data: */ + caddr_t rn_Key; /* object of search */ + caddr_t rn_Mask; /* netmask, if present */ + struct radix_node *rn_Dupedkey; + } rn_leaf; + struct { /* node only data: */ + int rn_Off; /* where to start compare */ + struct radix_node *rn_L;/* progeny */ + struct radix_node *rn_R;/* progeny */ + } rn_node; + } rn_u; +#ifdef RN_DEBUG + int rn_info; + struct radix_node *rn_twin; + struct radix_node *rn_ybro; +#endif +}; + +#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey +#define rn_key rn_u.rn_leaf.rn_Key +#define rn_mask rn_u.rn_leaf.rn_Mask +#define rn_off rn_u.rn_node.rn_Off +#define rn_l rn_u.rn_node.rn_L +#define rn_r rn_u.rn_node.rn_R + +/* + * Annotations to tree concerning potential routes applying to subtrees. + */ + +extern struct radix_mask { + short rm_b; /* bit offset; -1-index(netmask) */ + char rm_unused; /* cf. rn_bmask */ + u_char rm_flags; /* cf. rn_flags */ + struct radix_mask *rm_mklist; /* more masks to try */ + union { + caddr_t rmu_mask; /* the mask */ + struct radix_node *rmu_leaf; /* for normal routes */ + } rm_rmu; + int rm_refs; /* # of references to this struct */ +} *rn_mkfreelist; + +#define rm_mask rm_rmu.rmu_mask +#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */ + +#define MKGet(m) {\ + if (rn_mkfreelist) {\ + m = rn_mkfreelist; \ + rn_mkfreelist = (m)->rm_mklist; \ + } else \ + R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\ + +#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);} + +struct radix_node_head { + struct radix_node *rnh_treetop; + int rnh_addrsize; /* permit, but not require fixed keys */ + int rnh_pktsize; /* permit, but not require fixed keys */ + struct radix_node *(*rnh_addaddr) /* add based on sockaddr */ + __P((void *v, void *mask, + struct radix_node_head *head, struct radix_node nodes[])); + struct radix_node *(*rnh_addpkt) /* add based on packet hdr */ + __P((void *v, void *mask, + struct radix_node_head *head, struct radix_node nodes[])); + struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */ + __P((void *v, void *mask, struct radix_node_head *head)); + struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */ + __P((void *v, void *mask, struct radix_node_head *head)); + struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */ + __P((void *v, struct radix_node_head *head)); + struct radix_node *(*rnh_lookup) /* locate based on sockaddr */ + __P((void *v, void *mask, struct radix_node_head *head)); + struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */ + __P((void *v, struct radix_node_head *head)); + int (*rnh_walktree) /* traverse tree */ + __P((struct radix_node_head *, + int (*)(struct radix_node *, void *), void *)); + struct radix_node rnh_nodes[3]; /* empty tree for common case */ +}; + + +#ifndef _KERNEL +#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n)) +#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n)) +#define Bzero(p, n) bzero((char *)(p), (int)(n)); +#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n))) +#define Free(p) free((char *)p); +#else +#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) +#define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) +#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n)); +#define R_Malloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_DONTWAIT)) +#define Free(p) free((caddr_t)p, M_RTABLE); +#endif /* !_KERNEL */ + +#if defined(_KERNEL) || defined(_ROUTED) +void rn_init __P((void)); +int rn_inithead __P((void **, int)); +int rn_refines __P((void *, void *)); +int rn_walktree __P((struct radix_node_head *, + int (*)(struct radix_node *, void *), void *)); +struct radix_node + *rn_addmask __P((void *, int, int)), + *rn_addroute __P((void *, void *, struct radix_node_head *, + struct radix_node [2])), + *rn_delete __P((void *, void *, struct radix_node_head *)), + *rn_insert __P((void *, struct radix_node_head *, int *, + struct radix_node [2])), + *rn_lookup __P((void *, void *, struct radix_node_head *)), + *rn_match __P((void *, struct radix_node_head *)), + *rn_newpair __P((void *, int, struct radix_node[2])), + *rn_search __P((void *, struct radix_node *)), + *rn_search_m __P((void *, struct radix_node *, void *)); +#endif /* define(_KERNEL) || defined(_ROUTED) */ + +#endif /* !_NET_RADIX_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/net/raw_cb.h b/ecos/packages/net/tcpip/current/include/net/raw_cb.h new file mode 100644 index 0000000..68c0a25 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/raw_cb.h @@ -0,0 +1,105 @@ +//========================================================================== +// +// include/net/raw_cb.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: raw_cb.h,v 1.2 1996/03/03 21:07:17 niklas Exp $ */ +/* $NetBSD: raw_cb.h,v 1.9 1996/02/13 22:00:41 christos Exp $ */ + +/* + * Copyright (c) 1980, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)raw_cb.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NET_RAW_CB_H_ +#define _NET_RAW_CB_H_ + +/* + * Raw protocol interface control block. Used + * to tie a socket to the generic raw interface. + */ +struct rawcb { + LIST_ENTRY(rawcb) rcb_list; /* doubly linked list */ + struct socket *rcb_socket; /* back pointer to socket */ + struct sockaddr *rcb_faddr; /* destination address */ + struct sockaddr *rcb_laddr; /* socket's address */ + struct sockproto rcb_proto; /* protocol family, protocol */ +}; + +#define sotorawcb(so) ((struct rawcb *)(so)->so_pcb) + +/* + * Nominal space allocated to a raw socket. + */ +#define RAWSNDQ 8192 +#define RAWRCVQ 8192 + +#ifdef _KERNEL +LIST_HEAD(, rawcb) rawcb; /* head of list */ + +int raw_attach __P((struct socket *, int)); +void *raw_ctlinput __P((int, struct sockaddr *, void *)); +void raw_detach __P((struct rawcb *)); +void raw_disconnect __P((struct rawcb *)); +void raw_init __P((void)); +void raw_input __P((struct mbuf *, ...)); +int raw_usrreq __P((struct socket *, + int, struct mbuf *, struct mbuf *, struct mbuf *)); + +#endif /* _KERNEL */ + +#endif // _NET_RAW_CB_H_ diff --git a/ecos/packages/net/tcpip/current/include/net/route.h b/ecos/packages/net/tcpip/current/include/net/route.h new file mode 100644 index 0000000..622beb2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/net/route.h @@ -0,0 +1,383 @@ +//========================================================================== +// +// include/net/route.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: route.h,v 1.7 1999/12/08 06:50:18 itojun Exp $ */ +/* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */ + +/* + * Copyright (c) 1980, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)route.h 8.3 (Berkeley) 4/19/94 + */ + +#ifndef _NET_ROUTE_H_ +#define _NET_ROUTE_H_ + +#include <sys/queue.h> + +/* + * Kernel resident routing tables. + * + * The routing tables are initialized when interface addresses + * are set by making entries for all directly connected interfaces. + */ + +/* + * A route consists of a destination address and a reference + * to a routing entry. These are often held by protocols + * in their control blocks, e.g. inpcb. + */ +struct route { + struct rtentry *ro_rt; + struct sockaddr ro_dst; +}; + +/* + * These numbers are used by reliable protocols for determining + * retransmission behavior and are included in the routing structure. + */ +struct rt_metrics { + u_long rmx_locks; /* Kernel must leave these values alone */ + u_long rmx_mtu; /* MTU for this path */ + u_long rmx_hopcount; /* max hops expected */ + u_long rmx_expire; /* lifetime for route, e.g. redirect */ + u_long rmx_recvpipe; /* inbound delay-bandwith product */ + u_long rmx_sendpipe; /* outbound delay-bandwith product */ + u_long rmx_ssthresh; /* outbound gateway buffer limit */ + u_long rmx_rtt; /* estimated round trip time */ + u_long rmx_rttvar; /* estimated rtt variance */ + u_long rmx_pksent; /* packets sent using this route */ +}; + +/* + * rmx_rtt and rmx_rttvar are stored as microseconds; + * RTTTOPRHZ(rtt) converts to a value suitable for use + * by a protocol slowtimo counter. + */ +#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */ +#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ)) + +/* + * We distinguish between routes to hosts and routes to networks, + * preferring the former if available. For each route we infer + * the interface to use from the gateway address supplied when + * the route was entered. Routes that forward packets through + * gateways are marked so that the output routines know to address the + * gateway rather than the ultimate destination. + */ +#ifndef RNF_NORMAL +#include <net/radix.h> +#endif +struct rtentry { + struct radix_node rt_nodes[2]; /* tree glue, and other values */ +#define rt_key(r) ((struct sockaddr *)((r)->rt_nodes->rn_key)) +#define rt_mask(r) ((struct sockaddr *)((r)->rt_nodes->rn_mask)) + struct sockaddr *rt_gateway; /* value */ + u_int rt_flags; /* up/down?, host/net */ + short rt_refcnt; /* # held references */ + short rt_filler; /* XXX */ + u_long rt_use; /* raw # packets forwarded */ + struct ifnet *rt_ifp; /* the answer: interface to use */ + struct ifaddr *rt_ifa; /* the answer: interface to use */ + struct sockaddr *rt_genmask; /* for generation of cloned routes */ + caddr_t rt_llinfo; /* pointer to link level info cache */ + struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */ + struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */ + struct rtentry *rt_parent; /* If cloned, parent of this route. */ + LIST_HEAD(, rttimer) rt_timer; /* queue of timeouts for misc funcs */ +}; +#define rt_use rt_rmx.rmx_pksent + +#ifdef __ECOS +/* + * This structure modelled after the Linux 'route' functions + * Used by the SIOCADDRT and SIOCDELRT calls + */ +struct ecos_rtentry + { + struct sockaddr rt_dst; /* Target address. */ + struct sockaddr rt_gateway; /* Gateway addr (RTF_GATEWAY). */ + struct sockaddr rt_genmask; /* Target network mask (IP). */ + unsigned short int rt_flags; + unsigned char rt_tos; + unsigned char rt_class; + short int rt_metric; /* +1 for binary compatibility! */ + char *rt_dev; /* Forcing the device at add. */ + unsigned long int rt_mtu; /* Per route MTU/Window. */ + unsigned long int rt_window; /* Window clamping. */ + unsigned short int rt_irtt; /* Initial RTT. */ + }; +/* Compatibility hack. */ +#define rt_mss rt_mtu +#endif + +/* + * Following structure necessary for 4.3 compatibility; + * We should eventually move it to a compat file. + */ +struct ortentry { + u_int32_t rt_hash; /* to speed lookups */ + struct sockaddr rt_dst; /* key */ + struct sockaddr rt_gateway; /* value */ + int16_t rt_flags; /* up/down?, host/net */ + int16_t rt_refcnt; /* # held references */ + u_int32_t rt_ouse; /* raw # packets forwarded (was: rt_use) */ + struct ifnet *rt_ifp; /* the answer: interface to use */ +}; + +#define RTF_UP 0x1 /* route usable */ +#define RTF_GATEWAY 0x2 /* destination is a gateway */ +#define RTF_HOST 0x4 /* host entry (net otherwise) */ +#define RTF_REJECT 0x8 /* host or net unreachable */ +#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */ +#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */ +#define RTF_DONE 0x40 /* message confirmed */ +#define RTF_MASK 0x80 /* subnet mask present */ +#define RTF_CLONING 0x100 /* generate new routes on use */ +#define RTF_XRESOLVE 0x200 /* external daemon resolves name */ +#define RTF_LLINFO 0x400 /* generated by ARP or ESIS */ +#define RTF_STATIC 0x800 /* manually added */ +#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */ +#define RTF_PROTO3 0x2000 /* protocol specific routing flag */ +#define RTF_PROTO2 0x4000 /* protocol specific routing flag */ +#define RTF_PROTO1 0x8000 /* protocol specific routing flag */ + +/* + * New IPv6 routing flags. + * + * PROTO1 and PROTO2 are used, and defined in netinet6/ipv6_var.h. + */ +#define RTF_TUNNEL 0x100000 /* Tunnelling bit. */ + +/* + * Routing statistics. + */ +struct rtstat { + u_int32_t rts_badredirect; /* bogus redirect calls */ + u_int32_t rts_dynamic; /* routes created by redirects */ + u_int32_t rts_newgateway; /* routes modified by redirects */ + u_int32_t rts_unreach; /* lookups which failed */ + u_int32_t rts_wildcard; /* lookups satisfied by a wildcard */ +}; + +/* + * Structures for routing messages. + */ +struct rt_msghdr { + u_short rtm_msglen; /* to skip over non-understood messages */ + u_char rtm_version; /* future binary compatibility */ + u_char rtm_type; /* message type */ + u_short rtm_index; /* index for associated ifp */ + int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ + int rtm_addrs; /* bitmask identifying sockaddrs in msg */ + pid_t rtm_pid; /* identify sender */ + int rtm_seq; /* for sender to identify action */ + int rtm_errno; /* why failed */ + int rtm_use; /* from rtentry */ + u_long rtm_inits; /* which metrics we are initializing */ + struct rt_metrics rtm_rmx; /* metrics themselves */ +}; + +#define RTM_VERSION 3 /* Up the ante and ignore older versions */ + +#define RTM_ADD 0x1 /* Add Route */ +#define RTM_DELETE 0x2 /* Delete Route */ +#define RTM_CHANGE 0x3 /* Change Metrics or flags */ +#define RTM_GET 0x4 /* Report Metrics */ +#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */ +#define RTM_REDIRECT 0x6 /* Told to use different route */ +#define RTM_MISS 0x7 /* Lookup failed on this address */ +#define RTM_LOCK 0x8 /* fix specified metrics */ +#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */ +#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */ +#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */ +#define RTM_NEWADDR 0xc /* address being added to iface */ +#define RTM_DELADDR 0xd /* address being removed from iface */ +#define RTM_IFINFO 0xe /* iface going up/down etc. */ + +#define RTV_MTU 0x1 /* init or lock _mtu */ +#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */ +#define RTV_EXPIRE 0x4 /* init or lock _hopcount */ +#define RTV_RPIPE 0x8 /* init or lock _recvpipe */ +#define RTV_SPIPE 0x10 /* init or lock _sendpipe */ +#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */ +#define RTV_RTT 0x40 /* init or lock _rtt */ +#define RTV_RTTVAR 0x80 /* init or lock _rttvar */ + +/* + * Bitmask values for rtm_addr. + */ +#define RTA_DST 0x1 /* destination sockaddr present */ +#define RTA_GATEWAY 0x2 /* gateway sockaddr present */ +#define RTA_NETMASK 0x4 /* netmask sockaddr present */ +#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */ +#define RTA_IFP 0x10 /* interface name sockaddr present */ +#define RTA_IFA 0x20 /* interface addr sockaddr present */ +#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */ +#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */ + +/* + * Index offsets for sockaddr array for alternate internal encoding. + */ +#define RTAX_DST 0 /* destination sockaddr present */ +#define RTAX_GATEWAY 1 /* gateway sockaddr present */ +#define RTAX_NETMASK 2 /* netmask sockaddr present */ +#define RTAX_GENMASK 3 /* cloning mask sockaddr present */ +#define RTAX_IFP 4 /* interface name sockaddr present */ +#define RTAX_IFA 5 /* interface addr sockaddr present */ +#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */ +#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */ +#define RTAX_MAX 8 /* size of array to allocate */ + +struct rt_addrinfo { + int rti_addrs; + struct sockaddr *rti_info[RTAX_MAX]; +}; + +struct route_cb { + int ip_count; + int ip6_count; + int ns_count; + int iso_count; + int any_count; +}; + +/* + * This structure, and the prototypes for the rt_timer_{init,remove_all, + * add,timer} functions all used with the kind permission of BSDI. + * These allow functions to be called for routes at specific times. + */ + +struct rttimer { + TAILQ_ENTRY(rttimer) rtt_next; /* entry on timer queue */ + LIST_ENTRY(rttimer) rtt_link; /* multiple timers per rtentry */ + struct rttimer_queue *rtt_queue;/* back pointer to queue */ + struct rtentry *rtt_rt; /* Back pointer to the route */ + void (*rtt_func) __P((struct rtentry *, + struct rttimer *)); + time_t rtt_time; /* When this timer was registered */ +}; + +struct rttimer_queue { + long rtq_timeout; + TAILQ_HEAD(, rttimer) rtq_head; + LIST_ENTRY(rttimer_queue) rtq_link; +}; + +#ifdef _KERNEL +#define RTFREE(rt) do { \ + if ((rt)->rt_refcnt <= 1) \ + rtfree(rt); \ + else \ + (rt)->rt_refcnt--; \ +} while (0) + +/* + * Values for additional argument to rtalloc_noclone() and rtalloc2() + */ +#define ALL_CLONING 0 +#define ONNET_CLONING 1 +#define NO_CLONING 2 + +struct route_cb route_cb; +struct rtstat rtstat; +struct radix_node_head *rt_tables[AF_MAX+1]; + +struct socket; +void route_init __P((void)); +int route_output __P((struct mbuf *, ...)); +int route_usrreq __P((struct socket *, int, struct mbuf *, + struct mbuf *, struct mbuf *)); +void rt_ifmsg __P((struct ifnet *)); +void rt_maskedcopy __P((struct sockaddr *, + struct sockaddr *, struct sockaddr *)); +void rt_missmsg __P((int, struct rt_addrinfo *, int, int)); +void rt_newaddrmsg __P((int, struct ifaddr *, int, struct rtentry *)); +int rt_setgate __P((struct rtentry *, struct sockaddr *, + struct sockaddr *)); +void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *)); +int rt_timer_add __P((struct rtentry *, + void(*)(struct rtentry *, struct rttimer *), + struct rttimer_queue *)); +void rt_timer_init __P((void)); +struct rttimer_queue * + rt_timer_queue_create __P((u_int)); +void rt_timer_queue_change __P((struct rttimer_queue *, long)); +void rt_timer_queue_destroy __P((struct rttimer_queue *, int)); +void rt_timer_remove_all __P((struct rtentry *)); +void rt_timer_timer __P((void *)); +void rtable_init __P((void **)); +void rtalloc __P((struct route *)); +struct rtentry * + rtalloc1 __P((struct sockaddr *, int)); +void rtalloc_noclone __P((struct route *, int)); +struct rtentry * + rtalloc2 __P((struct sockaddr *, int, int)); +void rtfree __P((struct rtentry *)); +int rtinit __P((struct ifaddr *, int, int)); +int rtioctl __P((u_long, caddr_t, struct proc *)); +void rtredirect __P((struct sockaddr *, struct sockaddr *, + struct sockaddr *, int, struct sockaddr *, + struct rtentry **)); +int rtrequest __P((int, struct sockaddr *, + struct sockaddr *, struct sockaddr *, int, + struct rtentry **)); +void ipv4_tunnelsetup __P((struct rtentry *)); +#endif /* _KERNEL */ + +#endif // _NET_ROUTE_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/icmp6.h b/ecos/packages/net/tcpip/current/include/netinet/icmp6.h new file mode 100644 index 0000000..2c53488 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/icmp6.h @@ -0,0 +1,66 @@ +//========================================================================== +// +// include/netinet/icmp6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: icmp6.h,v 1.1 1999/12/08 06:50:18 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETINET_ICMP6_H_ +#define _NETINET_ICMP6_H_ + +#include <netinet6/icmp6.h> + +#endif /* !_NETINET_ICMP6_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/icmp_var.h b/ecos/packages/net/tcpip/current/include/netinet/icmp_var.h new file mode 100644 index 0000000..8ba142b --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/icmp_var.h @@ -0,0 +1,108 @@ +//========================================================================== +// +// include/netinet/icmp_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: icmp_var.h,v 1.4 1998/01/06 01:38:35 deraadt Exp $ */ +/* $NetBSD: icmp_var.h,v 1.8 1995/03/26 20:32:19 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)icmp_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_ICMP_VAR_H_ +#define _NETINET_ICMP_VAR_H_ + +/* + * Variables related to this implementation + * of the internet control message protocol. + */ +struct icmpstat { +/* statistics related to icmp packets generated */ + u_long icps_error; /* # of calls to icmp_error */ + u_long icps_oldshort; /* no error 'cuz old ip too short */ + u_long icps_oldicmp; /* no error 'cuz old was icmp */ + u_long icps_outhist[ICMP_MAXTYPE + 1]; +/* statistics related to input messages processed */ + u_long icps_badcode; /* icmp_code out of range */ + u_long icps_tooshort; /* packet < ICMP_MINLEN */ + u_long icps_checksum; /* bad checksum */ + u_long icps_badlen; /* calculated bound mismatch */ + u_long icps_reflect; /* number of responses */ + u_long icps_bmcastecho; /* rejected broadcast icmps */ + u_long icps_inhist[ICMP_MAXTYPE + 1]; +}; + +/* + * Names for ICMP sysctl objects + */ +#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */ +#define ICMPCTL_BMCASTECHO 2 /* reply to icmps to broadcast/mcast */ +#define ICMPCTL_MAXID 3 + +#define ICMPCTL_NAMES { \ + { 0, 0 }, \ + { "maskrepl", CTLTYPE_INT }, \ + { "bmcastecho", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL +struct icmpstat icmpstat; +#endif + +#endif // _NETINET_ICMP_VAR_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/if_arc.h b/ecos/packages/net/tcpip/current/include/netinet/if_arc.h new file mode 100644 index 0000000..424e4d3 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/if_arc.h @@ -0,0 +1,158 @@ +//========================================================================== +// +// include/netinet/if_arc.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_arc.h,v 1.2 1997/02/24 14:06:34 niklas Exp $ */ +/* $NetBSD: if_arc.h,v 1.5 1995/06/07 00:14:04 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: NetBSD: if_ether.h,v 1.10 1994/06/29 06:37:55 cgd Exp + * @(#)if_ether.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IF_ARC_H_ +#define _NETINET_IF_ARC_H_ + +/* + * Arcnet address - 1 octets + * don't know who uses this. + */ +struct arc_addr { + u_int8_t arc_addr_octet[1]; +}; + +/* + * Structure of a 2.5MB/s Arcnet header. + * as given to interface code. + */ +struct arc_header { + u_int8_t arc_shost; + u_int8_t arc_dhost; + u_int8_t arc_type; + /* + * only present for newstyle encoding with LL fragmentation. + * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead. + */ + u_int8_t arc_flag; + u_int16_t arc_seqid; + + /* + * only present in exception packets (arc_flag == 0xff) + */ + u_int8_t arc_type2; /* same as arc_type */ + u_int8_t arc_flag2; /* real flag value */ + u_int16_t arc_seqid2; /* real seqid value */ +}; + +#define ARC_ADDR_LEN 1 + +#define ARC_HDRLEN 3 +#define ARC_HDRNEWLEN 6 + +/* these lengths are data link layer length - 2*ARC_ADDR_LEN */ +#define ARC_MIN_LEN 1 +#define ARC_MIN_FORBID_LEN 254 +#define ARC_MAX_FORBID_LEN 256 +#define ARC_MAX_LEN 508 + + +/* RFC 1051 */ +#define ARCTYPE_IP_OLD 240 /* IP protocol */ +#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ + +/* RFC 1201 */ +#define ARCTYPE_IP 212 /* IP protocol */ +#define ARCTYPE_ARP 213 /* address resolution protocol */ +#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ + +#define ARCTYPE_ATALK 221 /* Appletalk */ +#define ARCTYPE_BANIAN 247 /* Banyan Vines */ +#define ARCTYPE_IPX 250 /* Novell IPX */ + +#define ARCMTU 507 +#define ARCMIN 0 + +struct arccom { + struct ifnet ac_if; /* network-visible interface */ + u_int8_t ac_anaddr; /* arcnet hardware address */ + struct in_addr ac_ipaddr; /* copy of ip address- XXX */ + + u_int16_t ac_seqid; /* seq. id used by PHDS encap. */ + + struct ac_frag { + u_int8_t af_maxflag; /* from first packet */ + u_int8_t af_lastseen; /* last split flag seen */ + u_int16_t af_seqid; + struct mbuf *af_packet; + } ac_fragtab[256]; /* indexed by sender ll address */ + +}; + +#ifdef _KERNEL +u_int8_t arcbroadcastaddr; + +void arc_ifattach __P((struct ifnet *)); +char *arc_sprintf __P((u_int8_t *)); +void arc_input __P((struct ifnet *, struct mbuf *)); +int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *)); +int arc_isphds __P((int)); +#endif + +#endif // _NETINET_IF_ARC_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/if_atm.h b/ecos/packages/net/tcpip/current/include/netinet/if_atm.h new file mode 100644 index 0000000..9b62458 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/if_atm.h @@ -0,0 +1,75 @@ +//========================================================================== +// +// include/netinet/if_atm.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_atm.h,v 1.3 1996/07/03 17:14:32 chuck Exp $ */ + +/* + * + * Copyright (c) 1996 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles D. Cranor and + * Washington University. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NETINET_IF_ATM_H_ +#define _NETINET_IF_ATM_H_ + +/* + * if_atm.h + */ + +void atm_rtrequest __P((int, struct rtentry *, struct sockaddr *)); +int atmresolve __P((struct rtentry *, struct mbuf *, struct sockaddr *, + struct atm_pseudohdr *)); + +#endif // _NETINET_IF_ATM_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/if_ether.h b/ecos/packages/net/tcpip/current/include/netinet/if_ether.h new file mode 100644 index 0000000..9b70fb9 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/if_ether.h @@ -0,0 +1,314 @@ +//========================================================================== +// +// include/netinet/if_ether.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_ether.h,v 1.10 1999/12/08 06:50:19 itojun Exp $ */ +/* $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_ether.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IF_ETHER_H_ +#define _NETINET_IF_ETHER_H_ + +/* + * Ethernet address - 6 octets + * this is only used by the ethers(3) functions. + */ +struct ether_addr { + u_int8_t ether_addr_octet[6]; +} __attribute__ ((aligned(1), packed)); + +/* + * Structure of a Ethernet header. + */ +#define ETHER_ADDR_LEN 6 + +struct ether_header { + u_int8_t ether_dhost[ETHER_ADDR_LEN]; + u_int8_t ether_shost[ETHER_ADDR_LEN]; + u_int16_t ether_type; +} __attribute__ ((aligned(1), packed)); + +#define ETHERTYPE_PUP 0x0200 /* PUP protocol */ +#define ETHERTYPE_IP 0x0800 /* IP protocol */ +#define ETHERTYPE_ARP 0x0806 /* address resolution protocol */ +#define ETHERTYPE_REVARP 0x8035 /* reverse addr resolution protocol */ +#define ETHERTYPE_IPV6 0x86DD /* IPv6 protocol */ + +/* + * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have + * (type-ETHERTYPE_TRAIL)*512 bytes of data followed + * by an ETHER type (as given above) and then the (variable-length) header. + */ +#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ +#define ETHERTYPE_NTRAILER 16 + +#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */ + +#define ETHERMTU 1500 +#define ETHERMIN (60-14) + +#ifdef _KERNEL +/* + * Macro to map an IP multicast address to an Ethernet multicast address. + * The high-order 25 bits of the Ethernet address are statically assigned, + * and the low-order 23 bits are taken from the low end of the IP address. + */ +#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \ + /* struct in_addr *ipaddr; */ \ + /* u_int8_t enaddr[ETHER_ADDR_LEN]; */ \ +{ \ + (enaddr)[0] = 0x01; \ + (enaddr)[1] = 0x00; \ + (enaddr)[2] = 0x5e; \ + (enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f; \ + (enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \ + (enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \ +} + +/* + * Macro to map an IPv6 multicast address to an Ethernet multicast address. + * The high-order 16 bits of the Ethernet address are statically assigned, + * and the low-order 32 bits are taken from the low end of the IPv6 address. + */ +#define ETHER_MAP_IPV6_MULTICAST(ip6addr, enaddr) \ + /* struct in6_addr *ip6addr; */ \ + /* u_int8_t enaddr[ETHER_ADDR_LEN]; */ \ +{ \ + (enaddr)[0] = 0x33; \ + (enaddr)[1] = 0x33; \ + (enaddr)[2] = ((u_int8_t *)ip6addr)[12]; \ + (enaddr)[3] = ((u_int8_t *)ip6addr)[13]; \ + (enaddr)[4] = ((u_int8_t *)ip6addr)[14]; \ + (enaddr)[5] = ((u_int8_t *)ip6addr)[15]; \ +} +#endif + +/* + * Ethernet Address Resolution Protocol. + * + * See RFC 826 for protocol description. Structure below is adapted + * to resolving internet addresses. Field names used correspond to + * RFC 826. + */ +struct ether_arp { + struct arphdr ea_hdr; /* fixed-size header */ + u_int8_t arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */ + u_int8_t arp_spa[4]; /* sender protocol address */ + u_int8_t arp_tha[ETHER_ADDR_LEN]; /* target hardware address */ + u_int8_t arp_tpa[4]; /* target protocol address */ +}; +#define arp_hrd ea_hdr.ar_hrd +#define arp_pro ea_hdr.ar_pro +#define arp_hln ea_hdr.ar_hln +#define arp_pln ea_hdr.ar_pln +#define arp_op ea_hdr.ar_op + +/* + * Structure shared between the ethernet driver modules and + * the address resolution code. For example, each ec_softc or il_softc + * begins with this structure. + */ +struct arpcom { + struct ifnet ac_if; /* network-visible interface */ + u_int8_t ac_enaddr[ETHER_ADDR_LEN]; /* ethernet hardware address */ + char ac__pad[2]; /* pad for some machines */ + LIST_HEAD(, ether_multi) ac_multiaddrs; /* list of ether multicast addrs */ + int ac_multicnt; /* length of ac_multiaddrs list */ +}; + +struct llinfo_arp { + LIST_ENTRY(llinfo_arp) la_list; + struct rtentry *la_rt; + struct mbuf *la_hold; /* last packet until resolved/timeout */ + long la_asked; /* last time we QUERIED for this addr */ +#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */ +}; + +struct sockaddr_inarp { + u_int8_t sin_len; + u_int8_t sin_family; + u_int16_t sin_port; + struct in_addr sin_addr; + struct in_addr sin_srcaddr; + u_int16_t sin_tos; + u_int16_t sin_other; +#define SIN_PROXY 1 +}; + +/* + * IP and ethernet specific routing flags + */ +#define RTF_USETRAILERS RTF_PROTO1 /* use trailers */ +#define RTF_ANNOUNCE RTF_PROTO2 /* announce new arp entry */ +#define RTF_PERMANENT_ARP RTF_PROTO3 /* only manual overwrite of entry */ + +#ifdef _KERNEL +extern u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN]; +extern u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN]; +extern u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN]; +extern struct ifqueue arpintrq; + +void arpwhohas __P((struct arpcom *, struct in_addr *)); +void arpintr __P((void)); +int arpresolve __P((struct arpcom *, + struct rtentry *, struct mbuf *, struct sockaddr *, u_char *)); +void arp_ifinit __P((struct arpcom *, struct ifaddr *)); +void arp_rtrequest __P((int, struct rtentry *, struct sockaddr *)); + +int ether_addmulti __P((struct ifreq *, struct arpcom *)); +int ether_delmulti __P((struct ifreq *, struct arpcom *)); +#endif /* _KERNEL */ + +/* + * Ethernet multicast address structure. There is one of these for each + * multicast address or range of multicast addresses that we are supposed + * to listen to on a particular interface. They are kept in a linked list, + * rooted in the interface's arpcom structure. (This really has nothing to + * do with ARP, or with the Internet address family, but this appears to be + * the minimally-disrupting place to put it.) + */ +struct ether_multi { + u_int8_t enm_addrlo[ETHER_ADDR_LEN]; /* low or only address of range */ + u_int8_t enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */ + struct arpcom *enm_ac; /* back pointer to arpcom */ + u_int enm_refcount; /* no. claims to this addr/range */ + LIST_ENTRY(ether_multi) enm_list; +}; + +/* + * Structure used by macros below to remember position when stepping through + * all of the ether_multi records. + */ +struct ether_multistep { + struct ether_multi *e_enm; +}; + +/* + * Macro for looking up the ether_multi record for a given range of Ethernet + * multicast addresses connected to a given arpcom structure. If no matching + * record is found, "enm" returns NULL. + */ +#define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm) \ + /* u_int8_t addrlo[ETHER_ADDR_LEN]; */ \ + /* u_int8_t addrhi[ETHER_ADDR_LEN]; */ \ + /* struct arpcom *ac; */ \ + /* struct ether_multi *enm; */ \ +{ \ + for ((enm) = (ac)->ac_multiaddrs.lh_first; \ + (enm) != NULL && \ + (bcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 || \ + bcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0); \ + (enm) = (enm)->enm_list.le_next); \ +} + +/* + * Macro to step through all of the ether_multi records, one at a time. + * The current position is remembered in "step", which the caller must + * provide. ETHER_FIRST_MULTI(), below, must be called to initialize "step" + * and get the first record. Both macros return a NULL "enm" when there + * are no remaining records. + */ +#define ETHER_NEXT_MULTI(step, enm) \ + /* struct ether_multistep step; */ \ + /* struct ether_multi *enm; */ \ +{ \ + if (((enm) = (step).e_enm) != NULL) \ + (step).e_enm = (enm)->enm_list.le_next; \ +} + +#define ETHER_FIRST_MULTI(step, ac, enm) \ + /* struct ether_multistep step; */ \ + /* struct arpcom *ac; */ \ + /* struct ether_multi *enm; */ \ +{ \ + (step).e_enm = (ac)->ac_multiaddrs.lh_first; \ + ETHER_NEXT_MULTI((step), (enm)); \ +} + +#ifdef _KERNEL + +extern struct ifnet *myip_ifp; + +void arp_rtrequest __P((int, struct rtentry *, struct sockaddr *)); +int arpresolve __P((struct arpcom *, struct rtentry *, struct mbuf *, + struct sockaddr *, u_char *)); +void arpintr __P((void)); +int arpioctl __P((u_long, caddr_t)); +void arp_ifinit __P((struct arpcom *, struct ifaddr *)); +void revarpinput __P((struct mbuf *)); +void in_revarpinput __P((struct mbuf *)); +void revarprequest __P((struct ifnet *)); +int revarpwhoarewe __P((struct ifnet *, struct in_addr *, struct in_addr *)); +int revarpwhoami __P((struct in_addr *, struct ifnet *)); +int db_show_arptab __P((void)); + +#else + +char *ether_ntoa __P((struct ether_addr *)); +struct ether_addr *ether_aton __P((char *)); +int ether_ntohost __P((char *, struct ether_addr *)); +int ether_hostton __P((char *, struct ether_addr *)); +int ether_line __P((char *, struct ether_addr *, char *)); + +#endif // _KERNEL + +#endif // _NETINET_IF_ETHER_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/igmp.h b/ecos/packages/net/tcpip/current/include/netinet/igmp.h new file mode 100644 index 0000000..4220ce2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/igmp.h @@ -0,0 +1,131 @@ +//========================================================================== +// +// include/netinet/igmp.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: igmp.h,v 1.3 1999/08/08 00:43:00 niklas Exp $ */ +/* $NetBSD: igmp.h,v 1.6 1995/05/31 06:08:21 mycroft Exp $ */ + +/* + * Copyright (c) 1988 Stephen Deering. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Stephen Deering of Stanford University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)igmp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IGMP_H_ +#define _NETINET_IGMP_H_ + +/* + * Internet Group Management Protocol (IGMP) definitions. + * + * MULTICAST 1.3 + */ + +/* + * IGMP packet format. + */ +struct igmp { + u_int8_t igmp_type; /* version & type of IGMP message */ + u_int8_t igmp_code; /* code for routing sub-messages */ + u_int16_t igmp_cksum; /* IP-style checksum */ + struct in_addr igmp_group; /* group address being reported */ +}; /* (zero for queries) */ + +#define IGMP_MINLEN 8 + +#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* membership query */ +#define IGMP_v1_HOST_MEMBERSHIP_REPORT 0x12 /* v1 membership report */ +#define IGMP_DVMRP 0x13 /* DVMRP routing message */ +#define IGMP_PIM 0x14 /* PIM routing message */ +#define IGMP_v2_HOST_MEMBERSHIP_REPORT 0x16 /* v2 membership report */ +#define IGMP_HOST_LEAVE_MESSAGE 0x17 /* leave-group message */ +#define IGMP_MTRACE_REPLY 0x1e /* traceroute reply */ +#define IGMP_MTRACE_QUERY 0x1f /* traceroute query */ + +#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */ + /* query (in seconds) */ + +#define IGMP_TIMER_SCALE 10 /* denominator for igmp_timer */ + +/* + * States for the IGMP v2 state table. + */ +#define IGMP_DELAYING_MEMBER 1 +#define IGMP_IDLE_MEMBER 2 +#define IGMP_LAZY_MEMBER 3 +#define IGMP_SLEEPING_MEMBER 4 +#define IGMP_AWAKENING_MEMBER 5 + +/* + * States for IGMP router version cache. + */ +#define IGMP_v1_ROUTER 1 +#define IGMP_v2_ROUTER 2 + +/* + * Revert to v2 if we haven't heard from the router in this amount of time. + */ +#define IGMP_AGE_THRESHOLD 540 + +#ifdef _KERNEL +void rti_delete __P((struct ifnet *)); +#endif + +#endif // _NETINET_IGMP_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/igmp_var.h b/ecos/packages/net/tcpip/current/include/netinet/igmp_var.h new file mode 100644 index 0000000..3a1820d --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/igmp_var.h @@ -0,0 +1,116 @@ +//========================================================================== +// +// include/netinet/igmp_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: igmp_var.h,v 1.3 1997/02/05 15:48:22 deraadt Exp $ */ +/* $NetBSD: igmp_var.h,v 1.9 1996/02/13 23:41:31 christos Exp $ */ + +/* + * Copyright (c) 1988 Stephen Deering. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Stephen Deering of Stanford University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)igmp_var.h 8.1 (Berkeley) 7/19/93 + */ + +#ifndef _NETINET_IGMP_VAR_H_ +#define _NETINET_IGMP_VAR_H_ + +/* + * Internet Group Management Protocol (IGMP), + * implementation-specific definitions. + * + * Written by Steve Deering, Stanford, May 1988. + * Modified by Rosen Sharma, Stanford, Aug 1994. + * Modified by Bill Fenner, Xerox PARC, Feb 1995. + * + * MULTICAST 1.3 + */ + +struct igmpstat { + u_long igps_rcv_total; /* total IGMP messages received */ + u_long igps_rcv_tooshort; /* received with too few bytes */ + u_long igps_rcv_badsum; /* received with bad checksum */ + u_long igps_rcv_queries; /* received membership queries */ + u_long igps_rcv_badqueries; /* received invalid queries */ + u_long igps_rcv_reports; /* received membership reports */ + u_long igps_rcv_badreports; /* received invalid reports */ + u_long igps_rcv_ourreports; /* received reports for our groups */ + u_long igps_snd_reports; /* sent membership reports */ +}; + +#ifdef _KERNEL +struct igmpstat igmpstat; + +/* + * Macro to compute a random timer value between 1 and (IGMP_MAX_REPORTING_ + * DELAY * countdown frequency). We assume that the routine random() + * is defined somewhere (and that it returns a positive number). + */ +#define IGMP_RANDOM_DELAY(X) (arc4random() % (X) + 1) + +void igmp_init __P((void)); +void igmp_input __P((struct mbuf *, ...)); +void igmp_joingroup __P((struct in_multi *)); +void igmp_leavegroup __P((struct in_multi *)); +void igmp_fasttimo __P((void)); +void igmp_slowtimo __P((void)); +#endif + +#endif // _NETINET_IGMP_VAR_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/in.h b/ecos/packages/net/tcpip/current/include/netinet/in.h new file mode 100644 index 0000000..128149b --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/in.h @@ -0,0 +1,680 @@ +//========================================================================== +// +// include/netinet/in.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in.h,v 1.27 1999/12/16 21:30:34 deraadt Exp $ */ +/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in.h 8.3 (Berkeley) 1/3/94 + */ + +/* + * Constants and structures defined by the internet system, + * Per RFC 790, September 1981, and numerous additions. + */ + +#ifndef _NETINET_IN_H_ +#define _NETINET_IN_H_ + +/* + * Protocols + */ +#define IPPROTO_IP 0 /* dummy for IP */ +#define IPPROTO_HOPOPTS IPPROTO_IP /* Hop-by-hop option header. */ +#define IPPROTO_ICMP 1 /* control message protocol */ +#define IPPROTO_IGMP 2 /* group mgmt protocol */ +#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */ +#define IPPROTO_IPIP 4 /* IP inside IP */ +#define IPPROTO_IPV4 IPPROTO_IPIP /* IP inside IP */ +#define IPPROTO_TCP 6 /* tcp */ +#define IPPROTO_EGP 8 /* exterior gateway protocol */ +#define IPPROTO_PUP 12 /* pup */ +#define IPPROTO_UDP 17 /* user datagram protocol */ +#define IPPROTO_IDP 22 /* xns idp */ +#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */ +#define IPPROTO_IPV6 41 /* IPv6 in IPv6 */ +#define IPPROTO_ROUTING 43 /* Routing header. */ +#define IPPROTO_FRAGMENT 44 /* Fragmentation/reassembly header. */ +#define IPPROTO_RSVP 46 /* resource reservation */ +#define IPPROTO_ESP 50 /* Encap. Security Payload */ +#define IPPROTO_AH 51 /* Authentication header */ +#define IPPROTO_ICMPV6 58 /* ICMP for IPv6 */ +#define IPPROTO_NONE 59 /* No next header */ +#define IPPROTO_DSTOPTS 60 /* Destination options header. */ +#define IPPROTO_EON 80 /* ISO cnlp */ +#define IPPROTO_ETHERIP 97 /* Ethernet in IPv4 */ +#define IPPROTO_ENCAP 98 /* encapsulation header */ +#define IPPROTO_PIM 103 /* Protocol indep. multicast */ +#define IPPROTO_IPCOMP 108 /* IP Payload Comp. Protocol */ +#define IPPROTO_RAW 255 /* raw IP packet */ + +#define IPPROTO_MAX 256 + +/* + * From FreeBSD: + * + * Local port number conventions: + * + * When a user does a bind(2) or connect(2) with a port number of zero, + * a non-conflicting local port address is chosen. + * The default range is IPPORT_RESERVED through + * IPPORT_USERRESERVED, although that is settable by sysctl. + * + * A user may set the IPPROTO_IP option IP_PORTRANGE to change this + * default assignment range. + * + * The value IP_PORTRANGE_DEFAULT causes the default behavior. + * + * The value IP_PORTRANGE_HIGH changes the range of candidate port numbers + * into the "high" range. These are reserved for client outbound connections + * which do not want to be filtered by any firewalls. + * + * The value IP_PORTRANGE_LOW changes the range to the "low" are + * that is (by convention) restricted to privileged processes. This + * convention is based on "vouchsafe" principles only. It is only secure + * if you trust the remote host to restrict these ports. + * + * The default range of ports and the high range can be changed by + * sysctl(3). (net.inet.ip.port{hi}{first,last}) + * + * Changing those values has bad security implications if you are + * using a a stateless firewall that is allowing packets outside of that + * range in order to allow transparent outgoing connections. + * + * Such a firewall configuration will generally depend on the use of these + * default values. If you change them, you may find your Security + * Administrator looking for you with a heavy object. + */ + +/* + * Ports < IPPORT_RESERVED are reserved for + * privileged processes (e.g. root). + * Ports > IPPORT_USERRESERVED are reserved + * for servers, not necessarily privileged. + */ +#define IPPORT_RESERVED 1024 +#define IPPORT_USERRESERVED 49151 + +/* + * Default local port range to use by setting IP_PORTRANGE_HIGH + */ +#define IPPORT_HIFIRSTAUTO 49152 +#define IPPORT_HILASTAUTO 65535 + +/* + * IP Version 4 Internet address (a structure for historical reasons) + */ +struct in_addr { + in_addr_t s_addr; +}; + +#if 0 /*NRL IPv6*/ +/* + * IP Version 6 Internet address + */ +struct in6_addr { + union { + u_int8_t s6u_addr8[16]; + u_int16_t s6u_addr16[8]; + u_int32_t s6u_addr32[4]; + } s6_u; +#define s6_addr s6_u.s6u_addr8 +/* + * The rest are common, but not guaranteed to be portable. 64 bit access are + * not available because the in6_addr in a sockaddr_in6 is not 64 bit aligned. + */ +#define s6_addr8 s6_u.s6u_addr8 +#define s6_addr16 s6_u.s6u_addr16 +#define s6_addr32 s6_u.s6u_addr32 +}; +#endif + +/* last return value of *_input(), meaning "all job for this pkt is done". */ +#define IPPROTO_DONE 257 + +/* + * Definitions of bits in internet address integers. + * On subnets, the decomposition of addresses to host and net parts + * is done according to subnet mask, not the masks here. + * + * By byte-swapping the constants, we avoid ever having to byte-swap IP + * addresses inside the kernel. Unfortunately, user-level programs rely + * on these macros not doing byte-swapping. + */ +#ifdef _KERNEL +#define __IPADDR(x) ((u_int32_t) htonl((u_int32_t)(x))) +#else +#define __IPADDR(x) ((u_int32_t)(x)) +#endif + +#define IN_CLASSA(i) (((u_int32_t)(i) & __IPADDR(0x80000000)) == \ + __IPADDR(0x00000000)) +#define IN_CLASSA_NET __IPADDR(0xff000000) +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST __IPADDR(0x00ffffff) +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(i) (((u_int32_t)(i) & __IPADDR(0xc0000000)) == \ + __IPADDR(0x80000000)) +#define IN_CLASSB_NET __IPADDR(0xffff0000) +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST __IPADDR(0x0000ffff) +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(i) (((u_int32_t)(i) & __IPADDR(0xe0000000)) == \ + __IPADDR(0xc0000000)) +#define IN_CLASSC_NET __IPADDR(0xffffff00) +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST __IPADDR(0x000000ff) + +#define IN_CLASSD(i) (((u_int32_t)(i) & __IPADDR(0xf0000000)) == \ + __IPADDR(0xe0000000)) +/* These ones aren't really net and host fields, but routing needn't know. */ +#define IN_CLASSD_NET __IPADDR(0xf0000000) +#define IN_CLASSD_NSHIFT 28 +#define IN_CLASSD_HOST __IPADDR(0x0fffffff) +#define IN_MULTICAST(i) IN_CLASSD(i) + +#define IN_EXPERIMENTAL(i) (((u_int32_t)(i) & __IPADDR(0xf0000000)) == \ + __IPADDR(0xf0000000)) +#define IN_BADCLASS(i) (((u_int32_t)(i) & __IPADDR(0xf0000000)) == \ + __IPADDR(0xf0000000)) + +#define IN_LOCAL_GROUP(i) (((u_int32_t)(i) & __IPADDR(0xffffff00)) == \ + __IPADDR(0xe0000000)) + +#define INADDR_ANY __IPADDR(0x00000000) +#define INADDR_LOOPBACK __IPADDR(0x7f000001) +#define INADDR_BROADCAST __IPADDR(0xffffffff) /* must be masked */ +#ifndef _KERNEL +#define INADDR_NONE __IPADDR(0xffffffff) /* -1 return */ +#endif + +#define INADDR_UNSPEC_GROUP __IPADDR(0xe0000000) /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP __IPADDR(0xe0000001) /* 224.0.0.1 */ +#define INADDR_MAX_LOCAL_GROUP __IPADDR(0xe00000ff) /* 224.0.0.255 */ + +#define IN_LOOPBACKNET 127 /* official! */ + +#if 0 /*NRL IPv6*/ +/* + * Tests for IPv6 address types + */ + +#define IN6_IS_ADDR_LINKLOCAL(addr) \ + (((addr)->s6_addr32[0] & htonl(0xffc00000)) == htonl(0xfe800000)) + +#define IN6_IS_ADDR_LOOPBACK(addr) \ + (((addr)->s6_addr32[0] == 0) && ((addr)->s6_addr32[1] == 0) && \ + ((addr)->s6_addr32[2] == 0) && ((addr)->s6_addr32[3] == htonl(1))) + +#define IN6_IS_ADDR_MULTICAST(addr) \ + ((addr)->s6_addr8[0] == 0xff) + +#define IN6_IS_ADDR_SITELOCAL(addr) \ + (((addr)->s6_addr32[0] & htonl(0xffc00000)) == htonl(0xfec00000)) + +#define IN6_IS_ADDR_UNSPECIFIED(addr) \ + (((addr)->s6_addr32[0] == 0) && ((addr)->s6_addr32[1] == 0) && \ + ((addr)->s6_addr32[2] == 0) && ((addr)->s6_addr32[3] == 0)) + +#define IN6_IS_ADDR_V4COMPAT(addr) \ + (((addr)->s6_addr32[0] == 0) && ((addr)->s6_addr32[1] == 0) && \ + ((addr)->s6_addr32[2] == 0) && ((addr)->s6_addr32[3] & ~htonl(1))) + +#define IN6_IS_ADDR_V4MAPPED(addr) \ + (((addr)->s6_addr32[0] == 0) && ((addr)->s6_addr32[1] == 0) && \ + ((addr)->s6_addr32[2] == htonl(0xffff))) + +#define IN6_ARE_ADDR_EQUAL(addr1, addr2) \ + (((addr1)->s6_addr32[0] == (addr2)->s6_addr32[0]) && \ + ((addr1)->s6_addr32[1] == (addr2)->s6_addr32[1]) && \ + ((addr1)->s6_addr32[2] == (addr2)->s6_addr32[2]) && \ + ((addr1)->s6_addr32[3] == (addr2)->s6_addr32[3])) + +/* + * IPv6 Multicast scoping. The scope is stored + * in the bottom 4 bits of the second byte of the + * multicast address. + */ + /* 0x0 */ /* reserved */ +#define IN6_NODE_LOCAL 0x1 /* node-local scope */ +#define IN6_LINK_LOCAL 0x2 /* link-local scope */ + /* 0x3 */ /* (unassigned) */ + /* 0x4 */ /* (unassigned) */ +#define IN6_SITE_LOCAL 0x5 /* site-local scope */ + /* 0x6 */ /* (unassigned) */ + /* 0x7 */ /* (unassigned) */ +#define IN6_ORG_LOCAL 0x8 /* organization-local scope */ + /* 0x9 */ /* (unassigned) */ + /* 0xA */ /* (unassigned) */ + /* 0xB */ /* (unassigned) */ + /* 0xC */ /* (unassigned) */ + /* 0xD */ /* (unassigned) */ +#define IN6_GLOBAL 0xE /* global scope */ + /* 0xF */ /* reserved */ + +#define IN6_MSCOPE(addr) ((addr)->s6_addr8[1] & 0x0f) + +#define IN6_IS_ADDR_MC_NODELOCAL(addr) \ + (IN6_IS_ADDR_MULTICAST(addr) && (IN6_MSCOPE(addr) == IN6_NODE_LOCAL)) +#define IN6_IS_ADDR_MC_LINKLOCAL(addr) \ + (IN6_IS_ADDR_MULTICAST(addr) && (IN6_MSCOPE(addr) == IN6_LINK_LOCAL)) +#define IN6_IS_ADDR_MC_SITELOCAL(addr) \ + (IN6_IS_ADDR_MULTICAST(addr) && (IN6_MSCOPE(addr) == IN6_SITE_LOCAL)) +#define IN6_IS_ADDR_MC_ORGLOCAL(addr) \ + (IN6_IS_ADDR_MULTICAST(addr) && (IN6_MSCOPE(addr) == IN6_ORG_LOCAL)) +#define IN6_IS_ADDR_MC_GLOBAL(addr) \ + (IN6_IS_ADDR_MULTICAST(addr) && (IN6_MSCOPE(addr) == IN6_GLOBAL)) + +/* + * Definitions of the IPv6 special addresses + */ +extern const struct in6_addr in6addr_any; +#define IN6ADDR_ANY_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}} + +extern const struct in6_addr in6addr_loopback; +#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}} +#endif + +/* + * IP Version 4 socket address. + */ +struct sockaddr_in { + u_int8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; + int8_t sin_zero[8]; +}; + +#if 0 /*NRL IPv6*/ +/* + * IP Version 6 socket address. + */ +#define SIN6_LEN 1 +struct sockaddr_in6 { + u_int8_t sin6_len; + sa_family_t sin6_family; + in_port_t sin6_port; + u_int32_t sin6_flowinfo; + struct in6_addr sin6_addr; + u_int32_t sin6_scope_id; +}; +#endif + +#define INET_ADDRSTRLEN 16 + +/* + * Structure used to describe IP options. + * Used to store options internally, to pass them to a process, + * or to restore options retrieved earlier. + * The ip_dst is used for the first-hop gateway when using a source route + * (this gets put into the header proper). + */ +struct ip_opts { + struct in_addr ip_dst; /* first hop, 0 w/o src rt */ +#if defined(__cplusplus) + int8_t Ip_opts[40]; /* cannot have same name as class */ +#else + int8_t ip_opts[40]; /* actually variable in size */ +#endif +}; + +/* + * Options for use with [gs]etsockopt at the IP level. + * First word of comment is data type; bool is stored in int. + */ +#define IP_OPTIONS 1 /* buf/ip_opts; set/get IP options */ +#define IP_HDRINCL 2 /* int; header is included with data */ +#define IP_TOS 3 /* int; IP type of service and preced. */ +#define IP_TTL 4 /* int; IP time to live */ +#define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */ +#define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */ +#define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */ +#define IP_RETOPTS 8 /* ip_opts; set/get IP options */ +#define IP_MULTICAST_IF 9 /* in_addr; set/get IP multicast i/f */ +#define IP_MULTICAST_TTL 10 /* u_char; set/get IP multicast ttl */ +#define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */ +#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */ +#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */ + +/* 14-17 left empty for future compatibility with FreeBSD */ + +#define IP_PORTRANGE 19 /* int; range to choose for unspec port */ +#define IP_AUTH_LEVEL 20 /* u_char; authentication used */ +#define IP_ESP_TRANS_LEVEL 21 /* u_char; transport encryption */ +#define IP_ESP_NETWORK_LEVEL 22 /* u_char; full-packet encryption */ + +#if 0 /* NRL IPv6 */ +#define IPV6_MULTICAST_IF 23 /* u_int; set/get multicast interface */ +#define IPV6_MULTICAST_HOPS 24 /* int; set/get multicast hop limit */ +#define IPV6_MULTICAST_LOOP 25 /* u_int; set/get multicast loopback */ +#define IPV6_JOIN_GROUP 26 /* ipv6_mreq; join multicast group */ +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP /* XXX - for compatibility */ +#define IPV6_LEAVE_GROUP 27 /* ipv6_mreq: leave multicast group */ +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP /* XXX - for compatibility */ +#define IPV6_ADDRFORM 28 /* int; get/set form of returned addrs */ +#define IPV6_UNICAST_HOPS 29 /* int; get/set unicast hop limit */ +#define IPV6_PKTINFO 30 /* int; receive in6_pktinfo as cmsg */ +#define IPV6_HOPLIMIT 31 /* int; receive int hoplimit as cmsg */ +#define IPV6_NEXTHOP 32 /* int; receive sockaddr_in6 as cmsg */ +#define IPV6_HOPOPTS 33 /* int; receive hop options as cmsg */ +#define IPV6_DSTOPTS 34 /* int; receive dst options as cmsg */ +#define IPV6_RTHDR 35 /* int; receive routing header as cmsg */ +#define IPV6_PKTOPTIONS 36 /* int; send/receive cmsgs for TCP */ +#define IPV6_CHECKSUM 37 /* int; offset to place send checksum */ +#define ICMPV6_FILTER 38 /* struct icmpv6_filter; get/set filter */ +#define ICMP6_FILTER ICMP6_FILTER +#endif + +#define IPSEC_OUTSA 39 /* set the outbound SA for a socket */ + +#if 0 /*KAME IPSEC*/ +#define IP_IPSEC_POLICY ?? /* struct; get/set security policy */ +#endif + +/* + * Security levels - IPsec, not IPSO + */ + +#define IPSEC_LEVEL_BYPASS 0x00 /* Bypass policy altogether */ +#define IPSEC_LEVEL_NONE 0x00 /* Send clear, accept any */ +#define IPSEC_LEVEL_AVAIL 0x01 /* Send secure if SA available */ +#define IPSEC_LEVEL_USE 0x02 /* Send secure, accept any */ +#define IPSEC_LEVEL_REQUIRE 0x03 /* Require secure inbound, also use */ +#define IPSEC_LEVEL_UNIQUE 0x04 /* Use outbound SA that is unique */ +#define IPSEC_LEVEL_DEFAULT IPSEC_LEVEL_AVAIL + +#define IPSEC_AUTH_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT +#define IPSEC_ESP_TRANS_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT +#define IPSEC_ESP_NETWORK_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT + +#if 0 /* NRL IPv6 */ +/* + * IPv6 Routing header types + */ +#define IPV6_RTHDR_TYPE_0 0 /* IPv6 Routing header type 0 */ + +#define IPV6_RTHDR_LOOSE 0 /* this hop need not be a neighbor */ +#define IPV6_RTHDR_STRICT 1 /* this hop must be a neighbor */ +#endif + +/* + * Defaults and limits for options + */ +#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */ +#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ +#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */ + +/* + * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. + */ +struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +}; + +#if 0 /* NRL IPv6 */ +/* + * Argument structure for IPV6_ADD_MEMBERSHIP and IPV6_DROP_MEMBERSHIP. + */ +struct ipv6_mreq { + struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */ + unsigned int ipv6mr_interface; /* Interface index */ +}; + +/* + * Argument structure for IPV6_PKTINFO control messages + */ +struct in6_pktinfo { + struct in6_addr ipi6_addr; + unsigned int ipi6_ifindex; +}; +#endif + +/* + * Argument for IP_PORTRANGE: + * - which range to search when port is unspecified at bind() or connect() + */ +#define IP_PORTRANGE_DEFAULT 0 /* default range */ +#define IP_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */ +#define IP_PORTRANGE_LOW 2 /* "low" - vouchsafe security */ + +/* + * Buffer lengths for strings containing printable IP addresses + */ +#define INET_ADDRSTRLEN 16 +#if 0 /* NRL IPv6 */ +#define INET6_ADDRSTRLEN 46 +#endif + +/* + * Definitions for inet sysctl operations. + * + * Third level is protocol number. + * Fourth level is desired variable within that protocol. + */ +#define IPPROTO_MAXID (IPPROTO_AH + 1) /* don't list to IPPROTO_MAX */ + +#define CTL_IPPROTO_NAMES { \ + { "ip", CTLTYPE_NODE }, \ + { "icmp", CTLTYPE_NODE }, \ + { "igmp", CTLTYPE_NODE }, \ + { "ggp", CTLTYPE_NODE }, \ + { "ip4", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { "tcp", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { "egp", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "pup", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "udp", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "esp", CTLTYPE_NODE }, \ + { "ah", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "etherip", CTLTYPE_NODE }, \ +} + +/* + * Names for IP sysctl objects + */ +#define IPCTL_FORWARDING 1 /* act as router */ +#define IPCTL_SENDREDIRECTS 2 /* may send redirects when forwarding */ +#define IPCTL_DEFTTL 3 /* default TTL */ +#ifdef notyet +#define IPCTL_DEFMTU 4 /* default MTU */ +#endif +#define IPCTL_SOURCEROUTE 5 /* may perform source routes */ +#define IPCTL_DIRECTEDBCAST 6 /* default broadcast behavior */ +#define IPCTL_IPPORT_FIRSTAUTO 7 +#define IPCTL_IPPORT_LASTAUTO 8 +#define IPCTL_IPPORT_HIFIRSTAUTO 9 +#define IPCTL_IPPORT_HILASTAUTO 10 +#define IPCTL_IPPORT_MAXQUEUE 11 +#define IPCTL_ENCDEBUG 12 +#define IPCTL_GIF_TTL 13 /* default TTL for gif encap packet */ +#define IPCTL_MAXID 14 + +#define IPCTL_NAMES { \ + { 0, 0 }, \ + { "forwarding", CTLTYPE_INT }, \ + { "redirect", CTLTYPE_INT }, \ + { "ttl", CTLTYPE_INT }, \ + /* { "mtu", CTLTYPE_INT }, */ { 0, 0 }, \ + { "sourceroute", CTLTYPE_INT }, \ + { "directed-broadcast", CTLTYPE_INT }, \ + { "portfirst", CTLTYPE_INT }, \ + { "portlast", CTLTYPE_INT }, \ + { "porthifirst", CTLTYPE_INT }, \ + { "porthilast", CTLTYPE_INT }, \ + { "maxqueue", CTLTYPE_INT }, \ + { "encdebug", CTLTYPE_INT }, \ + { "gifttl", CTLTYPE_INT }, \ +} + +/* INET6 stuff */ +#include <netinet6/in6.h> + +#ifndef _KERNEL + +#include <sys/cdefs.h> + +__BEGIN_DECLS +int bindresvport __P((int, struct sockaddr_in *)); +int bindresvport_af __P((int, struct sockaddr *, int af)); +__END_DECLS + +#else +int in_broadcast __P((struct in_addr, struct ifnet *)); +int in_canforward __P((struct in_addr)); +int in_cksum __P((struct mbuf *, int)); +int in_localaddr __P((struct in_addr)); +void in_socktrim __P((struct sockaddr_in *)); +char *inet_ntoa __P((struct in_addr)); +char *inet_ntoa_r __P((struct in_addr, char *)); + +#define satosin(sa) ((struct sockaddr_in *)(sa)) +#define sintosa(sin) ((struct sockaddr *)(sin)) +#define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) +#endif +#endif /* !_NETINET_IN_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/in_gif.h b/ecos/packages/net/tcpip/current/include/netinet/in_gif.h new file mode 100644 index 0000000..a8e5e2f --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/in_gif.h @@ -0,0 +1,71 @@ +//========================================================================== +// +// include/netinet/in_gif.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in_gif.h,v 1.1 1999/12/08 06:50:19 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETINET_IN_GIF_H_ +#define _NETINET_IN_GIF_H_ + +#define GIF_TTL 30 + +extern int ip_gif_ttl; + +void in_gif_input __P((struct mbuf *, ...)); +int in_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *)); + +#endif /*_NETINET_IN_GIF_H_*/ diff --git a/ecos/packages/net/tcpip/current/include/netinet/in_pcb.h b/ecos/packages/net/tcpip/current/include/netinet/in_pcb.h new file mode 100644 index 0000000..c65b070 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/in_pcb.h @@ -0,0 +1,308 @@ +//========================================================================== +// +// include/netinet/in_pcb.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in_pcb.h,v 1.19 1999/12/12 12:10:43 itojun Exp $ */ +/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IN_PCB_H_ +#define _NETINET_IN_PCB_H_ + +#include <sys/queue.h> +#if 0 /*KAME IPSEC*/ +#include <netinet6/ipsec.h> +#endif +#include <netinet6/ip6.h> +#include <netinet6/ip6_var.h> +#include <netinet6/icmp6.h> +#include <netinet/ip_ipsp.h> + +union inpaddru { + struct in6_addr iau_addr6; + struct { + uint8_t pad[12]; + struct in_addr inaddr; /* easier transition */ + } iau_a4u; +}; + +/* + * Common structure pcb for internet protocol implementation. + * Here are stored pointers to local and foreign host table + * entries, local and foreign socket numbers, and pointers + * up (to a socket structure) and down (to a protocol-specific) + * control block. + */ +struct inpcb { + LIST_ENTRY(inpcb) inp_hash; + CIRCLEQ_ENTRY(inpcb) inp_queue; + struct inpcbtable *inp_table; + union inpaddru inp_faddru; /* Foreign address. */ + union inpaddru inp_laddru; /* Local address. */ +#define inp_faddr inp_faddru.iau_a4u.inaddr +#define inp_faddr6 inp_faddru.iau_addr6 +#define inp_laddr inp_laddru.iau_a4u.inaddr +#define inp_laddr6 inp_laddru.iau_addr6 + u_int16_t inp_fport; /* foreign port */ + u_int16_t inp_lport; /* local port */ + struct socket *inp_socket; /* back pointer to socket */ + caddr_t inp_ppcb; /* pointer to per-protocol pcb */ + union { /* Route (notice increased size). */ + struct route ru_route; + struct route_in6 ru_route6; + } inp_ru; +#define inp_route inp_ru.ru_route +#define inp_route6 inp_ru.ru_route6 + int inp_flags; /* generic IP/datagram flags */ + union { /* Header prototype. */ + struct ip hu_ip; + struct ip6_hdr hu_ipv6; + } inp_hu; +#define inp_ip inp_hu.hu_ip +#define inp_ipv6 inp_hu.hu_ipv6 + struct mbuf *inp_options; /* IP options */ + struct ip6_pktopts *inp_outputopts6; /* IP6 options for outgoing packets */ + int inp_hops; + union { + struct ip_moptions *mou_mo; /* IPv4 multicast options */ + struct ip6_moptions *mou_mo6; /* IPv6 multicast options */ + } inp_mou; +#define inp_moptions inp_mou.mou_mo +#define inp_moptions6 inp_mou.mou_mo6 + u_char inp_seclevel[3]; /* Only the first 3 are used for now */ +#define SL_AUTH 0 /* Authentication level */ +#define SL_ESP_TRANS 1 /* ESP transport level */ +#define SL_ESP_NETWORK 2 /* ESP network (encapsulation) level */ + u_int8_t inp_secrequire:4, /* Condensed State from above */ + inp_secresult:4; /* Result from Key Management */ +#define SR_FAILED 1 /* Negotiation failed permanently */ +#define SR_SUCCESS 2 /* SA successfully established */ +#define SR_WAIT 3 /* Waiting for SA */ + TAILQ_ENTRY(inpcb) inp_tdb_next; + struct tdb *inp_tdb; /* If tdb_dst matches our dst, use */ + int inp_fflowinfo; /* Foreign flowlabel & priority */ + int inp_csumoffset; + struct icmp6_filter *inp_icmp6filt; +#if 0 /*KAME IPSEC*/ + struct secpolicy *inp_sp; /* security policy. It may not be + * used according to policy selection. + */ +#endif +}; + +struct inpcbtable { + CIRCLEQ_HEAD(, inpcb) inpt_queue; + LIST_HEAD(inpcbhead, inpcb) *inpt_hashtbl; + u_long inpt_hash; + u_int16_t inpt_lastport; +}; + +/* flags in inp_flags: */ +#define INP_RECVOPTS 0x001 /* receive incoming IP options */ +#define INP_RECVRETOPTS 0x002 /* receive IP options for reply */ +#define INP_RECVDSTADDR 0x004 /* receive IP dst address */ + +#define INP_RXDSTOPTS INP_RECVOPTS +#define INP_RXHOPOPTS INP_RECVRETOPTS +#define INP_RXINFO INP_RECVDSTADDR +#define INP_RXSRCRT 0x010 +#define INP_HOPLIMIT 0x020 + +#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR| \ + INP_RXSRCRT|INP_HOPLIMIT) + +#define INP_HDRINCL 0x008 /* user supplies entire IP header */ +#define INP_HIGHPORT 0x010 /* user wants "high" port binding */ +#define INP_LOWPORT 0x020 /* user wants "low" port binding */ + +/* + * These flags' values should be determined by either the transport + * protocol at PRU_BIND, PRU_LISTEN, PRU_CONNECT, etc, or by in_pcb*(). + */ +#define INP_IPV6 0x100 /* sotopf(inp->inp_socket) == PF_INET6 */ +#define INP_IPV6_UNDEC 0x200 /* PCB is PF_INET6, but listens for V4/V6 */ +#define INP_IPV6_MAPPED 0x400 /* PF_INET6 PCB which is connected to + * an IPv4 host, or is bound to + * an IPv4 address (specified with + * the mapped form of v6 addresses) */ +#define INP_IPV6_MCAST 0x800 /* Set if inp_moptions points to ipv6 ones */ + +#if 1 /*KAME*/ +/* flags in in6p_flags */ +#define IN6P_RECVOPTS INP_RECVOPTS /* receive incoming IP6 options */ +#define IN6P_RECVRETOPTS INP_RECVRETOPTS /* receive IP6 options for reply */ +#define IN6P_RECVDSTADDR INP_RECVDSTADDR /* receive IP6 dst address */ +#define IN6P_HIGHPORT INP_HIGHPORT /* user wants "high" port binding */ +#define IN6P_LOWPORT INP_LOWPORT /* user wants "low" port binding */ +#define IN6P_ANONPORT 0x40 /* port chosen for user */ +#define IN6P_FAITH 0x80 /* accept FAITH'ed connections */ +#define IN6P_PKTINFO 0x010000 +#define IN6P_HOPLIMIT 0x020000 +#define IN6P_NEXTHOP 0x040000 +#define IN6P_HOPOPTS 0x080000 +#define IN6P_DSTOPTS 0x100000 +#define IN6P_RTHDR 0x200000 +#define IN6P_CONTROLOPTS (0x3f0000 | IN6P_RECVOPTS | IN6P_RECVRETOPTS | IN6P_RECVDSTADDR) +#endif + +#define INPLOOKUP_WILDCARD 1 +#define INPLOOKUP_SETLOCAL 2 +#define INPLOOKUP_IPV6 4 + +#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb) + +/* macros for handling bitmap of ports not to allocate dynamically */ +#define DP_MAPBITS (sizeof(u_int32_t) * NBBY) +#define DP_MAPSIZE (howmany(IPPORT_RESERVED/2, DP_MAPBITS)) +#define DP_SET(m, p) ((m)[((p) - IPPORT_RESERVED/2) / DP_MAPBITS] |= (1 << ((p) % DP_MAPBITS))) +#define DP_CLR(m, p) ((m)[((p) - IPPORT_RESERVED/2) / DP_MAPBITS] &= ~(1 << ((p) % DP_MAPBITS))) +#define DP_ISSET(m, p) ((m)[((p) - IPPORT_RESERVED/2) / DP_MAPBITS] & (1 << ((p) % DP_MAPBITS))) + +/* default values for baddynamicports [see ip_init()] */ +#define DEFBADDYNAMICPORTS_TCP { 749, 750, 751, 760, 761, 871, 0 } +#define DEFBADDYNAMICPORTS_UDP { 750, 751, 0 } + +struct baddynamicports { + u_int32_t tcp[DP_MAPSIZE]; + u_int32_t udp[DP_MAPSIZE]; +}; + +#ifdef _KERNEL + +#define sotopf(so) (so->so_proto->pr_domain->dom_family) + +void in_losing __P((struct inpcb *)); +int in_pcballoc __P((struct socket *, void *)); +int in_pcbbind __P((void *, struct mbuf *)); +int in_pcbconnect __P((void *, struct mbuf *)); +void in_pcbdetach __P((void *)); +void in_pcbdisconnect __P((void *)); +struct inpcb * + in_pcbhashlookup __P((struct inpcbtable *, struct in_addr, + u_int, struct in_addr, u_int)); +#ifdef INET6 +struct inpcb * + in6_pcbhashlookup __P((struct inpcbtable *, struct in6_addr *, + u_int, struct in6_addr *, u_int)); +int in6_pcbbind __P((struct inpcb *, struct mbuf *)); +int in6_pcbconnect __P((struct inpcb *, struct mbuf *)); +int in6_setsockaddr __P((struct inpcb *, struct mbuf *)); +int in6_setpeeraddr __P((struct inpcb *, struct mbuf *)); +#endif /* INET6 */ +void in_pcbinit __P((struct inpcbtable *, int)); +struct inpcb * + in_pcblookup __P((struct inpcbtable *, void *, u_int, void *, + u_int, int)); +void in_pcbnotify __P((struct inpcbtable *, struct sockaddr *, + u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int))); +void in_pcbnotifyall __P((struct inpcbtable *, struct sockaddr *, + int, void (*)(struct inpcb *, int))); +void in_pcbrehash __P((struct inpcb *)); +void in_rtchange __P((struct inpcb *, int)); +void in_setpeeraddr __P((struct inpcb *, struct mbuf *)); +void in_setsockaddr __P((struct inpcb *, struct mbuf *)); +int in_baddynamic __P((u_int16_t, u_int16_t)); +extern struct sockaddr_in *in_selectsrc __P((struct sockaddr_in *, + struct route *, int, struct ip_moptions *, int *)); + +/* INET6 stuff */ +int in6_pcbnotify __P((struct inpcbtable *, struct sockaddr *, + u_int, struct in6_addr *, u_int, int, + void (*)(struct inpcb *, int))); +struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *, + struct ip6_pktopts *, + struct ip6_moptions *, + struct route_in6 *, + struct in6_addr *, int *)); +int in6_selecthlim __P((struct inpcb *, struct ifnet *)); +#endif + +#endif // _NETINET_IN_PCB_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/in_systm.h b/ecos/packages/net/tcpip/current/include/netinet/in_systm.h new file mode 100644 index 0000000..77cba0a --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/in_systm.h @@ -0,0 +1,93 @@ +//========================================================================== +// +// include/netinet/in_systm.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in_systm.h,v 1.2 1997/02/24 14:06:35 niklas Exp $ */ +/* $NetBSD: in_systm.h,v 1.8 1995/04/13 06:29:22 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_systm.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IN_SYSTM_H_ +#define _NETINET_IN_SYSTM_H_ + +/* + * Miscellaneous internetwork + * definitions for kernel. + */ + +/* + * Network types. + * + * Internally the system keeps counters in the headers with the bytes + * swapped so that VAX instructions will work on them. It reverses + * the bytes before transmission at each protocol level. The n_ types + * represent the types with the bytes in ``high-ender'' order. + */ +typedef u_int16_t n_short; /* short as received from the net */ +typedef u_int32_t n_long; /* long as received from the net */ + +typedef u_int32_t n_time; /* ms since 00:00 GMT, byte rev */ + +#ifdef _KERNEL +n_time iptime __P((void)); +#endif + +#endif // _NETINET_IN_SYSTM_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/in_var.h b/ecos/packages/net/tcpip/current/include/netinet/in_var.h new file mode 100644 index 0000000..db2a44e --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/in_var.h @@ -0,0 +1,254 @@ +//========================================================================== +// +// include/netinet/in_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in_var.h,v 1.3 1999/12/08 06:50:19 itojun Exp $ */ +/* $NetBSD: in_var.h,v 1.16 1996/02/13 23:42:15 christos Exp $ */ + +/* + * Copyright (c) 1985, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IN_VAR_H_ +#define _NETINET_IN_VAR_H_ + +#include <sys/queue.h> + +/* + * Interface address, Internet version. One of these structures + * is allocated for each interface with an Internet address. + * The ifaddr structure contains the protocol-independent part + * of the structure and is assumed to be first. + */ +struct in_ifaddr { + struct ifaddr ia_ifa; /* protocol-independent info */ +#define ia_ifp ia_ifa.ifa_ifp +#define ia_flags ia_ifa.ifa_flags + /* ia_{,sub}net{,mask} in host order */ + u_int32_t ia_net; /* network number of interface */ + u_int32_t ia_netmask; /* mask of net part */ + u_int32_t ia_subnet; /* subnet number, including net */ + u_int32_t ia_subnetmask; /* mask of subnet part */ + struct in_addr ia_netbroadcast; /* to recognize net broadcasts */ + TAILQ_ENTRY(in_ifaddr) ia_list; /* list of internet addresses */ + struct sockaddr_in ia_addr; /* reserve space for interface name */ + struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ +#define ia_broadaddr ia_dstaddr + struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ + LIST_HEAD(, in_multi) ia_multiaddrs; /* list of multicast addresses */ +}; + +struct in_aliasreq { + char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + struct sockaddr_in ifra_addr; + struct sockaddr_in ifra_dstaddr; +#define ifra_broadaddr ifra_dstaddr + struct sockaddr_in ifra_mask; +}; +/* + * Given a pointer to an in_ifaddr (ifaddr), + * return a pointer to the addr as a sockaddr_in. + */ +#define IA_SIN(ia) (&(((struct in_ifaddr *)(ia))->ia_addr)) + + +#ifdef _KERNEL +TAILQ_HEAD(in_ifaddrhead, in_ifaddr); +extern struct in_ifaddrhead in_ifaddr; +extern struct ifqueue ipintrq; /* ip packet input queue */ +extern int inetctlerrmap[]; +void in_socktrim __P((struct sockaddr_in *)); + + +/* + * Macro for finding the interface (ifnet structure) corresponding to one + * of our IP addresses. + */ +#define INADDR_TO_IFP(addr, ifp) \ + /* struct in_addr addr; */ \ + /* struct ifnet *ifp; */ \ +{ \ + register struct in_ifaddr *ia; \ +\ + for (ia = in_ifaddr.tqh_first; \ + ia != NULL && ia->ia_addr.sin_addr.s_addr != (addr).s_addr; \ + ia = ia->ia_list.tqe_next) \ + continue; \ + (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \ +} + +/* + * Macro for finding the internet address structure (in_ifaddr) corresponding + * to a given interface (ifnet structure). + */ +#define IFP_TO_IA(ifp, ia) \ + /* struct ifnet *ifp; */ \ + /* struct in_ifaddr *ia; */ \ +{ \ + for ((ia) = in_ifaddr.tqh_first; \ + (ia) != NULL && (ia)->ia_ifp != (ifp); \ + (ia) = (ia)->ia_list.tqe_next) \ + continue; \ +} +#endif + +/* + * Per-interface router version information. + */ +struct router_info { + struct ifnet *rti_ifp; + int rti_type; /* type of router on this interface */ + int rti_age; /* time since last v1 query */ + struct router_info *rti_next; +}; + +/* + * Internet multicast address structure. There is one of these for each IP + * multicast group to which this host belongs on a given network interface. + * They are kept in a linked list, rooted in the interface's in_ifaddr + * structure. + */ +struct in_multi { + struct in_addr inm_addr; /* IP multicast address */ + struct ifnet *inm_ifp; /* back pointer to ifnet */ + struct in_ifaddr *inm_ia; /* back pointer to in_ifaddr */ + u_int inm_refcount; /* no. membership claims by sockets */ + u_int inm_timer; /* IGMP membership report timer */ + LIST_ENTRY(in_multi) inm_list; /* list of multicast addresses */ + u_int inm_state; /* state of membership */ + struct router_info *inm_rti; /* router version info */ +}; + +#ifdef _KERNEL +/* + * Structure used by macros below to remember position when stepping through + * all of the in_multi records. + */ +struct in_multistep { + struct in_ifaddr *i_ia; + struct in_multi *i_inm; +}; + +/* + * Macro for looking up the in_multi record for a given IP multicast address + * on a given interface. If no matching record is found, "inm" returns NULL. + */ +#define IN_LOOKUP_MULTI(addr, ifp, inm) \ + /* struct in_addr addr; */ \ + /* struct ifnet *ifp; */ \ + /* struct in_multi *inm; */ \ +{ \ + register struct in_ifaddr *ia; \ +\ + IFP_TO_IA((ifp), ia); \ + if (ia == NULL) \ + (inm) = NULL; \ + else \ + for ((inm) = ia->ia_multiaddrs.lh_first; \ + (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \ + (inm) = inm->inm_list.le_next) \ + continue; \ +} + +/* + * Macro to step through all of the in_multi records, one at a time. + * The current position is remembered in "step", which the caller must + * provide. IN_FIRST_MULTI(), below, must be called to initialize "step" + * and get the first record. Both macros return a NULL "inm" when there + * are no remaining records. + */ +#define IN_NEXT_MULTI(step, inm) \ + /* struct in_multistep step; */ \ + /* struct in_multi *inm; */ \ +{ \ + if (((inm) = (step).i_inm) != NULL) \ + (step).i_inm = (inm)->inm_list.le_next; \ + else \ + while ((step).i_ia != NULL) { \ + (inm) = (step).i_ia->ia_multiaddrs.lh_first; \ + (step).i_ia = (step).i_ia->ia_list.tqe_next; \ + if ((inm) != NULL) { \ + (step).i_inm = (inm)->inm_list.le_next; \ + break; \ + } \ + } \ +} + +#define IN_FIRST_MULTI(step, inm) \ + /* struct in_multistep step; */ \ + /* struct in_multi *inm; */ \ +{ \ + (step).i_ia = in_ifaddr.tqh_first; \ + (step).i_inm = NULL; \ + IN_NEXT_MULTI((step), (inm)); \ +} + +int in_ifinit __P((struct ifnet *, + struct in_ifaddr *, struct sockaddr_in *, int)); +struct in_multi *in_addmulti __P((struct in_addr *, struct ifnet *)); +void in_delmulti __P((struct in_multi *)); +void in_ifscrub __P((struct ifnet *, struct in_ifaddr *)); +int in_control __P((struct socket *, u_long, caddr_t, struct ifnet *)); +#endif + + +/* INET6 stuff */ +#include <netinet6/in6_var.h> + +#endif // _NETINET_IN_VAR_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip.h b/ecos/packages/net/tcpip/current/include/netinet/ip.h new file mode 100644 index 0000000..4e4813b --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip.h @@ -0,0 +1,223 @@ +//========================================================================== +// +// include/netinet/ip.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip.h,v 1.6 1999/12/08 06:50:19 itojun Exp $ */ +/* $NetBSD: ip.h,v 1.9 1995/05/15 01:22:44 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IP_H_ +#define _NETINET_IP_H_ + +#include <netinet/in_systm.h> + +/* + * Definitions for internet protocol version 4. + * Per RFC 791, September 1981. + */ +#define IPVERSION 4 + +/* + * Structure of an internet header, naked of options. + */ +struct ip { +#if BYTE_ORDER == LITTLE_ENDIAN + u_int8_t ip_hl:4, /* header length */ + ip_v:4; /* version */ +#endif +#if BYTE_ORDER == BIG_ENDIAN + u_int8_t ip_v:4, /* version */ + ip_hl:4; /* header length */ +#endif + u_int8_t ip_tos; /* type of service */ + u_int16_t ip_len; /* total length */ + u_int16_t ip_id; /* identification */ + u_int16_t ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_int16_t ip_sum; /* checksum */ + struct in_addr ip_src, ip_dst; /* source and dest address */ +} __attribute__ ((aligned(1), packed)); + +#define IP_MAXPACKET 65535 /* maximum packet size */ + +/* + * Definitions for IP type of service (ip_tos) + */ +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +/* IPTOS_LOWCOST 0x02 XXX */ +#if 1 +/* ECN bits proposed by Sally Floyd */ +#define IPTOS_CE 0x01 /* congestion experienced */ +#define IPTOS_ECT 0x02 /* ECN-capable transport */ +#endif + +/* + * Definitions for IP precedence (also in ip_tos) (hopefully unused) + */ +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + +/* + * Definitions for options. + */ +#define IPOPT_COPIED(o) ((o)&0x80) +#define IPOPT_CLASS(o) ((o)&0x60) +#define IPOPT_NUMBER(o) ((o)&0x1f) + +#define IPOPT_CONTROL 0x00 +#define IPOPT_RESERVED1 0x20 +#define IPOPT_DEBMEAS 0x40 +#define IPOPT_RESERVED2 0x60 + +#define IPOPT_EOL 0 /* end of option list */ +#define IPOPT_NOP 1 /* no operation */ + +#define IPOPT_RR 7 /* record packet route */ +#define IPOPT_TS 68 /* timestamp */ +#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ +#define IPOPT_LSRR 131 /* loose source route */ +#define IPOPT_SATID 136 /* satnet id */ +#define IPOPT_SSRR 137 /* strict source route */ + +/* + * Offsets to fields in options other than EOL and NOP. + */ +#define IPOPT_OPTVAL 0 /* option ID */ +#define IPOPT_OLEN 1 /* option length */ +#define IPOPT_OFFSET 2 /* offset within option */ +#define IPOPT_MINOFF 4 /* min value of above */ + +/* + * Time stamp option structure. + */ +struct ip_timestamp { + u_int8_t ipt_code; /* IPOPT_TS */ + u_int8_t ipt_len; /* size of structure (variable) */ + u_int8_t ipt_ptr; /* index of current entry */ +#if BYTE_ORDER == LITTLE_ENDIAN + u_int8_t ipt_flg:4, /* flags, see below */ + ipt_oflw:4; /* overflow counter */ +#endif +#if BYTE_ORDER == BIG_ENDIAN + u_int8_t ipt_oflw:4, /* overflow counter */ + ipt_flg:4; /* flags, see below */ +#endif + union ipt_timestamp { + n_time ipt_time[1]; + struct ipt_ta { + struct in_addr ipt_addr; + n_time ipt_time; + } ipt_ta[1]; + } ipt_timestamp; +} __attribute__ ((aligned(1), packed)); + +/* flag bits for ipt_flg */ +#define IPOPT_TS_TSONLY 0 /* timestamps only */ +#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ +#define IPOPT_TS_PRESPEC 3 /* specified modules only */ + +/* bits for security (not byte swapped) */ +#define IPOPT_SECUR_UNCLASS 0x0000 +#define IPOPT_SECUR_CONFID 0xf135 +#define IPOPT_SECUR_EFTO 0x789a +#define IPOPT_SECUR_MMMM 0xbc4d +#define IPOPT_SECUR_RESTR 0xaf13 +#define IPOPT_SECUR_SECRET 0xd788 +#define IPOPT_SECUR_TOPSECRET 0x6bc5 + +/* + * Internet implementation parameters. + */ +#define MAXTTL 255 /* maximum time to live (seconds) */ +#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ +#define IPFRAGTTL 60 /* time to live for frags, slowhz */ +#define IPTTLDEC 1 /* subtracted when forwarding */ + +#define IP_MSS 576 /* default maximum segment size */ + +/* + * This is the real IPv4 psuedo header, used for computing the TCP and UDP + * checksums. For the Internet checksum, struct ipovly can be used instead. + * For stronger checksums, the real thing must be used. + */ +struct ippseudo { + struct in_addr ippseudo_src; /* source internet address */ + struct in_addr ippseudo_dst; /* destination internet address */ + u_int8_t ippseudo_pad; /* pad, must be zero */ + u_int8_t ippseudo_p; /* protocol */ + u_int16_t ippseudo_len; /* protocol length */ +} __attribute__ ((aligned(1), packed)); + +#endif // _NETINET_IP_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip6.h b/ecos/packages/net/tcpip/current/include/netinet/ip6.h new file mode 100644 index 0000000..2d91f94 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip6.h @@ -0,0 +1,32 @@ +//========================================================================== +// +// include/netinet/ip6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip6.h,v 1.1 1999/12/08 06:50:19 itojun Exp $ */ + +#include <netinet6/ip6.h> diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_ah.h b/ecos/packages/net/tcpip/current/include/netinet/ip_ah.h new file mode 100644 index 0000000..c958373 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_ah.h @@ -0,0 +1,145 @@ +//========================================================================== +// +// include/netinet/ip_ah.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_ah.h,v 1.19 1999/12/09 10:11:11 angelos Exp $ */ + +/* + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Niels Provos (provos@physnet.uni-hamburg.de). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Permission to use, copy, and modify this software without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IP_AH_H_ +#define _NETINET_IP_AH_H_ + +/* + * Authentication Header Processing + * Per RFC1826 (Atkinson, 1995) + */ + +struct ah_old +{ + u_int8_t ah_nh; /* Next header (protocol) */ + u_int8_t ah_hl; /* AH length, in 32-bit words */ + u_int16_t ah_rv; /* reserved, must be 0 */ + u_int32_t ah_spi; /* Security Parameters Index */ + u_int8_t ah_data[1]; /* More, really */ +}; + +#define AH_OLD_FLENGTH 8 /* size of fixed part */ + +struct ahstat +{ + u_int32_t ahs_hdrops; /* packet shorter than header shows */ + u_int32_t ahs_notdb; + u_int32_t ahs_badkcr; + u_int32_t ahs_badauth; + u_int32_t ahs_noxform; + u_int32_t ahs_qfull; + u_int32_t ahs_wrap; + u_int32_t ahs_replay; + u_int32_t ahs_badauthl; /* bad authenticator length */ + u_int32_t ahs_input; /* Input AH packets */ + u_int32_t ahs_output; /* Output AH packets */ + u_int32_t ahs_invalid; /* Trying to use an invalid TDB */ + u_int64_t ahs_ibytes; /* input bytes */ + u_int64_t ahs_obytes; /* output bytes */ + u_int32_t ahs_toobig; /* packet got larger than IP_MAXPACKET */ + u_int32_t ahs_pdrops; /* packet blocked due to policy */ +}; + +struct ah_new +{ + u_int8_t ah_nh; /* Next header (protocol) */ + u_int8_t ah_hl; /* AH length, in 32-bit words */ + u_int16_t ah_rv; /* reserved, must be 0 */ + u_int32_t ah_spi; /* Security Parameters Index */ + u_int32_t ah_rpl; /* Replay prevention */ + u_int8_t ah_data[AH_HMAC_HASHLEN];/* Authenticator */ +}; + +#define AH_NEW_FLENGTH (sizeof(struct ah_new)) + +/* Size of the largest hash function output used in AH-new, in bytes */ +#define AH_MAX_HASHLEN 20 + +/* + * Names for AH sysctl objects + */ +#define AHCTL_ENABLE 1 /* Enable AH processing */ +#define AHCTL_MAXID 2 + +#define AHCTL_NAMES { \ + { 0, 0 }, \ + { "enable", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL +void ah_input __P((struct mbuf *, ...)); +int ah_output __P((struct mbuf *, struct tdb *, struct mbuf **)); +int ah_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); + +#ifdef INET6 +void ah6_input __P((struct mbuf *, ...)); +#endif /* INET6 */ + +extern int ah_enable; +struct ahstat ahstat; +#endif /* _KERNEL */ + +#endif // _NETINET_IP_AH_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_auth.h b/ecos/packages/net/tcpip/current/include/netinet/ip_auth.h new file mode 100644 index 0000000..3324621 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_auth.h @@ -0,0 +1,96 @@ +//========================================================================== +// +// include/netinet/ip_auth.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_auth.h,v 1.4 1999/12/15 05:20:21 kjell Exp $ */ +/* + * Copyright (C) 1997-1998 by Darren Reed & Guido Van Rooij. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + */ + +#ifndef _NETINET_IP_AUTH_H__ +#define _NETINET_IP_AUTH_H__ + +#define FR_NUMAUTH 32 + +typedef struct frauth { + int fra_age; + int fra_index; + u_32_t fra_pass; + fr_info_t fra_info; +#if SOLARIS + queue_t *fra_q; +#endif +} frauth_t; + +typedef struct frauthent { + struct frentry fae_fr; + struct frauthent *fae_next; + u_long fae_age; +} frauthent_t; + +typedef struct fr_authstat { + U_QUAD_T fas_hits; + U_QUAD_T fas_miss; + u_long fas_nospace; + u_long fas_added; + u_long fas_sendfail; + u_long fas_sendok; + u_long fas_queok; + u_long fas_quefail; + u_long fas_expire; + frauthent_t *fas_faelist; +} fr_authstat_t; + + +extern frentry_t *ipauth; +extern struct fr_authstat fr_authstats; +extern int fr_defaultauthage; +extern int fr_authstart; +extern int fr_authend; +extern int fr_authsize; +extern int fr_authused; +extern u_32_t fr_checkauth __P((ip_t *, fr_info_t *)); +extern void fr_authexpire __P((void)); +extern void fr_authunload __P((void)); +extern mb_t *fr_authpkts[]; +#if defined(_KERNEL) && SOLARIS +extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *, qif_t *)); +#else +extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *)); +#endif +#if defined(__NetBSD__) || defined(__OpenBSD__) +extern int fr_auth_ioctl __P((caddr_t, u_long, frentry_t *, frentry_t **)); +#else +extern int fr_auth_ioctl __P((caddr_t, int, frentry_t *, frentry_t **)); +#endif +#endif /* _NETINET_IP_AUTH_H__ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_blf.h b/ecos/packages/net/tcpip/current/include/netinet/ip_blf.h new file mode 100644 index 0000000..c08fd2b --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_blf.h @@ -0,0 +1,108 @@ +//========================================================================== +// +// include/netinet/ip_blf.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_blf.h,v 1.2 1999/02/23 05:15:09 angelos Exp $ */ +/* + * Blowfish - a fast block cipher designed by Bruce Schneier + * + * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NETINET_IP_BLF_H_ +#define _NETINET_IP_BLF_H_ + +/* Schneier states the maximum key length to be 56 bytes. + * The way how the subkeys are initalized by the key up + * to (N+2)*4 i.e. 72 bytes are utilized. + * Warning: For normal blowfish encryption only 56 bytes + * of the key affect all cipherbits. + */ + +#define BLF_N 16 /* Number of Subkeys */ +#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ + +/* Blowfish context */ +typedef struct BlowfishContext { + u_int32_t S[4][256]; /* S-Boxes */ + u_int32_t P[BLF_N + 2]; /* Subkeys */ +} blf_ctx; + +/* Raw access to customized Blowfish + * blf_key is just: + * Blowfish_initstate( state ) + * Blowfish_expand0state( state, key, keylen ) + */ + +void Blowfish_encipher __P((blf_ctx *, u_int32_t *, u_int32_t *)); +void Blowfish_decipher __P((blf_ctx *, u_int32_t *, u_int32_t *)); +void Blowfish_initstate __P((blf_ctx *)); +void Blowfish_expand0state __P((blf_ctx *, const u_int8_t *, u_int16_t)); +void Blowfish_expandstate + __P((blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t)); + +/* Standard Blowfish */ + +void blf_key __P((blf_ctx *, const u_int8_t *, u_int16_t)); +void blf_enc __P((blf_ctx *, u_int32_t *, u_int16_t)); +void blf_dec __P((blf_ctx *, u_int32_t *, u_int16_t)); + +/* Converts u_int8_t to u_int32_t */ +u_int32_t Blowfish_stream2word __P((const u_int8_t *, u_int16_t , + u_int16_t *)); + +void blf_ecb_encrypt __P((blf_ctx *, u_int8_t *, u_int32_t)); +void blf_ecb_decrypt __P((blf_ctx *, u_int8_t *, u_int32_t)); + +#endif // _NETINET_IP_BLF_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_cast.h b/ecos/packages/net/tcpip/current/include/netinet/ip_cast.h new file mode 100644 index 0000000..4df26fd --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_cast.h @@ -0,0 +1,51 @@ +//========================================================================== +// +// include/netinet/ip_cast.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_cast.h,v 1.3 1999/02/17 18:09:55 deraadt Exp $ */ + +/* + * CAST-128 in C + * Written by Steve Reid <sreid@sea-to-sky.net> + * 100% Public Domain - no warranty + * Released 1997.10.11 + */ + +#ifndef _NETINET_IP_CAST_H_ +#define _NETINET_IP_CAST_H_ + +typedef struct { + u_int32_t xkey[32]; /* Key, after expansion */ + int rounds; /* Number of rounds to use, 12 or 16 */ +} cast_key; + +void cast_setkey __P((cast_key * key, u_int8_t * rawkey, int keybytes)); +void cast_encrypt __P((cast_key * key, u_int8_t * inblock, u_int8_t * outblock)); +void cast_decrypt __P((cast_key * key, u_int8_t * inblock, u_int8_t * outblock)); + +#endif /* ifndef _NETINET_IP_CAST_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_castsb.h b/ecos/packages/net/tcpip/current/include/netinet/ip_castsb.h new file mode 100644 index 0000000..7447e77 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_castsb.h @@ -0,0 +1,577 @@ +//========================================================================== +// +// include/netinet/ip_castsb.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_castsb.h,v 1.2 1999/02/17 18:09:55 deraadt Exp $ */ +/* + * CAST-128 in C + * Written by Steve Reid <sreid@sea-to-sky.net> + * 100% Public Domain - no warranty + * Released 1997.10.11 + */ + +#ifndef _NETINET_IP_CASTSB_H_ +#define _NETINET_IP_CASTSB_H_ + +static const u_int32_t cast_sbox1[256] = { + 0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A, + 0x1E213F2F, 0x9C004DD3, 0x6003E540, 0xCF9FC949, + 0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675, + 0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E, + 0x28683B6F, 0xC07FD059, 0xFF2379C8, 0x775F50E2, + 0x43C340D3, 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D, + 0xA1C9E0D6, 0x346C4819, 0x61B76D87, 0x22540F2F, + 0x2ABE32E1, 0xAA54166B, 0x22568E3A, 0xA2D341D0, + 0x66DB40C8, 0xA784392F, 0x004DFF2F, 0x2DB9D2DE, + 0x97943FAC, 0x4A97C1D8, 0x527644B7, 0xB5F437A7, + 0xB82CBAEF, 0xD751D159, 0x6FF7F0ED, 0x5A097A1F, + 0x827B68D0, 0x90ECF52E, 0x22B0C054, 0xBC8E5935, + 0x4B6D2F7F, 0x50BB64A2, 0xD2664910, 0xBEE5812D, + 0xB7332290, 0xE93B159F, 0xB48EE411, 0x4BFF345D, + 0xFD45C240, 0xAD31973F, 0xC4F6D02E, 0x55FC8165, + 0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D, 0xC19B0C50, + 0x882240F2, 0x0C6E4F38, 0xA4E4BFD7, 0x4F5BA272, + 0x564C1D2F, 0xC59C5319, 0xB949E354, 0xB04669FE, + 0xB1B6AB8A, 0xC71358DD, 0x6385C545, 0x110F935D, + 0x57538AD5, 0x6A390493, 0xE63D37E0, 0x2A54F6B3, + 0x3A787D5F, 0x6276A0B5, 0x19A6FCDF, 0x7A42206A, + 0x29F9D4D5, 0xF61B1891, 0xBB72275E, 0xAA508167, + 0x38901091, 0xC6B505EB, 0x84C7CB8C, 0x2AD75A0F, + 0x874A1427, 0xA2D1936B, 0x2AD286AF, 0xAA56D291, + 0xD7894360, 0x425C750D, 0x93B39E26, 0x187184C9, + 0x6C00B32D, 0x73E2BB14, 0xA0BEBC3C, 0x54623779, + 0x64459EAB, 0x3F328B82, 0x7718CF82, 0x59A2CEA6, + 0x04EE002E, 0x89FE78E6, 0x3FAB0950, 0x325FF6C2, + 0x81383F05, 0x6963C5C8, 0x76CB5AD6, 0xD49974C9, + 0xCA180DCF, 0x380782D5, 0xC7FA5CF6, 0x8AC31511, + 0x35E79E13, 0x47DA91D0, 0xF40F9086, 0xA7E2419E, + 0x31366241, 0x051EF495, 0xAA573B04, 0x4A805D8D, + 0x548300D0, 0x00322A3C, 0xBF64CDDF, 0xBA57A68E, + 0x75C6372B, 0x50AFD341, 0xA7C13275, 0x915A0BF5, + 0x6B54BFAB, 0x2B0B1426, 0xAB4CC9D7, 0x449CCD82, + 0xF7FBF265, 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324, + 0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02, 0xC8BD25AC, + 0xEADF55B3, 0xD5BD9E98, 0xE31231B2, 0x2AD5AD6C, + 0x954329DE, 0xADBE4528, 0xD8710F69, 0xAA51C90F, + 0xAA786BF6, 0x22513F1E, 0xAA51A79B, 0x2AD344CC, + 0x7B5A41F0, 0xD37CFBAD, 0x1B069505, 0x41ECE491, + 0xB4C332E6, 0x032268D4, 0xC9600ACC, 0xCE387E6D, + 0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9, 0xD4DF39DE, + 0xE01063DA, 0x4736F464, 0x5AD328D8, 0xB347CC96, + 0x75BB0FC3, 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A, + 0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10, 0xAC39570A, + 0x3F04442F, 0x6188B153, 0xE0397A2E, 0x5727CB79, + 0x9CEB418F, 0x1CACD68D, 0x2AD37C96, 0x0175CB9D, + 0xC69DFF09, 0xC75B65F0, 0xD9DB40D8, 0xEC0E7779, + 0x4744EAD4, 0xB11C3274, 0xDD24CB9E, 0x7E1C54BD, + 0xF01144F9, 0xD2240EB1, 0x9675B3FD, 0xA3AC3755, + 0xD47C27AF, 0x51C85F4D, 0x56907596, 0xA5BB15E6, + 0x580304F0, 0xCA042CF1, 0x011A37EA, 0x8DBFAADB, + 0x35BA3E4A, 0x3526FFA0, 0xC37B4D09, 0xBC306ED9, + 0x98A52666, 0x5648F725, 0xFF5E569D, 0x0CED63D0, + 0x7C63B2CF, 0x700B45E1, 0xD5EA50F1, 0x85A92872, + 0xAF1FBDA7, 0xD4234870, 0xA7870BF3, 0x2D3B4D79, + 0x42E04198, 0x0CD0EDE7, 0x26470DB8, 0xF881814C, + 0x474D6AD7, 0x7C0C5E5C, 0xD1231959, 0x381B7298, + 0xF5D2F4DB, 0xAB838653, 0x6E2F1E23, 0x83719C9E, + 0xBD91E046, 0x9A56456E, 0xDC39200C, 0x20C8C571, + 0x962BDA1C, 0xE1E696FF, 0xB141AB08, 0x7CCA89B9, + 0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D, + 0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF +}; + +static const u_int32_t cast_sbox2[256] = { + 0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380, + 0xFE61CF7A, 0xEEC5207A, 0x55889C94, 0x72FC0651, + 0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA, + 0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3, + 0xA0B52F7B, 0x59E83605, 0xEE15B094, 0xE9FFD909, + 0xDC440086, 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB, + 0xD1DA4181, 0x3B092AB1, 0xF997F1C1, 0xA5E6CF7B, + 0x01420DDB, 0xE4E7EF5B, 0x25A1FF41, 0xE180F806, + 0x1FC41080, 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4, + 0x98DE8B7F, 0x77E83F4E, 0x79929269, 0x24FA9F7B, + 0xE113C85B, 0xACC40083, 0xD7503525, 0xF7EA615F, + 0x62143154, 0x0D554B63, 0x5D681121, 0xC866C359, + 0x3D63CF73, 0xCEE234C0, 0xD4D87E87, 0x5C672B21, + 0x071F6181, 0x39F7627F, 0x361E3084, 0xE4EB573B, + 0x602F64A4, 0xD63ACD9C, 0x1BBC4635, 0x9E81032D, + 0x2701F50C, 0x99847AB4, 0xA0E3DF79, 0xBA6CF38C, + 0x10843094, 0x2537A95E, 0xF46F6FFE, 0xA1FF3B1F, + 0x208CFB6A, 0x8F458C74, 0xD9E0A227, 0x4EC73A34, + 0xFC884F69, 0x3E4DE8DF, 0xEF0E0088, 0x3559648D, + 0x8A45388C, 0x1D804366, 0x721D9BFD, 0xA58684BB, + 0xE8256333, 0x844E8212, 0x128D8098, 0xFED33FB4, + 0xCE280AE1, 0x27E19BA5, 0xD5A6C252, 0xE49754BD, + 0xC5D655DD, 0xEB667064, 0x77840B4D, 0xA1B6A801, + 0x84DB26A9, 0xE0B56714, 0x21F043B7, 0xE5D05860, + 0x54F03084, 0x066FF472, 0xA31AA153, 0xDADC4755, + 0xB5625DBF, 0x68561BE6, 0x83CA6B94, 0x2D6ED23B, + 0xECCF01DB, 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709, + 0x33B4A34C, 0x397BC8D6, 0x5EE22B95, 0x5F0E5304, + 0x81ED6F61, 0x20E74364, 0xB45E1378, 0xDE18639B, + 0x881CA122, 0xB96726D1, 0x8049A7E8, 0x22B7DA7B, + 0x5E552D25, 0x5272D237, 0x79D2951C, 0xC60D894C, + 0x488CB402, 0x1BA4FE5B, 0xA4B09F6B, 0x1CA815CF, + 0xA20C3005, 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9, + 0x0BEEFF53, 0xE3214517, 0xB4542835, 0x9F63293C, + 0xEE41E729, 0x6E1D2D7C, 0x50045286, 0x1E6685F3, + 0xF33401C6, 0x30A22C95, 0x31A70850, 0x60930F13, + 0x73F98417, 0xA1269859, 0xEC645C44, 0x52C877A9, + 0xCDFF33A6, 0xA02B1741, 0x7CBAD9A2, 0x2180036F, + 0x50D99C08, 0xCB3F4861, 0xC26BD765, 0x64A3F6AB, + 0x80342676, 0x25A75E7B, 0xE4E6D1FC, 0x20C710E6, + 0xCDF0B680, 0x17844D3B, 0x31EEF84D, 0x7E0824E4, + 0x2CCB49EB, 0x846A3BAE, 0x8FF77888, 0xEE5D60F6, + 0x7AF75673, 0x2FDD5CDB, 0xA11631C1, 0x30F66F43, + 0xB3FAEC54, 0x157FD7FA, 0xEF8579CC, 0xD152DE58, + 0xDB2FFD5E, 0x8F32CE19, 0x306AF97A, 0x02F03EF8, + 0x99319AD5, 0xC242FA0F, 0xA7E3EBB0, 0xC68E4906, + 0xB8DA230C, 0x80823028, 0xDCDEF3C8, 0xD35FB171, + 0x088A1BC8, 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D, + 0xC72FEFFA, 0x22822E99, 0x82C570B4, 0xD8D94E89, + 0x8B1C34BC, 0x301E16E6, 0x273BE979, 0xB0FFEAA6, + 0x61D9B8C6, 0x00B24869, 0xB7FFCE3F, 0x08DC283B, + 0x43DAF65A, 0xF7E19798, 0x7619B72F, 0x8F1C9BA4, + 0xDC8637A0, 0x16A7D3B1, 0x9FC393B7, 0xA7136EEB, + 0xC6BCC63E, 0x1A513742, 0xEF6828BC, 0x520365D6, + 0x2D6A77AB, 0x3527ED4B, 0x821FD216, 0x095C6E2E, + 0xDB92F2FB, 0x5EEA29CB, 0x145892F5, 0x91584F7F, + 0x5483697B, 0x2667A8CC, 0x85196048, 0x8C4BACEA, + 0x833860D4, 0x0D23E0F9, 0x6C387E8A, 0x0AE6D249, + 0xB284600C, 0xD835731D, 0xDCB1C647, 0xAC4C56EA, + 0x3EBD81B3, 0x230EABB0, 0x6438BC87, 0xF0B5B1FA, + 0x8F5EA2B3, 0xFC184642, 0x0A036B7A, 0x4FB089BD, + 0x649DA589, 0xA345415E, 0x5C038323, 0x3E5D3BB9, + 0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF, + 0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1 +}; + +static const u_int32_t cast_sbox3[256] = { + 0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907, + 0x47607FFF, 0x369FE44B, 0x8C1FC644, 0xAECECA90, + 0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE, + 0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5, + 0x11107D9F, 0x07647DB9, 0xB2E3E4D4, 0x3D4F285E, + 0xB9AFA820, 0xFADE82E0, 0xA067268B, 0x8272792E, + 0x553FB2C0, 0x489AE22B, 0xD4EF9794, 0x125E3FBC, + 0x21FFFCEE, 0x825B1BFD, 0x9255C5ED, 0x1257A240, + 0x4E1A8302, 0xBAE07FFF, 0x528246E7, 0x8E57140E, + 0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8, 0xC982B5A5, + 0xA8C01DB7, 0x579FC264, 0x67094F31, 0xF2BD3F5F, + 0x40FFF7C1, 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B, + 0x99B03DBF, 0xB5DBC64B, 0x638DC0E6, 0x55819D99, + 0xA197C81C, 0x4A012D6E, 0xC5884A28, 0xCCC36F71, + 0xB843C213, 0x6C0743F1, 0x8309893C, 0x0FEDDD5F, + 0x2F7FE850, 0xD7C07F7E, 0x02507FBF, 0x5AFB9A04, + 0xA747D2D0, 0x1651192E, 0xAF70BF3E, 0x58C31380, + 0x5F98302E, 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82, + 0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49, 0x50DA88B8, + 0x8427F4A0, 0x1EAC5790, 0x796FB449, 0x8252DC15, + 0xEFBD7D9B, 0xA672597D, 0xADA840D8, 0x45F54504, + 0xFA5D7403, 0xE83EC305, 0x4F91751A, 0x925669C2, + 0x23EFE941, 0xA903F12E, 0x60270DF2, 0x0276E4B6, + 0x94FD6574, 0x927985B2, 0x8276DBCB, 0x02778176, + 0xF8AF918D, 0x4E48F79E, 0x8F616DDF, 0xE29D840E, + 0x842F7D83, 0x340CE5C8, 0x96BBB682, 0x93B4B148, + 0xEF303CAB, 0x984FAF28, 0x779FAF9B, 0x92DC560D, + 0x224D1E20, 0x8437AA88, 0x7D29DC96, 0x2756D3DC, + 0x8B907CEE, 0xB51FD240, 0xE7C07CE3, 0xE566B4A1, + 0xC3E9615E, 0x3CF8209D, 0x6094D1E3, 0xCD9CA341, + 0x5C76460E, 0x00EA983B, 0xD4D67881, 0xFD47572C, + 0xF76CEDD9, 0xBDA8229C, 0x127DADAA, 0x438A074E, + 0x1F97C090, 0x081BDB8A, 0x93A07EBE, 0xB938CA15, + 0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC, 0x64380E51, + 0x68CC7BFB, 0xD90F2788, 0x12490181, 0x5DE5FFD4, + 0xDD7EF86A, 0x76A2E214, 0xB9A40368, 0x925D958F, + 0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B, 0xFAF7933B, + 0x6D498623, 0x193CBCFA, 0x27627545, 0x825CF47A, + 0x61BD8BA0, 0xD11E42D1, 0xCEAD04F4, 0x127EA392, + 0x10428DB7, 0x8272A972, 0x9270C4A8, 0x127DE50B, + 0x285BA1C8, 0x3C62F44F, 0x35C0EAA5, 0xE805D231, + 0x428929FB, 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B, + 0x1F081FAB, 0x108618AE, 0xFCFD086D, 0xF9FF2889, + 0x694BCC11, 0x236A5CAE, 0x12DECA4D, 0x2C3F8CC5, + 0xD2D02DFE, 0xF8EF5896, 0xE4CF52DA, 0x95155B67, + 0x494A488C, 0xB9B6A80C, 0x5C8F82BC, 0x89D36B45, + 0x3A609437, 0xEC00C9A9, 0x44715253, 0x0A874B49, + 0xD773BC40, 0x7C34671C, 0x02717EF6, 0x4FEB5536, + 0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0, 0x50B4EF6D, + 0x07478CD1, 0x006E1888, 0xA2E53F55, 0xB9E6D4BC, + 0xA2048016, 0x97573833, 0xD7207D67, 0xDE0F8F3D, + 0x72F87B33, 0xABCC4F33, 0x7688C55D, 0x7B00A6B0, + 0x947B0001, 0x570075D2, 0xF9BB88F8, 0x8942019E, + 0x4264A5FF, 0x856302E0, 0x72DBD92B, 0xEE971B69, + 0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D, 0xE5C98767, + 0xCF1FEBD2, 0x61EFC8C2, 0xF1AC2571, 0xCC8239C2, + 0x67214CB8, 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE, + 0xF90A5C38, 0x0FF0443D, 0x606E6DC6, 0x60543A49, + 0x5727C148, 0x2BE98A1D, 0x8AB41738, 0x20E1BE24, + 0xAF96DA0F, 0x68458425, 0x99833BE5, 0x600D457D, + 0x282F9350, 0x8334B362, 0xD91D1120, 0x2B6D8DA0, + 0x642B1E31, 0x9C305A00, 0x52BCE688, 0x1B03588A, + 0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5, + 0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783 +}; + +static const u_int32_t cast_sbox4[256] = { + 0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298, + 0x4A4F7BDB, 0x64AD8C57, 0x85510443, 0xFA020ED1, + 0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120, + 0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF, + 0x28147F5F, 0x4FA2B8CD, 0xC9430040, 0x0CC32220, + 0xFDD30B30, 0xC0A5374F, 0x1D2D00D9, 0x24147B15, + 0xEE4D111A, 0x0FCA5167, 0x71FF904C, 0x2D195FFE, + 0x1A05645F, 0x0C13FEFE, 0x081B08CA, 0x05170121, + 0x80530100, 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701, + 0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A, 0x7293EA25, + 0xCE84FFDF, 0xF5718801, 0x3DD64B04, 0xA26F263B, + 0x7ED48400, 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5, + 0x2649ABDF, 0xAEA0C7F5, 0x36338CC1, 0x503F7E93, + 0xD3772061, 0x11B638E1, 0x72500E03, 0xF80EB2BB, + 0xABE0502E, 0xEC8D77DE, 0x57971E81, 0xE14F6746, + 0xC9335400, 0x6920318F, 0x081DBB99, 0xFFC304A5, + 0x4D351805, 0x7F3D5CE3, 0xA6C866C6, 0x5D5BCCA9, + 0xDAEC6FEA, 0x9F926F91, 0x9F46222F, 0x3991467D, + 0xA5BF6D8E, 0x1143C44F, 0x43958302, 0xD0214EEB, + 0x022083B8, 0x3FB6180C, 0x18F8931E, 0x281658E6, + 0x26486E3E, 0x8BD78A70, 0x7477E4C1, 0xB506E07C, + 0xF32D0A25, 0x79098B02, 0xE4EABB81, 0x28123B23, + 0x69DEAD38, 0x1574CA16, 0xDF871B62, 0x211C40B7, + 0xA51A9EF9, 0x0014377B, 0x041E8AC8, 0x09114003, + 0xBD59E4D2, 0xE3D156D5, 0x4FE876D5, 0x2F91A340, + 0x557BE8DE, 0x00EAE4A7, 0x0CE5C2EC, 0x4DB4BBA6, + 0xE756BDFF, 0xDD3369AC, 0xEC17B035, 0x06572327, + 0x99AFC8B0, 0x56C8C391, 0x6B65811C, 0x5E146119, + 0x6E85CB75, 0xBE07C002, 0xC2325577, 0x893FF4EC, + 0x5BBFC92D, 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24, + 0x20C763EF, 0xC366A5FC, 0x9C382880, 0x0ACE3205, + 0xAAC9548A, 0xECA1D7C7, 0x041AFA32, 0x1D16625A, + 0x6701902C, 0x9B757A54, 0x31D477F7, 0x9126B031, + 0x36CC6FDB, 0xC70B8B46, 0xD9E66A48, 0x56E55A79, + 0x026A4CEB, 0x52437EFF, 0x2F8F76B4, 0x0DF980A5, + 0x8674CDE3, 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF, + 0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20, 0x2E096B7C, + 0x1741A254, 0xE5B6A035, 0x213D42F6, 0x2C1C7C26, + 0x61C2F50F, 0x6552DAF9, 0xD2C231F8, 0x25130F69, + 0xD8167FA2, 0x0418F2C8, 0x001A96A6, 0x0D1526AB, + 0x63315C21, 0x5E0A72EC, 0x49BAFEFD, 0x187908D9, + 0x8D0DBD86, 0x311170A7, 0x3E9B640C, 0xCC3E10D7, + 0xD5CAD3B6, 0x0CAEC388, 0xF73001E1, 0x6C728AFF, + 0x71EAE2A1, 0x1F9AF36E, 0xCFCBD12F, 0xC1DE8417, + 0xAC07BE6B, 0xCB44A1D8, 0x8B9B0F56, 0x013988C3, + 0xB1C52FCA, 0xB4BE31CD, 0xD8782806, 0x12A3A4E2, + 0x6F7DE532, 0x58FD7EB6, 0xD01EE900, 0x24ADFFC2, + 0xF4990FC5, 0x9711AAC5, 0x001D7B95, 0x82E5E7D2, + 0x109873F6, 0x00613096, 0xC32D9521, 0xADA121FF, + 0x29908415, 0x7FBB977F, 0xAF9EB3DB, 0x29C9ED2A, + 0x5CE2A465, 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091, + 0xD49E2CE7, 0x0CE454A9, 0xD60ACD86, 0x015F1919, + 0x77079103, 0xDEA03AF6, 0x78A8565E, 0xDEE356DF, + 0x21F05CBE, 0x8B75E387, 0xB3C50651, 0xB8A5C3EF, + 0xD8EEB6D2, 0xE523BE77, 0xC2154529, 0x2F69EFDF, + 0xAFE67AFB, 0xF470C4B2, 0xF3E0EB5B, 0xD6CC9876, + 0x39E4460C, 0x1FDA8538, 0x1987832F, 0xCA007367, + 0xA99144F8, 0x296B299E, 0x492FC295, 0x9266BEAB, + 0xB5676E69, 0x9BD3DDDA, 0xDF7E052F, 0xDB25701C, + 0x1B5E51EE, 0xF65324E6, 0x6AFCE36C, 0x0316CC04, + 0x8644213E, 0xB7DC59D0, 0x7965291F, 0xCCD6FD43, + 0x41823979, 0x932BCDF6, 0xB657C34D, 0x4EDFD282, + 0x7AE5290C, 0x3CB9536B, 0x851E20FE, 0x9833557E, + 0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1, 0x0AEF7ED2 +}; + +static const u_int32_t cast_sbox5[256] = { + 0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911, + 0xB86A7FFF, 0x1DD358F5, 0x44DD9D44, 0x1731167F, + 0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00, + 0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A, + 0xE6A2E77F, 0xF0C720CD, 0xC4494816, 0xCCF5C180, + 0x38851640, 0x15B0A848, 0xE68B18CB, 0x4CAADEFF, + 0x5F480A01, 0x0412B2AA, 0x259814FC, 0x41D0EFE2, + 0x4E40B48D, 0x248EB6FB, 0x8DBA1CFE, 0x41A99B02, + 0x1A550A04, 0xBA8F65CB, 0x7251F4E7, 0x95A51725, + 0xC106ECD7, 0x97A5980A, 0xC539B9AA, 0x4D79FE6A, + 0xF2F3F763, 0x68AF8040, 0xED0C9E56, 0x11B4958B, + 0xE1EB5A88, 0x8709E6B0, 0xD7E07156, 0x4E29FEA7, + 0x6366E52D, 0x02D1C000, 0xC4AC8E05, 0x9377F571, + 0x0C05372A, 0x578535F2, 0x2261BE02, 0xD642A0C9, + 0xDF13A280, 0x74B55BD2, 0x682199C0, 0xD421E5EC, + 0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9, 0x3D959981, + 0x5C1FF900, 0xFE38D399, 0x0C4EFF0B, 0x062407EA, + 0xAA2F4FB1, 0x4FB96976, 0x90C79505, 0xB0A8A774, + 0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27, 0xE66A4263, + 0xDF65001F, 0x0EC50966, 0xDFDD55BC, 0x29DE0655, + 0x911E739A, 0x17AF8975, 0x32C7911C, 0x89F89468, + 0x0D01E980, 0x524755F4, 0x03B63CC9, 0x0CC844B2, + 0xBCF3F0AA, 0x87AC36E9, 0xE53A7426, 0x01B3D82B, + 0x1A9E7449, 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910, + 0xB868BF80, 0x0D26F3FD, 0x9342EDE7, 0x04A5C284, + 0x636737B6, 0x50F5B616, 0xF24766E3, 0x8ECA36C1, + 0x136E05DB, 0xFEF18391, 0xFB887A37, 0xD6E7F7D4, + 0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE, 0xEC2941DA, + 0x26E46695, 0xB7566419, 0xF654EFC5, 0xD08D58B7, + 0x48925401, 0xC1BACB7F, 0xE5FF550F, 0xB6083049, + 0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1, 0x223A66CE, + 0xC62BF3CD, 0x9E0885F9, 0x68CB3E47, 0x086C010F, + 0xA21DE820, 0xD18B69DE, 0xF3F65777, 0xFA02C3F6, + 0x407EDAC3, 0xCBB3D550, 0x1793084D, 0xB0D70EBA, + 0x0AB378D5, 0xD951FB0C, 0xDED7DA56, 0x4124BBE4, + 0x94CA0B56, 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE, + 0x580A249F, 0x94F74BC0, 0xE327888E, 0x9F7B5561, + 0xC3DC0280, 0x05687715, 0x646C6BD7, 0x44904DB3, + 0x66B4F0A3, 0xC0F1648A, 0x697ED5AF, 0x49E92FF6, + 0x309E374F, 0x2CB6356A, 0x85808573, 0x4991F840, + 0x76F0AE02, 0x083BE84D, 0x28421C9A, 0x44489406, + 0x736E4CB8, 0xC1092910, 0x8BC95FC6, 0x7D869CF4, + 0x134F616F, 0x2E77118D, 0xB31B2BE1, 0xAA90B472, + 0x3CA5D717, 0x7D161BBA, 0x9CAD9010, 0xAF462BA2, + 0x9FE459D2, 0x45D34559, 0xD9F2DA13, 0xDBC65487, + 0xF3E4F94E, 0x176D486F, 0x097C13EA, 0x631DA5C7, + 0x445F7382, 0x175683F4, 0xCDC66A97, 0x70BE0288, + 0xB3CDCF72, 0x6E5DD2F3, 0x20936079, 0x459B80A5, + 0xBE60E2DB, 0xA9C23101, 0xEBA5315C, 0x224E42F2, + 0x1C5C1572, 0xF6721B2C, 0x1AD2FFF3, 0x8C25404E, + 0x324ED72F, 0x4067B7FD, 0x0523138E, 0x5CA3BC78, + 0xDC0FD66E, 0x75922283, 0x784D6B17, 0x58EBB16E, + 0x44094F85, 0x3F481D87, 0xFCFEAE7B, 0x77B5FF76, + 0x8C2302BF, 0xAAF47556, 0x5F46B02A, 0x2B092801, + 0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A, 0x66D5E7C0, + 0xDF3B0874, 0x95055110, 0x1B5AD7A8, 0xF61ED5AD, + 0x6CF6E479, 0x20758184, 0xD0CEFA65, 0x88F7BE58, + 0x4A046826, 0x0FF6F8F3, 0xA09C7F70, 0x5346ABA0, + 0x5CE96C28, 0xE176EDA3, 0x6BAC307F, 0x376829D2, + 0x85360FA9, 0x17E3FE2A, 0x24B79767, 0xF5A96B20, + 0xD6CD2595, 0x68FF1EBF, 0x7555442C, 0xF19F06BE, + 0xF9E0659A, 0xEEB9491D, 0x34010718, 0xBB30CAB8, + 0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55, + 0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4 +}; + +static const u_int32_t cast_sbox6[256] = { + 0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C, + 0x95DB08E7, 0x016843B4, 0xECED5CBC, 0x325553AC, + 0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9, + 0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138, + 0x33F14961, 0xC01937BD, 0xF506C6DA, 0xE4625E7E, + 0xA308EA99, 0x4E23E33C, 0x79CBD7CC, 0x48A14367, + 0xA3149619, 0xFEC94BD5, 0xA114174A, 0xEAA01866, + 0xA084DB2D, 0x09A8486F, 0xA888614A, 0x2900AF98, + 0x01665991, 0xE1992863, 0xC8F30C60, 0x2E78EF3C, + 0xD0D51932, 0xCF0FEC14, 0xF7CA07D2, 0xD0A82072, + 0xFD41197E, 0x9305A6B0, 0xE86BE3DA, 0x74BED3CD, + 0x372DA53C, 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3, + 0x083919A7, 0x9FBAEED9, 0x49DBCFB0, 0x4E670C53, + 0x5C3D9C01, 0x64BDB941, 0x2C0E636A, 0xBA7DD9CD, + 0xEA6F7388, 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D, + 0xF0D48D8C, 0xB88153E2, 0x08A19866, 0x1AE2EAC8, + 0x284CAF89, 0xAA928223, 0x9334BE53, 0x3B3A21BF, + 0x16434BE3, 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9, + 0x80226DAE, 0xC340A4A3, 0xDF7E9C09, 0xA694A807, + 0x5B7C5ECC, 0x221DB3A6, 0x9A69A02F, 0x68818A54, + 0xCEB2296F, 0x53C0843A, 0xFE893655, 0x25BFE68A, + 0xB4628ABC, 0xCF222EBF, 0x25AC6F48, 0xA9A99387, + 0x53BDDB65, 0xE76FFBE7, 0xE967FD78, 0x0BA93563, + 0x8E342BC1, 0xE8A11BE9, 0x4980740D, 0xC8087DFC, + 0x8DE4BF99, 0xA11101A0, 0x7FD37975, 0xDA5A26C0, + 0xE81F994F, 0x9528CD89, 0xFD339FED, 0xB87834BF, + 0x5F04456D, 0x22258698, 0xC9C4C83B, 0x2DC156BE, + 0x4F628DAA, 0x57F55EC5, 0xE2220ABE, 0xD2916EBF, + 0x4EC75B95, 0x24F2C3C0, 0x42D15D99, 0xCD0D7FA0, + 0x7B6E27FF, 0xA8DC8AF0, 0x7345C106, 0xF41E232F, + 0x35162386, 0xE6EA8926, 0x3333B094, 0x157EC6F2, + 0x372B74AF, 0x692573E4, 0xE9A9D848, 0xF3160289, + 0x3A62EF1D, 0xA787E238, 0xF3A5F676, 0x74364853, + 0x20951063, 0x4576698D, 0xB6FAD407, 0x592AF950, + 0x36F73523, 0x4CFB6E87, 0x7DA4CEC0, 0x6C152DAA, + 0xCB0396A8, 0xC50DFE5D, 0xFCD707AB, 0x0921C42F, + 0x89DFF0BB, 0x5FE2BE78, 0x448F4F33, 0x754613C9, + 0x2B05D08D, 0x48B9D585, 0xDC049441, 0xC8098F9B, + 0x7DEDE786, 0xC39A3373, 0x42410005, 0x6A091751, + 0x0EF3C8A6, 0x890072D6, 0x28207682, 0xA9A9F7BE, + 0xBF32679D, 0xD45B5B75, 0xB353FD00, 0xCBB0E358, + 0x830F220A, 0x1F8FB214, 0xD372CF08, 0xCC3C4A13, + 0x8CF63166, 0x061C87BE, 0x88C98F88, 0x6062E397, + 0x47CF8E7A, 0xB6C85283, 0x3CC2ACFB, 0x3FC06976, + 0x4E8F0252, 0x64D8314D, 0xDA3870E3, 0x1E665459, + 0xC10908F0, 0x513021A5, 0x6C5B68B7, 0x822F8AA0, + 0x3007CD3E, 0x74719EEF, 0xDC872681, 0x073340D4, + 0x7E432FD9, 0x0C5EC241, 0x8809286C, 0xF592D891, + 0x08A930F6, 0x957EF305, 0xB7FBFFBD, 0xC266E96F, + 0x6FE4AC98, 0xB173ECC0, 0xBC60B42A, 0x953498DA, + 0xFBA1AE12, 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB, + 0xE2969123, 0x257F0C3D, 0x9348AF49, 0x361400BC, + 0xE8816F4A, 0x3814F200, 0xA3F94043, 0x9C7A54C2, + 0xBC704F57, 0xDA41E7F9, 0xC25AD33A, 0x54F4A084, + 0xB17F5505, 0x59357CBE, 0xEDBD15C8, 0x7F97C5AB, + 0xBA5AC7B5, 0xB6F6DEAF, 0x3A479C3A, 0x5302DA25, + 0x653D7E6A, 0x54268D49, 0x51A477EA, 0x5017D55B, + 0xD7D25D88, 0x44136C76, 0x0404A8C8, 0xB8E5A121, + 0xB81A928A, 0x60ED5869, 0x97C55B96, 0xEAEC991B, + 0x29935913, 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5, + 0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35, 0xA0E1D855, + 0xD36B4CF1, 0xF544EDEB, 0xB0E93524, 0xBEBB8FBD, + 0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454, + 0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F +}; + +static const u_int32_t cast_sbox7[256] = { + 0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693, + 0x2A8D7F6F, 0xAB9BC912, 0xDE6008A1, 0x2028DA1F, + 0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82, + 0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE, + 0xA05FBCF6, 0xCD4181E9, 0xE150210C, 0xE24EF1BD, + 0xB168C381, 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43, + 0x4D495001, 0x38BE4341, 0x913CEE1D, 0x92A79C3F, + 0x089766BE, 0xBAEEADF4, 0x1286BECF, 0xB6EACB19, + 0x2660C200, 0x7565BDE4, 0x64241F7A, 0x8248DCA9, + 0xC3B3AD66, 0x28136086, 0x0BD8DFA8, 0x356D1CF2, + 0x107789BE, 0xB3B2E9CE, 0x0502AA8F, 0x0BC0351E, + 0x166BF52A, 0xEB12FF82, 0xE3486911, 0xD34D7516, + 0x4E7B3AFF, 0x5F43671B, 0x9CF6E037, 0x4981AC83, + 0x334266CE, 0x8C9341B7, 0xD0D854C0, 0xCB3A6C88, + 0x47BC2829, 0x4725BA37, 0xA66AD22B, 0x7AD61F1E, + 0x0C5CBAFA, 0x4437F107, 0xB6E79962, 0x42D2D816, + 0x0A961288, 0xE1A5C06E, 0x13749E67, 0x72FC081A, + 0xB1D139F7, 0xF9583745, 0xCF19DF58, 0xBEC3F756, + 0xC06EBA30, 0x07211B24, 0x45C28829, 0xC95E317F, + 0xBC8EC511, 0x38BC46E9, 0xC6E6FA14, 0xBAE8584A, + 0xAD4EBC46, 0x468F508B, 0x7829435F, 0xF124183B, + 0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D, 0x16E39264, + 0x92544A8B, 0x009B4FC3, 0xABA68CED, 0x9AC96F78, + 0x06A5B79A, 0xB2856E6E, 0x1AEC3CA9, 0xBE838688, + 0x0E0804E9, 0x55F1BE56, 0xE7E5363B, 0xB3A1F25D, + 0xF7DEBB85, 0x61FE033C, 0x16746233, 0x3C034C28, + 0xDA6D0C74, 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802, + 0x98F8F35A, 0x1626A49F, 0xEED82B29, 0x1D382FE3, + 0x0C4FB99A, 0xBB325778, 0x3EC6D97B, 0x6E77A6A9, + 0xCB658B5C, 0xD45230C7, 0x2BD1408B, 0x60C03EB7, + 0xB9068D78, 0xA33754F4, 0xF430C87D, 0xC8A71302, + 0xB96D8C32, 0xEBD4E7BE, 0xBE8B9D2D, 0x7979FB06, + 0xE7225308, 0x8B75CF77, 0x11EF8DA4, 0xE083C858, + 0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0, 0x5DDA0033, + 0xF28EBFB0, 0xF5B9C310, 0xA0EAC280, 0x08B9767A, + 0xA3D9D2B0, 0x79D34217, 0x021A718D, 0x9AC6336A, + 0x2711FD60, 0x438050E3, 0x069908A8, 0x3D7FEDC4, + 0x826D2BEF, 0x4EEB8476, 0x488DCF25, 0x36C9D566, + 0x28E74E41, 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF, + 0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6, 0x9EA80509, + 0xF22B017D, 0xA4173F70, 0xDD1E16C3, 0x15E0D7F9, + 0x50B1B887, 0x2B9F4FD5, 0x625ABA82, 0x6A017962, + 0x2EC01B9C, 0x15488AA9, 0xD716E740, 0x40055A2C, + 0x93D29A22, 0xE32DBF9A, 0x058745B9, 0x3453DC1E, + 0xD699296E, 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07, + 0xB87242D1, 0x19DE7EAE, 0x053E561A, 0x15AD6F8C, + 0x66626C1C, 0x7154C24C, 0xEA082B2A, 0x93EB2939, + 0x17DCB0F0, 0x58D4F2AE, 0x9EA294FB, 0x52CF564C, + 0x9883FE66, 0x2EC40581, 0x763953C3, 0x01D6692E, + 0xD3A0C108, 0xA1E7160E, 0xE4F2DFA6, 0x693ED285, + 0x74904698, 0x4C2B0EDD, 0x4F757656, 0x5D393378, + 0xA132234F, 0x3D321C5D, 0xC3F5E194, 0x4B269301, + 0xC79F022F, 0x3C997E7E, 0x5E4F9504, 0x3FFAFBBD, + 0x76F7AD0E, 0x296693F4, 0x3D1FCE6F, 0xC61E45BE, + 0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0, 0x4E72B567, + 0x5592A33D, 0xB5229301, 0xCFD2A87F, 0x60AEB767, + 0x1814386B, 0x30BCC33D, 0x38A0C07D, 0xFD1606F2, + 0xC363519B, 0x589DD390, 0x5479F8E6, 0x1CB8D647, + 0x97FD61A9, 0xEA7759F4, 0x2D57539D, 0x569A58CF, + 0xE84E63AD, 0x462E1B78, 0x6580F87E, 0xF3817914, + 0x91DA55F4, 0x40A230F3, 0xD1988F35, 0xB6E318D2, + 0x3FFA50BC, 0x3D40F021, 0xC3C0BDAE, 0x4958C24C, + 0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA, + 0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3 +}; + +static const u_int32_t cast_sbox8[256] = { + 0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095, + 0x7789F8B7, 0xE6C1121B, 0x0E241600, 0x052CE8B5, + 0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174, + 0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC, + 0xDE9ADEB1, 0x0A0CC32C, 0xBE197029, 0x84A00940, + 0xBB243A0F, 0xB4D137CF, 0xB44E79F0, 0x049EEDFD, + 0x0B15A15D, 0x480D3168, 0x8BBBDE5A, 0x669DED42, + 0xC7ECE831, 0x3F8F95E7, 0x72DF191B, 0x7580330D, + 0x94074251, 0x5C7DCDFA, 0xABBE6D63, 0xAA402164, + 0xB301D40A, 0x02E7D1CA, 0x53571DAE, 0x7A3182A2, + 0x12A8DDEC, 0xFDAA335D, 0x176F43E8, 0x71FB46D4, + 0x38129022, 0xCE949AD4, 0xB84769AD, 0x965BD862, + 0x82F3D055, 0x66FB9767, 0x15B80B4E, 0x1D5B47A0, + 0x4CFDE06F, 0xC28EC4B8, 0x57E8726E, 0x647A78FC, + 0x99865D44, 0x608BD593, 0x6C200E03, 0x39DC5FF6, + 0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632, 0x70108C0C, + 0xBBD35049, 0x2998DF04, 0x980CF42A, 0x9B6DF491, + 0x9E7EDD53, 0x06918548, 0x58CB7E07, 0x3B74EF2E, + 0x522FFFB1, 0xD24708CC, 0x1C7E27CD, 0xA4EB215B, + 0x3CF1D2E2, 0x19B47A38, 0x424F7618, 0x35856039, + 0x9D17DEE7, 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8, + 0x09C467CD, 0xC18910B1, 0xE11DBF7B, 0x06CD1AF8, + 0x7170C608, 0x2D5E3354, 0xD4DE495A, 0x64C6D006, + 0xBCC0C62C, 0x3DD00DB3, 0x708F8F34, 0x77D51B42, + 0x264F620F, 0x24B8D2BF, 0x15C1B79E, 0x46A52564, + 0xF8D7E54E, 0x3E378160, 0x7895CDA5, 0x859C15A5, + 0xE6459788, 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB, + 0x7F229B1E, 0x31842E7B, 0x24259FD7, 0xF8BEF472, + 0x835FFCB8, 0x6DF4C1F2, 0x96F5B195, 0xFD0AF0FC, + 0xB0FE134C, 0xE2506D3D, 0x4F9B12EA, 0xF215F225, + 0xA223736F, 0x9FB4C428, 0x25D04979, 0x34C713F8, + 0xC4618187, 0xEA7A6E98, 0x7CD16EFC, 0x1436876C, + 0xF1544107, 0xBEDEEE14, 0x56E9AF27, 0xA04AA441, + 0x3CF7C899, 0x92ECBAE6, 0xDD67016D, 0x151682EB, + 0xA842EEDF, 0xFDBA60B4, 0xF1907B75, 0x20E3030F, + 0x24D8C29E, 0xE139673B, 0xEFA63FB8, 0x71873054, + 0xB6F2CF3B, 0x9F326442, 0xCB15A4CC, 0xB01A4504, + 0xF1E47D8D, 0x844A1BE5, 0xBAE7DFDC, 0x42CBDA70, + 0xCD7DAE0A, 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C, + 0xCEA4D428, 0x79D130A4, 0x3486EBFB, 0x33D3CDDC, + 0x77853B53, 0x37EFFCB5, 0xC5068778, 0xE580B3E6, + 0x4E68B8F4, 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C, + 0x132A4F94, 0x43B7950E, 0x2FEE7D1C, 0x223613BD, + 0xDD06CAA2, 0x37DF932B, 0xC4248289, 0xACF3EBC3, + 0x5715F6B7, 0xEF3478DD, 0xF267616F, 0xC148CBE4, + 0x9052815E, 0x5E410FAB, 0xB48A2465, 0x2EDA7FA4, + 0xE87B40E4, 0xE98EA084, 0x5889E9E1, 0xEFD390FC, + 0xDD07D35B, 0xDB485694, 0x38D7E5B2, 0x57720101, + 0x730EDEBC, 0x5B643113, 0x94917E4F, 0x503C2FBA, + 0x646F1282, 0x7523D24A, 0xE0779695, 0xF9C17A8F, + 0x7A5B2121, 0xD187B896, 0x29263A4D, 0xBA510CDF, + 0x81F47C9F, 0xAD1163ED, 0xEA7B5965, 0x1A00726E, + 0x11403092, 0x00DA6D77, 0x4A0CDD61, 0xAD1F4603, + 0x605BDFB0, 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A, + 0xA0E736A0, 0x5564A6B9, 0x10853209, 0xC7EB8F37, + 0x2DE705CA, 0x8951570F, 0xDF09822B, 0xBD691A6C, + 0xAA12E4F2, 0x87451C0F, 0xE0F6A27A, 0x3ADA4819, + 0x4CF1764F, 0x0D771C2B, 0x67CDB156, 0x350D8384, + 0x5938FA0F, 0x42399EF3, 0x36997B07, 0x0E84093D, + 0x4AA93E61, 0x8360D87B, 0x1FA98B0C, 0x1149382C, + 0xE97625A5, 0x0614D1B7, 0x0E25244B, 0x0C768347, + 0x589E8D82, 0x0D2059D1, 0xA466BB1E, 0xF8DA0A82, + 0x04F19130, 0xBA6E4EC0, 0x99265164, 0x1EE7230D, + 0x50B2AD80, 0xEAEE6801, 0x8DB2A283, 0xEA8BF59E +}; + +#endif // _NETINET_IP_CASTSB_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_ecn.h b/ecos/packages/net/tcpip/current/include/netinet/ip_ecn.h new file mode 100644 index 0000000..08e43f2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_ecn.h @@ -0,0 +1,90 @@ +//========================================================================== +// +// include/netinet/ip_ecn.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_ecn.h,v 1.1 1999/12/08 06:50:19 itojun Exp $ */ + +/* + * Copyright (C) 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * KAME Id: ip_ecn.h,v 1.2 1999/08/19 12:57:44 itojun Exp + */ + +#ifndef _NETINET_IP_ECN_H_ +#define _NETINET_IP_ECN_H_ + +/* + * ECN consideration on tunnel ingress/egress operation. + * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt + */ + +#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__) +#if defined(_KERNEL) && !defined(_LKM) +#include "opt_inet.h" +#endif +#endif + +#define ECN_ALLOWED 1 /* ECN allowed */ +#define ECN_FORBIDDEN 0 /* ECN forbidden */ +#define ECN_NOCARE (-1) /* no consideration to ECN */ + +#if defined(KERNEL) || defined(_KERNEL) +extern void ip_ecn_ingress __P((int, u_int8_t *, u_int8_t *)); +extern void ip_ecn_egress __P((int, u_int8_t *, u_int8_t *)); +#ifdef INET6 +extern void ip6_ecn_ingress __P((int, u_int32_t *, u_int32_t *)); +extern void ip6_ecn_egress __P((int, u_int32_t *, u_int32_t *)); +#endif +#endif + +#endif // _NETINET_IP_ECN_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_esp.h b/ecos/packages/net/tcpip/current/include/netinet/ip_esp.h new file mode 100644 index 0000000..1c65473 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_esp.h @@ -0,0 +1,139 @@ +//========================================================================== +// +// include/netinet/ip_esp.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_esp.h,v 1.26 1999/12/09 00:33:29 angelos Exp $ */ + +/* + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Niels Provos (provos@physnet.uni-hamburg.de). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Permission to use, copy, and modify this software without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IP_ESP_H_ +#define _NETINET_IP_ESP_H_ + +/* + * Encapsulation Security Payload Processing + * Per RFC1827 (Atkinson, 1995) + */ + +/* Various defines for the "new" ESP */ +#define ESP_NEW_ALEN 12 /* 96bits authenticator */ + +struct esp_old +{ + u_int32_t esp_spi; /* Security Parameters Index */ + u_int8_t esp_iv[8]; /* iv[4] may actually be data! */ +}; + +#define ESP_OLD_FLENGTH 12 +#define ESP_NEW_FLENGTH 16 + +struct esp_new +{ + u_int32_t esp_spi; /* Security Parameter Index */ + u_int32_t esp_rpl; /* Sequence Number, Replay Counter */ + u_int8_t esp_iv[8]; /* Data may start already at iv[0]! */ +}; + +struct espstat +{ + u_int32_t esps_hdrops; /* packet shorter than header shows */ + u_int32_t esps_notdb; + u_int32_t esps_badkcr; + u_int32_t esps_qfull; + u_int32_t esps_noxform; + u_int32_t esps_badilen; + u_int32_t esps_wrap; /* Replay counter wrapped around */ + u_int32_t esps_badenc; /* Bad encryption detected */ + u_int32_t esps_badauth; /* Only valid for transforms with auth */ + u_int32_t esps_replay; /* Possible packet replay detected */ + u_int32_t esps_input; /* Input ESP packets */ + u_int32_t esps_output; /* Output ESP packets */ + u_int32_t esps_invalid; /* Trying to use an invalid TDB */ + u_int64_t esps_ibytes; /* input bytes */ + u_int64_t esps_obytes; /* output bytes */ + u_int32_t esps_toobig; /* packet got larger than IP_MAXPACKET */ + u_int32_t esps_pdrops; /* packet blocked due to policy */ +}; + +/* + * Names for ESP sysctl objects + */ +#define ESPCTL_ENABLE 1 /* Enable ESP processing */ +#define ESPCTL_MAXID 2 + +#define ESPCTL_NAMES { \ + { 0, 0 }, \ + { "enable", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL +void esp_input __P((struct mbuf *, ...)); +int esp_output __P((struct mbuf *, struct tdb *, struct mbuf **)); +int esp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); + +#ifdef INET6 +void esp6_input __P((struct mbuf *, ...)); +#endif /* INET6 */ + +extern int esp_enable; +struct espstat espstat; +#endif /* _Kernel */ + +#endif // _NETINET_IP_ESP_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_ether.h b/ecos/packages/net/tcpip/current/include/netinet/ip_ether.h new file mode 100644 index 0000000..bac3985 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_ether.h @@ -0,0 +1,93 @@ +//========================================================================== +// +// include/netinet/ip_ether.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_ether.h,v 1.2 1999/10/29 02:00:23 angelos Exp $ */ + +/* + * The author of this code is Angelos D. Keromytis (angelos@adk.gr) + * + * This code was written by Angelos D. Keromytis in October 1999. + * + * Copyright (C) 1999, by Angelos D. Keromytis. + * + * Permission to use, copy, and modify this software without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IP_ETHER_H_ +#define _NETINET_IP_ETHER_H_ + +/* + * Ethernet-inside-IP processing. + */ + +struct etheripstat +{ + u_int32_t etherip_hdrops; /* packet shorter than header shows */ + u_int32_t etherip_qfull; /* bridge queue full, packet dropped */ + u_int32_t etherip_noifdrops; /* no interface/bridge information */ + u_int32_t etherip_pdrops; /* packet dropped due to policy */ + u_int32_t etherip_adrops; /* all other drops */ + u_int32_t etherip_ipackets; /* total input packets */ + u_int32_t etherip_opackets; /* total output packets */ + u_int64_t etherip_ibytes; /* input bytes */ + u_int64_t etherip_obytes; /* output bytes */ +}; + +/* + * Names for IP4 sysctl objects + */ +#define ETHERIPCTL_ALLOW 1 /* accept incoming EtherIP packets */ +#define ETHERIPCTL_MAXID 2 + +#define ETHERIPCTL_NAMES { \ + { 0, 0 }, \ + { "allow", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL +int etherip_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); + +extern int etherip_allow; +extern struct etheripstat etheripstat; +#endif + +#endif // _NETINET_IP_ETHER_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_fil.h b/ecos/packages/net/tcpip/current/include/netinet/ip_fil.h new file mode 100644 index 0000000..8924e01 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_fil.h @@ -0,0 +1,605 @@ +//========================================================================== +// +// include/netinet/ip_fil.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_fil.h,v 1.13 1999/12/15 05:20:21 kjell Exp $ */ +/* + * Copyright (C) 1993-1998 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + * @(#)ip_fil.h 1.35 6/5/96 + */ + +#ifndef _NETINET_IP_FIL_H__ +#define _NETINET_IP_FIL_H__ + +/* + * Pathnames for various IP Filter control devices. Used by LKM + * and userland, so defined here. + */ +#define IPNAT_NAME "/dev/ipnat" +#define IPSTATE_NAME "/dev/ipstate" +#define IPAUTH_NAME "/dev/ipauth" + +#ifndef SOLARIS +# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#endif + +#if defined(KERNEL) && !defined(_KERNEL) +# define _KERNEL +#endif + +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +#if defined(__STDC__) || defined(__GNUC__) +# define SIOCADAFR _IOW('r', 60, struct frentry) +# define SIOCRMAFR _IOW('r', 61, struct frentry) +# define SIOCSETFF _IOW('r', 62, u_int) +# define SIOCGETFF _IOR('r', 63, u_int) +# define SIOCGETFS _IOR('r', 64, struct friostat) +# define SIOCIPFFL _IOWR('r', 65, int) +# define SIOCIPFFB _IOR('r', 66, int) +# define SIOCADIFR _IOW('r', 67, struct frentry) +# define SIOCRMIFR _IOW('r', 68, struct frentry) +# define SIOCSWAPA _IOR('r', 69, u_int) +# define SIOCINAFR _IOW('r', 70, struct frentry) +# define SIOCINIFR _IOW('r', 71, struct frentry) +# define SIOCFRENB _IOW('r', 72, u_int) +# define SIOCFRSYN _IOW('r', 73, u_int) +# define SIOCFRZST _IOWR('r', 74, struct friostat) +# define SIOCZRLST _IOWR('r', 75, struct frentry) +# define SIOCAUTHW _IOWR('r', 76, struct fr_info) +# define SIOCAUTHR _IOWR('r', 77, struct fr_info) +# define SIOCATHST _IOWR('r', 78, struct fr_authstat) +#else +# define SIOCADAFR _IOW(r, 60, struct frentry) +# define SIOCRMAFR _IOW(r, 61, struct frentry) +# define SIOCSETFF _IOW(r, 62, u_int) +# define SIOCGETFF _IOR(r, 63, u_int) +# define SIOCGETFS _IOR(r, 64, struct friostat) +# define SIOCIPFFL _IOWR(r, 65, int) +# define SIOCIPFFB _IOR(r, 66, int) +# define SIOCADIFR _IOW(r, 67, struct frentry) +# define SIOCRMIFR _IOW(r, 68, struct frentry) +# define SIOCSWAPA _IOR(r, 69, u_int) +# define SIOCINAFR _IOW(r, 70, struct frentry) +# define SIOCINIFR _IOW(r, 71, struct frentry) +# define SIOCFRENB _IOW(r, 72, u_int) +# define SIOCFRSYN _IOW(r, 73, u_int) +# define SIOCFRZST _IOWR(r, 74, struct friostat) +# define SIOCZRLST _IOWR(r, 75, struct frentry) +# define SIOCAUTHW _IOWR(r, 76, struct fr_info) +# define SIOCAUTHR _IOWR(r, 77, struct fr_info) +# define SIOCATHST _IOWR(r, 78, struct fr_authstat) +#endif +#define SIOCADDFR SIOCADAFR +#define SIOCDELFR SIOCRMAFR +#define SIOCINSFR SIOCINAFR + +typedef struct fr_ip { + u_char fi_v:4; /* IP version */ + u_char fi_fl:4; /* packet flags */ + u_char fi_tos; /* IP packet TOS */ + u_char fi_ttl; /* IP packet TTL */ + u_char fi_p; /* IP packet protocol */ + struct in_addr fi_src; /* source address from packet */ + struct in_addr fi_dst; /* destination address from packet */ + u_32_t fi_optmsk; /* bitmask composed from IP options */ + u_short fi_secmsk; /* bitmask composed from IP security options */ + u_short fi_auth; /* authentication code from IP sec. options */ +} fr_ip_t; + +#define FI_OPTIONS (FF_OPTIONS >> 24) +#define FI_TCPUDP (FF_TCPUDP >> 24) /* TCP/UCP implied comparison*/ +#define FI_FRAG (FF_FRAG >> 24) +#define FI_SHORT (FF_SHORT >> 24) +#define FI_CMP (FI_OPTIONS|FI_TCPUDP|FI_SHORT) + +/* + * These are both used by the state and NAT code to indicate that one port or + * the other should be treated as a wildcard. + */ +#define FI_W_SPORT 0x00000100 +#define FI_W_DPORT 0x00000200 +#define FI_WILD (FI_W_SPORT|FI_W_DPORT) + +typedef struct fr_info { + void *fin_ifp; /* interface packet is `on' */ + struct fr_ip fin_fi; /* IP Packet summary */ + u_short fin_data[2]; /* TCP/UDP ports, ICMP code/type */ + u_char fin_out; /* in or out ? 1 == out, 0 == in */ + u_char fin_rev; /* state only: 1 = reverse */ + u_short fin_hlen; /* length of IP header in bytes */ + u_char fin_tcpf; /* TCP header flags (SYN, ACK, etc) */ + /* From here on is packet specific */ + u_char fin_icode; /* ICMP error to return */ + u_short fin_rule; /* rule # last matched */ + u_short fin_group; /* group number, -1 for none */ + struct frentry *fin_fr; /* last matching rule */ + char *fin_dp; /* start of data past IP header */ + u_short fin_dlen; /* length of data portion of packet */ + u_short fin_id; /* IP packet id field */ + void *fin_mp; /* pointer to pointer to mbuf */ +#if SOLARIS && defined(_KERNEL) + void *fin_qfm; /* pointer to mblk where pkt starts */ + void *fin_qif; +#endif +} fr_info_t; + +/* + * Size for compares on fr_info structures + */ +#define FI_CSIZE offsetof(fr_info_t, fin_icode) + +/* + * Size for copying cache fr_info structure + */ +#define FI_COPYSIZE offsetof(fr_info_t, fin_dp) + +typedef struct frdest { + void *fd_ifp; + struct in_addr fd_ip; + char fd_ifname[IFNAMSIZ]; +} frdest_t; + +typedef struct frentry { + struct frentry *fr_next; + u_short fr_group; /* group to which this rule belongs */ + u_short fr_grhead; /* group # which this rule starts */ + struct frentry *fr_grp; + int fr_ref; /* reference count - for grouping */ + void *fr_ifa; +#if BSD >= 199306 + void *fr_oifa; +#endif + /* + * These are only incremented when a packet matches this rule and + * it is the last match + */ + U_QUAD_T fr_hits; + U_QUAD_T fr_bytes; + /* + * Fields after this may not change whilst in the kernel. + */ + struct fr_ip fr_ip; + struct fr_ip fr_mip; /* mask structure */ + + u_char fr_tcpfm; /* tcp flags mask */ + u_char fr_tcpf; /* tcp flags */ + + u_short fr_icmpm; /* data for ICMP packets (mask) */ + u_short fr_icmp; + + u_char fr_scmp; /* data for port comparisons */ + u_char fr_dcmp; + u_short fr_dport; + u_short fr_sport; + u_short fr_stop; /* top port for <> and >< */ + u_short fr_dtop; /* top port for <> and >< */ + u_32_t fr_flags; /* per-rule flags && options (see below) */ + u_short fr_skip; /* # of rules to skip */ + u_short fr_loglevel; /* syslog log facility + priority */ + int (*fr_func) __P((int, ip_t *, fr_info_t *)); /* call this function */ + char fr_icode; /* return ICMP code */ + char fr_ifname[IFNAMSIZ]; +#if BSD >= 199306 + char fr_oifname[IFNAMSIZ]; +#endif + struct frdest fr_tif; /* "to" interface */ + struct frdest fr_dif; /* duplicate packet interfaces */ +} frentry_t; + +#define fr_proto fr_ip.fi_p +#define fr_ttl fr_ip.fi_ttl +#define fr_tos fr_ip.fi_tos +#define fr_dst fr_ip.fi_dst +#define fr_src fr_ip.fi_src +#define fr_dmsk fr_mip.fi_dst +#define fr_smsk fr_mip.fi_src + +#ifndef offsetof +#define offsetof(t,m) (int)((&((t *)0L)->m)) +#endif +#define FR_CMPSIZ (sizeof(struct frentry) - offsetof(frentry_t, fr_ip)) + +/* + * fr_flags + */ +#define FR_BLOCK 0x00001 /* do not allow packet to pass */ +#define FR_PASS 0x00002 /* allow packet to pass */ +#define FR_OUTQUE 0x00004 /* outgoing packets */ +#define FR_INQUE 0x00008 /* ingoing packets */ +#define FR_LOG 0x00010 /* Log */ +#define FR_LOGB 0x00011 /* Log-fail */ +#define FR_LOGP 0x00012 /* Log-pass */ +#define FR_LOGBODY 0x00020 /* Log the body */ +#define FR_LOGFIRST 0x00040 /* Log the first byte if state held */ +#define FR_RETRST 0x00080 /* Return TCP RST packet - reset connection */ +#define FR_RETICMP 0x00100 /* Return ICMP unreachable packet */ +#define FR_FAKEICMP 0x00180 /* Return ICMP unreachable with fake source */ +#define FR_NOMATCH 0x00200 /* no match occured */ +#define FR_ACCOUNT 0x00400 /* count packet bytes */ +#define FR_KEEPFRAG 0x00800 /* keep fragment information */ +#define FR_KEEPSTATE 0x01000 /* keep `connection' state information */ +#define FR_INACTIVE 0x02000 +#define FR_QUICK 0x04000 /* match & stop processing list */ +#define FR_FASTROUTE 0x08000 /* bypass normal routing */ +#define FR_CALLNOW 0x10000 /* call another function (fr_func) if matches */ +#define FR_DUP 0x20000 /* duplicate packet */ +#define FR_LOGORBLOCK 0x40000 /* block the packet if it can't be logged */ +#define FR_NOTSRCIP 0x80000 /* not the src IP# */ +#define FR_NOTDSTIP 0x100000 /* not the dst IP# */ +#define FR_AUTH 0x200000 /* use authentication */ +#define FR_PREAUTH 0x400000 /* require preauthentication */ +#define FR_DONTCACHE 0x800000 /* don't cache the result */ + +#define FR_LOGMASK (FR_LOG|FR_LOGP|FR_LOGB) +#define FR_RETMASK (FR_RETICMP|FR_RETRST|FR_FAKEICMP) + +/* + * These correspond to #define's for FI_* and are stored in fr_flags + */ +#define FF_OPTIONS 0x01000000 +#define FF_TCPUDP 0x02000000 +#define FF_FRAG 0x04000000 +#define FF_SHORT 0x08000000 +/* + * recognized flags for SIOCGETFF and SIOCSETFF, and get put in fr_flags + */ +#define FF_LOGPASS 0x10000000 +#define FF_LOGBLOCK 0x20000000 +#define FF_LOGNOMATCH 0x40000000 +#define FF_LOGGING (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH) +#define FF_BLOCKNONIP 0x80000000 /* Solaris2 Only */ + +#define FR_NONE 0 +#define FR_EQUAL 1 +#define FR_NEQUAL 2 +#define FR_LESST 3 +#define FR_GREATERT 4 +#define FR_LESSTE 5 +#define FR_GREATERTE 6 +#define FR_OUTRANGE 7 +#define FR_INRANGE 8 + +typedef struct filterstats { + u_long fr_pass; /* packets allowed */ + u_long fr_block; /* packets denied */ + u_long fr_nom; /* packets which don't match any rule */ + u_long fr_ppkl; /* packets allowed and logged */ + u_long fr_bpkl; /* packets denied and logged */ + u_long fr_npkl; /* packets unmatched and logged */ + u_long fr_pkl; /* packets logged */ + u_long fr_skip; /* packets to be logged but buffer full */ + u_long fr_ret; /* packets for which a return is sent */ + u_long fr_acct; /* packets for which counting was performed */ + u_long fr_bnfr; /* bad attempts to allocate fragment state */ + u_long fr_nfr; /* new fragment state kept */ + u_long fr_cfr; /* add new fragment state but complete pkt */ + u_long fr_bads; /* bad attempts to allocate packet state */ + u_long fr_ads; /* new packet state kept */ + u_long fr_chit; /* cached hit */ + u_long fr_tcpbad; /* TCP checksum check failures */ + u_long fr_pull[2]; /* good and bad pullup attempts */ +#if SOLARIS + u_long fr_notdata; /* PROTO/PCPROTO that have no data */ + u_long fr_nodata; /* mblks that have no data */ + u_long fr_bad; /* bad IP packets to the filter */ + u_long fr_notip; /* packets passed through no on ip queue */ + u_long fr_drop; /* packets dropped - no info for them! */ +#endif +} filterstats_t; + +/* + * For SIOCGETFS + */ +typedef struct friostat { + struct filterstats f_st[2]; + struct frentry *f_fin[2]; + struct frentry *f_fout[2]; + struct frentry *f_acctin[2]; + struct frentry *f_acctout[2]; + struct frentry *f_auth; + struct frgroup *f_groups[3][2]; + u_long f_froute[2]; + int f_active; /* 1 or 0 - active rule set */ + int f_defpass; /* default pass - from fr_pass */ + int f_running; /* 1 if running, else 0 */ + int f_logging; /* 1 if enabled, else 0 */ + char f_version[32]; /* version string */ +} friostat_t; + +typedef struct optlist { + u_short ol_val; + int ol_bit; +} optlist_t; + + +/* + * Group list structure. + */ +typedef struct frgroup { + u_short fg_num; + struct frgroup *fg_next; + struct frentry *fg_head; + struct frentry **fg_start; +} frgroup_t; + + +/* + * Log structure. Each packet header logged is prepended by one of these. + * Following this in the log records read from the device will be an ipflog + * structure which is then followed by any packet data. + */ +typedef struct iplog { + u_32_t ipl_magic; + u_int ipl_count; + u_long ipl_sec; + u_long ipl_usec; + size_t ipl_dsize; + struct iplog *ipl_next; +} iplog_t; + +#define IPL_MAGIC 0x49504c4d /* 'IPLM' */ + +typedef struct ipflog { +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + u_char fl_ifname[IFNAMSIZ]; +#else + u_int fl_unit; + u_char fl_ifname[4]; +#endif + u_char fl_plen; /* extra data after hlen */ + u_char fl_hlen; /* length of IP headers saved */ + u_short fl_rule; /* assume never more than 64k rules, total */ + u_short fl_group; + u_short fl_loglevel; /* syslog log level */ + u_32_t fl_flags; + u_32_t fl_lflags; +} ipflog_t; + + +#if !defined(__OpenBSD__) +# ifndef ICMP_UNREACH_FILTER +# define ICMP_UNREACH_FILTER 13 +# endif +#endif + +#ifndef IPF_LOGGING +# define IPF_LOGGING 0 +#endif +#ifndef IPF_DEFAULT_PASS +# define IPF_DEFAULT_PASS FR_PASS +#endif + +#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) +#define IPLLOGSIZE 8192 + +/* + * Device filenames for reading log information. Use ipf on Solaris2 because + * ipl is already a name used by something else. + */ +#ifndef IPL_NAME +# if SOLARIS +# define IPL_NAME "/dev/ipf" +# else +# define IPL_NAME "/dev/ipl" +# endif +#endif +#define IPL_NAT IPNAT_NAME +#define IPL_STATE IPSTATE_NAME +#define IPL_AUTH IPAUTH_NAME + +#define IPL_LOGIPF 0 /* Minor device #'s for accessing logs */ +#define IPL_LOGNAT 1 +#define IPL_LOGSTATE 2 +#define IPL_LOGAUTH 3 +#define IPL_LOGMAX 3 + +#if !defined(CDEV_MAJOR) && defined (__FreeBSD_version) && \ + (__FreeBSD_version >= 220000) +# define CDEV_MAJOR 79 +#endif + +/* + * Post NetBSD 1.2 has the PFIL interface for packet filters. This turns + * on those hooks. We don't need any special mods in non-IP Filter code + * with this! + */ +#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \ + (defined(NetBSD1_2) && NetBSD1_2 > 1) +# if (NetBSD >= 199905) +# define PFIL_HOOKS +# endif +# ifdef PFIL_HOOKS +# define NETBSD_PF +# endif +#endif + + +#ifndef _KERNEL +extern int fr_check __P((ip_t *, int, void *, int, mb_t **)); +extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); +extern int send_reset __P((ip_t *, struct ifnet *)); +extern int icmp_error __P((ip_t *, struct ifnet *)); +extern int ipf_log __P((void)); +extern int ipfr_fastroute __P((ip_t *, fr_info_t *, frdest_t *)); +extern struct ifnet *get_unit __P((char *)); +# if defined(__NetBSD__) || defined(__OpenBSD__) || \ + (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) +extern int iplioctl __P((dev_t, u_long, caddr_t, int)); +# else +extern int iplioctl __P((dev_t, int, caddr_t, int)); +# endif +extern int iplopen __P((dev_t, int)); +extern int iplclose __P((dev_t, int)); +#else /* #ifndef _KERNEL */ +# if defined(__NetBSD__) && defined(PFIL_HOOKS) +extern void ipfilterattach __P((int)); +# endif + +#if !defined(__OpenBSD__) +/* + * OpenBSD has this call in the kernel but doesn't export it to userland. + * See ip_fil.c for actual hook and more details. + */ +extern int iplattach __P((void)); +#endif + +extern int ipl_enable __P((void)); +extern int ipl_disable __P((void)); +extern void ipflog_init __P((void)); +extern int ipflog_clear __P((minor_t)); +extern int ipflog_read __P((minor_t, struct uio *)); +extern int ipflog __P((u_int, ip_t *, fr_info_t *, mb_t *)); +extern int ipllog __P((int, fr_info_t *, void **, size_t *, int *, int)); +# if SOLARIS +extern int fr_check __P((ip_t *, int, void *, int, qif_t *, mb_t **)); +extern int (*fr_checkp) __P((ip_t *, int, void *, + int, qif_t *, mb_t **)); +extern int icmp_error __P((ip_t *, int, int, qif_t *, struct in_addr)); +# if SOLARIS2 >= 7 +extern int iplioctl __P((dev_t, int, intptr_t, int, cred_t *, int *)); +# else +extern int iplioctl __P((dev_t, int, int *, int, cred_t *, int *)); +# endif +extern int iplopen __P((dev_t *, int, int, cred_t *)); +extern int iplclose __P((dev_t, int, int, cred_t *)); +extern int ipfsync __P((void)); +extern int send_reset __P((fr_info_t *, ip_t *, qif_t *)); +extern int ipfr_fastroute __P((qif_t *, ip_t *, mblk_t *, mblk_t **, + fr_info_t *, frdest_t *)); +extern void copyin_mblk __P((mblk_t *, size_t, size_t, char *)); +extern void copyout_mblk __P((mblk_t *, size_t, size_t, char *)); +extern int fr_qin __P((queue_t *, mblk_t *)); +extern int fr_qout __P((queue_t *, mblk_t *)); +# ifdef IPFILTER_LOG +extern int iplread __P((dev_t, struct uio *, cred_t *)); +# endif +# else /* SOLARIS */ +extern int fr_check __P((ip_t *, int, void *, int, mb_t **)); +extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); +# ifdef linux +extern int send_reset __P((tcpiphdr_t *, struct ifnet *)); +# else +extern int send_reset __P((fr_info_t *, struct ip *)); +extern int send_icmp_err __P((ip_t *, int, int, void *, struct in_addr)); +# endif +extern int ipfr_fastroute __P((mb_t *, fr_info_t *, frdest_t *)); +extern size_t mbufchainlen __P((mb_t *)); +# ifdef __sgi +# include <sys/cred.h> +extern int iplioctl __P((dev_t, int, caddr_t, int, cred_t *, int *)); +extern int iplopen __P((dev_t *, int, int, cred_t *)); +extern int iplclose __P((dev_t, int, int, cred_t *)); +extern int iplread __P((dev_t, struct uio *, cred_t *)); +extern int ipfsync __P((void)); +extern int ipfilter_sgi_attach __P((void)); +extern void ipfilter_sgi_detach __P((void)); +extern void ipfilter_sgi_intfsync __P((void)); +# else +# ifdef IPFILTER_LKM +extern int iplidentify __P((char *)); +# endif +# if (_BSDI_VERSION >= 199510) || (__FreeBSD_version >= 220000) || \ + (NetBSD >= 199511) || defined(__OpenBSD__) +# if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || \ + defined(__OpenBSD__) || (__FreeBSD_version >= 300000) +extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +# else +extern int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); +# endif +extern int iplopen __P((dev_t, int, int, struct proc *)); +extern int iplclose __P((dev_t, int, int, struct proc *)); +# else +# ifndef linux +extern int iplopen __P((dev_t, int)); +extern int iplclose __P((dev_t, int)); +extern int iplioctl __P((dev_t, int, caddr_t, int)); +# else +extern int iplioctl(struct inode *, struct file *, u_int, u_long); +extern int iplopen __P((struct inode *, struct file *)); +extern void iplclose __P((struct inode *, struct file *)); +# endif /* !linux */ +# endif /* (_BSDI_VERSION >= 199510) */ +# if BSD >= 199306 +extern int iplread __P((dev_t, struct uio *, int)); +# else +# ifndef linux +extern int iplread __P((dev_t, struct uio *)); +# else +extern int iplread(struct inode *, struct file *, char *, int); +# endif /* !linux */ +# endif /* BSD >= 199306 */ +# endif /* __ sgi */ +# endif /* SOLARIS */ +#endif /* #ifndef _KERNEL */ + +extern void fixskip __P((frentry_t **, frentry_t *, int)); +extern int countbits __P((u_32_t)); +extern int ipldetach __P((void)); +extern u_short fr_tcpsum __P((mb_t *, ip_t *, tcphdr_t *)); +extern int fr_scanlist __P((u_32_t, ip_t *, fr_info_t *, void *)); +extern u_short ipf_cksum __P((u_short *, int)); +extern int fr_copytolog __P((int, char *, int)); +extern void fr_forgetifp __P((void *)); +extern int frflush __P((minor_t, int)); +extern void frsync __P((void)); +extern frgroup_t *fr_addgroup __P((u_int, frentry_t *, minor_t, int)); +extern frgroup_t *fr_findgroup __P((u_int, u_32_t, minor_t, int, frgroup_t ***)); +extern void fr_delgroup __P((u_int, u_32_t, minor_t, int)); +extern void fr_makefrip __P((int, ip_t *, fr_info_t *)); +extern int fr_ifpaddr __P((void *, struct in_addr *)); +extern char *memstr __P((char *, char *, int, int)); +extern int ipl_unreach; +extern int ipl_inited; +extern u_long ipl_frouteok[2]; +extern int fr_pass; +extern int fr_flags; +extern int fr_active; +extern fr_info_t frcache[2]; +extern char ipfilter_version[]; +#ifdef IPFILTER_LOG +extern iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; +extern size_t iplused[IPL_LOGMAX + 1]; +#endif +extern struct frentry *ipfilter[2][2], *ipacct[2][2]; +extern struct frgroup *ipfgroups[3][2]; +extern struct filterstats frstats[]; + +#endif /* _NETINET_IP_FIL_H__ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_fil_compat.h b/ecos/packages/net/tcpip/current/include/netinet/ip_fil_compat.h new file mode 100644 index 0000000..e6f77cd --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_fil_compat.h @@ -0,0 +1,865 @@ +//========================================================================== +// +// include/netinet/ip_compat.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_fil_compat.h,v 1.11 1999/12/15 05:20:21 kjell Exp $ */ +/* + * Copyright (C) 1993-1998 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + * @(#)ip_compat.h 1.8 1/14/96 + */ + +#ifndef _NETINET_IP_COMPAT_H__ +#define _NETINET_IP_COMPAT_H__ + +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif +#ifndef __STDC__ +# undef const +# define const +#endif + +#ifndef SOLARIS +#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#endif + +#if defined(_KERNEL) || defined(KERNEL) || defined(__KERNEL__) +# undef KERNEL +# undef _KERNEL +# undef __KERNEL__ +# define KERNEL +# define _KERNEL +# define __KERNEL__ +#endif + +#if defined(__SVR4) || defined(__svr4__) || defined(__sgi) +#define index strchr +# if !defined(KERNEL) +# define bzero(a,b) memset(a,0,b) +# define bcmp memcmp +# define bcopy(a,b,c) memmove(b,a,c) +# endif +#endif + +#ifndef offsetof +#define offsetof(t,m) (int)((&((t *)0L)->m)) +#endif + +#if defined(__sgi) || defined(bsdi) +struct ether_addr { + u_char ether_addr_octet[6]; +}; +#endif + +#if defined(__sgi) && !defined(IPFILTER_LKM) +# ifdef __STDC__ +# define IPL_EXTERN(ep) ipfilter##ep +# else +# define IPL_EXTERN(ep) ipfilter/**/ep +# endif +#else +# ifdef __STDC__ +# define IPL_EXTERN(ep) ipl##ep +# else +# define IPL_EXTERN(ep) ipl/**/ep +# endif +#endif + +#ifdef linux +# include <sys/sysmacros.h> +#endif +#if SOLARIS +# define MTYPE(m) ((m)->b_datap->db_type) +# include <sys/isa_defs.h> +# include <sys/ioccom.h> +# include <sys/sysmacros.h> +# include <sys/kmem.h> +/* + * because Solaris 2 defines these in two places :-/ + */ +# undef IPOPT_EOL +# undef IPOPT_NOP +# undef IPOPT_LSRR +# undef IPOPT_RR +# undef IPOPT_SSRR +# ifndef KERNEL +# define _KERNEL +# undef RES_INIT +# include <inet/common.h> +# include <inet/ip.h> +# include <inet/ip_ire.h> +# undef _KERNEL +# else /* _KERNEL */ +# include <inet/common.h> +# include <inet/ip.h> +# include <inet/ip_ire.h> +# endif /* _KERNEL */ +# if SOLARIS2 >= 8 +# include <netinet/ip6.h> +# include <inet/ip6.h> +# define ipif_local_addr ipif_lcl_addr +# endif +#else +# if !defined(__sgi) +typedef int minor_t; +#endif +#endif /* SOLARIS */ +#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) + +#ifndef IP_OFFMASK +#define IP_OFFMASK 0x1fff +#endif + +#if BSD > 199306 +# define USE_QUAD_T +# define U_QUAD_T u_quad_t +# define QUAD_T quad_t +#else /* BSD > 199306 */ +# define U_QUAD_T u_long +# define QUAD_T long +#endif /* BSD > 199306 */ + +/* + * These operating systems already take care of the problem for us. + */ +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \ + defined(__sgi) +typedef u_int32_t u_32_t; +#else +/* + * Really, any arch where sizeof(long) != sizeof(int). + */ +# if defined(__alpha__) || defined(__alpha) || defined(_LP64) +typedef unsigned int u_32_t; +# else +typedef unsigned long u_32_t; +# endif +#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __sgi */ + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/* + * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108. + * + * Basic Option + * + * 00000001 - (Reserved 4) + * 00111101 - Top Secret + * 01011010 - Secret + * 10010110 - Confidential + * 01100110 - (Reserved 3) + * 11001100 - (Reserved 2) + * 10101011 - Unclassified + * 11110001 - (Reserved 1) + */ +#define IPSO_CLASS_RES4 0x01 +#define IPSO_CLASS_TOPS 0x3d +#define IPSO_CLASS_SECR 0x5a +#define IPSO_CLASS_CONF 0x96 +#define IPSO_CLASS_RES3 0x66 +#define IPSO_CLASS_RES2 0xcc +#define IPSO_CLASS_UNCL 0xab +#define IPSO_CLASS_RES1 0xf1 + +#define IPSO_AUTH_GENSER 0x80 +#define IPSO_AUTH_ESI 0x40 +#define IPSO_AUTH_SCI 0x20 +#define IPSO_AUTH_NSA 0x10 +#define IPSO_AUTH_DOE 0x08 +#define IPSO_AUTH_UN 0x06 +#define IPSO_AUTH_FTE 0x01 + +/* + * IP option #defines + */ +/*#define IPOPT_RR 7 */ +#define IPOPT_ZSU 10 /* ZSU */ +#define IPOPT_MTUP 11 /* MTUP */ +#define IPOPT_MTUR 12 /* MTUR */ +#define IPOPT_ENCODE 15 /* ENCODE */ +/*#define IPOPT_TS 68 */ +#define IPOPT_TR 82 /* TR */ +/*#define IPOPT_SECURITY 130 */ +/*#define IPOPT_LSRR 131 */ +#define IPOPT_E_SEC 133 /* E-SEC */ +#define IPOPT_CIPSO 134 /* CIPSO */ +/*#define IPOPT_SATID 136 */ +#ifndef IPOPT_SID +# define IPOPT_SID IPOPT_SATID +#endif +/*#define IPOPT_SSRR 137 */ +#define IPOPT_ADDEXT 147 /* ADDEXT */ +#define IPOPT_VISA 142 /* VISA */ +#define IPOPT_IMITD 144 /* IMITD */ +#define IPOPT_EIP 145 /* EIP */ +#define IPOPT_FINN 205 /* FINN */ + + +#if defined(__FreeBSD__) && defined(KERNEL) +# if __FreeBSD__ < 3 +# include <machine/spl.h> +# endif +# if defined(IPFILTER_LKM) && !defined(ACTUALLY_LKM_NOT_KERNEL) +# define ACTUALLY_LKM_NOT_KERNEL +# endif +#endif /* __FreeBSD__ && KERNEL */ + +/* + * Build some macros and #defines to enable the same code to compile anywhere + * Well, that's the idea, anyway :-) + */ +#ifdef KERNEL +# if SOLARIS +# define ATOMIC_INC(x) { mutex_enter(&ipf_rw); (x)++; \ + mutex_exit(&ipf_rw); } +# define ATOMIC_DEC(x) { mutex_enter(&ipf_rw); (x)--; \ + mutex_exit(&ipf_rw); } +# define MUTEX_ENTER(x) mutex_enter(x) +# if 1 +# define KRWLOCK_T krwlock_t +# define READ_ENTER(x) rw_enter(x, RW_READER) +# define WRITE_ENTER(x) rw_enter(x, RW_WRITER) +# define RW_UPGRADE(x) { if (rw_tryupgrade(x) == 0) { \ + rw_exit(x); \ + rw_enter(x, RW_WRITER); } \ + } +# define MUTEX_DOWNGRADE(x) rw_downgrade(x) +# define RWLOCK_INIT(x, y, z) rw_init((x), (y), RW_DRIVER, (z)) +# define RWLOCK_EXIT(x) rw_exit(x) +# define RW_DESTROY(x) rw_destroy(x) +# else +# define KRWLOCK_T kmutex_t +# define READ_ENTER(x) mutex_enter(x) +# define WRITE_ENTER(x) mutex_enter(x) +# define MUTEX_DOWNGRADE(x) ; +# define RWLOCK_INIT(x, y, z) mutex_init((x), (y), MUTEX_DRIVER, (z)) +# define RWLOCK_EXIT(x) mutex_exit(x) +# define RW_DESTROY(x) mutex_destroy(x) +# endif +# define MUTEX_EXIT(x) mutex_exit(x) +# define MTOD(m,t) (t)((m)->b_rptr) +# define IRCOPY(a,b,c) copyin((a), (b), (c)) +# define IWCOPY(a,b,c) copyout((a), (b), (c)) +# define FREE_MB_T(m) freemsg(m) +# define SPL_NET(x) ; +# define SPL_IMP(x) ; +# undef SPL_X +# define SPL_X(x) ; +# ifdef sparc +# define ntohs(x) (x) +# define ntohl(x) (x) +# define htons(x) (x) +# define htonl(x) (x) +# endif /* sparc */ +# define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) +# define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) +# define GET_MINOR(x) getminor(x) +typedef struct qif { + struct qif *qf_next; + ill_t *qf_ill; + kmutex_t qf_lock; + void *qf_iptr; + void *qf_optr; + queue_t *qf_in; + queue_t *qf_out; + struct qinit *qf_wqinfo; + struct qinit *qf_rqinfo; + struct qinit qf_wqinit; + struct qinit qf_rqinit; + mblk_t *qf_m; /* These three fields are for passing data up from */ + queue_t *qf_q; /* fr_qin and fr_qout to the packet processing. */ + size_t qf_off; + size_t qf_len; /* this field is used for in ipfr_fastroute */ + char qf_name[8]; + /* + * in case the ILL has disappeared... + */ + size_t qf_hl; /* header length */ +} qif_t; +extern ill_t *get_unit __P((char *)); +# define GETUNIT(n) get_unit((n)) +# else /* SOLARIS */ +# if defined(__sgi) +# define hz HZ +# include <sys/ksynch.h> +# define IPF_LOCK_PL plhi +# include <sys/sema.h> +#undef kmutex_t +typedef struct { + lock_t *l; + int pl; +} kmutex_t; +# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \ + (x)++; MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \ + (x)--; MUTEX_EXIT(&ipf_rw); } +# define MUTEX_ENTER(x) (x)->pl = LOCK((x)->l, IPF_LOCK_PL); +# define KRWLOCK_T kmutex_t +# define READ_ENTER(x) MUTEX_ENTER(x) +# define WRITE_ENTER(x) MUTEX_ENTER(x) +# define RW_UPGRADE(x) ; +# define MUTEX_DOWNGRADE(x) ; +# define RWLOCK_EXIT(x) MUTEX_EXIT(x) +# define MUTEX_EXIT(x) UNLOCK((x)->l, (x)->pl); +# else /* __sgi */ +# define ATOMIC_INC(x) (x)++ +# define ATOMIC_DEC(x) (x)-- +# define MUTEX_ENTER(x) ; +# define READ_ENTER(x) ; +# define WRITE_ENTER(x) ; +# define RW_UPGRADE(x) ; +# define MUTEX_DOWNGRADE(x) ; +# define RWLOCK_EXIT(x) ; +# define MUTEX_EXIT(x) ; +# endif /* __sgi */ +# ifndef linux +# define FREE_MB_T(m) m_freem(m) +# define MTOD(m,t) mtod(m,t) +# define IRCOPY(a,b,c) bcopy((a), (b), (c)) +# define IWCOPY(a,b,c) bcopy((a), (b), (c)) +# endif /* !linux */ +# endif /* SOLARIS */ + +# ifdef sun +# if !SOLARIS +# include <sys/kmem_alloc.h> +# define GETUNIT(n) ifunit((n), IFNAMSIZ) +# endif +# else +# ifndef linux +# define GETUNIT(n) ifunit((n)) +# endif +# endif /* sun */ + +# if defined(sun) && !defined(linux) || defined(__sgi) +# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) +# define SLEEP(id, n) sleep((id), PZERO+1) +# define WAKEUP(id) wakeup(id) +# define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) +# define KFREES(x,s) kmem_free((char *)(x), (s)) +# if !SOLARIS +extern void m_copydata __P((struct mbuf *, int, int, caddr_t)); +extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); +# endif +# ifdef __sgi +# include <sys/kmem.h> +# include <sys/ddi.h> +# define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) +# define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) +# define GET_MINOR(x) getminor(x) +# else +# if !SOLARIS +# define KMALLOC(a,b) (a) = (b)new_kmem_alloc(sizeof(*(a)), \ + KMEM_NOSLEEP) +# define KMALLOCS(a,b,c) (a) = (b)new_kmem_alloc((c), KMEM_NOSLEEP) +# endif /* SOLARIS */ +# endif /* __sgi */ +# endif /* sun && !linux */ +# ifndef GET_MINOR +# define GET_MINOR(x) minor(x) +# endif +# if (BSD >= 199306) || defined(__FreeBSD__) +# include <vm/vm.h> +# if !defined(__FreeBSD__) || (defined (__FreeBSD__) && __FreeBSD__>=3) +# include <vm/vm_extern.h> +# include <sys/proc.h> +extern vm_map_t kmem_map; +# else /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ +# include <vm/vm_kern.h> +# endif /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ +# ifdef M_PFIL +# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFIL, M_NOWAIT) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFIL, M_NOWAIT) +# define KFREE(x) FREE((x), M_PFIL) +# define KFREES(x,s) FREE((x), M_PFIL) +# else +# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, M_NOWAIT) +# define KFREE(x) FREE((x), M_TEMP) +# define KFREES(x,s) FREE((x), M_TEMP) +# endif /* M_PFIL */ +# define UIOMOVE(a,b,c,d) uiomove(a,b,d) +# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) +# define WAKEUP(id) wakeup(id) +# endif /* BSD */ +# if defined(NetBSD) && NetBSD <= 1991011 && NetBSD >= 199407 +# define SPL_NET(x) x = splsoftnet() +# define SPL_X(x) (void) splx(x) +# else +# if !SOLARIS && !defined(linux) +# define SPL_IMP(x) x = splimp() +# define SPL_NET(x) x = splnet() +# define SPL_X(x) (void) splx(x) +# endif +# endif /* NetBSD && NetBSD <= 1991011 && NetBSD >= 199407 */ +# define PANIC(x,y) if (x) panic y +#else /* KERNEL */ +# define SLEEP(x,y) ; +# define WAKEUP(x) ; +# define PANIC(x,y) ; +# define ATOMIC_INC(x) (x)++ +# define ATOMIC_DEC(x) (x)-- +# define MUTEX_ENTER(x) ; +# define READ_ENTER(x) ; +# define WRITE_ENTER(x) ; +# define RW_UPGRADE(x) ; +# define MUTEX_DOWNGRADE(x) ; +# define RWLOCK_EXIT(x) ; +# define MUTEX_EXIT(x) ; +# define SPL_NET(x) ; +# define SPL_IMP(x) ; +# undef SPL_X +# define SPL_X(x) ; +# define KMALLOC(a,b) (a) = (b)malloc(sizeof(*a)) +# define KMALLOCS(a,b,c) (a) = (b)malloc(c) +# define KFREE(x) free(x) +# define KFREES(x,s) free(x) +# define GETUNIT(x) get_unit(x) +# define IRCOPY(a,b,c) bcopy((a), (b), (c)) +# define IWCOPY(a,b,c) bcopy((a), (b), (c)) +#endif /* KERNEL */ + +#if SOLARIS +typedef mblk_t mb_t; +# if SOLARIS2 >= 7 +# ifdef lint +# define ALIGN32(ptr) (ptr ? 0L : 0L) +# define ALIGN16(ptr) (ptr ? 0L : 0L) +# else +# define ALIGN32(ptr) (ptr) +# define ALIGN16(ptr) (ptr) +# endif +# endif +#else +# ifdef linux +# ifndef kernel +typedef struct mb { + struct mb *next; + u_int len; + u_char *data; +} mb_t; +# else +typedef struct sk_buff mb_t; +# endif +# else +typedef struct mbuf mb_t; +# endif +#endif /* SOLARIS */ + +#if defined(linux) || defined(__sgi) +/* + * These #ifdef's are here mainly for linux, but who knows, they may + * not be in other places or maybe one day linux will grow up and some + * of these will turn up there too. + */ +#ifndef ICMP_MINLEN +# define ICMP_MINLEN 8 +#endif +#ifndef ICMP_UNREACH +# define ICMP_UNREACH ICMP_DEST_UNREACH +#endif +#ifndef ICMP_SOURCEQUENCH +# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH +#endif +#ifndef ICMP_TIMXCEED +# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED +#endif +#ifndef ICMP_PARAMPROB +# define ICMP_PARAMPROB ICMP_PARAMETERPROB +#endif +#ifndef ICMP_TSTAMP +# define ICMP_TSTAMP ICMP_TIMESTAMP +#endif +#ifndef ICMP_TSTAMPREPLY +# define ICMP_TSTAMPREPLY ICMP_TIMESTAMPREPLY +#endif +#ifndef ICMP_IREQ +# define ICMP_IREQ ICMP_INFO_REQUEST +#endif +#ifndef ICMP_IREQREPLY +# define ICMP_IREQREPLY ICMP_INFO_REPLY +#endif +#ifndef ICMP_MASKREQ +# define ICMP_MASKREQ ICMP_ADDRESS +#endif +#ifndef ICMP_MASKREPLY +# define ICMP_MASKREPLY ICMP_ADDRESSREPLY +#endif +#ifndef IPVERSION +# define IPVERSION 4 +#endif +#ifndef IPOPT_MINOFF +# define IPOPT_MINOFF 4 +#endif +#ifndef IPOPT_COPIED +# define IPOPT_COPIED(x) ((x)&0x80) +#endif +#ifndef IPOPT_EOL +# define IPOPT_EOL 0 +#endif +#ifndef IPOPT_NOP +# define IPOPT_NOP 1 +#endif +#ifndef IP_MF +# define IP_MF ((u_short)0x2000) +#endif +#ifndef ETHERTYPE_IP +# define ETHERTYPE_IP ((u_short)0x0800) +#endif +#ifndef TH_FIN +# define TH_FIN 0x01 +#endif +#ifndef TH_SYN +# define TH_SYN 0x02 +#endif +#ifndef TH_RST +# define TH_RST 0x04 +#endif +#ifndef TH_PUSH +# define TH_PUSH 0x08 +#endif +#ifndef TH_ACK +# define TH_ACK 0x10 +#endif +#ifndef TH_URG +# define TH_URG 0x20 +#endif +#ifndef IPOPT_EOL +# define IPOPT_EOL 0 +#endif +#ifndef IPOPT_NOP +# define IPOPT_NOP 1 +#endif +#ifndef IPOPT_RR +# define IPOPT_RR 7 +#endif +#ifndef IPOPT_TS +# define IPOPT_TS 68 +#endif +#ifndef IPOPT_SECURITY +# define IPOPT_SECURITY 130 +#endif +#ifndef IPOPT_LSRR +# define IPOPT_LSRR 131 +#endif +#ifndef IPOPT_SATID +# define IPOPT_SATID 136 +#endif +#ifndef IPOPT_SSRR +# define IPOPT_SSRR 137 +#endif +#ifndef IPOPT_SECUR_UNCLASS +# define IPOPT_SECUR_UNCLASS ((u_short)0x0000) +#endif +#ifndef IPOPT_SECUR_CONFID +# define IPOPT_SECUR_CONFID ((u_short)0xf135) +#endif +#ifndef IPOPT_SECUR_EFTO +# define IPOPT_SECUR_EFTO ((u_short)0x789a) +#endif +#ifndef IPOPT_SECUR_MMMM +# define IPOPT_SECUR_MMMM ((u_short)0xbc4d) +#endif +#ifndef IPOPT_SECUR_RESTR +# define IPOPT_SECUR_RESTR ((u_short)0xaf13) +#endif +#ifndef IPOPT_SECUR_SECRET +# define IPOPT_SECUR_SECRET ((u_short)0xd788) +#endif +#ifndef IPOPT_SECUR_TOPSECRET +# define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5) +#endif +#ifndef IPOPT_OLEN +# define IPOPT_OLEN 1 +#endif +#endif /* linux || __sgi */ + +#ifdef linux +#include <linux/in_systm.h> +/* + * TCP States + */ +#define TCPS_CLOSED 0 /* closed */ +#define TCPS_LISTEN 1 /* listening for connection */ +#define TCPS_SYN_SENT 2 /* active, have sent syn */ +#define TCPS_SYN_RECEIVED 3 /* have send and received syn */ +/* states < TCPS_ESTABLISHED are those where connections not established */ +#define TCPS_ESTABLISHED 4 /* established */ +#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ +/* states > TCPS_CLOSE_WAIT are those where user has closed */ +#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ +#define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ +#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ +/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ +#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ +#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ + +/* + * file flags. + */ +#ifdef WRITE +#define FWRITE WRITE +#define FREAD READ +#else +#define FWRITE _IOC_WRITE +#define FREAD _IOC_READ +#endif +/* + * mbuf related problems. + */ +#define mtod(m,t) (t)((m)->data) +#define m_len len +#define m_next next + +#ifdef IP_DF +#undef IP_DF +#endif +#define IP_DF 0x4000 + +typedef struct { + __u16 th_sport; + __u16 th_dport; + __u32 th_seq; + __u32 th_ack; +# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ + defined(vax) + __u8 th_res:4; + __u8 th_off:4; +#else + __u8 th_off:4; + __u8 th_res:4; +#endif + __u8 th_flags; + __u16 th_win; + __u16 th_sum; + __u16 th_urp; +} tcphdr_t; + +typedef struct { + __u16 uh_sport; + __u16 uh_dport; + __u16 uh_ulen; + __u16 uh_sum; +} udphdr_t; + +typedef struct { +# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ + defined(vax) + __u8 ip_hl:4; + __u8 ip_v:4; +# else + __u8 ip_v:4; + __u8 ip_hl:4; +# endif + __u8 ip_tos; + __u16 ip_len; + __u16 ip_id; + __u16 ip_off; + __u8 ip_ttl; + __u8 ip_p; + __u16 ip_sum; + struct in_addr ip_src; + struct in_addr ip_dst; +} ip_t; + +/* + * Structure of an icmp header. + */ +typedef struct icmp { + __u8 icmp_type; /* type of message, see below */ + __u8 icmp_code; /* type sub code */ + __u16 icmp_cksum; /* ones complement cksum of struct */ + union { + __u8 ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ + struct ih_idseq { + __u16 icd_id; + __u16 icd_seq; + } ih_idseq; + int ih_void; + } icmp_hun; +# define icmp_pptr icmp_hun.ih_pptr +# define icmp_gwaddr icmp_hun.ih_gwaddr +# define icmp_id icmp_hun.ih_idseq.icd_id +# define icmp_seq icmp_hun.ih_idseq.icd_seq +# define icmp_void icmp_hun.ih_void + union { + struct id_ts { + n_time its_otime; + n_time its_rtime; + n_time its_ttime; + } id_ts; + struct id_ip { + ip_t idi_ip; + /* options and then 64 bits of data */ + } id_ip; + u_long id_mask; + char id_data[1]; + } icmp_dun; +# define icmp_otime icmp_dun.id_ts.its_otime +# define icmp_rtime icmp_dun.id_ts.its_rtime +# define icmp_ttime icmp_dun.id_ts.its_ttime +# define icmp_ip icmp_dun.id_ip.idi_ip +# define icmp_mask icmp_dun.id_mask +# define icmp_data icmp_dun.id_data +} icmphdr_t; + +# ifndef LINUX_IPOVLY +# define LINUX_IPOVLY +struct ipovly { + caddr_t ih_next, ih_prev; /* for protocol sequence q's */ + u_char ih_x1; /* (unused) */ + u_char ih_pr; /* protocol */ + short ih_len; /* protocol length */ + struct in_addr ih_src; /* source internet address */ + struct in_addr ih_dst; /* destination internet address */ +}; +# endif + +typedef struct { + __u8 ether_dhost[6]; + __u8 ether_shost[6]; + __u16 ether_type; +} ether_header_t; + +typedef struct uio { + int uio_resid; + int uio_rw; + caddr_t uio_buf; +} uio_t; + +# define UIO_READ 0 +# define UIO_WRITE 1 +# define UIOMOVE(a, b, c, d) uiomove(a,b,c,d) + +/* + * For masking struct ifnet onto struct device + */ +# define if_name name + +# ifdef KERNEL +# define GETUNIT(x) dev_get(x) +# define FREE_MB_T(m) kfree_skb(m, FREE_WRITE) +# define uniqtime do_gettimeofday +# undef INT_MAX +# undef UINT_MAX +# undef LONG_MAX +# undef ULONG_MAX +# include <linux/netdevice.h> +# define SPL_X(x) +# define SPL_NET(x) +# define SPL_IMP(x) + +# define bcmp(a,b,c) memcmp(a,b,c) +# define bcopy(a,b,c) memcpy(b,a,c) +# define bzero(a,c) memset(a,0,c) + +# define UNITNAME(n) dev_get((n)) + +# define KMALLOC(a,b) (a) = (b)kmalloc(sizeof(*(a)), GFP_ATOMIC) +# define KMALLOCS(a,b,c) (a) = (b)kmalloc((c), GFP_ATOMIC) +# define KFREE(x) kfree_s((x), sizeof(*(x))) +# define KFREES(x,s) kfree_s((x), (s)) +# define IRCOPY(a,b,c) { \ + error = verify_area(VERIFY_READ, (a) ,(c)); \ + if (!error) \ + memcpy_fromfs((b), (a), (c)); \ + } +# define IWCOPY(a,b,c) { \ + error = verify_area(VERIFY_WRITE, (b), (c)); \ + if (!error) \ + memcpy_tofs((b), (a), (c)); \ + } +# else +# define __KERNEL__ +# undef INT_MAX +# undef UINT_MAX +# undef LONG_MAX +# undef ULONG_MAX +# define s8 __s8 +# define u8 __u8 +# define s16 __s16 +# define u16 __u16 +# define s32 __s32 +# define u32 __u32 +# include <linux/netdevice.h> +# undef __KERNEL__ +# endif +# define ifnet device +#else +typedef struct tcphdr tcphdr_t; +typedef struct udphdr udphdr_t; +typedef struct icmp icmphdr_t; +typedef struct ip ip_t; +typedef struct ether_header ether_header_t; +#endif /* linux */ +typedef struct tcpiphdr tcpiphdr_t; + +#if defined(hpux) || defined(linux) +struct ether_addr { + char ether_addr_octet[6]; +}; +#endif + +/* + * XXX - This is one of those *awful* hacks which nobody likes + */ +#ifdef ultrix +#define A_A +#else +#define A_A & +#endif + +#ifndef ICMP_ROUTERADVERT +# define ICMP_ROUTERADVERT 9 +#endif +#ifndef ICMP_ROUTERSOLICIT +# define ICMP_ROUTERSOLICIT 10 +#endif +/* + * ICMP error replies have an IP header (20 bytes), 8 bytes of ICMP data, + * another IP header and then 64 bits of data, totalling 56. Of course, + * the last 64 bits is dependant on that being available. + */ +#define ICMPERR_ICMPHLEN 8 +#define ICMPERR_IPICMPHLEN (20 + 8) +#define ICMPERR_MINPKTLEN (20 + 8 + 20) +#define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) + +#endif /* _NETINET_IP_COMPAT_H__ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_frag.h b/ecos/packages/net/tcpip/current/include/netinet/ip_frag.h new file mode 100644 index 0000000..c61df9d --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_frag.h @@ -0,0 +1,92 @@ +//========================================================================== +// +// include/netinet/ip_fil.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_frag.h,v 1.9 1999/12/15 05:20:22 kjell Exp $ */ +/* + * Copyright (C) 1993-1998 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + * @(#)ip_frag.h 1.5 3/24/96 + */ + +#ifndef _NETINET_IP_FRAG_H__ +#define _NETINET_IP_FRAG_H__ + +#define IPFT_SIZE 257 + +typedef struct ipfr { + struct ipfr *ipfr_next, *ipfr_prev; + void *ipfr_data; + struct in_addr ipfr_src; + struct in_addr ipfr_dst; + u_short ipfr_id; + u_char ipfr_p; + u_char ipfr_tos; + u_short ipfr_off; + u_short ipfr_ttl; + frentry_t *ipfr_rule; +} ipfr_t; + + +typedef struct ipfrstat { + u_long ifs_exists; /* add & already exists */ + u_long ifs_nomem; + u_long ifs_new; + u_long ifs_hits; + u_long ifs_expire; + u_long ifs_inuse; + struct ipfr **ifs_table; + struct ipfr **ifs_nattab; +} ipfrstat_t; + +#define IPFR_CMPSZ (4 + 4 + 2 + 1 + 1) + +extern int fr_ipfrttl; +extern ipfrstat_t *ipfr_fragstats __P((void)); +extern int ipfr_newfrag __P((ip_t *, fr_info_t *, u_int)); +extern int ipfr_nat_newfrag __P((ip_t *, fr_info_t *, u_int, struct nat *)); +extern nat_t *ipfr_nat_knownfrag __P((ip_t *, fr_info_t *)); +extern frentry_t *ipfr_knownfrag __P((ip_t *, fr_info_t *)); +extern void ipfr_forget __P((void *)); +extern void ipfr_unload __P((void)); + +#if (BSD >= 199306) || SOLARIS || defined(__sgi) +# if defined(SOLARIS2) && (SOLARIS2 < 7) +extern void ipfr_slowtimer __P((void)); +# else +extern void ipfr_slowtimer __P((void *)); +# endif +#else +extern int ipfr_slowtimer __P((void)); +#endif + +#endif /* _NETINET_IP_FIL_H__ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_icmp.h b/ecos/packages/net/tcpip/current/include/netinet/ip_icmp.h new file mode 100644 index 0000000..fd92260 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_icmp.h @@ -0,0 +1,223 @@ +//========================================================================== +// +// include/netinet/ip_icmp.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_icmp.h,v 1.9 1999/01/07 09:20:17 deraadt Exp $ */ +/* $NetBSD: ip_icmp.h,v 1.10 1996/02/13 23:42:28 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IP_ICMP_H_ +#define _NETINET_IP_ICMP_H_ + +/* + * Interface Control Message Protocol Definitions. + * Per RFC 792, September 1981. + */ + +/* + * ICMP Router Advertisement data + */ +struct icmp_ra_addr { + n_long ira_addr; + n_long ira_preference; +} __attribute__ ((aligned(1), packed)); + +/* + * Structure of an icmp header. + */ +struct icmp { + u_int8_t icmp_type; /* type of message, see below */ + u_int8_t icmp_code; /* type sub code */ + u_int16_t icmp_cksum; /* ones complement cksum of struct */ + union { + u_int8_t ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ + struct ih_idseq { + n_short icd_id; + n_short icd_seq; + } ih_idseq; + int32_t ih_void; + + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ + struct ih_pmtu { + n_short ipm_void; + n_short ipm_nextmtu; + } ih_pmtu; + + struct ih_rtradv { + u_int8_t irt_num_addrs; + u_int8_t irt_wpa; + n_short irt_lifetime; + } ih_rtradv; + } icmp_hun; +#define icmp_pptr icmp_hun.ih_pptr +#define icmp_gwaddr icmp_hun.ih_gwaddr +#define icmp_id icmp_hun.ih_idseq.icd_id +#define icmp_seq icmp_hun.ih_idseq.icd_seq +#define icmp_void icmp_hun.ih_void +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu +#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs +#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa +#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime + union { + struct id_ts { + n_time its_otime; + n_time its_rtime; + n_time its_ttime; + } id_ts; + struct id_ip { + struct ip idi_ip; + /* options and then 64 bits of data */ + } id_ip; + u_int32_t id_mask; + int8_t id_data[1]; + } icmp_dun; +#define icmp_otime icmp_dun.id_ts.its_otime +#define icmp_rtime icmp_dun.id_ts.its_rtime +#define icmp_ttime icmp_dun.id_ts.its_ttime +#define icmp_ip icmp_dun.id_ip.idi_ip +#define icmp_mask icmp_dun.id_mask +#define icmp_data icmp_dun.id_data +} __attribute__ ((aligned(1), packed)); + +/* + * For IPv6 transition related ICMP errors. + */ +#define ICMP_V6ADVLENMIN (8 + sizeof(struct ip) + 40) +#define ICMP_V6ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 40) + +/* + * Lower bounds on packet lengths for various types. + * For the error advice packets must first insure that the + * packet is large enought to contain the returned ip header. + * Only then can we do the check to see if 64 bits of packet + * data have been returned, since we need to check the returned + * ip header length. + */ +#define ICMP_MINLEN 8 /* abs minimum */ +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ +#define ICMP_MASKLEN 12 /* address mask */ +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) + /* N.B.: must separately check that ip_hl >= 5 */ + +/* + * Definition of type and code field values. + */ +#define ICMP_ECHOREPLY 0 /* echo reply */ +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* for crypto devs */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_FILTER_PROHIB 13 /* prohibited access */ +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* precedence violat'n*/ +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ +#define ICMP_REDIRECT 5 /* shorter route, codes: */ +#define ICMP_REDIRECT_NET 0 /* for network */ +#define ICMP_REDIRECT_HOST 1 /* for host */ +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ +#define ICMP_ECHO 8 /* echo service */ +#define ICMP_ROUTERADVERT 9 /* router advertisement */ +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ +#define ICMP_TIMXCEED 11 /* time exceeded, code: */ +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ +#define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ +#define ICMP_TSTAMP 13 /* timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ +#define ICMP_IREQ 15 /* information request */ +#define ICMP_IREQREPLY 16 /* information reply */ +#define ICMP_MASKREQ 17 /* address mask request */ +#define ICMP_MASKREPLY 18 /* address mask reply */ + +#define ICMP_MAXTYPE 18 + +#define ICMP_INFOTYPE(type) \ + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) + +#ifdef _KERNEL +void icmp_error __P((struct mbuf *, int, int, n_long, struct ifnet *)); +void icmp_input __P((struct mbuf *, ...)); +void icmp_reflect __P((struct mbuf *)); +void icmp_send __P((struct mbuf *, struct mbuf *)); +int icmp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); +#endif + +#endif // _NETINET_IP_ICMP_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_ip4.h b/ecos/packages/net/tcpip/current/include/netinet/ip_ip4.h new file mode 100644 index 0000000..c5ab059 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_ip4.h @@ -0,0 +1,110 @@ +//========================================================================== +// +// include/netinet/ip_ip4.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_ip4.h,v 1.16 1999/12/09 09:02:59 angelos Exp $ */ + +/* + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr) and + * Niels Provos (provos@physnet.uni-hamburg.de). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis. + * + * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * + * Permission to use, copy, and modify this software without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IP_IP4_H_ +#define _NETINET_IP_IP4_H_ + +/* + * IP-inside-IP processing. + * Not quite all the functionality of RFC-1853, but the main idea is there. + */ + +struct ip4stat +{ + u_int32_t ip4s_ipackets; /* total input packets */ + u_int32_t ip4s_opackets; /* total output packets */ + u_int32_t ip4s_hdrops; /* packet shorter than header shows */ + u_int32_t ip4s_qfull; + u_int64_t ip4s_ibytes; + u_int64_t ip4s_obytes; + u_int32_t ip4s_pdrops; /* packet dropped due to policy */ + u_int32_t ip4s_spoof; /* IP spoofing attempts */ + u_int32_t ip4s_family; /* Protocol family mismatch */ + u_int32_t ip4s_unspec; /* Missing tunnel endpoint address */ +}; + +#define IP4_DEFAULT_TTL 0 +#define IP4_SAME_TTL -1 + +/* + * Names for IP4 sysctl objects + */ +#define IP4CTL_ALLOW 1 /* accept incoming IP4 packets */ +#define IP4CTL_MAXID 2 + +#define IP4CTL_NAMES { \ + { 0, 0 }, \ + { "allow", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL +int ip4_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); + +extern int ip4_allow; +extern struct ip4stat ip4stat; +#endif + +#endif // _NETINET_IP_IP4_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_ipsp.h b/ecos/packages/net/tcpip/current/include/netinet/ip_ipsp.h new file mode 100644 index 0000000..98f1e4f --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_ipsp.h @@ -0,0 +1,600 @@ +//========================================================================== +// +// include/netinet/ipsp.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_ipsp.h,v 1.50 1999/12/08 12:10:25 angelos Exp $ */ + +/* + * The authors of this code are John Ioannidis (ji@tla.org), + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Niklas Hallqvist (niklas@appli.se). + * + * This code was written by John Ioannidis for BSD/OS in Athens, Greece, + * in November 1995. + * + * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, + * by Angelos D. Keromytis. + * + * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis + * and Niels Provos. + * + * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist. + * + * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, + * Angelos D. Keromytis and Niels Provos. + * Copyright (c) 1999 Niklas Hallqvist. + * + * Permission to use, copy, and modify this software without fee + * is hereby granted, provided that this entire notice is included in + * all copies of any software which is or includes a copy or + * modification of this software. + * You may use this code under the GNU public license if you so wish. Please + * contribute changes back to the authors under this freer than GPL license + * so that we may further the use of strong encryption without limitations to + * all. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + */ + +#ifndef _NETINET_IPSP_H_ +#define _NETINET_IPSP_H_ + +/* + * IPSP global definitions. + */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <netinet/in.h> +#ifndef __ECOS +#include <sys/md5k.h> +#endif +#include <netinet/ip_sha1.h> +#include <netinet/ip_rmd160.h> +#include <netinet/ip_blf.h> +#include <netinet/ip_cast.h> +#include <netinet/ip_skipjack.h> + +union sockaddr_union +{ + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; +}; + +/* HMAC key sizes */ +#define MD5HMAC96_KEYSIZE 16 +#define SHA1HMAC96_KEYSIZE 20 +#define RIPEMD160HMAC96_KEYSIZE 20 + +/* IV lengths */ +#define ESP_DES_IVS 8 +#define ESP_3DES_IVS 8 +#define ESP_BLF_IVS 8 +#define ESP_CAST_IVS 8 +#define ESP_SKIPJACK_IVS 8 +#define ESP_MAX_IVS 8 /* Keep updated */ + +/* Block sizes -- it is assumed that they're powers of 2 */ +#define ESP_DES_BLKS 8 +#define ESP_3DES_BLKS 8 +#define ESP_BLF_BLKS 8 +#define ESP_CAST_BLKS 8 +#define ESP_SKIPJACK_BLKS 8 +#define ESP_MAX_BLKS 8 /* Keep updated */ + +#define HMAC_BLOCK_LEN 64 + +#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */ +#define AH_HMAC_RPLENGTH 4 /* 32 bits of replay counter */ +#define AH_HMAC_INITIAL_RPL 1 /* Replay counter initial value */ + +/* HMAC definitions */ +#define HMAC_IPAD_VAL 0x36 +#define HMAC_OPAD_VAL 0x5C +#define HMAC_BLOCK_LEN 64 + +/* Authenticator lengths */ +#define AH_MD5_ALEN 16 +#define AH_SHA1_ALEN 20 +#define AH_RMD160_ALEN 20 +#define AH_ALEN_MAX 20 /* Keep updated */ + +/* Reserved SPI numbers */ +#define SPI_LOCAL_USE 0 +#define SPI_RESERVED_MIN 1 +#define SPI_RESERVED_MAX 255 + +struct sockaddr_encap +{ + u_int8_t sen_len; /* length */ + u_int8_t sen_family; /* PF_KEY */ + u_int16_t sen_type; /* see SENT_* */ + union + { + u_int8_t Data[16]; /* other stuff mapped here */ + + struct /* SENT_IP4 */ + { + struct in_addr Src; + struct in_addr Dst; + u_int16_t Sport; + u_int16_t Dport; + u_int8_t Proto; + u_int8_t Filler[3]; + } Sip4; + + struct /* SENT_IP6 */ + { + struct in6_addr Src; + struct in6_addr Dst; + u_int16_t Sport; + u_int16_t Dport; + u_int8_t Proto; + u_int8_t Filler[3]; + } Sip6; + + struct /* SENT_IPSP */ + { + struct in_addr Dst; + u_int32_t Spi; + u_int8_t Sproto; + u_int8_t Filler[7]; + } Sipsp; + + struct /* SENT_IPSP6 */ + { + struct in6_addr Dst; + u_int32_t Spi; + u_int8_t Sproto; + u_int8_t Filler[7]; + } Sipsp6; + } Sen; +}; + +#define sen_data Sen.Data +#define sen_ip_src Sen.Sip4.Src +#define sen_ip_dst Sen.Sip4.Dst +#define sen_proto Sen.Sip4.Proto +#define sen_sport Sen.Sip4.Sport +#define sen_dport Sen.Sip4.Dport +#define sen_ip6_src Sen.Sip6.Src +#define sen_ip6_dst Sen.Sip6.Dst +#define sen_ip6_proto Sen.Sip6.Proto +#define sen_ip6_sport Sen.Sip6.Sport +#define sen_ip6_dport Sen.Sip6.Dport +#define sen_ipsp_dst Sen.Sipsp.Dst +#define sen_ipsp_spi Sen.Sipsp.Spi +#define sen_ipsp_sproto Sen.Sipsp.Sproto +#define sen_ipsp6_dst Sen.Sipsp6.Dst +#define sen_ipsp6_spi Sen.Sipsp6.Spi +#define sen_ipsp6_sproto Sen.Sipsp6.Sproto + +/* + * The "type" is really part of the address as far as the routing + * system is concerned. By using only one bit in the type field + * for each type, we sort-of make sure that different types of + * encapsulation addresses won't be matched against the wrong type. + * + */ + +#define SENT_IP4 0x0001 /* data is two struct in_addr */ +#define SENT_IPSP 0x0002 /* data as in IP4/6 plus SPI */ +#define SENT_IP6 0x0004 +#define SENT_IPSP6 0x0008 + +/* + * SENT_HDRLEN is the length of the "header" + * SENT_*_LEN are the lengths of various forms of sen_data + * SENT_*_OFF are the offsets in the sen_data array of various fields + */ + +#define SENT_HDRLEN (2 * sizeof(u_int8_t) + sizeof(u_int16_t)) + +#define SENT_IP4_SRCOFF (0) +#define SENT_IP4_DSTOFF (sizeof (struct in_addr)) + +#define SENT_IP6_SRCOFF (0) +#define SENT_IP6_DSTOFF (sizeof (struct in6_addr)) + +#define SENT_IP4_LEN 20 +#define SENT_IPSP_LEN 20 +#define SENT_IP6_LEN 44 +#define SENT_IPSP6_LEN 32 + +#define NOTIFY_SOFT_EXPIRE 0 /* Soft expiration of SA */ +#define NOTIFY_HARD_EXPIRE 1 /* Hard expiration of SA */ +#define NOTIFY_REQUEST_SA 2 /* Establish an SA */ + +#define NOTIFY_SATYPE_CONF 1 /* SA should do encryption */ +#define NOTIFY_SATYPE_AUTH 2 /* SA should do authentication */ +#define NOTIFY_SATYPE_TUNNEL 4 /* SA should use tunneling */ + +/* + * For encapsulation routes are possible not only for the destination + * address but also for the protocol, source and destination ports + * if available + */ + +struct route_enc { + struct rtentry *re_rt; + struct sockaddr_encap re_dst; +}; + +struct flow +{ + struct flow *flow_next; /* Next in flow chain */ + struct flow *flow_prev; /* Previous in flow chain */ + struct tdb *flow_sa; /* Pointer to the SA */ + union sockaddr_union flow_src; /* Source address */ + union sockaddr_union flow_srcmask; /* Source netmask */ + union sockaddr_union flow_dst; /* Destination address */ + union sockaddr_union flow_dstmask; /* Destination netmask */ + u_int8_t flow_proto; /* Transport protocol, if applicable */ + u_int8_t foo[3]; /* Alignment */ +}; + +struct tdb /* tunnel descriptor block */ +{ + struct tdb *tdb_hnext; /* Next in hash chain */ + struct tdb *tdb_onext; /* Next in output */ + struct tdb *tdb_inext; /* Previous in output */ + + struct xformsw *tdb_xform; /* Transformation to use */ + struct enc_xform *tdb_encalgxform; /* Encryption algorithm xform */ + struct auth_hash *tdb_authalgxform; /* Authentication algorithm xform */ + +#define TDBF_UNIQUE 0x00001 /* This should not be used by others */ +#define TDBF_TIMER 0x00002 /* Absolute expiration timer in use */ +#define TDBF_BYTES 0x00004 /* Check the byte counters */ +#define TDBF_ALLOCATIONS 0x00008 /* Check the flows counters */ +#define TDBF_INVALID 0x00010 /* This SPI is not valid yet/anymore */ +#define TDBF_FIRSTUSE 0x00020 /* Expire after first use */ +#define TDBF_HALFIV 0x00040 /* Use half-length IV (ESP old only) */ +#define TDBF_SOFT_TIMER 0x00080 /* Soft expiration */ +#define TDBF_SOFT_BYTES 0x00100 /* Soft expiration */ +#define TDBF_SOFT_ALLOCATIONS 0x00200 /* Soft expiration */ +#define TDBF_SOFT_FIRSTUSE 0x00400 /* Soft expiration */ +#define TDBF_PFS 0x00800 /* Ask for PFS from Key Mgmt. */ +#define TDBF_TUNNELING 0x01000 /* Force IP-IP encapsulation */ + u_int32_t tdb_flags; /* Flags related to this TDB */ + + TAILQ_ENTRY(tdb) tdb_expnext; /* Expiration cluster list link */ + TAILQ_ENTRY(tdb) tdb_explink; /* Expiration ordered list link */ + + u_int32_t tdb_exp_allocations; /* Expire after so many flows */ + u_int32_t tdb_soft_allocations; /* Expiration warning */ + u_int32_t tdb_cur_allocations; /* Total number of allocations */ + + u_int64_t tdb_exp_bytes; /* Expire after so many bytes passed */ + u_int64_t tdb_soft_bytes; /* Expiration warning */ + u_int64_t tdb_cur_bytes; /* Current count of bytes */ + + u_int64_t tdb_exp_timeout; /* When does the SPI expire */ + u_int64_t tdb_soft_timeout; /* Send a soft-expire warning */ + u_int64_t tdb_established; /* When was the SPI established */ + u_int64_t tdb_timeout; /* Next absolute expiration time. */ + + u_int64_t tdb_first_use; /* When was it first used */ + u_int64_t tdb_soft_first_use; /* Soft warning */ + u_int64_t tdb_exp_first_use; /* Expire if tdb_first_use + + * tdb_exp_first_use <= curtime */ + + u_int32_t tdb_spi; /* SPI */ + u_int16_t tdb_amxkeylen; /* AH-old only */ + u_int16_t tdb_ivlen; /* IV length */ + u_int8_t tdb_sproto; /* IPsec protocol */ + u_int8_t tdb_wnd; /* Replay window */ + u_int8_t tdb_satype; /* SA type (RFC2367, PF_KEY) */ + u_int8_t tdb_FILLER; /* Padding */ + + union sockaddr_union tdb_dst; /* Destination address for this SA */ + union sockaddr_union tdb_src; /* Source address for this SA */ + union sockaddr_union tdb_proxy; + + u_int8_t *tdb_key; /* Key material (schedules) */ + u_int8_t *tdb_ictx; /* Authentication contexts */ + u_int8_t *tdb_octx; + u_int8_t *tdb_srcid; /* Source ID for this SA */ + u_int8_t *tdb_dstid; /* Destination ID for this SA */ + u_int8_t *tdb_amxkey; /* AH-old only */ + + union + { + u_int8_t Iv[ESP_3DES_IVS]; /* That's enough space */ + u_int32_t Ivl; /* Make sure this is 4 bytes */ + u_int64_t Ivq; /* Make sure this is 8 bytes! */ + }IV; +#define tdb_iv IV.Iv +#define tdb_ivl IV.Ivl +#define tdb_ivq IV.Ivq + + u_int32_t tdb_rpl; /* Replay counter */ + u_int32_t tdb_bitmap; /* Used for replay sliding window */ + u_int32_t tdb_initial; /* Initial replay value */ + + u_int32_t tdb_epoch; /* Used by the kernfs interface */ + u_int16_t tdb_srcid_len; + u_int16_t tdb_dstid_len; + u_int16_t tdb_srcid_type; + u_int16_t tdb_dstid_type; + + caddr_t tdb_interface; + struct flow *tdb_flow; /* Which flows use this SA */ + + struct tdb *tdb_bind_out; /* Outgoing SA to use */ + TAILQ_HEAD(tdb_bind_head, tdb) tdb_bind_in; + TAILQ_ENTRY(tdb) tdb_bind_in_next; /* Refering Incoming SAs */ + TAILQ_HEAD(tdb_inp_head, inpcb) tdb_inp; +}; + +#ifndef __ECOS +union authctx_old { + MD5_CTX md5ctx; + SHA1_CTX sha1ctx; +}; + +union authctx { + MD5_CTX md5ctx; + SHA1_CTX sha1ctx; + RMD160_CTX rmd160ctx; +}; +#endif + +struct tdb_ident { + u_int32_t spi; + union sockaddr_union dst; + u_int8_t proto; +}; + +struct auth_hash { + int type; + char *name; + u_int16_t keysize; + u_int16_t hashsize; + u_int16_t ctxsize; + void (*Init)(void *); + void (*Update)(void *, u_int8_t *, u_int16_t); + void (*Final)(u_int8_t *, void *); +}; + +struct enc_xform { + int type; + char *name; + u_int16_t blocksize, ivsize; + u_int16_t minkey, maxkey; + u_int32_t ivmask; /* Or all possible modes, zero iv = 1 */ + void (*encrypt)(struct tdb *, u_int8_t *); + void (*decrypt)(struct tdb *, u_int8_t *); + void (*setkey)(u_int8_t **, u_int8_t *, int len); + void (*zerokey)(u_int8_t **); +}; + +struct ipsecinit +{ + u_int8_t *ii_enckey; + u_int8_t *ii_authkey; + u_int16_t ii_enckeylen; + u_int16_t ii_authkeylen; + u_int8_t ii_encalg; + u_int8_t ii_authalg; +}; + +struct xformsw +{ + u_short xf_type; /* Unique ID of xform */ + u_short xf_flags; /* flags (see below) */ + char *xf_name; /* human-readable name */ + int (*xf_attach)(void); /* called at config time */ + int (*xf_init)(struct tdb *, struct xformsw *, struct ipsecinit *); + int (*xf_zeroize)(struct tdb *); /* termination */ + struct mbuf *(*xf_input)(struct mbuf *, struct tdb *, int, int); /* input */ + int (*xf_output)(struct mbuf *, struct tdb *, struct mbuf **, int, int); /* output */ +}; + +/* xform IDs */ +#define XF_IP4 1 /* IP inside IP */ +#define XF_OLD_AH 2 /* RFCs 1828 & 1852 */ +#define XF_OLD_ESP 3 /* RFCs 1829 & 1851 */ +#define XF_NEW_AH 4 /* AH HMAC 96bits */ +#define XF_NEW_ESP 5 /* ESP + auth 96bits + replay counter */ +#define XF_TCPSIGNATURE 6 /* TCP MD5 Signature option, RFC 2358 */ + +/* xform attributes */ +#define XFT_AUTH 0x0001 +#define XFT_CONF 0x0100 + +#define IPSEC_ZEROES_SIZE 256 /* Larger than an IP6 extension hdr. */ +#define IPSEC_KERNFS_BUFSIZE 4096 + +#if BYTE_ORDER == LITTLE_ENDIAN +static __inline u_int64_t +htonq(u_int64_t q) +{ + register u_int32_t u, l; + u = q >> 32; + l = (u_int32_t) q; + + return htonl(u) | ((u_int64_t)htonl(l) << 32); +} + +#define ntohq(_x) htonq(_x) + +#elif BYTE_ORDER == BIG_ENDIAN + +#define htonq(_x) (_x) +#define ntohq(_x) htonq(_x) + +#else +#error "Please fix <machine/endian.h>" +#endif + +#ifdef _KERNEL + +/* + * Protects all tdb lists. + * Must at least be splsoftnet (note: do not use splsoftclock as it is + * special on some architectures, assuming it is always an spl lowering + * operation). + */ +#define spltdb splsoftnet + +extern int encdebug; +extern int ipsec_in_use; +extern u_int8_t hmac_ipad_buffer[64]; +extern u_int8_t hmac_opad_buffer[64]; + +extern TAILQ_HEAD(expclusterlist_head, tdb) expclusterlist; +extern TAILQ_HEAD(explist_head, tdb) explist; +extern struct xformsw xformsw[], *xformswNXFORMSW; + +/* Check if a given tdb has encryption, authentication and/or tunneling */ +#define TDB_ATTRIB(x) (((x)->tdb_encalgxform ? NOTIFY_SATYPE_CONF : 0)| \ + ((x)->tdb_authalgxform ? NOTIFY_SATYPE_AUTH : 0)) + +/* Traverse spi chain and get attributes */ + +#define SPI_CHAIN_ATTRIB(have, TDB_DIR, TDBP) do {\ + int s = spltdb(); \ + struct tdb *tmptdb = (TDBP); \ + \ + (have) = 0; \ + while (tmptdb && tmptdb->tdb_xform) { \ + if (tmptdb == NULL || tmptdb->tdb_flags & TDBF_INVALID) \ + break; \ + (have) |= TDB_ATTRIB(tmptdb); \ + tmptdb = tmptdb->TDB_DIR; \ + } \ + splx(s); \ +} while (0) + +/* Misc. */ +extern char *inet_ntoa4(struct in_addr); + +#ifdef INET6 +extern char *inet6_ntoa4(struct in6_addr); +#endif /* INET6 */ + +extern char *ipsp_address(union sockaddr_union); + +/* TDB management routines */ +extern void tdb_add_inp(struct tdb *tdb, struct inpcb *inp); +extern u_int32_t reserve_spi(u_int32_t, u_int32_t, union sockaddr_union *, + union sockaddr_union *, u_int8_t, int *); +extern struct tdb *gettdb(u_int32_t, union sockaddr_union *, u_int8_t); +extern void puttdb(struct tdb *); +extern void tdb_delete(struct tdb *, int, int); +extern int tdb_init(struct tdb *, u_int16_t, struct ipsecinit *); +extern void tdb_expiration(struct tdb *, int); +/* Flag values for the last argument of tdb_expiration(). */ +#define TDBEXP_EARLY 1 /* The tdb is likely to end up early. */ +#define TDBEXP_TIMEOUT 2 /* Maintain expiration timeout. */ +extern int tdb_walk(int (*)(struct tdb *, void *), void *); +extern void handle_expirations(void *); + +/* Flow management routines */ +extern struct flow *get_flow(void); +extern void put_flow(struct flow *, struct tdb *); +extern void delete_flow(struct flow *, struct tdb *); +extern struct flow *find_flow(union sockaddr_union *, union sockaddr_union *, + union sockaddr_union *, union sockaddr_union *, + u_int8_t, struct tdb *); +extern struct flow *find_global_flow(union sockaddr_union *, + union sockaddr_union *, + union sockaddr_union *, + union sockaddr_union *, u_int8_t); + +/* XF_IP4 */ +extern int ipe4_attach(void); +extern int ipe4_init(struct tdb *, struct xformsw *, struct ipsecinit *); +extern int ipe4_zeroize(struct tdb *); +extern int ipe4_output(struct mbuf *, struct tdb *, struct mbuf **, int, int); +extern void ipe4_input __P((struct mbuf *, ...)); +extern void ip4_input __P((struct mbuf *, ...)); + +/* XF_ETHERIP */ +extern int etherip_output(struct mbuf *, struct tdb *, struct mbuf **, + int, int); +extern void etherip_input __P((struct mbuf *, ...)); + +/* XF_OLD_AH */ +extern int ah_old_attach(void); +extern int ah_old_init(struct tdb *, struct xformsw *, struct ipsecinit *); +extern int ah_old_zeroize(struct tdb *); +extern int ah_old_output(struct mbuf *, struct tdb *, struct mbuf **, + int, int); +extern struct mbuf *ah_old_input(struct mbuf *, struct tdb *, int, int); + +/* XF_NEW_AH */ +extern int ah_new_attach(void); +extern int ah_new_init(struct tdb *, struct xformsw *, struct ipsecinit *); +extern int ah_new_zeroize(struct tdb *); +extern int ah_new_output(struct mbuf *, struct tdb *, struct mbuf **, + int, int); +extern struct mbuf *ah_new_input(struct mbuf *, struct tdb *, int, int); + +/* XF_OLD_ESP */ +extern int esp_old_attach(void); +extern int esp_old_init(struct tdb *, struct xformsw *, struct ipsecinit *); +extern int esp_old_zeroize(struct tdb *); +extern int esp_old_output(struct mbuf *, struct tdb *, struct mbuf **, + int, int); +extern struct mbuf *esp_old_input(struct mbuf *, struct tdb *, int, int); + +/* XF_NEW_ESP */ +extern int esp_new_attach(void); +extern int esp_new_init(struct tdb *, struct xformsw *, struct ipsecinit *); +extern int esp_new_zeroize(struct tdb *); +extern int esp_new_output(struct mbuf *, struct tdb *, struct mbuf **, + int, int); +extern struct mbuf *esp_new_input(struct mbuf *, struct tdb *, int, int); + +/* XF_TCPSIGNATURE */ +extern int tcp_signature_tdb_attach __P((void)); +extern int tcp_signature_tdb_init __P((struct tdb *, struct xformsw *, + struct ipsecinit *)); +extern int tcp_signature_tdb_zeroize __P((struct tdb *)); +extern struct mbuf *tcp_signature_tdb_input __P((struct mbuf *, struct tdb *)); +extern int tcp_signature_tdb_output __P((struct mbuf *, struct tdb *, + struct mbuf **)); + +/* Padding */ +extern caddr_t m_pad(struct mbuf *, int, int); + +/* Replay window */ +extern int checkreplaywindow32(u_int32_t, u_int32_t, u_int32_t *, u_int32_t, + u_int32_t *); + +extern unsigned char ipseczeroes[]; +#endif /* _KERNEL */ +#endif /* _NETINET_IPSP_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_mroute.h b/ecos/packages/net/tcpip/current/include/netinet/ip_mroute.h new file mode 100644 index 0000000..19edf20 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_mroute.h @@ -0,0 +1,269 @@ +//========================================================================== +// +// include/netinet/ip_mroute.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_mroute.h,v 1.5 1999/12/08 06:50:20 itojun Exp $ */ +/* $NetBSD: ip_mroute.h,v 1.10 1996/02/13 23:42:55 christos Exp $ */ + +/* + * Definitions for IP multicast forwarding. + * + * Written by David Waitzman, BBN Labs, August 1988. + * Modified by Steve Deering, Stanford, February 1989. + * Modified by Ajit Thyagarajan, PARC, August 1993. + * Modified by Ajit Thyagarajan, PARC, August 1994. + * + * MROUTING Revision: 1.2 + */ + +#ifndef _NETINET_IP_MROUTE_H_ +#define _NETINET_IP_MROUTE_H_ + +#include <sys/queue.h> + +/* + * Multicast Routing set/getsockopt commands. + */ +#define MRT_INIT 100 /* initialize forwarder */ +#define MRT_DONE 101 /* shut down forwarder */ +#define MRT_ADD_VIF 102 /* create virtual interface */ +#define MRT_DEL_VIF 103 /* delete virtual interface */ +#define MRT_ADD_MFC 104 /* insert forwarding cache entry */ +#define MRT_DEL_MFC 105 /* delete forwarding cache entry */ +#define MRT_VERSION 106 /* get kernel version number */ +#define MRT_ASSERT 107 /* enable PIM assert processing */ + + +/* + * Types and macros for handling bitmaps with one bit per virtual interface. + */ +#define MAXVIFS 32 +typedef u_int32_t vifbitmap_t; +typedef u_int16_t vifi_t; /* type of a vif index */ + +#define VIFM_SET(n, m) ((m) |= (1 << (n))) +#define VIFM_CLR(n, m) ((m) &= ~(1 << (n))) +#define VIFM_ISSET(n, m) ((m) & (1 << (n))) +#define VIFM_SETALL(m) ((m) = 0xffffffff) +#define VIFM_CLRALL(m) ((m) = 0x00000000) +#define VIFM_COPY(mfrom, mto) ((mto) = (mfrom)) +#define VIFM_SAME(m1, m2) ((m1) == (m2)) + +#define VIFF_TUNNEL 0x1 /* vif represents a tunnel end-point */ +#define VIFF_SRCRT 0x2 /* tunnel uses IP src routing */ + +/* + * Argument structure for MRT_ADD_VIF. + * (MRT_DEL_VIF takes a single vifi_t argument.) + */ +struct vifctl { + vifi_t vifc_vifi; /* the index of the vif to be added */ + u_int8_t vifc_flags; /* VIFF_ flags defined below */ + u_int8_t vifc_threshold; /* min ttl required to forward on vif */ + u_int32_t vifc_rate_limit; /* max rate */ + struct in_addr vifc_lcl_addr;/* local interface address */ + struct in_addr vifc_rmt_addr;/* remote address (tunnels only) */ +}; + +/* + * Argument structure for MRT_ADD_MFC and MRT_DEL_MFC. + * (mfcc_tos to be added at a future point) + */ +struct mfcctl { + struct in_addr mfcc_origin; /* ip origin of mcasts */ + struct in_addr mfcc_mcastgrp; /* multicast group associated */ + vifi_t mfcc_parent; /* incoming vif */ + u_int8_t mfcc_ttls[MAXVIFS]; /* forwarding ttls on vifs */ +}; + +/* + * Argument structure used by mrouted to get src-grp pkt counts. + */ +struct sioc_sg_req { + struct in_addr src; + struct in_addr grp; + u_long pktcnt; + u_long bytecnt; + u_long wrong_if; +}; + +/* + * Argument structure used by mrouted to get vif pkt counts. + */ +struct sioc_vif_req { + vifi_t vifi; /* vif number */ + u_long icount; /* input packet count on vif */ + u_long ocount; /* output packet count on vif */ + u_long ibytes; /* input byte count on vif */ + u_long obytes; /* output byte count on vif */ +}; + + +/* + * The kernel's multicast routing statistics. + */ +struct mrtstat { + u_long mrts_mfc_lookups; /* # forw. cache hash table hits */ + u_long mrts_mfc_misses; /* # forw. cache hash table misses */ + u_long mrts_upcalls; /* # calls to mrouted */ + u_long mrts_no_route; /* no route for packet's origin */ + u_long mrts_bad_tunnel; /* malformed tunnel options */ + u_long mrts_cant_tunnel; /* no room for tunnel options */ + u_long mrts_wrong_if; /* arrived on wrong interface */ + u_long mrts_upq_ovflw; /* upcall Q overflow */ + u_long mrts_cache_cleanups; /* # entries with no upcalls */ + u_long mrts_drop_sel; /* pkts dropped selectively */ + u_long mrts_q_overflow; /* pkts dropped - Q overflow */ + u_long mrts_pkt2large; /* pkts dropped - size > BKT SIZE */ + u_long mrts_upq_sockfull; /* upcalls dropped - socket full */ +}; + + +#ifdef _KERNEL + +/* + * Token bucket filter at each vif + */ +struct tbf { + u_int32_t last_pkt_t; /* arr. time of last pkt */ + u_int32_t n_tok; /* no of tokens in bucket */ + u_int32_t q_len; /* length of queue at this vif */ +}; + +/* + * The kernel's virtual-interface structure. + */ +struct vif { + u_int8_t v_flags; /* VIFF_ flags defined above */ + u_int8_t v_threshold; /* min ttl required to forward on vif */ + u_int32_t v_rate_limit; /* max rate */ + struct tbf v_tbf; /* token bucket structure at intf. */ + struct in_addr v_lcl_addr; /* local interface address */ + struct in_addr v_rmt_addr; /* remote address (tunnels only) */ + struct ifnet *v_ifp; /* pointer to interface */ + u_long v_pkt_in; /* # pkts in on interface */ + u_long v_pkt_out; /* # pkts out on interface */ + u_long v_bytes_in; /* # bytes in on interface */ + u_long v_bytes_out; /* # bytes out on interface */ + struct route v_route; /* cached route if this is a tunnel */ +#ifdef RSVP_ISI + int v_rsvp_on; /* # RSVP listening on this vif */ + struct socket *v_rsvpd; /* # RSVPD daemon */ +#endif /* RSVP_ISI */ +}; + +/* + * The kernel's multicast forwarding cache entry structure. + * (A field for the type of service (mfc_tos) is to be added + * at a future point.) + */ +struct mfc { + LIST_ENTRY(mfc) mfc_hash; + struct in_addr mfc_origin; /* ip origin of mcasts */ + struct in_addr mfc_mcastgrp; /* multicast group associated */ + vifi_t mfc_parent; /* incoming vif */ + u_int8_t mfc_ttls[MAXVIFS]; /* forwarding ttls on vifs */ + u_long mfc_pkt_cnt; /* pkt count for src-grp */ + u_long mfc_byte_cnt; /* byte count for src-grp */ + u_long mfc_wrong_if; /* wrong if for src-grp */ + int mfc_expire; /* time to clean entry up */ + struct timeval mfc_last_assert; /* last time I sent an assert */ + struct rtdetq *mfc_stall; /* pkts waiting for route */ +}; + +/* + * Structure used to communicate from kernel to multicast router. + * (Note the convenient similarity to an IP packet.) + */ +struct igmpmsg { + u_int32_t unused1; + u_int32_t unused2; + u_int8_t im_msgtype; /* what type of message */ +#define IGMPMSG_NOCACHE 1 +#define IGMPMSG_WRONGVIF 2 + u_int8_t im_mbz; /* must be zero */ + u_int8_t im_vif; /* vif rec'd on */ + u_int8_t unused3; + struct in_addr im_src, im_dst; +}; + +/* + * Argument structure used for pkt info. while upcall is made. + */ +struct rtdetq { + struct mbuf *m; /* a copy of the packet */ + struct ifnet *ifp; /* interface pkt came in on */ +#ifdef UPCALL_TIMING + struct timeval t; /* timestamp */ +#endif /* UPCALL_TIMING */ + struct rtdetq *next; +}; + +#define MFCTBLSIZ 256 +#define MAX_UPQ 4 /* max. no of pkts in upcall Q */ + +/* + * Token bucket filter code + */ +#define MAX_BKT_SIZE 10000 /* 10K bytes size */ +#define MAXQSIZE 10 /* max. no of pkts in token queue */ + +/* + * Queue structure at each vif + */ +struct pkt_queue { + u_int32_t pkt_len; /* length of packet in queue */ + struct mbuf *pkt_m; /* pointer to packet mbuf */ + struct ip *pkt_ip; /* pointer to ip header */ +}; + +int ip_mrouter_set __P((int, struct socket *, struct mbuf **)); +int ip_mrouter_get __P((int, struct socket *, struct mbuf **)); +int mrt_ioctl __P((u_long, caddr_t)); +int ip_mrouter_done __P((void)); +void reset_vif __P((struct vif *)); +void vif_delete __P((struct ifnet *)); +#ifdef RSVP_ISI +int ip_mforward __P((struct mbuf *, struct ifnet *, struct ip_moptions *)); +int legal_vif_num __P((int)); +int ip_rsvp_vif_init __P((struct socket *, struct mbuf *)); +int ip_rsvp_vif_done __P((struct socket *, struct mbuf *)); +void ip_rsvp_force_done __P((struct socket *)); +#if 0 +void rsvp_input __P((struct mbuf *, struct ifnet *)); +#else +void rsvp_input __P((struct mbuf *, int, int)); +#endif +#else +int ip_mforward __P((struct mbuf *, struct ifnet *)); +#endif +void ipip_input __P((struct mbuf *, ...)); + +#endif /* _KERNEL */ + +#endif // _NETINET_IP_MROUTE_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_nat.h b/ecos/packages/net/tcpip/current/include/netinet/ip_nat.h new file mode 100644 index 0000000..3afc4a9 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_nat.h @@ -0,0 +1,277 @@ +//========================================================================== +// +// include/netinet/ip_nat.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_nat.h,v 1.13 1999/12/15 05:20:22 kjell Exp $ */ +/* + * Copyright (C) 1995-1998 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + * @(#)ip_nat.h 1.5 2/4/96 + */ + +#ifndef _NETINET_IP_NAT_H__ +#define _NETINET_IP_NAT_H__ + +#ifndef SOLARIS +#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#endif + +#if defined(__STDC__) || defined(__GNUC__) +#define SIOCADNAT _IOW('r', 80, struct ipnat) +#define SIOCRMNAT _IOW('r', 81, struct ipnat) +#define SIOCGNATS _IOR('r', 82, struct natstat) +#define SIOCGNATL _IOWR('r', 83, struct natlookup) +#define SIOCGFRST _IOR('r', 84, struct ipfrstat) +#define SIOCGIPST _IOR('r', 85, struct ips_stat) +#define SIOCFLNAT _IOWR('r', 86, int) +#define SIOCCNATL _IOWR('r', 87, int) +#else +#define SIOCADNAT _IOW(r, 80, struct ipnat) +#define SIOCRMNAT _IOW(r, 81, struct ipnat) +#define SIOCGNATS _IOR(r, 82, struct natstat) +#define SIOCGNATL _IOWR(r, 83, struct natlookup) +#define SIOCGFRST _IOR(r, 84, struct ipfrstat) +#define SIOCGIPST _IOR(r, 85, struct ips_stat) +#define SIOCFLNAT _IOWR(r, 86, int) +#define SIOCCNATL _IOWR(r, 87, int) +#endif + +#undef LARGE_NAT /* define this if you're setting up a system to NAT + * LARGE numbers of networks/hosts - i.e. in the + * hundreds or thousands. In such a case, you should + * also change the RDR_SIZE and NAT_SIZE below to more + * appropriate sizes. The figures below were used for + * a setup with 1000-2000 networks to NAT. + */ +#define NAT_SIZE 127 +#define RDR_SIZE 127 +#define NAT_TABLE_SZ 127 +#ifdef LARGE_NAT +#undef NAT_SIZE +#undef RDR_SIZE +#undef NAT_TABLE_SZ +#define NAT_SIZE 2047 +#define RDR_SIZE 2047 +#define NAT_TABLE_SZ 16383 +#endif +#ifndef APR_LABELLEN +#define APR_LABELLEN 16 +#endif +#define NAT_HW_CKSUM 0x80000000 + +#define DEF_NAT_AGE 1200 /* 10 minutes (600 seconds) */ + +typedef struct nat { + u_long nat_age; + int nat_flags; + u_32_t nat_sumd[2]; + u_32_t nat_ipsumd; + void *nat_data; + void *nat_aps; /* proxy session */ + frentry_t *nat_fr; /* filter rule ptr if appropriate */ + struct in_addr nat_inip; + struct in_addr nat_outip; + struct in_addr nat_oip; /* other ip */ + U_QUAD_T nat_pkts; + U_QUAD_T nat_bytes; + u_short nat_oport; /* other port */ + u_short nat_inport; + u_short nat_outport; + u_short nat_use; + u_char nat_tcpstate[2]; + u_char nat_p; /* protocol for NAT */ + struct ipnat *nat_ptr; /* pointer back to the rule */ + struct nat *nat_next; + struct nat *nat_hnext[2]; + struct nat **nat_hstart[2]; + void *nat_ifp; + int nat_dir; +} nat_t; + +typedef struct ipnat { + struct ipnat *in_next; + struct ipnat *in_rnext; + struct ipnat *in_mnext; + void *in_ifp; + void *in_apr; + u_long in_space; + u_int in_use; + u_int in_hits; + struct in_addr in_nextip; + u_short in_pnext; + u_short in_ppip; /* ports per IP */ + u_short in_ippip; /* IP #'s per IP# */ + u_short in_flags; /* From here to in_dport must be reflected */ + u_short in_port[2]; /* correctly in IPN_CMPSIZ */ + struct in_addr in_in[2]; + struct in_addr in_out[2]; + struct in_addr in_src[2]; + int in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */ + char in_ifname[IFNAMSIZ]; + char in_plabel[APR_LABELLEN]; /* proxy label */ + char in_p; /* protocol */ + u_short in_dport; +} ipnat_t; + +#define in_pmin in_port[0] /* Also holds static redir port */ +#define in_pmax in_port[1] +#define in_nip in_nextip.s_addr +#define in_inip in_in[0].s_addr +#define in_inmsk in_in[1].s_addr +#define in_outip in_out[0].s_addr +#define in_outmsk in_out[1].s_addr +#define in_srcip in_src[0].s_addr +#define in_srcmsk in_src[1].s_addr + +#define NAT_OUTBOUND 0 +#define NAT_INBOUND 1 + +#define NAT_MAP 0x01 +#define NAT_REDIRECT 0x02 +#define NAT_BIMAP (NAT_MAP|NAT_REDIRECT) +#define NAT_MAPBLK 0x04 + +#define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */ +#define USABLE_PORTS (65536 - MAPBLK_MINPORT) + +#define IPN_CMPSIZ (sizeof(ipnat_t) - offsetof(ipnat_t, in_flags)) + +typedef struct natlookup { + struct in_addr nl_inip; + struct in_addr nl_outip; + struct in_addr nl_realip; + int nl_flags; + u_short nl_inport; + u_short nl_outport; + u_short nl_realport; +} natlookup_t; + +typedef struct natstat { + u_long ns_mapped[2]; + u_long ns_rules; + u_long ns_added; + u_long ns_expire; + u_long ns_inuse; + u_long ns_logged; + u_long ns_logfail; + nat_t **ns_table[2]; + ipnat_t *ns_list; + void *ns_apslist; + u_int ns_nattab_sz; + u_int ns_rultab_sz; + u_int ns_rdrtab_sz; + nat_t *ns_instances; +} natstat_t; + +#define IPN_ANY 0x00 +#define IPN_TCP 0x01 +#define IPN_UDP 0x02 +#define IPN_TCPUDP (IPN_TCP|IPN_UDP) +#define IPN_DELETE 0x04 +#define IPN_ICMPERR 0x08 +#define IPN_RF (IPN_TCPUDP|IPN_DELETE|IPN_ICMPERR) +#define IPN_AUTOPORTMAP 0x10 +#define IPN_RANGE 0x20 +#define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_RANGE) + + +typedef struct natlog { + struct in_addr nl_origip; + struct in_addr nl_outip; + struct in_addr nl_inip; + u_short nl_origport; + u_short nl_outport; + u_short nl_inport; + u_short nl_type; + int nl_rule; + U_QUAD_T nl_pkts; + U_QUAD_T nl_bytes; +} natlog_t; + + +#define NL_NEWMAP NAT_MAP +#define NL_NEWRDR NAT_REDIRECT +#define NL_EXPIRE 0xffff + +#define NAT_HASH_FN(k,m) (((k) + ((k) >> 12)) % (m)) + +#define LONG_SUM(in) (((in) & 0xffff) + ((in) >> 16)) + +#define CALC_SUMD(s1, s2, sd) { \ + (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ + (s2) = ((s2) & 0xffff) + ((s2) >> 16); \ + /* Do it twice */ \ + (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ + (s2) = ((s2) & 0xffff) + ((s2) >> 16); \ + /* Because ~1 == -2, We really need ~1 == -1 */ \ + if ((s1) > (s2)) (s2)--; \ + (sd) = (s2) - (s1); \ + (sd) = ((sd) & 0xffff) + ((sd) >> 16); } + + +extern u_int ipf_nattable_sz; +extern u_int ipf_natrules_sz; +extern u_int ipf_rdrrules_sz; +extern void ip_natsync __P((void *)); +extern u_long fr_defnatage; +extern u_long fr_defnaticmpage; +extern nat_t **nat_table[2]; +extern nat_t *nat_instances; +extern ipnat_t **nat_rules; +extern ipnat_t **rdr_rules; +extern natstat_t nat_stats; +#if defined(__NetBSD__) || defined(__OpenBSD__) +extern int nat_ioctl __P((caddr_t, u_long, int)); +#else +extern int nat_ioctl __P((caddr_t, int, int)); +#endif +extern void nat_ifdetach __P((struct ifnet *)); +extern int nat_init __P((void)); +extern nat_t *nat_new __P((ipnat_t *, ip_t *, fr_info_t *, u_int, int)); +extern nat_t *nat_outlookup __P((void *, u_int, u_int, struct in_addr, + struct in_addr, u_32_t)); +extern nat_t *nat_inlookup __P((void *, u_int, u_int, struct in_addr, + struct in_addr, u_32_t)); +extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr, + struct in_addr)); +extern nat_t *nat_lookupredir __P((natlookup_t *)); +extern nat_t *nat_icmpinlookup __P((ip_t *, fr_info_t *)); +extern nat_t *nat_icmpin __P((ip_t *, fr_info_t *, u_int *)); + +extern int ip_natout __P((ip_t *, fr_info_t *)); +extern int ip_natin __P((ip_t *, fr_info_t *)); +extern void ip_natunload __P((void)), ip_natexpire __P((void)); +extern void nat_log __P((struct nat *, u_int)); +extern void fix_incksum __P((u_short *, u_32_t, int)); +extern void fix_outcksum __P((u_short *, u_32_t, int)); + +#endif /* _NETINET_IP_NAT_H__ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_proxy.h b/ecos/packages/net/tcpip/current/include/netinet/ip_proxy.h new file mode 100644 index 0000000..c66ac1e --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_proxy.h @@ -0,0 +1,158 @@ +//========================================================================== +// +// include/netinet/ip_proxy.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_proxy.h,v 1.4 1999/12/15 05:20:23 kjell Exp $ */ +/* + * Copyright (C) 1997-1998 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + */ + +#ifndef _NETINET_IP_PROXY_H__ +#define _NETINET_IP_PROXY_H__ + +#ifndef SOLARIS +#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#endif + +#ifndef APR_LABELLEN +#define APR_LABELLEN 16 +#endif +#define AP_SESS_SIZE 53 + +struct nat; +struct ipnat; + +typedef struct ap_tcp { + u_short apt_sport; /* source port */ + u_short apt_dport; /* destination port */ + short apt_sel[2]; /* {seq,ack}{off,min} set selector */ + short apt_seqoff[2]; /* sequence # difference */ + tcp_seq apt_seqmin[2]; /* don't change seq-off until after this */ + short apt_ackoff[2]; /* sequence # difference */ + tcp_seq apt_ackmin[2]; /* don't change seq-off until after this */ + u_char apt_state[2]; /* connection state */ +} ap_tcp_t; + +typedef struct ap_udp { + u_short apu_sport; /* source port */ + u_short apu_dport; /* destination port */ +} ap_udp_t; + +typedef struct ap_session { + struct aproxy *aps_apr; + union { + struct ap_tcp apu_tcp; + struct ap_udp apu_udp; + } aps_un; + u_int aps_flags; + U_QUAD_T aps_bytes; /* bytes sent */ + U_QUAD_T aps_pkts; /* packets sent */ + void *aps_nat; /* pointer back to nat struct */ + void *aps_data; /* private data */ + int aps_p; /* protocol */ + int aps_psiz; /* size of private data */ + struct ap_session *aps_hnext; + struct ap_session *aps_next; +} ap_session_t ; + +#define aps_sport aps_un.apu_tcp.apt_sport +#define aps_dport aps_un.apu_tcp.apt_dport +#define aps_sel aps_un.apu_tcp.apt_sel +#define aps_seqoff aps_un.apu_tcp.apt_seqoff +#define aps_seqmin aps_un.apu_tcp.apt_seqmin +#define aps_state aps_un.apu_tcp.apt_state +#define aps_ackoff aps_un.apu_tcp.apt_ackoff +#define aps_ackmin aps_un.apu_tcp.apt_ackmin + + +typedef struct aproxy { + char apr_label[APR_LABELLEN]; /* Proxy label # */ + u_char apr_p; /* protocol */ + int apr_ref; /* +1 per rule referencing it */ + int apr_flags; + int (* apr_init) __P((void)); + int (* apr_new) __P((fr_info_t *, ip_t *, + ap_session_t *, struct nat *)); + int (* apr_inpkt) __P((fr_info_t *, ip_t *, + ap_session_t *, struct nat *)); + int (* apr_outpkt) __P((fr_info_t *, ip_t *, + ap_session_t *, struct nat *)); +} aproxy_t; + +#define APR_DELETE 1 + + +/* + * Real audio proxy structure and #defines + */ +typedef struct { + int rap_seenpna; + int rap_seenver; + int rap_version; + int rap_eos; /* End Of Startup */ + int rap_gotid; + int rap_gotlen; + int rap_mode; + int rap_sdone; + u_short rap_plport; + u_short rap_prport; + u_short rap_srport; + char rap_svr[19]; + u_32_t rap_sbf; /* flag to indicate which of the 19 bytes have + * been filled + */ + tcp_seq rap_sseq; +} raudio_t; + +#define RA_ID_END 0 +#define RA_ID_UDP 1 +#define RA_ID_ROBUST 7 + +#define RAP_M_UDP 1 +#define RAP_M_ROBUST 2 +#define RAP_M_TCP 4 +#define RAP_M_UDP_ROBUST (RAP_M_UDP|RAP_M_ROBUST) + + +extern ap_session_t *ap_sess_tab[AP_SESS_SIZE]; +extern ap_session_t *ap_sess_list; +extern aproxy_t ap_proxies[]; + +extern int appr_init __P((void)); +extern int appr_ok __P((ip_t *, tcphdr_t *, struct ipnat *)); +extern void appr_free __P((aproxy_t *)); +extern void aps_free __P((ap_session_t *)); +extern int appr_check __P((ip_t *, fr_info_t *, struct nat *)); +extern aproxy_t *appr_match __P((u_int, char *)); + +#endif /* _NETINET_IP_PROXY_H__ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_rmd160.h b/ecos/packages/net/tcpip/current/include/netinet/ip_rmd160.h new file mode 100644 index 0000000..ce94ca1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_rmd160.h @@ -0,0 +1,66 @@ +//========================================================================== +// +// include/netinet/rmd160.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_rmd160.h,v 1.3 1999/02/17 18:10:08 deraadt Exp $ */ + +/* + * FILE: rmd160.h + * + * CONTENTS: Header file for a sample C-implementation of the + * RIPEMD-160 hash-function. + * TARGET: any computer with an ANSI C compiler + * + * AUTHOR: Antoon Bosselaers, ESAT-COSIC + * DATE: 1 March 1996 + * VERSION: 1.0 + * + * Copyright (c) Katholieke Universiteit Leuven + * 1996, All Rights Reserved + * + */ + +#ifndef _NETINET_RMD160_H /* make sure this file is read only once */ +#define _NETINET_RMD160_H + +typedef struct { + u_int32_t state[5]; /* state (ABCDE) */ + u_int32_t length[2]; /* number of bits */ + u_char bbuffer[64]; /* overflow buffer */ + u_int32_t buflen; /* number of chars in bbuffer */ +} RMD160_CTX; + +void RMD160Init __P((RMD160_CTX *context)); +void RMD160Transform __P((u_int32_t state[5], const u_int32_t block[16])); +void RMD160Update __P((RMD160_CTX *context, const u_char *data, u_int nbytes)); +void RMD160Final __P((u_char digest[20], RMD160_CTX *context)); +char *RMD160End __P((RMD160_CTX *, char *)); +char *RMD160File __P((char *, char *)); +char *RMD160Data __P((const u_char *, size_t, char *)); + +#endif /* _NETINET_RMD160_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_sha1.h b/ecos/packages/net/tcpip/current/include/netinet/ip_sha1.h new file mode 100644 index 0000000..02d2fe1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_sha1.h @@ -0,0 +1,52 @@ +//========================================================================== +// +// include/netinet/sha1.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_sha1.h,v 1.5 1999/02/17 18:10:24 deraadt Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid <steve@edmweb.com> + * 100% Public Domain + */ + +#ifndef _NETINET_SHA1_H_ +#define _NETINET_SHA1_H_ + +typedef struct { + u_int32_t state[5]; + u_int32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform __P((u_int32_t state[5], unsigned char buffer[64])); +void SHA1Init __P((SHA1_CTX* context)); +void SHA1Update __P((SHA1_CTX* context, unsigned char* data, unsigned int len)); +void SHA1Final __P((unsigned char digest[20], SHA1_CTX* context)); + +#endif /* _NETINET_SHA1_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_skipjack.h b/ecos/packages/net/tcpip/current/include/netinet/ip_skipjack.h new file mode 100644 index 0000000..3a1ea20 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_skipjack.h @@ -0,0 +1,50 @@ +//========================================================================== +// +// include/netinet/ip_skipjack.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* + * Further optimized test implementation of SKIPJACK algorithm + * Mark Tillotson <markt@chaos.org.uk>, 25 June 98 + * Optimizations suit RISC (lots of registers) machine best. + * + * based on unoptimized implementation of + * Panu Rissanen <bande@lut.fi> 960624 + * + * SKIPJACK and KEA Algorithm Specifications + * Version 2.0 + * 29 May 1998 +*/ + +#ifndef _NETINET_IP_SKIPJACK_H_ +#define _NETINET_IP_SKIPJACK_H_ + +extern void skipjack_forwards __P((u_int8_t *plain, u_int8_t *cipher, u_int8_t **key)); +extern void skipjack_backwards __P((u_int8_t *cipher, u_int8_t *plain, u_int8_t **key)); +extern void subkey_table_gen __P((u_int8_t *key, u_int8_t **key_tables)); + +#endif // _NETINET_IP_SKIPJACK_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_state.h b/ecos/packages/net/tcpip/current/include/netinet/ip_state.h new file mode 100644 index 0000000..8b488f1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_state.h @@ -0,0 +1,194 @@ +//========================================================================== +// +// include/netinet/ip_state.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_state.h,v 1.10 1999/12/15 05:20:23 kjell Exp $ */ +/* + * Copyright (C) 1995-1998 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed + */ + +#ifndef _NETINET_IP_STATE_H__ +#define _NETINET_IP_STATE_H__ + +#define IPSTATE_SIZE 257 +#define IPSTATE_MAX 2048 /* Maximum number of states held */ + +#define PAIRS(s1,d1,s2,d2) ((((s1) == (s2)) && ((d1) == (d2))) ||\ + (((s1) == (d2)) && ((d1) == (s2)))) +#define IPPAIR(s1,d1,s2,d2) PAIRS((s1).s_addr, (d1).s_addr, \ + (s2).s_addr, (d2).s_addr) + + +typedef struct udpstate { + u_short us_sport; + u_short us_dport; +} udpstate_t; + +typedef struct icmpstate { + u_short ics_id; + u_short ics_seq; + u_char ics_type; +} icmpstate_t; + +typedef struct tcpdata { + u_32_t td_end; + u_32_t td_maxend; + u_short td_maxwin; +} tcpdata_t; + +typedef struct tcpstate { + u_short ts_sport; + u_short ts_dport; + tcpdata_t ts_data[2]; + u_char ts_state[2]; +} tcpstate_t; + +typedef struct ipstate { + struct ipstate *is_next; + u_long is_age; + u_int is_pass; + U_QUAD_T is_pkts; + U_QUAD_T is_bytes; + void *is_ifpin; + void *is_ifpout; + frentry_t *is_rule; + struct in_addr is_src; + struct in_addr is_dst; + u_char is_p; /* Protocol */ + u_char is_rout; /* Is rule in/out ? */ + u_32_t is_flags; + u_32_t is_opt; /* packet options set */ + u_32_t is_optmsk; /* " " mask */ + u_short is_sec; /* security options set */ + u_short is_secmsk; /* " " mask */ + u_short is_auth; /* authentication options set */ + u_short is_authmsk; /* " " mask */ + union { + icmpstate_t is_ics; + tcpstate_t is_ts; + udpstate_t is_us; + } is_ps; +} ipstate_t; + +#define is_icmp is_ps.is_ics +#define is_type is_icmp.ics_type +#define is_code is_icmp.ics_code +#define is_tcp is_ps.is_ts +#define is_udp is_ps.is_us +#define is_send is_tcp.ts_data[0].td_end +#define is_dend is_tcp.ts_data[1].td_end +#define is_maxswin is_tcp.ts_data[0].td_maxwin +#define is_maxdwin is_tcp.ts_data[1].td_maxwin +#define is_maxsend is_tcp.ts_data[0].td_maxend +#define is_maxdend is_tcp.ts_data[1].td_maxend +#define is_sport is_tcp.ts_sport +#define is_dport is_tcp.ts_dport +#define is_state is_tcp.ts_state + +#define TH_OPENING (TH_SYN|TH_ACK) +/* + * is_flags: + * Bits 0 - 3 are use as a mask with the current packet's bits to check for + * whether it is short, tcp/udp, a fragment or the presence of IP options. + * Bits 4 - 7 are set from the initial packet and contain what the packet + * anded with bits 0-3 must match. + * Bits 8,9 are used to indicate wildcard source/destination port matching. + */ + + +typedef struct ipslog { + U_QUAD_T isl_pkts; + U_QUAD_T isl_bytes; + struct in_addr isl_src; + struct in_addr isl_dst; + u_char isl_p; + u_char isl_flags; + u_char isl_state[2]; + u_short isl_type; + union { + u_short isl_filler[2]; + u_short isl_ports[2]; + u_short isl_icmp; + } isl_ps; +} ipslog_t; + +#define isl_sport isl_ps.isl_ports[0] +#define isl_dport isl_ps.isl_ports[1] +#define isl_itype isl_ps.isl_icmp + +#define ISL_NEW 0 +#define ISL_EXPIRE 0xffff +#define ISL_FLUSH 0xfffe + + +typedef struct ips_stat { + u_long iss_hits; + u_long iss_miss; + u_long iss_max; + u_long iss_tcp; + u_long iss_udp; + u_long iss_icmp; + u_long iss_nomem; + u_long iss_expire; + u_long iss_fin; + u_long iss_active; + u_long iss_logged; + u_long iss_logfail; + u_long iss_inuse; + ipstate_t **iss_table; +} ips_stat_t; + + +extern u_long fr_tcpidletimeout; +extern u_long fr_tcpclosewait; +extern u_long fr_tcplastack; +extern u_long fr_tcptimeout; +extern u_long fr_tcpclosed; +extern u_long fr_udptimeout; +extern u_long fr_icmptimeout; +extern int fr_stateinit __P((void)); +extern int fr_tcpstate __P((ipstate_t *, fr_info_t *, ip_t *, tcphdr_t *)); +extern ipstate_t *fr_addstate __P((ip_t *, fr_info_t *, u_int)); +extern frentry_t *fr_checkstate __P((ip_t *, fr_info_t *)); +extern void fr_timeoutstate __P((void)); +extern void fr_tcp_age __P((u_long *, u_char *, ip_t *, fr_info_t *, int)); +extern void fr_stateunload __P((void)); +extern void ipstate_log __P((struct ipstate *, u_int)); +#if defined(__NetBSD__) || defined(__OpenBSD__) +extern int fr_state_ioctl __P((caddr_t, u_long, int)); +#else +extern int fr_state_ioctl __P((caddr_t, int, int)); +#endif + +#endif /* _NETINET_IP_STATE_H__ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ip_var.h b/ecos/packages/net/tcpip/current/include/netinet/ip_var.h new file mode 100644 index 0000000..301c1c1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ip_var.h @@ -0,0 +1,239 @@ +//========================================================================== +// +// include/netinet/ip_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_var.h,v 1.12 1999/12/08 06:50:20 itojun Exp $ */ +/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IP_VAR_H_ +#define _NETINET_IP_VAR_H_ + +#include <sys/queue.h> + +/* + * Overlay for ip header used by other protocols (tcp, udp). + */ +struct ipovly { + u_int8_t ih_x1[9]; /* (unused) */ + u_int8_t ih_pr; /* protocol */ + u_int16_t ih_len; /* protocol length */ + struct in_addr ih_src; /* source internet address */ + struct in_addr ih_dst; /* destination internet address */ +}; + +/* + * Ip (reassembly or sequence) queue structures. + * + * XXX -- The following explains why the ipqe_m field is here, for TCP's use: + * We want to avoid doing m_pullup on incoming packets but that + * means avoiding dtom on the tcp reassembly code. That in turn means + * keeping an mbuf pointer in the reassembly queue (since we might + * have a cluster). As a quick hack, the source & destination + * port numbers (which are no longer needed once we've located the + * tcpcb) are overlayed with an mbuf pointer. + */ +LIST_HEAD(ipqehead, ipqent); +struct ipqent { + LIST_ENTRY(ipqent) ipqe_q; + union { + struct ip *_ip; + struct tcphdr *_tcp; + } _ipqe_u1; + union { + u_int8_t _mff; /* for IP fragmentation */ + struct mbuf *_m; /* XXX for TCP; see above */ + } _ipqe_u2; +}; +#define ipqe_ip _ipqe_u1._ip +#define ipqe_tcp _ipqe_u1._tcp +#define ipqe_mff _ipqe_u2._mff +#define ipqe_m _ipqe_u2._m + +/* + * Ip reassembly queue structure. Each fragment + * being reassembled is attached to one of these structures. + * They are timed out after ipq_ttl drops to 0, and may also + * be reclaimed if memory becomes tight. + */ +struct ipq { + LIST_ENTRY(ipq) ipq_q; /* to other reass headers */ + u_int8_t ipq_ttl; /* time for reass q to live */ + u_int8_t ipq_p; /* protocol of this fragment */ + u_int16_t ipq_id; /* sequence id for reassembly */ + struct ipqehead ipq_fragq; /* to ip fragment queue */ + struct in_addr ipq_src, ipq_dst; +}; + +/* + * Structure stored in mbuf in inpcb.ip_options + * and passed to ip_output when ip options are in use. + * The actual length of the options (including ipopt_dst) + * is in m_len. + */ +#define MAX_IPOPTLEN 40 + +struct ipoption { + struct in_addr ipopt_dst; /* first-hop dst if source routed */ + int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ +}; + +/* + * Structure attached to inpcb.ip_moptions and + * passed to ip_output when IP multicast options are in use. + */ +struct ip_moptions { + struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */ + u_int8_t imo_multicast_ttl; /* TTL for outgoing multicasts */ + u_int8_t imo_multicast_loop; /* 1 => hear sends if a member */ + u_int16_t imo_num_memberships; /* no. memberships this socket */ + struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS]; +}; + +struct ipstat { + u_long ips_total; /* total packets received */ + u_long ips_badsum; /* checksum bad */ + u_long ips_tooshort; /* packet too short */ + u_long ips_toosmall; /* not enough data */ + u_long ips_badhlen; /* ip header length < data size */ + u_long ips_badlen; /* ip length < ip header length */ + u_long ips_fragments; /* fragments received */ + u_long ips_fragdropped; /* frags dropped (dups, out of space) */ + u_long ips_fragtimeout; /* fragments timed out */ + u_long ips_forward; /* packets forwarded */ + u_long ips_cantforward; /* packets rcvd for unreachable dest */ + u_long ips_redirectsent; /* packets forwarded on same net */ + u_long ips_noproto; /* unknown or unsupported protocol */ + u_long ips_delivered; /* datagrams delivered to upper level*/ + u_long ips_localout; /* total ip packets generated here */ + u_long ips_odropped; /* lost packets due to nobufs, etc. */ + u_long ips_reassembled; /* total packets reassembled ok */ + u_long ips_fragmented; /* datagrams sucessfully fragmented */ + u_long ips_ofragments; /* output fragments created */ + u_long ips_cantfrag; /* don't fragment flag was set, etc. */ + u_long ips_badoptions; /* error in option processing */ + u_long ips_noroute; /* packets discarded due to no route */ + u_long ips_badvers; /* ip version != 4 */ + u_long ips_rawout; /* total raw ip packets generated */ + u_long ips_badfrags; /* malformed fragments (bad length) */ + u_long ips_rcvmemdrop; /* frags dropped for lack of memory */ + u_long ips_toolong; /* ip length > max ip packet size */ + u_long ips_nogif; /* no match gif found */ +}; + +#ifdef _KERNEL +/* flags passed to ip_output as last parameter */ +#define IP_FORWARDING 0x1 /* most of ip header exists */ +#define IP_RAWOUTPUT 0x2 /* raw ip header exists */ +#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */ +#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ + +#ifdef IPSEC +#define IP_ENCAPSULATED 0x0800 /* encapsulated already */ +#endif + +extern struct ipstat ipstat; +#ifndef RANDOM_IP_ID +extern u_short ip_id; /* ip packet ctr, for ids */ +#endif +LIST_HEAD(ipqhead, ipq) ipq; /* ip reass. queue */ +extern int ip_defttl; /* default IP ttl */ +extern int ipforwarding; /* IPforwarding state */ + +int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); +int ip_dooptions __P((struct mbuf *)); +void ip_drain __P((void)); +void ip_flush __P((void)); +void ip_forward __P((struct mbuf *, int)); +void ip_freef __P((struct ipq *)); +void ip_freemoptions __P((struct ip_moptions *)); +int ip_getmoptions __P((int, struct ip_moptions *, struct mbuf **)); +void ip_init __P((void)); +int ip_mforward __P((struct mbuf *, struct ifnet *)); +int ip_optcopy __P((struct ip *, struct ip *)); +int ip_output __P((struct mbuf *, ...)); +int ip_pcbopts __P((struct mbuf **, struct mbuf *)); +struct ip * + ip_reass __P((struct ipqent *, struct ipq *)); +struct in_ifaddr * + in_iawithaddr __P((struct in_addr, struct mbuf *)); +struct in_ifaddr * + ip_rtaddr __P((struct in_addr)); +u_int16_t + ip_randomid __P((void)); +int ip_setmoptions __P((int, struct ip_moptions **, struct mbuf *)); +void ip_slowtimo __P((void)); +struct mbuf * + ip_srcroute __P((void)); +void ip_stripoptions __P((struct mbuf *, struct mbuf *)); +int ip_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); +void ipintr __P((void)); +void ipv4_input __P((struct mbuf *, ...)); +int rip_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); +void rip_init __P((void)); +void rip_input __P((struct mbuf *, ...)); +int rip_output __P((struct mbuf *, ...)); +int rip_usrreq __P((struct socket *, + int, struct mbuf *, struct mbuf *, struct mbuf *)); +#endif + +#endif // _NETINET_IP_VAR_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/ipl.h b/ecos/packages/net/tcpip/current/include/netinet/ipl.h new file mode 100644 index 0000000..71540b1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/ipl.h @@ -0,0 +1,46 @@ +//========================================================================== +// +// include/netinet/ipl.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ipl.h,v 1.2 1999/12/17 06:17:08 kjell Exp $ */ +/* + * Copyright (C) 1993-1999 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + * + * @(#)ipl.h 1.21 6/5/96 + */ + +#ifndef __IPL_H__ +#define __IPL_H__ + +#define IPL_VERSION "IP Filter: v3.3.5" + +#endif diff --git a/ecos/packages/net/tcpip/current/include/netinet/tcp.h b/ecos/packages/net/tcpip/current/include/netinet/tcp.h new file mode 100644 index 0000000..2c65b81 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/tcp.h @@ -0,0 +1,155 @@ +//========================================================================== +// +// include/netinet/tcp.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp.h,v 1.8 1999/07/06 20:17:52 cmetz Exp $ */ +/* $NetBSD: tcp.h,v 1.8 1995/04/17 05:32:58 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_H_ +#define _NETINET_TCP_H_ + +typedef u_int32_t tcp_seq; + +/* + * TCP header. + * Per RFC 793, September, 1981. + */ +struct tcphdr { + u_int16_t th_sport; /* source port */ + u_int16_t th_dport; /* destination port */ + tcp_seq th_seq; /* sequence number */ + tcp_seq th_ack; /* acknowledgement number */ +#if BYTE_ORDER == LITTLE_ENDIAN + u_int8_t th_x2:4, /* (unused) */ + th_off:4; /* data offset */ +#endif +#if BYTE_ORDER == BIG_ENDIAN + u_int8_t th_off:4, /* data offset */ + th_x2:4; /* (unused) */ +#endif + u_int8_t th_flags; +#define TH_FIN 0x01 +#define TH_SYN 0x02 +#define TH_RST 0x04 +#define TH_PUSH 0x08 +#define TH_ACK 0x10 +#define TH_URG 0x20 + u_int16_t th_win; /* window */ + u_int16_t th_sum; /* checksum */ + u_int16_t th_urp; /* urgent pointer */ +} __attribute__ ((aligned(1), packed)); +#define th_reseqlen th_urp /* TCP data length for + resequencing/reassembly */ + +#define TCPOPT_EOL 0 +#define TCPOPT_NOP 1 +#define TCPOPT_MAXSEG 2 +#define TCPOLEN_MAXSEG 4 +#define TCPOPT_WINDOW 3 +#define TCPOLEN_WINDOW 3 +#define TCPOPT_SACK_PERMITTED 4 /* Experimental */ +#define TCPOLEN_SACK_PERMITTED 2 +#define TCPOPT_SACK 5 /* Experimental */ +#define TCPOLEN_SACK 8 /* 2*sizeof(tcp_seq) */ +#define TCPOPT_TIMESTAMP 8 +#define TCPOLEN_TIMESTAMP 10 +#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ +#define TCPOPT_SIGNATURE 19 +#define TCPOLEN_SIGNATURE 18 + +#define MAX_TCPOPTLEN 40 /* Absolute maximum TCP options len */ + +#define TCPOPT_TSTAMP_HDR \ + (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) + +/* Option definitions */ +#define TCPOPT_SACK_PERMIT_HDR \ +(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_SACK_PERMITTED<<8|TCPOLEN_SACK_PERMITTED) +#define TCPOPT_SACK_HDR (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_SACK<<8) +/* Miscellaneous constants */ +#define MAX_SACK_BLKS 6 /* Max # SACK blocks stored at sender side */ +#define TCP_MAX_SACK 3 /* MAX # SACKs sent in any segment */ + +#define TCP_MAXBURST 4 /* Max # packets after leaving Fast Rxmit */ + +/* + * Default maximum segment size for TCP. + * With an IP MSS of 576, this is 536, + * but 512 is probably more convenient. + * This should be defined as min(512, IP_MSS - sizeof (struct tcpiphdr)). + */ +#define TCP_MSS 512 + +#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ + +#define TCP_MAX_WINSHIFT 14 /* maximum window shift */ + +/* + * User-settable options (used with setsockopt). + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce pkts */ +#define TCP_MAXSEG 0x02 /* set maximum segment size */ +#define TCP_SIGNATURE_ENABLE 0x04 /* enable TCP MD5 signature option */ +#define TCP_SACK_DISABLE 0x300 /* disable SACKs (if enabled by def.) */ + +#endif /* !_NETINET_TCP_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet/tcp_debug.h b/ecos/packages/net/tcpip/current/include/netinet/tcp_debug.h new file mode 100644 index 0000000..44093fe --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/tcp_debug.h @@ -0,0 +1,99 @@ +//========================================================================== +// +// include/netinet/tcp_debug.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_debug.h,v 1.4 1999/01/11 02:01:35 deraadt Exp $ */ +/* $NetBSD: tcp_debug.h,v 1.5 1994/06/29 06:38:38 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_debug.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_DEBUG_H_ +#define _NETINET_TCP_DEBUG_H_ + +#include <netinet6/tcpipv6.h> + +#ifdef TCPDEBUG +struct tcp_debug { + n_time td_time; + short td_act; + short td_ostate; + caddr_t td_tcb; + struct tcpiphdr td_ti; + struct tcpipv6hdr td_ti6; + short td_req; + struct tcpcb td_cb; +}; + +#define TA_INPUT 0 +#define TA_OUTPUT 1 +#define TA_USER 2 +#define TA_RESPOND 3 +#define TA_DROP 4 + +char *tanames[] = + { "input", "output", "user", "respond", "drop" }; + +#define TCP_NDEBUG 100 +struct tcp_debug tcp_debug[TCP_NDEBUG]; +int tcp_debx; +#endif + +#endif // _NETINET_TCP_DEBUG_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/tcp_fsm.h b/ecos/packages/net/tcpip/current/include/netinet/tcp_fsm.h new file mode 100644 index 0000000..5bda84c --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/tcp_fsm.h @@ -0,0 +1,123 @@ +//========================================================================== +// +// include/netinet_tcp_fsm.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_fsm.h,v 1.4 1997/11/08 19:54:12 deraadt Exp $ */ +/* $NetBSD: tcp_fsm.h,v 1.6 1994/10/14 16:01:48 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_fsm.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_FSM_H_ +#define _NETINET_TCP_FSM_H_ + +/* + * TCP FSM state definitions. + * Per RFC793, September, 1981. + */ + +#define TCP_NSTATES 11 + +#define TCPS_CLOSED 0 /* closed */ +#define TCPS_LISTEN 1 /* listening for connection */ +#define TCPS_SYN_SENT 2 /* active, have sent syn */ +#define TCPS_SYN_RECEIVED 3 /* have sent and received syn */ +/* states < TCPS_ESTABLISHED are those where connections not established */ +#define TCPS_ESTABLISHED 4 /* established */ +#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ +/* states > TCPS_CLOSE_WAIT are those where user has closed */ +#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ +#define TCPS_CLOSING 7 /* closed xchd FIN; await ACK */ +#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ +/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ +#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ +#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ + +#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) +#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED) +#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) + +#ifdef TCPOUTFLAGS +/* + * Flags used when sending segments in tcp_output. + * Basic flags (TH_RST,TH_ACK,TH_SYN,TH_FIN) are totally + * determined by state, with the proviso that TH_FIN is sent only + * if all data queued for output is included in the segment. + */ +u_char tcp_outflags[TCP_NSTATES] = { + TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, + TH_ACK, TH_ACK, + TH_FIN|TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, +}; +#endif + +#ifdef KPROF +int tcp_acounts[TCP_NSTATES][PRU_NREQ]; +#endif + +#ifdef TCPSTATES +char *tcpstates[] = { + "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", + "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", + "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", +}; +#endif + +#endif // _NETINET_TCP_FSM_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/tcp_seq.h b/ecos/packages/net/tcpip/current/include/netinet/tcp_seq.h new file mode 100644 index 0000000..462ac53 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/tcp_seq.h @@ -0,0 +1,99 @@ +//========================================================================== +// +// include/netinet_tcp_seq.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_seq.h,v 1.2 1997/02/24 14:06:46 niklas Exp $ */ +/* $NetBSD: tcp_seq.h,v 1.6 1995/03/26 20:32:35 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_seq.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_SEQ_H_ +#define _NETINET_TCP_SEQ_H_ + +/* + * TCP sequence numbers are 32 bit integers operated + * on with modular arithmetic. These macros can be + * used to compare such integers. + */ +#define SEQ_LT(a,b) ((int)((a)-(b)) < 0) +#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) +#define SEQ_GT(a,b) ((int)((a)-(b)) > 0) +#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0) + +/* + * Macros to initialize tcp sequence numbers for + * send and receive from initial send and receive + * sequence numbers. + */ +#define tcp_rcvseqinit(tp) \ + (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1 + +#define tcp_sendseqinit(tp) \ + (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \ + (tp)->iss + +#define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ + +#ifdef _KERNEL +tcp_seq tcp_iss; /* tcp initial send seq # */ +#endif + +#endif // _NETINET_TCP_SEQ_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/tcp_timer.h b/ecos/packages/net/tcpip/current/include/netinet/tcp_timer.h new file mode 100644 index 0000000..920441c --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/tcp_timer.h @@ -0,0 +1,166 @@ +//========================================================================== +// +// include/netinet_tcp_timer.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_timer.h,v 1.3 1997/02/24 14:06:46 niklas Exp $ */ +/* $NetBSD: tcp_timer.h,v 1.6 1995/03/26 20:32:37 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_TIMER_H_ +#define _NETINET_TCP_TIMER_H_ + +/* + * Definitions of the TCP timers. These timers are counted + * down PR_SLOWHZ times a second. + */ +#define TCPT_NTIMERS 4 + +#define TCPT_REXMT 0 /* retransmit */ +#define TCPT_PERSIST 1 /* retransmit persistance */ +#define TCPT_KEEP 2 /* keep alive */ +#define TCPT_2MSL 3 /* 2*msl quiet time timer */ + +/* + * The TCPT_REXMT timer is used to force retransmissions. + * The TCP has the TCPT_REXMT timer set whenever segments + * have been sent for which ACKs are expected but not yet + * received. If an ACK is received which advances tp->snd_una, + * then the retransmit timer is cleared (if there are no more + * outstanding segments) or reset to the base value (if there + * are more ACKs expected). Whenever the retransmit timer goes off, + * we retransmit one unacknowledged segment, and do a backoff + * on the retransmit timer. + * + * The TCPT_PERSIST timer is used to keep window size information + * flowing even if the window goes shut. If all previous transmissions + * have been acknowledged (so that there are no retransmissions in progress), + * and the window is too small to bother sending anything, then we start + * the TCPT_PERSIST timer. When it expires, if the window is nonzero, + * we go to transmit state. Otherwise, at intervals send a single byte + * into the peer's window to force him to update our window information. + * We do this at most as often as TCPT_PERSMIN time intervals, + * but no more frequently than the current estimate of round-trip + * packet time. The TCPT_PERSIST timer is cleared whenever we receive + * a window update from the peer. + * + * The TCPT_KEEP timer is used to keep connections alive. If an + * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time, + * but not yet established, then we drop the connection. Once the connection + * is established, if the connection is idle for TCPTV_KEEP_IDLE time + * (and keepalives have been enabled on the socket), we begin to probe + * the connection. We force the peer to send us a segment by sending: + * <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK> + * This segment is (deliberately) outside the window, and should elicit + * an ack segment in response from the peer. If, despite the TCPT_KEEP + * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE + * amount of time probing, then we drop the connection. + */ + +/* + * Time constants. + */ +#define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */ +#define TCPTV_SRTTBASE 0 /* base roundtrip time; + if 0, no idea yet */ +#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */ + +#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */ +#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */ + +#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */ +#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */ +#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */ +#define TCPTV_KEEPCNT 8 /* max probes before drop */ + +#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */ +#define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) /* max allowable REXMT value */ + +#define TCP_LINGERTIME 120 /* linger at most 2 minutes */ + +#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ + +#ifdef TCPTIMERS +char *tcptimers[] = + { "REXMT", "PERSIST", "KEEP", "2MSL" }; +#endif + +/* + * Force a time value to be in a certain range. + */ +#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \ + (tv) = (value); \ + if ((tv) < (tvmin)) \ + (tv) = (tvmin); \ + else if ((tv) > (tvmax)) \ + (tv) = (tvmax); \ +} + +#ifdef _KERNEL +extern int tcptv_keep_init; +extern int tcp_keepidle; /* time before keepalive probes begin */ +extern int tcp_keepintvl; /* time between keepalive probes */ +extern int tcp_maxidle; /* time to drop after starting probes */ +extern int tcp_ttl; /* time to live for TCP segs */ +extern int tcp_backoff[]; +#endif + +#endif // _NETINET_TCP_TIMER_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/tcp_var.h b/ecos/packages/net/tcpip/current/include/netinet/tcp_var.h new file mode 100644 index 0000000..f495240 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/tcp_var.h @@ -0,0 +1,428 @@ +//========================================================================== +// +// include/netinet_tcp_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_var.h,v 1.25 1999/12/08 06:50:20 itojun Exp $ */ +/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_var.h 8.3 (Berkeley) 4/10/94 + */ + +#ifndef _NETINET_TCP_VAR_H_ +#define _NETINET_TCP_VAR_H_ + +struct sackblk { + tcp_seq start; /* start seq no. of sack block */ + tcp_seq end; /* end seq no. */ +}; + +struct sackhole { + tcp_seq start; /* start seq no. of hole */ + tcp_seq end; /* end seq no. */ + int dups; /* number of dup(s)acks for this hole */ + tcp_seq rxmit; /* next seq. no in hole to be retransmitted */ + struct sackhole *next; /* next in list */ +}; + +/* + * Kernel variables for tcp. + */ + +/* + * Tcp control block, one per tcp; fields: + */ +struct tcpcb { + struct ipqehead segq; /* sequencing queue */ + short t_state; /* state of this connection */ + short t_timer[TCPT_NTIMERS]; /* tcp timers */ + short t_rxtshift; /* log(2) of rexmt exp. backoff */ + short t_rxtcur; /* current retransmit value */ + short t_dupacks; /* consecutive dup acks recd */ + u_short t_maxseg; /* maximum segment size */ + char t_force; /* 1 if forcing out a byte */ + u_short t_flags; +#define TF_ACKNOW 0x0001 /* ack peer immediately */ +#define TF_DELACK 0x0002 /* ack, but try to delay it */ +#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */ +#define TF_NOOPT 0x0008 /* don't use tcp options */ +#define TF_SENTFIN 0x0010 /* have sent FIN */ +#define TF_REQ_SCALE 0x0020 /* have/will request window scaling */ +#define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */ +#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */ +#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */ +#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */ +#define TF_SIGNATURE 0x0400 /* require TCP MD5 signature */ + + struct mbuf *t_template; /* skeletal packet for transmit */ + struct inpcb *t_inpcb; /* back pointer to internet pcb */ +/* + * The following fields are used as in the protocol specification. + * See RFC783, Dec. 1981, page 21. + */ +/* send sequence variables */ + tcp_seq snd_una; /* send unacknowledged */ + tcp_seq snd_nxt; /* send next */ + tcp_seq snd_up; /* send urgent pointer */ + tcp_seq snd_wl1; /* window update seg seq number */ + tcp_seq snd_wl2; /* window update seg ack number */ + tcp_seq iss; /* initial send sequence number */ + u_long snd_wnd; /* send window */ +#ifdef TCP_SACK + int sack_disable; /* disable SACK for this connection */ + int snd_numholes; /* number of holes seen by sender */ + struct sackhole *snd_holes; /* linked list of holes (sorted) */ +#if defined(TCP_SACK) && defined(TCP_FACK) + tcp_seq snd_fack; /* for FACK congestion control */ + u_long snd_awnd; /* snd_nxt - snd_fack + */ + /* retransmitted data */ + int retran_data; /* amount of outstanding retx. data */ +#endif /* TCP_FACK */ +#endif /* TCP_SACK */ +#if defined(TCP_SACK) || defined(TCP_NEWRENO) + tcp_seq snd_last; /* for use in fast recovery */ +#endif +/* receive sequence variables */ + u_long rcv_wnd; /* receive window */ + tcp_seq rcv_nxt; /* receive next */ + tcp_seq rcv_up; /* receive urgent pointer */ + tcp_seq irs; /* initial receive sequence number */ +#ifdef TCP_SACK + tcp_seq rcv_laststart; /* start of last segment recd. */ + tcp_seq rcv_lastend; /* end of ... */ + tcp_seq rcv_lastsack; /* last seq number(+1) sack'd by rcv'r*/ + int rcv_numsacks; /* # distinct sack blks present */ + struct sackblk sackblks[MAX_SACK_BLKS]; /* seq nos. of sack blocks */ +#endif + +/* + * Additional variables for this implementation. + */ +/* receive variables */ + tcp_seq rcv_adv; /* advertised window */ +/* retransmit variables */ + tcp_seq snd_max; /* highest sequence number sent; + * used to recognize retransmits + */ +/* congestion control (for slow start, source quench, retransmit after loss) */ + u_long snd_cwnd; /* congestion-controlled window */ + u_long snd_ssthresh; /* snd_cwnd size threshhold for + * for slow start exponential to + * linear switch + */ + u_int t_maxopd; /* mss plus options */ + +/* + * transmit timing stuff. See below for scale of srtt and rttvar. + * "Variance" is actually smoothed difference. + */ + short t_idle; /* inactivity time */ + short t_rtt; /* round trip time */ + tcp_seq t_rtseq; /* sequence number being timed */ + short t_srtt; /* smoothed round-trip time */ + short t_rttvar; /* variance in round-trip time */ + u_short t_rttmin; /* minimum rtt allowed */ + u_long max_sndwnd; /* largest window peer has offered */ + +/* out-of-band data */ + char t_oobflags; /* have some */ + char t_iobc; /* input character */ +#define TCPOOB_HAVEDATA 0x01 +#define TCPOOB_HADDATA 0x02 + short t_softerror; /* possible error not yet reported */ + +/* RFC 1323 variables */ + u_char snd_scale; /* window scaling for send window */ + u_char rcv_scale; /* window scaling for recv window */ + u_char request_r_scale; /* pending window scaling */ + u_char requested_s_scale; + u_int32_t ts_recent; /* timestamp echo data */ + u_int32_t ts_recent_age; /* when last updated */ + tcp_seq last_ack_sent; + +/* TUBA stuff */ + caddr_t t_tuba_pcb; /* next level down pcb for TCP over z */ + + int pf; +}; + +#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb) +#define sototcpcb(so) (intotcpcb(sotoinpcb(so))) + +/* + * The smoothed round-trip time and estimated variance + * are stored as fixed point numbers scaled by the values below. + * For convenience, these scales are also used in smoothing the average + * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed). + * With these scales, srtt has 3 bits to the right of the binary point, + * and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the + * binary point, and is smoothed with an ALPHA of 0.75. + */ +#define TCP_RTT_SCALE 8 /* multiplier for srtt; 3 bits frac. */ +#define TCP_RTT_SHIFT 3 /* shift for srtt; 3 bits frac. */ +#define TCP_RTTVAR_SCALE 4 /* multiplier for rttvar; 2 bits */ +#define TCP_RTTVAR_SHIFT 2 /* multiplier for rttvar; 2 bits */ + +/* + * The initial retransmission should happen at rtt + 4 * rttvar. + * Because of the way we do the smoothing, srtt and rttvar + * will each average +1/2 tick of bias. When we compute + * the retransmit timer, we want 1/2 tick of rounding and + * 1 extra tick because of +-1/2 tick uncertainty in the + * firing of the timer. The bias will give us exactly the + * 1.5 tick we need. But, because the bias is + * statistical, we have to test that we don't drop below + * the minimum feasible timer (which is 2 ticks). + * This macro assumes that the value of TCP_RTTVAR_SCALE + * is the same as the multiplier for rttvar. + */ +#define TCP_REXMTVAL(tp) \ + ((((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) >> 2) + +/* + * TCP statistics. + * Many of these should be kept per connection, + * but that's inconvenient at the moment. + */ +struct tcpstat { + u_int32_t tcps_connattempt; /* connections initiated */ + u_int32_t tcps_accepts; /* connections accepted */ + u_int32_t tcps_connects; /* connections established */ + u_int32_t tcps_drops; /* connections dropped */ + u_int32_t tcps_conndrops; /* embryonic connections dropped */ + u_int32_t tcps_closed; /* conn. closed (includes drops) */ + u_int32_t tcps_segstimed; /* segs where we tried to get rtt */ + u_int32_t tcps_rttupdated; /* times we succeeded */ + u_int32_t tcps_delack; /* delayed acks sent */ + u_int32_t tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ + u_int32_t tcps_rexmttimeo; /* retransmit timeouts */ + u_int32_t tcps_persisttimeo; /* persist timeouts */ + u_int32_t tcps_persistdrop; /* connections dropped in persist */ + u_int32_t tcps_keeptimeo; /* keepalive timeouts */ + u_int32_t tcps_keepprobe; /* keepalive probes sent */ + u_int32_t tcps_keepdrops; /* connections dropped in keepalive */ + + u_int32_t tcps_sndtotal; /* total packets sent */ + u_int32_t tcps_sndpack; /* data packets sent */ + u_int64_t tcps_sndbyte; /* data bytes sent */ + u_int32_t tcps_sndrexmitpack; /* data packets retransmitted */ + u_int64_t tcps_sndrexmitbyte; /* data bytes retransmitted */ + u_int64_t tcps_sndrexmitfast; /* Fast retransmits */ + u_int32_t tcps_sndacks; /* ack-only packets sent */ + u_int32_t tcps_sndprobe; /* window probes sent */ + u_int32_t tcps_sndurg; /* packets sent with URG only */ + u_int32_t tcps_sndwinup; /* window update-only packets sent */ + u_int32_t tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ + + u_int32_t tcps_rcvtotal; /* total packets received */ + u_int32_t tcps_rcvpack; /* packets received in sequence */ + u_int64_t tcps_rcvbyte; /* bytes received in sequence */ + u_int32_t tcps_rcvbadsum; /* packets received with ccksum errs */ + u_int32_t tcps_rcvbadoff; /* packets received with bad offset */ + u_int32_t tcps_rcvmemdrop; /* packets dropped for lack of memory */ + u_int32_t tcps_rcvnosec; /* packets dropped for lack of ipsec */ + u_int32_t tcps_rcvshort; /* packets received too short */ + u_int32_t tcps_rcvduppack; /* duplicate-only packets received */ + u_int64_t tcps_rcvdupbyte; /* duplicate-only bytes received */ + u_int32_t tcps_rcvpartduppack; /* packets with some duplicate data */ + u_int64_t tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ + u_int32_t tcps_rcvoopack; /* out-of-order packets received */ + u_int64_t tcps_rcvoobyte; /* out-of-order bytes received */ + u_int32_t tcps_rcvpackafterwin; /* packets with data after window */ + u_int64_t tcps_rcvbyteafterwin; /* bytes rcvd after window */ + u_int32_t tcps_rcvafterclose; /* packets rcvd after "close" */ + u_int32_t tcps_rcvwinprobe; /* rcvd window probe packets */ + u_int32_t tcps_rcvdupack; /* rcvd duplicate acks */ + u_int32_t tcps_rcvacktoomuch; /* rcvd acks for unsent data */ + u_int32_t tcps_rcvackpack; /* rcvd ack packets */ + u_int64_t tcps_rcvackbyte; /* bytes acked by rcvd acks */ + u_int32_t tcps_rcvwinupd; /* rcvd window update packets */ + u_int32_t tcps_pawsdrop; /* segments dropped due to PAWS */ + u_int32_t tcps_predack; /* times hdr predict ok for acks */ + u_int32_t tcps_preddat; /* times hdr predict ok for data pkts */ + + u_int32_t tcps_pcbhashmiss; /* input packets missing pcb hash */ + u_int32_t tcps_noport; /* no socket on port */ + u_int32_t tcps_badsyn; /* SYN packet with src==dst rcv'ed */ + + u_int32_t tcps_rcvbadsig; /* rcvd bad/missing TCP signatures */ + u_int64_t tcps_rcvgoodsig; /* rcvd good TCP signatures */ +}; + +/* + * Names for TCP sysctl objects. + */ + +#define TCPCTL_RFC1323 1 /* enable/disable RFC1323 timestamps/scaling */ +#define TCPCTL_KEEPINITTIME 2 /* TCPT_KEEP value */ +#define TCPCTL_KEEPIDLE 3 /* allow tcp_keepidle to be changed */ +#define TCPCTL_KEEPINTVL 4 /* allow tcp_keepintvl to be changed */ +#define TCPCTL_SLOWHZ 5 /* return kernel idea of PR_SLOWHZ */ +#define TCPCTL_BADDYNAMIC 6 /* return bad dynamic port bitmap */ +#define TCPCTL_RECVSPACE 7 /* receive buffer space */ +#define TCPCTL_SENDSPACE 8 /* send buffer space */ +#define TCPCTL_IDENT 9 /* get connection owner */ +#define TCPCTL_SACK 10 /* selective acknowledgement, rfc 2018 */ +#define TCPCTL_MSSDFLT 11 /* Default maximum segment size */ +#define TCPCTL_MAXID 12 + +#define TCPCTL_NAMES { \ + { 0, 0 }, \ + { "rfc1323", CTLTYPE_INT }, \ + { "keepinittime", CTLTYPE_INT }, \ + { "keepidle", CTLTYPE_INT }, \ + { "keepintvl", CTLTYPE_INT }, \ + { "slowhz", CTLTYPE_INT }, \ + { "baddynamic", CTLTYPE_STRUCT }, \ + { "recvspace", CTLTYPE_INT }, \ + { "sendspace", CTLTYPE_INT }, \ + { "ident", CTLTYPE_STRUCT }, \ + { "sack", CTLTYPE_INT }, \ + { "mssdflt", CTLTYPE_INT }, \ +} + +struct tcp_ident_mapping { + struct sockaddr faddr, laddr; + int euid, ruid; +}; + +#ifdef _KERNEL +struct inpcbtable tcbtable; /* head of queue of active tcpcb's */ +struct tcpstat tcpstat; /* tcp statistics */ +u_int32_t tcp_now; /* for RFC 1323 timestamps */ +extern int tcp_do_rfc1323; /* enabled/disabled? */ +extern int tcp_mssdflt; /* default maximum segment size */ +#ifdef TCP_SACK +extern int tcp_do_sack; /* SACK enabled/disabled */ +#endif + +int tcp_attach __P((struct socket *)); +void tcp_canceltimers __P((struct tcpcb *)); +struct tcpcb * + tcp_close __P((struct tcpcb *)); +#if defined(INET6) && !defined(TCP6) +void tcp6_ctlinput __P((int, struct sockaddr *, void *)); +#endif +void *tcp_ctlinput __P((int, struct sockaddr *, void *)); +int tcp_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); +struct tcpcb * + tcp_disconnect __P((struct tcpcb *)); +struct tcpcb * + tcp_drop __P((struct tcpcb *, int)); +void tcp_dooptions __P((struct tcpcb *, u_char *, int, struct tcphdr *, + int *, u_int32_t *, u_int32_t *)); +void tcp_drain __P((void)); +void tcp_fasttimo __P((void)); +void tcp_init __P((void)); +#if defined(INET6) && !defined(TCP6) +int tcp6_input __P((struct mbuf **, int *, int)); +#endif +void tcp_input __P((struct mbuf *, ...)); +int tcp_mss __P((struct tcpcb *, u_int)); +struct tcpcb * + tcp_newtcpcb __P((struct inpcb *)); +void tcp_notify __P((struct inpcb *, int)); +int tcp_output __P((struct tcpcb *)); +void tcp_pulloutofband __P((struct socket *, u_int, struct mbuf *, int)); +void tcp_quench __P((struct inpcb *, int)); +int tcp_reass __P((struct tcpcb *, struct tcphdr *, struct mbuf *, int *)); +void tcp_respond __P((struct tcpcb *, caddr_t, struct mbuf *, tcp_seq, + tcp_seq, int)); +void tcp_setpersist __P((struct tcpcb *)); +void tcp_slowtimo __P((void)); +struct mbuf * + tcp_template __P((struct tcpcb *)); +struct tcpcb * + tcp_timers __P((struct tcpcb *, int)); +void tcp_trace __P((int, int, struct tcpcb *, caddr_t, int, int)); +struct tcpcb * + tcp_usrclosed __P((struct tcpcb *)); +int tcp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); +#if defined(INET6) && !defined(TCP6) +int tcp6_usrreq __P((struct socket *, + int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *)); +#endif +int tcp_usrreq __P((struct socket *, + int, struct mbuf *, struct mbuf *, struct mbuf *)); +void tcp_xmit_timer __P((struct tcpcb *, int)); +void tcpdropoldhalfopen __P((struct tcpcb *, u_int16_t)); +#ifdef TCP_SACK +int tcp_sack_option __P((struct tcpcb *,struct tcphdr *,u_char *,int)); +void tcp_update_sack_list __P((struct tcpcb *tp)); +void tcp_del_sackholes __P((struct tcpcb *, struct tcphdr *)); +void tcp_clean_sackreport __P((struct tcpcb *tp)); +void tcp_sack_adjust __P((struct tcpcb *tp)); +struct sackhole * + tcp_sack_output __P((struct tcpcb *tp)); +int tcp_sack_partialack __P((struct tcpcb *, struct tcphdr *)); +#ifdef DEBUG +void tcp_print_holes __P((struct tcpcb *tp)); +#endif +#endif /* TCP_SACK */ +#if defined(TCP_NEWRENO) || defined(TCP_SACK) +int tcp_newreno __P((struct tcpcb *, struct tcphdr *)); +u_long tcp_seq_subtract __P((u_long, u_long )); +#endif /* TCP_NEWRENO || TCP_SACK */ +#ifdef TCP_SIGNATURE +int tcp_signature_apply __P((caddr_t, caddr_t, unsigned int)); +#endif /* TCP_SIGNATURE */ + +#endif /* _KERNEL */ + +#endif // _NETINET_TCP_VAR_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/tcpip.h b/ecos/packages/net/tcpip/current/include/netinet/tcpip.h new file mode 100644 index 0000000..d8c59b3 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/tcpip.h @@ -0,0 +1,95 @@ +//========================================================================== +// +// include/netinet/tcpip.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcpip.h,v 1.4 1997/08/26 20:02:35 deraadt Exp $ */ +/* $NetBSD: tcpip.h,v 1.6 1995/11/21 01:07:44 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcpip.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCPIP_H_ +#define _NETINET_TCPIP_H_ + +/* + * Tcp+ip header, after ip options removed. + */ +struct tcpiphdr { + /* overlaid ip structure */ + struct ipovly ti_i __attribute__ ((aligned(1), packed)); + struct tcphdr ti_t; /* tcp header */ +}; +#define ti_x1 ti_i.ih_x1 +#define ti_pr ti_i.ih_pr +#define ti_len ti_i.ih_len +#define ti_src ti_i.ih_src +#define ti_dst ti_i.ih_dst +#define ti_sport ti_t.th_sport +#define ti_dport ti_t.th_dport +#define ti_seq ti_t.th_seq +#define ti_ack ti_t.th_ack +#define ti_x2 ti_t.th_x2 +#define ti_off ti_t.th_off +#define ti_flags ti_t.th_flags +#define ti_win ti_t.th_win +#define ti_sum ti_t.th_sum +#define ti_urp ti_t.th_urp + +#endif // _NETINET_TCPIP_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/udp.h b/ecos/packages/net/tcpip/current/include/netinet/udp.h new file mode 100644 index 0000000..644497d --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/udp.h @@ -0,0 +1,82 @@ +//========================================================================== +// +// include/netinet/udp.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: udp.h,v 1.3 1997/02/24 14:06:47 niklas Exp $ */ +/* $NetBSD: udp.h,v 1.6 1995/04/13 06:37:10 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_UDP_H_ +#define _NETINET_UDP_H_ + +/* + * Udp protocol header. + * Per RFC 768, September, 1981. + */ +struct udphdr { + u_int16_t uh_sport; /* source port */ + u_int16_t uh_dport; /* destination port */ + u_int16_t uh_ulen; /* udp length */ + u_int16_t uh_sum; /* udp checksum */ +} __attribute__ ((aligned(1), packed)); + +#endif // _NETINET_UDP_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet/udp_var.h b/ecos/packages/net/tcpip/current/include/netinet/udp_var.h new file mode 100644 index 0000000..62949db --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet/udp_var.h @@ -0,0 +1,141 @@ +//========================================================================== +// +// include/netinet/udp_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: udp_var.h,v 1.9 1999/12/08 06:50:20 itojun Exp $ */ +/* $NetBSD: udp_var.h,v 1.12 1996/02/13 23:44:41 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_UDP_VAR_H_ +#define _NETINET_UDP_VAR_H_ + +/* + * UDP kernel structures and variables. + */ +struct udpiphdr { + /* overlaid ip structure */ + struct ipovly ui_i __attribute__ ((aligned(1), packed)); + struct udphdr ui_u; /* udp header */ +}; +#define ui_x1 ui_i.ih_x1 +#define ui_pr ui_i.ih_pr +#define ui_len ui_i.ih_len +#define ui_src ui_i.ih_src +#define ui_dst ui_i.ih_dst +#define ui_sport ui_u.uh_sport +#define ui_dport ui_u.uh_dport +#define ui_ulen ui_u.uh_ulen +#define ui_sum ui_u.uh_sum + +struct udpstat { + /* input statistics: */ + u_long udps_ipackets; /* total input packets */ + u_long udps_hdrops; /* packet shorter than header */ + u_long udps_badsum; /* checksum error */ + u_long udps_nosum; /* no checksum */ + u_long udps_badlen; /* data length larger than packet */ + u_long udps_noport; /* no socket on port */ + u_long udps_noportbcast; /* of above, arrived as broadcast */ + u_long udps_nosec; /* dropped for lack of ipsec */ + u_long udps_fullsock; /* not delivered, input socket full */ + u_long udps_pcbhashmiss; /* input packets missing pcb hash */ + /* output statistics: */ + u_long udps_opackets; /* total output packets */ +}; + +/* + * Names for UDP sysctl objects + */ +#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ +#define UDPCTL_BADDYNAMIC 2 /* return bad dynamic port bitmap */ +#define UDPCTL_RECVSPACE 3 /* receive buffer space */ +#define UDPCTL_SENDSPACE 4 /* send buffer space */ +#define UDPCTL_MAXID 5 + +#define UDPCTL_NAMES { \ + { 0, 0 }, \ + { "checksum", CTLTYPE_INT }, \ + { "baddynamic", CTLTYPE_STRUCT }, \ + { "recvspace", CTLTYPE_INT }, \ + { "sendspace", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL +struct inpcbtable udbtable; +struct udpstat udpstat; + +#if defined(INET6) && !defined(TCP6) +void udp6_ctlinput __P((int, struct sockaddr *, void *)); +int udp6_input __P((struct mbuf **, int *, int)); +int udp6_usrreq __P((struct socket *, + int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *)); +#endif +void *udp_ctlinput __P((int, struct sockaddr *, void *)); +void udp_init __P((void)); +void udp_input __P((struct mbuf *, ...)); +int udp_output __P((struct mbuf *, ...)); +int udp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); +int udp_usrreq __P((struct socket *, + int, struct mbuf *, struct mbuf *, struct mbuf *)); +#endif + +#endif // _NETINET_UDP_VAR_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/debug.h b/ecos/packages/net/tcpip/current/include/netinet6/debug.h new file mode 100644 index 0000000..6ea57f7 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/debug.h @@ -0,0 +1,244 @@ +//========================================================================== +// +// include/netinet6_sys_debug.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_SYS_DEBUG_H +#define _NETINET6_SYS_DEBUG_H 1 + +#ifdef DEBUG_NRL +#include <sys/osdep.h> +#else /* DEBUG_NRL */ +#if __OpenBSD__ +#include <netinet6/osdep.h> +#else /* __OpenBSD__ */ +#include <sys/osdep.h> +#endif /* __OpenBSD__ */ +#endif /* DEBUG_NRL */ + +/* Non-ANSI compilers don't stand a chance. You PROBABLY need GNU C. */ +#ifndef __STDC__ +#error An ANSI C compiler is required here. +#endif /* __STDC__ */ + +#ifndef _KERN_DEBUG_GENERIC_C +extern int debug_level; +#endif /* _KERN_DEBUG_GENERIC_DEBUG_C */ + +/* Debugging levels */ + +#define __DEBUG_LEVEL_ALL (INT_MAX-1) /* Report all messages. */ +#define __DEBUG_LEVEL_NONE 0 /* Report no messages. */ + +#define __DEBUG_LEVEL_CRITICAL 3 +#define __DEBUG_LEVEL_ERROR 7 +#define __DEBUG_LEVEL_MAJOREVENT 10 +#define __DEBUG_LEVEL_EVENT 15 +#define __DEBUG_LEVEL_GROSSEVENT 20 +#define __DEBUG_LEVEL_FINISHED 1000 + +/* Compatibility macros */ + +#define __DEBUG_LEVEL_MAJOR_EVENT __DEBUG_LEVEL_MAJOREVENT +#define __DEBUG_LEVEL_GROSS_EVENT __DEBUG_LEVEL_GROSSEVENT +#define __DEBUG_LEVEL_IDL_CRITICAL __DEBUG_LEVEL_CRITICAL +#define __DEBUG_LEVEL_IDL_ERROR __DEBUG_LEVEL_ERROR +#define __DEBUG_LEVEL_IDL_MAJOR_EVENT __DEBUG_LEVEL_MAJOREVENT +#define __DEBUG_LEVEL_IDL_EVENT __DEBUG_LEVEL_EVENT +#define __DEBUG_LEVEL_IDL_GROSS_EVENT __DEBUG_LEVEL_GROSSEVENT +#define __DEBUG_LEVEL_IDL_FINISHED __DEBUG_LEVEL_FINISHED + +/* Unless you have optimization turned off and your compiler is drain bamaged, + this will turn in to a syntactically inert no-op - cmetz */ +#define __DEBUG_NOP do { } while (0) + +#ifdef DEBUG_NRL +/* + * Make sure argument for DPRINTF is in parentheses. + * + * For both DPRINTF and DDO, and attempt was made to make both macros + * be usable as normal C statments. There is a small amount of compiler + * trickery (if-else clauses with effectively null statements), which may + * cause a few compilers to complain. + */ + +#ifndef __GENERIC_DEBUG_LEVEL +#define __GENERIC_DEBUG_LEVEL debug_level +#endif /* __GENERIC_DEBUG_LEVEL */ + +/* + * DPRINTF() is a general printf statement. The "arg" is literally what + * would follow the function name printf, which means it has to be in + * parenthesis. Unlimited arguments can be used this way. + * + * EXAMPLE: + * DPRINTF(IDL_MAJOR_EVENT,("Hello, world. IP version %d.\n",vers)); + */ +#undef DPRINTF +#define DPRINTF(lev,arg) \ + if (__DEBUG_LEVEL_ ## lev <= __GENERIC_DEBUG_LEVEL) { \ + printf arg; \ + } else \ + __DEBUG_NOP + +/* + * DDO() executes a series of statements at a certain debug level. The + * "stmt" argument is a statement in the sense of a "statement list" in a + * C grammar. "stmt" does not have to end with a semicolon. + * + * EXAMPLE: + * DDO(IDL_CRITICAL,dump_ipv6(header), dump_inpcb(inp)); + */ +#undef DDO +#define DDO(lev,stmt) \ + if (__DEBUG_LEVEL_ ## lev <= __GENERIC_DEBUG_LEVEL) { \ + stmt ; \ + } else \ + __DEBUG_NOP + +/* + * DP() is a shortcut for DPRINTF(). Basically: + * + * DP(lev, var, fmt) == DPRINTF(IDL_lev, ("var = %fmt\n", var)) + * + * It is handy for printing single variables without a lot of typing. + * + * EXAMPLE: + * + * DP(CRITICAL,length,d); + * same as DPRINTF(IDL_CRITICAL, ("length = %d\n", length)) + */ +#undef DP +#define DP(lev, var, fmt) \ + DPRINTF(lev, (#var " = %" #fmt "\n", var)) + +#undef DEBUG_STATUS +#if defined(__GNUC__) && (__GNUC__ >= 2) +#define DEBUG_STATUS debug_status(__FILE__ ":" __FUNCTION__, __LINE__, __builtin_return_address(0)) +#else /* defined(__GNUC__) && (__GNUC__ >= 2) */ +#define DEBUG_STATUS debug_status(__FILE__, __LINE__, (void *)0) +#endif /* defined(__GNUC__) && (__GNUC__ >= 2) */ + +/* Call as: + + DS(); +*/ +#undef DS +#define DS() DPRINTF(IDL_CRITICAL, ("%s\n", DEBUG_STATUS)) +#else /* DEBUG_NRL */ +#undef DPRINTF +#define DPRINTF(lev,arg) __DEBUG_NOP +#undef DDO +#define DDO(lev, stmt) __DEBUG_NOP +#undef DP +#define DP(x, y, z) __DEBUG_NOP +#undef DS +#define DS() __DEBUG_NOP +#endif /* DEBUG_NRL */ + +#ifdef DEBUG_MALLOC +void *debug_malloc_malloc(unsigned int n, char *creator); +void debug_malloc_free(void *p); +void debug_malloc_dump(void); +void debug_malloc_flush(void); +#endif /* DEBUG_MALLOC */ + +#ifdef DEBUG_NRL +char *debug_status(char *filefunction, unsigned int line, void *returnaddress); +void dump_buf_small(void *, int); +void debug_dump_buf(void *, int); +void dump_packet(void *buf, int len); + +struct dump_flags { + int val; + char *name; +}; +void dump_flags(struct dump_flags *, int); + +struct sockaddr; +void dump_sockaddr(struct sockaddr *); +void dump_smart_sockaddr(void *); + +#ifdef __linux__ +struct sk_buff; +void dump_skb(struct sk_buff *); +#endif /* __linux__ */ + +#ifdef OSDEP_BSD +struct sockaddr_dl; +void dump_sockaddr_dl(struct sockaddr_dl *); +struct mbuf; +void dump_mbuf_flags(struct mbuf *); +void dump_mbuf_hdr(struct mbuf *); +void dump_mbuf(struct mbuf *); +void dump_mchain_hdr(struct mbuf *); +void dump_mchain(struct mbuf *); +void dump_mbuf_tcpdump(struct mbuf *); +struct ifaddr; +void dump_ifa(struct ifaddr *); +struct ifnet; +void dump_ifp(struct ifnet *); +struct route; +void dump_route(struct route *); +struct rtentry; +void dump_rtentry(struct rtentry *); +struct inpcb; +void dump_inpcb(struct inpcb *); +#if __NetBSD__ || __OpenBSD__ +struct inpcbtable; +void dump_inpcbs(struct inpcbtable *); +#else /* __NetBSD__ || __OpenBSD__ */ +void dump_inpcbs(struct inpcb *); +#endif /* __NetBSD__ || __OpenBSD__ */ +#endif /* OSDEP_BSD */ + +#ifdef INET +struct in_addr; +void dump_in_addr(struct in_addr *); +struct sockaddr_in; +void dump_sockaddr_in(struct sockaddr_in *); +#endif /* INET */ + +#ifdef INET6 +#include <netinet6/debug_inet6.h> +#endif /* INET6 */ +#endif /* DEBUG_NRL */ + +#endif /* _NETINET6_SYS_DEBUG_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/debug_inet6.h b/ecos/packages/net/tcpip/current/include/netinet6/debug_inet6.h new file mode 100644 index 0000000..6e6dc95 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/debug_inet6.h @@ -0,0 +1,55 @@ +//========================================================================== +// +// include/netinet6_debug_inet6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% copyright-nrl-95 +This software is Copyright 1995-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_DEBUG_INET6_H +#define _NETINET6_DEBUG_INET6_H 1 + +struct in6_addr; +void dump_in6_addr(struct in6_addr *); +struct sockaddr_in6; +void dump_sockaddr_in6(struct sockaddr_in6 *); +struct ipv6; +void dump_ipv6(struct ipv6 *ipv6); +struct ipv6_icmp; +void dump_ipv6_icmp(struct ipv6_icmp *icp); +struct discq; +void dump_discq(struct discq *dq); +#endif /* _NETINET6_DEBUG_INET6_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/icmp6.h b/ecos/packages/net/tcpip/current/include/netinet6/icmp6.h new file mode 100644 index 0000000..bf3076d --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/icmp6.h @@ -0,0 +1,680 @@ +//========================================================================== +// +// include/netinet6_icmpv6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: icmp6.h,v 1.2 1999/12/10 10:04:27 angelos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET6_ICMPV6_H_ +#define _NETINET6_ICMPV6_H_ + +#define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr) + - sizeof(struct icmp6_hdr) */ + +struct icmp6_hdr { + u_int8_t icmp6_type; /* type field */ + u_int8_t icmp6_code; /* code field */ + u_int16_t icmp6_cksum; /* checksum field */ + union { + u_int32_t icmp6_un_data32[1]; /* type-specific field */ + u_int16_t icmp6_un_data16[2]; /* type-specific field */ + u_int8_t icmp6_un_data8[4]; /* type-specific field */ + } icmp6_dataun; +}; + +#define icmp6_data32 icmp6_dataun.icmp6_un_data32 +#define icmp6_data16 icmp6_dataun.icmp6_un_data16 +#define icmp6_data8 icmp6_dataun.icmp6_un_data8 +#define icmp6_pptr icmp6_data32[0] /* parameter prob */ +#define icmp6_mtu icmp6_data32[0] /* packet too big */ +#define icmp6_id icmp6_data16[0] /* echo request/reply */ +#define icmp6_seq icmp6_data16[1] /* echo request/reply */ +#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */ + +#define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */ +#define ICMP6_PACKET_TOO_BIG 2 /* packet too big */ +#define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */ +#define ICMP6_PARAM_PROB 4 /* ip6 header bad */ + +#define ICMP6_ECHO_REQUEST 128 /* echo service */ +#define ICMP6_ECHO_REPLY 129 /* echo reply */ +#define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */ +#define MLD6_LISTENER_QUERY 130 /* multicast listener query */ +#define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */ +#define MLD6_LISTENER_REPORT 131 /* multicast listener report */ +#define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */ +#define MLD6_LISTENER_DONE 132 /* multicast listener done */ + +#define ND_ROUTER_SOLICIT 133 /* router solicitation */ +#define ND_ROUTER_ADVERT 134 /* router advertisment */ +#define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */ +#define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisment */ +#define ND_REDIRECT 137 /* redirect */ + +#define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */ + +#define ICMP6_WRUREQUEST 139 /* who are you request */ +#define ICMP6_WRUREPLY 140 /* who are you reply */ +#define ICMP6_FQDN_QUERY 139 /* FQDN query */ +#define ICMP6_FQDN_REPLY 140 /* FQDN reply */ +#define ICMP6_NI_QUERY 139 /* node information request */ +#define ICMP6_NI_REPLY 140 /* node information reply */ + +/* The definitions below are experimental. TBA */ +#define MLD6_MTRACE_RESP 141 /* mtrace response(to sender) */ +#define MLD6_MTRACE 142 /* mtrace messages */ + +#define ICMP6_MAXTYPE 142 + +#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */ +#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */ +#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */ +#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ +#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ +#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */ + +#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */ +#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */ + +#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */ +#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */ +#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */ + +#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */ + +#define ICMP6_NI_SUCESS 0 /* node information successful reply */ +#define ICMP6_NI_REFUSED 1 /* node information request is refused */ +#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */ + +#define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */ +#define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */ +#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */ + +/* Used in kernel only */ +#define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */ +#define ND_REDIRECT_ROUTER 1 /* redirect to a better router */ + +/* + * Multicast Listener Discovery + */ +struct mld6_hdr { + struct icmp6_hdr mld6_hdr; + struct in6_addr mld6_addr; /* multicast address */ +}; + +#define mld6_type mld6_hdr.icmp6_type +#define mld6_code mld6_hdr.icmp6_code +#define mld6_cksum mld6_hdr.icmp6_cksum +#define mld6_maxdelay mld6_hdr.icmp6_data16[0] +#define mld6_reserved mld6_hdr.icmp6_data16[1] + +/* + * Neighbor Discovery + */ + +struct nd_router_solicit { /* router solicitation */ + struct icmp6_hdr nd_rs_hdr; + /* could be followed by options */ +}; + +#define nd_rs_type nd_rs_hdr.icmp6_type +#define nd_rs_code nd_rs_hdr.icmp6_code +#define nd_rs_cksum nd_rs_hdr.icmp6_cksum +#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0] + +struct nd_router_advert { /* router advertisement */ + struct icmp6_hdr nd_ra_hdr; + u_int32_t nd_ra_reachable; /* reachable time */ + u_int32_t nd_ra_retransmit; /* retransmit timer */ + /* could be followed by options */ +}; + +#define nd_ra_type nd_ra_hdr.icmp6_type +#define nd_ra_code nd_ra_hdr.icmp6_code +#define nd_ra_cksum nd_ra_hdr.icmp6_cksum +#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0] +#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1] +#define ND_RA_FLAG_MANAGED 0x80 +#define ND_RA_FLAG_OTHER 0x40 +#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1] + +struct nd_neighbor_solicit { /* neighbor solicitation */ + struct icmp6_hdr nd_ns_hdr; + struct in6_addr nd_ns_target; /*target address */ + /* could be followed by options */ +}; + +#define nd_ns_type nd_ns_hdr.icmp6_type +#define nd_ns_code nd_ns_hdr.icmp6_code +#define nd_ns_cksum nd_ns_hdr.icmp6_cksum +#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0] + +struct nd_neighbor_advert { /* neighbor advertisement */ + struct icmp6_hdr nd_na_hdr; + struct in6_addr nd_na_target; /* target address */ + /* could be followed by options */ +}; + +#define nd_na_type nd_na_hdr.icmp6_type +#define nd_na_code nd_na_hdr.icmp6_code +#define nd_na_cksum nd_na_hdr.icmp6_cksum +#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0] +#if BYTE_ORDER == BIG_ENDIAN +#define ND_NA_FLAG_ROUTER 0x80000000 +#define ND_NA_FLAG_SOLICITED 0x40000000 +#define ND_NA_FLAG_OVERRIDE 0x20000000 +#else +#if BYTE_ORDER == LITTLE_ENDIAN +#define ND_NA_FLAG_ROUTER 0x80 +#define ND_NA_FLAG_SOLICITED 0x40 +#define ND_NA_FLAG_OVERRIDE 0x20 +#endif +#endif + +struct nd_redirect { /* redirect */ + struct icmp6_hdr nd_rd_hdr; + struct in6_addr nd_rd_target; /* target address */ + struct in6_addr nd_rd_dst; /* destination address */ + /* could be followed by options */ +}; + +#define nd_rd_type nd_rd_hdr.icmp6_type +#define nd_rd_code nd_rd_hdr.icmp6_code +#define nd_rd_cksum nd_rd_hdr.icmp6_cksum +#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] + +struct nd_opt_hdr { /* Neighbor discovery option header */ + u_int8_t nd_opt_type; + u_int8_t nd_opt_len; + /* followed by option specific data*/ +}; + +#define ND_OPT_SOURCE_LINKADDR 1 +#define ND_OPT_TARGET_LINKADDR 2 +#define ND_OPT_PREFIX_INFORMATION 3 +#define ND_OPT_REDIRECTED_HEADER 4 +#define ND_OPT_MTU 5 + +struct nd_opt_prefix_info { /* prefix information */ + u_int8_t nd_opt_pi_type; + u_int8_t nd_opt_pi_len; + u_int8_t nd_opt_pi_prefix_len; + u_int8_t nd_opt_pi_flags_reserved; + u_int32_t nd_opt_pi_valid_time; + u_int32_t nd_opt_pi_preferred_time; + u_int32_t nd_opt_pi_reserved2; + struct in6_addr nd_opt_pi_prefix; +}; + +#define ND_OPT_PI_FLAG_ONLINK 0x80 +#define ND_OPT_PI_FLAG_AUTO 0x40 + +struct nd_opt_rd_hdr { /* redirected header */ + u_int8_t nd_opt_rh_type; + u_int8_t nd_opt_rh_len; + u_int16_t nd_opt_rh_reserved1; + u_int32_t nd_opt_rh_reserved2; + /* followed by IP header and data */ +}; + +struct nd_opt_mtu { /* MTU option */ + u_int8_t nd_opt_mtu_type; + u_int8_t nd_opt_mtu_len; + u_int16_t nd_opt_mtu_reserved; + u_int32_t nd_opt_mtu_mtu; +}; + +/* + * icmp6 namelookup + */ + +struct icmp6_namelookup { + struct icmp6_hdr icmp6_nl_hdr; + u_int64_t icmp6_nl_nonce; + u_int32_t icmp6_nl_ttl; +#if 0 + u_int8_t icmp6_nl_len; + u_int8_t icmp6_nl_name[3]; +#endif + /* could be followed by options */ +}; + +/* + * icmp6 node information + */ +struct icmp6_nodeinfo { + struct icmp6_hdr icmp6_ni_hdr; + u_int64_t icmp6_ni_nonce; + /* could be followed by reply data */ +}; + +#define ni_type icmp6_ni_hdr.icmp6_type +#define ni_code icmp6_ni_hdr.icmp6_code +#define ni_cksum icmp6_ni_hdr.icmp6_cksum +#define ni_qtype icmp6_ni_hdr.icmp6_data16[0] +#define ni_flags icmp6_ni_hdr.icmp6_data16[1] + + +#define NI_QTYPE_NOOP 0 /* NOOP */ +#define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */ +#define NI_QTYPE_FQDN 2 /* FQDN */ +#define NI_QTYPE_NODEADDR 3 /* Node Addresses. XXX: spec says 2, but it may be a typo... */ + +#if BYTE_ORDER == BIG_ENDIAN +#define NI_SUPTYPE_FLAG_COMPRESS 0x1 +#define NI_FQDN_FLAG_VALIDTTL 0x1 +#define NI_NODEADDR_FLAG_LINKLOCAL 0x1 +#define NI_NODEADDR_FLAG_SITELOCAL 0x2 +#define NI_NODEADDR_FLAG_GLOBAL 0x4 +#define NI_NODEADDR_FLAG_ALL 0x8 +#define NI_NODEADDR_FLAG_TRUNCATE 0x10 +#define NI_NODEADDR_FLAG_ANYCAST 0x20 /* just experimental. not in spec */ +#elif BYTE_ORDER == LITTLE_ENDIAN +#define NI_SUPTYPE_FLAG_COMPRESS 0x0100 +#define NI_FQDN_FLAG_VALIDTTL 0x0100 +#define NI_NODEADDR_FLAG_LINKLOCAL 0x0100 +#define NI_NODEADDR_FLAG_SITELOCAL 0x0200 +#define NI_NODEADDR_FLAG_GLOBAL 0x0400 +#define NI_NODEADDR_FLAG_ALL 0x0800 +#define NI_NODEADDR_FLAG_TRUNCATE 0x1000 +#define NI_NODEADDR_FLAG_ANYCAST 0x2000 /* just experimental. not in spec */ +#endif + +struct ni_reply_fqdn { + u_int32_t ni_fqdn_ttl; /* TTL */ + u_int8_t ni_fqdn_namelen; /* length in octets of the FQDN */ + u_int8_t ni_fqdn_name[3]; /* XXX: alignment */ +}; + +/* + * Router Renumbering. as router-renum-08.txt + */ +#if BYTE_ORDER == BIG_ENDIAN /* net byte order */ +struct icmp6_router_renum { /* router renumbering header */ + struct icmp6_hdr rr_hdr; + u_int8_t rr_segnum; + u_int8_t rr_test : 1; + u_int8_t rr_reqresult : 1; + u_int8_t rr_forceapply : 1; + u_int8_t rr_specsite : 1; + u_int8_t rr_prevdone : 1; + u_int8_t rr_flags_reserved : 3; + u_int16_t rr_maxdelay; + u_int32_t rr_reserved; +}; +#elif BYTE_ORDER == LITTLE_ENDIAN +struct icmp6_router_renum { /* router renumbering header */ + struct icmp6_hdr rr_hdr; + u_int8_t rr_segnum; + u_int8_t rr_flags_reserved : 3; + u_int8_t rr_prevdone : 1; + u_int8_t rr_specsite : 1; + u_int8_t rr_forceapply : 1; + u_int8_t rr_reqresult : 1; + u_int8_t rr_test : 1; + u_int16_t rr_maxdelay; + u_int32_t rr_reserved; +}; +#endif /* BYTE_ORDER */ + +#define rr_type rr_hdr.icmp6_type +#define rr_code rr_hdr.icmp6_code +#define rr_cksum rr_hdr.icmp6_cksum +#define rr_seqnum rr_hdr.icmp6_data32[0] + +struct rr_pco_match { /* match prefix part */ + u_int8_t rpm_code; + u_int8_t rpm_len; + u_int8_t rpm_ordinal; + u_int8_t rpm_matchlen; + u_int8_t rpm_minlen; + u_int8_t rpm_maxlen; + u_int16_t rpm_reserved; + struct in6_addr rpm_prefix; +}; + +#define RPM_PCO_ADD 1 +#define RPM_PCO_CHANGE 2 +#define RPM_PCO_SETGLOBAL 3 +#define RPM_PCO_MAX 4 + +#if BYTE_ORDER == BIG_ENDIAN /* net byte order */ +struct rr_pco_use { /* use prefix part */ + u_int8_t rpu_uselen; + u_int8_t rpu_keeplen; + u_int8_t rpu_mask_onlink : 1; + u_int8_t rpu_mask_autonomous : 1; + u_int8_t rpu_mask_reserved : 6; + u_int8_t rpu_onlink : 1; + u_int8_t rpu_autonomous : 1; + u_int8_t rpu_raflags_reserved : 6; + u_int32_t rpu_vltime; + u_int32_t rpu_pltime; + u_int32_t rpu_decr_vltime : 1; + u_int32_t rpu_decr_pltime : 1; + u_int32_t rpu_flags_reserved : 6; + u_int32_t rpu_reserved : 24; + struct in6_addr rpu_prefix; +}; +#elif BYTE_ORDER == LITTLE_ENDIAN +struct rr_pco_use { /* use prefix part */ + u_int8_t rpu_uselen; + u_int8_t rpu_keeplen; + u_int8_t rpu_mask_reserved : 6; + u_int8_t rpu_mask_autonomous : 1; + u_int8_t rpu_mask_onlink : 1; + u_int8_t rpu_raflags_reserved : 6; + u_int8_t rpu_autonomous : 1; + u_int8_t rpu_onlink : 1; + u_int32_t rpu_vltime; + u_int32_t rpu_pltime; + u_int32_t rpu_flags_reserved : 6; + u_int32_t rpu_decr_pltime : 1; + u_int32_t rpu_decr_vltime : 1; + u_int32_t rpu_reserved : 24; + struct in6_addr rpu_prefix; +}; +#endif /* BYTE_ORDER */ + +#if BYTE_ORDER == BIG_ENDIAN /* net byte order */ +struct rr_result { /* router renumbering result message */ + u_int8_t rrr_reserved; + u_int8_t rrr_flags_reserved : 6; + u_int8_t rrr_outofbound : 1; + u_int8_t rrr_forbidden : 1; + u_int8_t rrr_ordinal; + u_int8_t rrr_matchedlen; + u_int32_t rrr_ifid; + struct in6_addr rrr_prefix; +}; +#elif BYTE_ORDER == LITTLE_ENDIAN +struct rr_result { /* router renumbering result message */ + u_int8_t rrr_reserved; + u_int8_t rrr_forbidden : 1; + u_int8_t rrr_outofbound : 1; + u_int8_t rrr_flags_reserved : 6; + u_int8_t rrr_ordinal; + u_int8_t rrr_matchedlen; + u_int32_t rrr_ifid; + struct in6_addr rrr_prefix; +}; +#endif /* BYTE_ORDER */ + +/* + * icmp6 filter structures. + */ + +struct icmp6_filter { + u_int32_t icmp6_filter[8]; +}; + +#ifdef _KERNEL +#define ICMP6_FILTER_SETPASSALL(filterp) \ + { \ + int i; u_char *p; \ + p = (u_char *)filterp; \ + for (i = 0; i < sizeof(struct icmp6_filter); i++) \ + p[i] = 0xff; \ + } +#define ICMP6_FILTER_SETBLOCKALL(filterp) \ + bzero(filterp, sizeof(struct icmp6_filter)) +#else /* _KERNEL */ +#define ICMP6_FILTER_SETPASSALL(filterp) \ + memset(filterp, 0xff, sizeof(struct icmp6_filter)) +#define ICMP6_FILTER_SETBLOCKALL(filterp) \ + memset(filterp, 0x00, sizeof(struct icmp6_filter)) +#endif /* _KERNEL */ + +#define ICMP6_FILTER_SETPASS(type, filterp) \ + (((filterp)->icmp6_filter[(type) >> 5]) |= (1 << ((type) & 31))) +#define ICMP6_FILTER_SETBLOCK(type, filterp) \ + (((filterp)->icmp6_filter[(type) >> 5]) &= ~(1 << ((type) & 31))) +#define ICMP6_FILTER_WILLPASS(type, filterp) \ + ((((filterp)->icmp6_filter[(type) >> 5]) & (1 << ((type) & 31))) != 0) +#define ICMP6_FILTER_WILLBLOCK(type, filterp) \ + ((((filterp)->icmp6_filter[(type) >> 5]) & (1 << ((type) & 31))) == 0) + +/* + * Variables related to this implementation + * of the internet control message protocol version 6. + */ +struct icmp6stat { +/* statistics related to icmp6 packets generated */ + u_quad_t icp6s_error; /* # of calls to icmp6_error */ + u_quad_t icp6s_canterror; /* no error 'cuz old was icmp */ + u_quad_t icp6s_toofreq; /* no error 'cuz rate limitation */ + u_quad_t icp6s_outhist[256]; +/* statistics related to input message processed */ + u_quad_t icp6s_badcode; /* icmp6_code out of range */ + u_quad_t icp6s_tooshort; /* packet < sizeof(struct icmp6_hdr) */ + u_quad_t icp6s_checksum; /* bad checksum */ + u_quad_t icp6s_badlen; /* calculated bound mismatch */ + u_quad_t icp6s_reflect; /* number of responses */ + u_quad_t icp6s_inhist[256]; + u_quad_t icp6s_nd_toomanyopt; /* too many ND options */ +}; + +/* + * Names for ICMP sysctl objects + */ +#define ICMPV6CTL_STATS 1 +#define ICMPV6CTL_REDIRACCEPT 2 /* accept/process redirects */ +#define ICMPV6CTL_REDIRTIMEOUT 3 /* redirect cache time */ +#define ICMPV6CTL_ERRRATELIMIT 5 /* ICMPv6 error rate limitation */ +#define ICMPV6CTL_ND6_PRUNE 6 +#define ICMPV6CTL_ND6_DELAY 8 +#define ICMPV6CTL_ND6_UMAXTRIES 9 +#define ICMPV6CTL_ND6_MMAXTRIES 10 +#define ICMPV6CTL_ND6_USELOOPBACK 11 +#define ICMPV6CTL_ND6_PROXYALL 12 +#define ICMPV6CTL_MAXID 13 + +#define ICMPV6CTL_NAMES { \ + { 0, 0 }, \ + { 0, 0 }, \ + { "rediraccept", CTLTYPE_INT }, \ + { "redirtimeout", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "errratelimit", CTLTYPE_INT }, \ + { "nd6_prune", CTLTYPE_INT }, \ + { 0, 0 }, \ + { "nd6_delay", CTLTYPE_INT }, \ + { "nd6_umaxtries", CTLTYPE_INT }, \ + { "nd6_mmaxtries", CTLTYPE_INT }, \ + { "nd6_useloopback", CTLTYPE_INT }, \ + { "nd6_proxyall", CTLTYPE_INT }, \ +} + +#define ICMPV6CTL_VARS { \ + 0, \ + 0, \ + &icmp6_rediraccept, \ + &icmp6_redirtimeout, \ + 0, \ + 0, \ + &icmp6errratelim, \ + &nd6_prune, \ + 0, \ + &nd6_delay, \ + &nd6_umaxtries, \ + &nd6_mmaxtries, \ + &nd6_useloopback, \ + &nd6_proxyall, \ +} + +#define RTF_PROBEMTU RTF_PROTO1 + +#ifdef _KERNEL +# ifdef __STDC__ +struct rtentry; +struct rttimer; +struct in6_multi; +# endif +void icmp6_init __P((void)); +void icmp6_paramerror __P((struct mbuf *, int)); +void icmp6_error __P((struct mbuf *, int, int, int)); +int icmp6_input __P((struct mbuf **, int *, int)); +void icmp6_fasttimo __P((void)); +void icmp6_reflect __P((struct mbuf *, size_t)); +void icmp6_prepare __P((struct mbuf *)); +void icmp6_redirect_input __P((struct mbuf *, int)); +void icmp6_redirect_output __P((struct mbuf *, struct rtentry *)); +int icmp6_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); + +/* XXX: is this the right place for these macros? */ +#define icmp6_ifstat_inc(ifp, tag) \ +do { \ + if ((ifp) && (ifp)->if_index <= if_index \ + && (ifp)->if_index < icmp6_ifstatmax \ + && icmp6_ifstat && icmp6_ifstat[(ifp)->if_index]) { \ + icmp6_ifstat[(ifp)->if_index]->tag++; \ + } \ +} while (0) + +#define icmp6_ifoutstat_inc(ifp, type, code) \ +do { \ + icmp6_ifstat_inc(ifp, ifs6_out_msg); \ + if (type < ICMP6_INFOMSG_MASK) \ + icmp6_ifstat_inc(ifp, ifs6_out_error); \ + switch(type) { \ + case ICMP6_DST_UNREACH: \ + icmp6_ifstat_inc(ifp, ifs6_out_dstunreach); \ + if (code == ICMP6_DST_UNREACH_ADMIN) \ + icmp6_ifstat_inc(ifp, ifs6_out_adminprohib); \ + break; \ + case ICMP6_PACKET_TOO_BIG: \ + icmp6_ifstat_inc(ifp, ifs6_out_pkttoobig); \ + break; \ + case ICMP6_TIME_EXCEEDED: \ + icmp6_ifstat_inc(ifp, ifs6_out_timeexceed); \ + break; \ + case ICMP6_PARAM_PROB: \ + icmp6_ifstat_inc(ifp, ifs6_out_paramprob); \ + break; \ + case ICMP6_ECHO_REQUEST: \ + icmp6_ifstat_inc(ifp, ifs6_out_echo); \ + break; \ + case ICMP6_ECHO_REPLY: \ + icmp6_ifstat_inc(ifp, ifs6_out_echoreply); \ + break; \ + case MLD6_LISTENER_QUERY: \ + icmp6_ifstat_inc(ifp, ifs6_out_mldquery); \ + break; \ + case MLD6_LISTENER_REPORT: \ + icmp6_ifstat_inc(ifp, ifs6_out_mldreport); \ + break; \ + case MLD6_LISTENER_DONE: \ + icmp6_ifstat_inc(ifp, ifs6_out_mlddone); \ + break; \ + case ND_ROUTER_SOLICIT: \ + icmp6_ifstat_inc(ifp, ifs6_out_routersolicit); \ + break; \ + case ND_ROUTER_ADVERT: \ + icmp6_ifstat_inc(ifp, ifs6_out_routeradvert); \ + break; \ + case ND_NEIGHBOR_SOLICIT: \ + icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); \ + break; \ + case ND_NEIGHBOR_ADVERT: \ + icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); \ + break; \ + case ND_REDIRECT: \ + icmp6_ifstat_inc(ifp, ifs6_out_redirect); \ + break; \ + } \ +} while (0) + +extern int icmp6_rediraccept; /* accept/process redirects */ +extern int icmp6_redirtimeout; /* cache time for redirect routes */ +#endif /* _KERNEL */ + +#endif /* not _NETINET6_ICMPV6_H_ */ + diff --git a/ecos/packages/net/tcpip/current/include/netinet6/icmpv6.h b/ecos/packages/net/tcpip/current/include/netinet6/icmpv6.h new file mode 100644 index 0000000..0bc4903 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/icmpv6.h @@ -0,0 +1,110 @@ +//========================================================================== +// +// include/netinet6_icmpv6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% portions-copyright-nrl-97 +Portions of this software are Copyright 1997-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_ICMPV6_H +#define _NETINET6_ICMPV6_H 1 + +#include <netinet6/ipv6.h> + +struct icmpv6hdr { + uint8_t icmpv6_type; /* type field */ + uint8_t icmpv6_code; /* code field */ + uint16_t icmpv6_cksum; /* checksum field */ + union { + uint32_t un_data32[1]; /* type-specific field */ + uint16_t un_data16[2]; /* type-specific field */ + uint8_t un_data8[4]; /* type-specific field */ + } icmpv6_dataun; +}; + +#define icmpv6_data32 icmpv6_dataun.un_data32 +#define icmpv6_data16 icmpv6_dataun.un_data16 +#define icmpv6_data8 icmpv6_dataun.un_data8 +#define icmpv6_pptr icmpv6_data32[0] /* parameter prob */ +#define icmpv6_mtu icmpv6_data32[0] /* packet too big */ +#define icmpv6_id icmpv6_data16[0] /* echo request/reply */ +#define icmpv6_seq icmpv6_data16[1] /* echo request/reply */ +#define icmpv6_maxdelay icmpv6_data16[0] /* mcast group membership */ + +#define ICMPV6_DST_UNREACH 1 +#define ICMPV6_PACKET_TOOBIG 2 +#define ICMPV6_TIME_EXCEEDED 3 +#define ICMPV6_PARAMETER_PROBLEM 4 + +#define ICMPV6_INFOMSG_MASK 128 /* all informational messages */ +#define ICMPV6_ECHO_REQUEST 128 +#define ICMPV6_ECHO_REPLY 129 +#define ICMPV6_MEMBERSHIP_QUERY 130 +#define ICMPV6_MEMBERSHIP_REPORT 131 +#define ICMPV6_MEMBERSHIP_REDUCTION 132 + +#define ICMPV6_UNREACH_NOROUTE 0 +#define ICMPV6_UNREACH_ADMIN 1 /* administratively prohibited */ +#define ICMPV6_UNREACH_NOTNEIGHBOR 2 /* not a neighbor (and must be) */ +#define ICMPV6_UNREACH_ADDRESS 3 +#define ICMPV6_UNREACH_PORT 4 + +#define ICMPV6_EXCEEDED_HOPS 0 /* Hop Limit == 0 in transit */ +#define ICMPV6_EXCEEDED_REASSEMBLY 1 /* Reassembly time out */ + +#define ICMPV6_PARAMPROB_HDR 0 /* erroneous header field */ +#define ICMPV6_PARAMPROB_NEXTHDR 1 /* unrecognized Next Header */ +#define ICMPV6_PARAMPROB_OPTION 2 /* unrecognized option */ + +struct icmpv6_filter { + uint32_t data[8]; /* 8*32 = 256 bits */ +}; + +#define ICMPV6_FILTER_WILLPASS(type, filterp) \ + ((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) == 0) +#define ICMPV6_FILTER_WILLBLOCK(type, filterp) \ + ((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) != 0) +#define ICMPV6_FILTER_SETPASS(type, filterp) \ + ((((filterp)->data[(type) >> 5]) &= ~(1 << ((type) & 31)))) +#define ICMPV6_FILTER_SETBLOCK(type, filterp) \ + ((((filterp)->data[(type) >> 5]) |= (1 << ((type) & 31)))) +#define ICMPV6_FILTER_SETPASSALL(filterp) \ + memset((filterp), 0, sizeof(struct icmpv6_filter)) +#define ICMPV6_FILTER_SETBLOCKALL(filterp) \ + memset((filterp), 0xff, sizeof(struct icmpv6_filter)) + +#endif /* _NETINET6_ICMPV6_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/icmpv6_var.h b/ecos/packages/net/tcpip/current/include/netinet6/icmpv6_var.h new file mode 100644 index 0000000..2c29a76 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/icmpv6_var.h @@ -0,0 +1,82 @@ +//========================================================================== +// +// include/netinet6_icmpv6_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% copyright-nrl-95 +This software is Copyright 1995-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_ICMPV6_VAR_H +#define _NETINET6_ICMPV6_VAR_H 1 + +#if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802 +#define _ICMPV6STAT_TYPE u_quad_t +#else /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802 */ +#define _ICMPV6STAT_TYPE u_long +#endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802 */ + +struct icmpv6stat +{ + _ICMPV6STAT_TYPE icps_error; + _ICMPV6STAT_TYPE icps_tooshort; + _ICMPV6STAT_TYPE icps_checksum; + _ICMPV6STAT_TYPE icps_outhist[ICMPV6_MAXTYPE+1]; + _ICMPV6STAT_TYPE icps_badlen; + _ICMPV6STAT_TYPE icps_badcode; + _ICMPV6STAT_TYPE icps_reflect; /* Number of in-kernel responses */ + _ICMPV6STAT_TYPE icps_inhist[ICMPV6_MAXTYPE+1]; +}; + +/* + * Names for ICMPV6 sysctl objects + */ +#define ICMPV6CTL_STATS 1 /* statistics */ +#define ICMPV6CTL_MAXID 2 + +#define ICMPV6CTL_NAMES { \ + { 0, 0 }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + +#define ICMPV6CTL_VARS { \ + 0, \ + 0, \ +} + +#if defined(_KERNEL) || defined(KERNEL) +struct icmpv6stat icmpv6stat; +#endif /* defined(_KERNEL) || defined(KERNEL) */ +#endif /* _NETINET6_ICMPV6_VAR_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/in6.h b/ecos/packages/net/tcpip/current/include/netinet6/in6.h new file mode 100644 index 0000000..e5b572e --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/in6.h @@ -0,0 +1,682 @@ +//========================================================================== +// +// include/netinet6_in6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in6.h,v 1.9 1999/12/10 08:53:17 angelos Exp $ */ +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in.h 8.3 (Berkeley) 1/3/94 + */ + +#ifndef _NETINET6_IN6_H_ +#define _NETINET6_IN6_H_ + +#if !defined(_XOPEN_SOURCE) +#include <sys/queue.h> +#endif + +/* + * Identification of the network protocol stack + */ +#define __KAME__ +#define __KAME_VERSION "19991208/OpenBSD-current" + +/* + * Local port number conventions: + * + * Ports < IPPORT_RESERVED are reserved for privileged processes (e.g. root), + * unless a kernel is compiled with IPNOPRIVPORTS defined. + * + * When a user does a bind(2) or connect(2) with a port number of zero, + * a non-conflicting local port address is chosen. + * + * The default range is IPPORT_ANONMIX to IPPORT_ANONMAX, although + * that is settable by sysctl(3); net.inet.ip.anonportmin and + * net.inet.ip.anonportmax respectively. + * + * A user may set the IPPROTO_IP option IP_PORTRANGE to change this + * default assignment range. + * + * The value IP_PORTRANGE_DEFAULT causes the default behavior. + * + * The value IP_PORTRANGE_HIGH is the same as IP_PORTRANGE_DEFAULT, + * and exists only for FreeBSD compatibility purposes. + * + * The value IP_PORTRANGE_LOW changes the range to the "low" are + * that is (by convention) restricted to privileged processes. + * This convention is based on "vouchsafe" principles only. + * It is only secure if you trust the remote host to restrict these ports. + * The range is IPPORT_RESERVEDMIN to IPPORT_RESERVEDMAX. + */ + +#define IPV6PORT_RESERVED 1024 +#define IPV6PORT_ANONMIN 49152 +#define IPV6PORT_ANONMAX 65535 +#define IPV6PORT_RESERVEDMIN 600 +#define IPV6PORT_RESERVEDMAX (IPV6PORT_RESERVED-1) + +/* + * IPv6 address + */ +struct in6_addr { + union { + u_int8_t __u6_addr8[16]; + u_int16_t __u6_addr16[8]; + u_int32_t __u6_addr32[4]; + } __u6_addr; /* 128-bit IP6 address */ +}; + +#define s6_addr __u6_addr.__u6_addr8 +#ifdef _KERNEL /*XXX nonstandard*/ +#define s6_addr8 __u6_addr.__u6_addr8 +#define s6_addr16 __u6_addr.__u6_addr16 +#define s6_addr32 __u6_addr.__u6_addr32 +#endif + +#define INET6_ADDRSTRLEN 46 + +/* + * Socket address for IPv6 + */ +#if !defined(_XOPEN_SOURCE) +#define SIN6_LEN +#endif +struct sockaddr_in6 { + u_char sin6_len; /* length of this struct(sa_family_t)*/ + u_char sin6_family; /* AF_INET6 (sa_family_t) */ + u_int16_t sin6_port; /* Transport layer port # (in_port_t)*/ + u_int32_t sin6_flowinfo; /* IP6 flow information */ + struct in6_addr sin6_addr; /* IP6 address */ + u_int32_t sin6_scope_id; /* intface scope id */ +}; + +/* + * Local definition for masks + */ +#ifdef _KERNEL /*XXX nonstandard*/ +#define IN6MASK0 {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}} +#define IN6MASK32 {{{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}} +#define IN6MASK64 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}} +#define IN6MASK96 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}} +#define IN6MASK128 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}} +#endif + +#ifdef _KERNEL +extern const struct in6_addr in6mask0; +extern const struct in6_addr in6mask32; +extern const struct in6_addr in6mask64; +extern const struct in6_addr in6mask96; +extern const struct in6_addr in6mask128; +#endif /* _KERNEL */ + +/* + * Macros started with IPV6_ADDR is KAME local + */ +#ifdef _KERNEL /*XXX nonstandard*/ +#if BYTE_ORDER == BIG_ENDIAN +#define IPV6_ADDR_INT32_ONE 1 +#define IPV6_ADDR_INT32_TWO 2 +#define IPV6_ADDR_INT32_MNL 0xff010000 +#define IPV6_ADDR_INT32_MLL 0xff020000 +#define IPV6_ADDR_INT32_SMP 0x0000ffff +#define IPV6_ADDR_INT16_ULL 0xfe80 +#define IPV6_ADDR_INT16_USL 0xfec0 +#define IPV6_ADDR_INT16_MLL 0xff02 +#elif BYTE_ORDER == LITTLE_ENDIAN +#define IPV6_ADDR_INT32_ONE 0x01000000 +#define IPV6_ADDR_INT32_TWO 0x02000000 +#define IPV6_ADDR_INT32_MNL 0x000001ff +#define IPV6_ADDR_INT32_MLL 0x000002ff +#define IPV6_ADDR_INT32_SMP 0xffff0000 +#define IPV6_ADDR_INT16_ULL 0x80fe +#define IPV6_ADDR_INT16_USL 0xc0fe +#define IPV6_ADDR_INT16_MLL 0x02ff +#endif +#endif + +/* + * Definition of some useful macros to handle IP6 addresses + */ +#define IN6ADDR_ANY_INIT \ + {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}} +#define IN6ADDR_LOOPBACK_INIT \ + {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} +#define IN6ADDR_NODELOCAL_ALLNODES_INIT \ + {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} +#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \ + {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} +#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \ + {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}} + +extern const struct in6_addr in6addr_any; +extern const struct in6_addr in6addr_loopback; +extern const struct in6_addr in6addr_nodelocal_allnodes; +extern const struct in6_addr in6addr_linklocal_allnodes; +extern const struct in6_addr in6addr_linklocal_allrouters; + +/* + * Equality + * NOTE: Some of kernel programming environment (for example, openbsd/sparc) + * does not supply memcmp(). For userland memcmp() is preferred as it is + * in ANSI standard. + */ +#ifdef _KERNEL +#define IN6_ARE_ADDR_EQUAL(a, b) \ + (bcmp((a), (b), sizeof(struct in6_addr)) == 0) +#else +#define IN6_ARE_ADDR_EQUAL(a, b) \ + (memcmp((a), (b), sizeof(struct in6_addr)) == 0) +#endif + +/* + * Unspecified + */ +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + ((*(u_int32_t *)(&(a)->s6_addr[0]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[4]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[8]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[12]) == 0)) + +/* + * Loopback + */ +#define IN6_IS_ADDR_LOOPBACK(a) \ + ((*(u_int32_t *)(&(a)->s6_addr[0]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[4]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[8]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[12]) == ntohl(1))) + +/* + * IPv4 compatible + */ +#define IN6_IS_ADDR_V4COMPAT(a) \ + ((*(u_int32_t *)(&(a)->s6_addr[0]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[4]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[8]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[12]) != 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[12]) != ntohl(1))) + +/* + * Mapped + */ +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((*(u_int32_t *)(&(a)->s6_addr[0]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[4]) == 0) && \ + (*(u_int32_t *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff))) + +/* + * KAME Scope Values + */ + +#ifdef _KERNEL /*XXX nonstandard*/ +#define IPV6_ADDR_SCOPE_NODELOCAL 0x01 +#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02 +#define IPV6_ADDR_SCOPE_SITELOCAL 0x05 +#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */ +#define IPV6_ADDR_SCOPE_GLOBAL 0x0e +#else +#define __IPV6_ADDR_SCOPE_NODELOCAL 0x01 +#define __IPV6_ADDR_SCOPE_LINKLOCAL 0x02 +#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05 +#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */ +#define __IPV6_ADDR_SCOPE_GLOBAL 0x0e +#endif + +/* + * Unicast Scope + * Note that we must check topmost 10 bits only, not 16 bits (see RFC2373). + */ +#define IN6_IS_ADDR_LINKLOCAL(a) \ + (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80)) +#define IN6_IS_ADDR_SITELOCAL(a) \ + (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0)) + +/* + * Multicast + */ +#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff) + +#ifdef _KERNEL /*XXX nonstandard*/ +#define IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f) +#else +#define __IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f) +#endif + +/* + * Multicast Scope + */ +#ifdef _KERNEL /*refers nonstandard items */ +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_NODELOCAL)) +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_LINKLOCAL)) +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_SITELOCAL)) +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_ORGLOCAL)) +#define IN6_IS_ADDR_MC_GLOBAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_GLOBAL)) +#else +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL)) +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL)) +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL)) +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL)) +#define IN6_IS_ADDR_MC_GLOBAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL)) +#endif + +/* + * Wildcard Socket + */ +#if 0 /*pre-RFC2553*/ +#define IN6_IS_ADDR_ANY(a) IN6_IS_ADDR_UNSPECIFIED(a) +#endif + +/* + * KAME Scope + */ +#ifdef _KERNEL /*nonstandard*/ +#define IN6_IS_SCOPE_LINKLOCAL(a) \ + ((IN6_IS_ADDR_LINKLOCAL(a)) || \ + (IN6_IS_ADDR_MC_LINKLOCAL(a))) +#endif + +/* + * IP6 route structure + */ +#if !defined(_XOPEN_SOURCE) +struct route_in6 { + struct rtentry *ro_rt; + struct sockaddr_in6 ro_dst; +}; +#endif + +/* + * Options for use with [gs]etsockopt at the IPV6 level. + * First word of comment is data type; bool is stored in int. + */ +#define IPV6_OPTIONS 1 /* buf/ip6_opts; set/get IP6 options */ +/* no hdrincl */ +#define IPV6_SOCKOPT_RESERVED1 3 /* reserved for future use */ +#define IPV6_UNICAST_HOPS 4 /* int; IP6 hops */ +#define IPV6_RECVOPTS 5 /* bool; receive all IP6 opts w/dgram */ +#define IPV6_RECVRETOPTS 6 /* bool; receive IP6 opts for response */ +#define IPV6_RECVDSTADDR 7 /* bool; receive IP6 dst addr w/dgram */ +#define IPV6_RETOPTS 8 /* ip6_opts; set/get IP6 options */ +#define IPV6_MULTICAST_IF 9 /* u_char; set/get IP6 multicast i/f */ +#define IPV6_MULTICAST_HOPS 10 /* u_char; set/get IP6 multicast hops */ +#define IPV6_MULTICAST_LOOP 11 /* u_char; set/get IP6 multicast loopback */ +#define IPV6_JOIN_GROUP 12 /* ip6_mreq; join a group membership */ +#define IPV6_LEAVE_GROUP 13 /* ip6_mreq; leave a group membership */ +#define IPV6_PORTRANGE 14 /* int; range to choose for unspec port */ +#define ICMP6_FILTER 18 /* icmp6_filter; icmp6 filter */ +#define IPV6_PKTINFO 19 /* bool; send/rcv if, src/dst addr */ +#define IPV6_HOPLIMIT 20 /* bool; hop limit */ +#define IPV6_NEXTHOP 21 /* bool; next hop addr */ +#define IPV6_HOPOPTS 22 /* bool; hop-by-hop option */ +#define IPV6_DSTOPTS 23 /* bool; destination option */ +#define IPV6_RTHDR 24 /* bool; routing header */ +#define IPV6_PKTOPTIONS 25 /* buf/cmsghdr; set/get IPv6 options */ +#define IPV6_CHECKSUM 26 /* int; checksum offset for raw socket */ +#define IPV6_BINDV6ONLY 27 /* bool; only bind INET6 at null bind */ + +#if 1 /*IPSEC*/ +#define IPV6_IPSEC_POLICY 28 /* struct; get/set security policy */ +#endif +#define IPV6_FAITH 29 /* bool; accept FAITH'ed connections */ + +#if 1 /*IPV6FIREWALL*/ +#define IPV6_FW_ADD 30 /* add a firewall rule to chain */ +#define IPV6_FW_DEL 31 /* delete a firewall rule from chain */ +#define IPV6_FW_FLUSH 32 /* flush firewall rule chain */ +#define IPV6_FW_ZERO 33 /* clear single/all firewall counter(s) */ +#define IPV6_FW_GET 34 /* get entire firewall rule chain */ +#endif + +#define IPV6_RTHDR_LOOSE 0 /* this hop need not be a neighbor. XXX old spec */ +#define IPV6_RTHDR_STRICT 1 /* this hop must be a neighbor. XXX old spec */ +#define IPV6_RTHDR_TYPE_0 0 /* IPv6 routing header type 0 */ + +/* + * Defaults and limits for options + */ +#define IPV6_DEFAULT_MULTICAST_HOPS 1 /* normally limit m'casts to 1 hop */ +#define IPV6_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ + +/* + * Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP. + */ +struct ipv6_mreq { + struct in6_addr ipv6mr_multiaddr; + u_int ipv6mr_interface; +}; + +/* + * IPV6_PKTINFO: Packet information(RFC2292 sec 5) + */ +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + u_int ipi6_ifindex; /* send/recv interface index */ +}; + +/* + * Argument for IPV6_PORTRANGE: + * - which range to search when port is unspecified at bind() or connect() + */ +#define IPV6_PORTRANGE_DEFAULT 0 /* default range */ +#define IPV6_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */ +#define IPV6_PORTRANGE_LOW 2 /* "low" - vouchsafe security */ + +#if !defined(_XOPEN_SOURCE) +/* + * Definitions for inet6 sysctl operations. + * + * Third level is protocol number. + * Fourth level is desired variable within that protocol. + */ +#define IPV6PROTO_MAXID (IPPROTO_PIM + 1) /* don't list to IPV6PROTO_MAX */ + +#define CTL_IPV6PROTO_NAMES { \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { "tcp6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "udp6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { "ip6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { "ipsec6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "icmp6", CTLTYPE_NODE }, \ + { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "pim6", CTLTYPE_NODE }, \ +} + +/* + * Names for IP sysctl objects + */ +#define IPV6CTL_FORWARDING 1 /* act as router */ +#define IPV6CTL_SENDREDIRECTS 2 /* may send redirects when forwarding*/ +#define IPV6CTL_DEFHLIM 3 /* default Hop-Limit */ +#ifdef notyet +#define IPV6CTL_DEFMTU 4 /* default MTU */ +#endif +#define IPV6CTL_FORWSRCRT 5 /* forward source-routed dgrams */ +#define IPV6CTL_STATS 6 /* stats */ +#define IPV6CTL_MRTSTATS 7 /* multicast forwarding stats */ +#define IPV6CTL_MRTPROTO 8 /* multicast routing protocol */ +#define IPV6CTL_MAXFRAGPACKETS 9 /* max packets reassembly queue */ +#define IPV6CTL_SOURCECHECK 10 /* verify source route and intf */ +#define IPV6CTL_SOURCECHECK_LOGINT 11 /* minimume logging interval */ +#define IPV6CTL_ACCEPT_RTADV 12 +#define IPV6CTL_KEEPFAITH 13 +#define IPV6CTL_LOG_INTERVAL 14 +#define IPV6CTL_HDRNESTLIMIT 15 +#define IPV6CTL_DAD_COUNT 16 +#define IPV6CTL_AUTO_FLOWLABEL 17 +#define IPV6CTL_DEFMCASTHLIM 18 +#define IPV6CTL_GIF_HLIM 19 /* default HLIM for gif encap packet */ +#define IPV6CTL_KAME_VERSION 20 +#define IPV6CTL_USE_DEPRECATED 21 /* use deprecated addr (RFC2462 5.5.4) */ +#define IPV6CTL_RR_PRUNE 22 /* walk timer for router renumbering */ +#ifdef MAPPED_ADDR_ENABLED +#define IPV6CTL_MAPPED_ADDR 23 +#endif /* MAPPED_ADDR_ENABLED */ +/* New entries should be added here from current IPV6CTL_MAXID value. */ +#define IPV6CTL_MAXID 24 + +#ifdef MAPPED_ADDR_ENABLED +#define IPV6CTL_NAMES_MAPPED_ADDR "mapped_addr" +#define IPV6CTL_TYPE_MAPPED_ADDR CTLTYPE_INT +#define IPV6CTL_VARS_MAPPED_ADDR &ip6_mapped_addr_on +#else /* MAPPED_ADDR_ENABLED */ +#define IPV6CTL_NAMES_MAPPED_ADDR 0 +#define IPV6CTL_TYPE_MAPPED_ADDR 0 +#define IPV6CTL_VARS_MAPPED_ADDR 0 +#endif /* MAPPED_ADDR_ENABLED */ + +#define IPV6CTL_NAMES { \ + { 0, 0 }, \ + { "forwarding", CTLTYPE_INT }, \ + { "redirect", CTLTYPE_INT }, \ + { "hlim", CTLTYPE_INT }, \ + { "mtu", CTLTYPE_INT }, \ + { "forwsrcrt", CTLTYPE_INT }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "mrtproto", CTLTYPE_INT }, \ + { "maxfragpackets", CTLTYPE_INT }, \ + { "sourcecheck", CTLTYPE_INT }, \ + { "sourcecheck_logint", CTLTYPE_INT }, \ + { "accept_rtadv", CTLTYPE_INT }, \ + { "keepfaith", CTLTYPE_INT }, \ + { "log_interval", CTLTYPE_INT }, \ + { "hdrnestlimit", CTLTYPE_INT }, \ + { "dad_count", CTLTYPE_INT }, \ + { "auto_flowlabel", CTLTYPE_INT }, \ + { "defmcasthlim", CTLTYPE_INT }, \ + { "gifhlim", CTLTYPE_INT }, \ + { "kame_version", CTLTYPE_STRING }, \ + { "use_deprecated", CTLTYPE_INT }, \ + { "rr_prune", CTLTYPE_INT }, \ + { IPV6CTL_NAMES_MAPPED_ADDR, IPV6CTL_TYPE_MAPPED_ADDR }, \ +} + +#define IPV6CTL_VARS { \ + 0, \ + &ip6_forwarding, \ + &ip6_sendredirects, \ + &ip6_defhlim, \ + 0, \ + &ip6_forward_srcrt, \ + 0, \ + 0, \ + 0, \ + &ip6_maxfragpackets, \ + &ip6_sourcecheck, \ + &ip6_sourcecheck_interval, \ + &ip6_accept_rtadv, \ + &ip6_keepfaith, \ + &ip6_log_interval, \ + &ip6_hdrnestlimit, \ + &ip6_dad_count, \ + &ip6_auto_flowlabel, \ + &ip6_defmcasthlim, \ + &ip6_gif_hlim, \ + 0, \ + &ip6_use_deprecated, \ + &ip6_rr_prune, \ + IPV6CTL_VARS_MAPPED_ADDR, \ +} +#endif /* !_XOPEN_SOURCE */ + +#ifdef _KERNEL +struct cmsghdr; +struct mbuf; +struct ifnet; + +int in6_canforward __P((struct in6_addr *, struct in6_addr *)); +int in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t)); +int in6_localaddr __P((struct in6_addr *)); +int in6_addrscope __P((struct in6_addr *)); +struct in6_ifaddr *in6_ifawithscope __P((struct ifnet *, struct in6_addr *)); +struct in6_ifaddr *in6_ifawithifp __P((struct ifnet *, struct in6_addr *)); +extern void in6_if_up __P((struct ifnet *)); +#ifdef MAPPED_ADDR_ENABLED +struct sockaddr; + +void in6_sin6_2_sin __P((struct sockaddr_in *sin, + struct sockaddr_in6 *sin6)); +void in6_sin_2_v4mapsin6 __P((struct sockaddr_in *sin, + struct sockaddr_in6 *sin6)); +void in6_sin6_2_sin_in_sock __P((struct sockaddr *nam)); +void in6_sin_2_v4mapsin6_in_sock __P((struct sockaddr **nam)); +#endif /* MAPPED_ADDR_ENABLED */ + +#define satosin6(sa) ((struct sockaddr_in6 *)(sa)) +#define sin6tosa(sin6) ((struct sockaddr *)(sin6)) +#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) +#endif /* _KERNEL */ + +__BEGIN_DECLS +struct cmsghdr; + +extern int inet6_option_space(int); +extern int inet6_option_init(void *, struct cmsghdr **, int); +extern int inet6_option_append(struct cmsghdr *, const u_int8_t *, int, int); +extern u_int8_t *inet6_option_alloc(struct cmsghdr *, int, int, int); +extern int inet6_option_next(const struct cmsghdr *, u_int8_t **); +extern int inet6_option_find(const struct cmsghdr *, u_int8_t **, int); + +extern size_t inet6_rthdr_space __P((int, int)); +extern struct cmsghdr *inet6_rthdr_init __P((void *, int)); +extern int inet6_rthdr_add __P((struct cmsghdr *, const struct in6_addr *, + unsigned int)); +extern int inet6_rthdr_lasthop __P((struct cmsghdr *, unsigned int)); +#if 0 /* not implemented yet */ +extern int inet6_rthdr_reverse __P((const struct cmsghdr *, struct cmsghdr *)); +#endif +extern int inet6_rthdr_segments __P((const struct cmsghdr *)); +extern struct in6_addr *inet6_rthdr_getaddr __P((struct cmsghdr *, int)); +extern int inet6_rthdr_getflags __P((const struct cmsghdr *, int)); +__END_DECLS + +#endif /* !_NETINET6_IN6_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/in6_gif.h b/ecos/packages/net/tcpip/current/include/netinet6/in6_gif.h new file mode 100644 index 0000000..ff3caf9 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/in6_gif.h @@ -0,0 +1,69 @@ +//========================================================================== +// +// include/netinet6_in6_gif.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in6_gif.h,v 1.1 1999/12/08 06:50:21 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETINET6_IN6_GIF_H_ +#define _NETINET6_IN6_GIF_H_ + +#define GIF_HLIM 30 + +int in6_gif_input __P((struct mbuf **, int *, int)); +int in6_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *)); + +#endif /*_NETINET6_IN6_GIF_H_*/ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/in6_ifattach.h b/ecos/packages/net/tcpip/current/include/netinet6/in6_ifattach.h new file mode 100644 index 0000000..45d96a1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/in6_ifattach.h @@ -0,0 +1,79 @@ +//========================================================================== +// +// include/netinet6_in6_ifattach.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in6_ifattach.h,v 1.1 1999/12/08 06:50:21 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETINET6_IN6_IFATTACH_H_ +#define _NETINET6_IN6_IFATTACH_H_ + +#ifdef _KERNEL +extern int found_first_ifid; + +int in6_ifattach_getifid __P((struct ifnet *)); +void in6_ifattach_p2p __P((void)); +void in6_ifattach __P((struct ifnet *, u_int, caddr_t, int)); +void in6_ifdetach __P((struct ifnet *)); +#endif /* _KERNEL */ + +#define IN6_IFT_LOOP 1 +#define IN6_IFT_P2P 2 +#define IN6_IFT_802 3 +#define IN6_IFT_P2P802 4 +#define IN6_IFT_ARCNET 5 + +#endif /* _NETINET6_IN6_IFATTACH_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/in6_pcb.h b/ecos/packages/net/tcpip/current/include/netinet6/in6_pcb.h new file mode 100644 index 0000000..29cca2e --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/in6_pcb.h @@ -0,0 +1,207 @@ +//========================================================================== +// +// include/netinet6_in6_pcb.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in6_pcb.h,v 1.1 1999/12/08 06:50:21 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET6_IN6_PCB_H_ +#define _NETINET6_IN6_PCB_H_ + +#include <sys/queue.h> + +/* + * Common structure pcb for internet protocol implementation. + * Here are stored pointers to local and foreign host table + * entries, local and foreign socket numbers, and pointers + * up (to a socket structure) and down (to a protocol-specific) + * control block. + */ +struct icmp6_filter; +struct inpcbpolicy; + +struct in6pcb { + struct in6pcb *in6p_next, *in6p_prev; + /* pointers to other pcb's */ + struct in6pcb *in6p_head; /* pointer back to chain of + in6pcb's for this protocol */ + struct in6_addr in6p_faddr; /* foreign host table entry */ + u_short in6p_fport; /* foreign port */ + struct in6_addr in6p_laddr; /* local host table entry */ + u_short in6p_lport; /* local port */ + u_int32_t in6p_flowinfo; /* priority and flowlabel */ + struct socket *in6p_socket; /* back pointer to socket */ + caddr_t in6p_ppcb; /* pointer to per-protocol pcb */ + struct route_in6 in6p_route; /* placeholder for routing entry */ + int in6p_flags; /* generic IP6/datagram flags */ + int in6p_hops; /* default hop limit */ + struct ip6_hdr in6p_ip6; /* header prototype */ + struct mbuf *in6p_options; /* IP6 options */ + struct ip6_pktopts *in6p_outputopts; /* IP6 options for outgoing packets */ + struct ip6_moptions *in6p_moptions; /* IP6 multicast options */ + u_short in6p_ifindex; + /* should move the following just after next/prev */ + LIST_ENTRY(in6pcb) in6p_hlist; /* hash chain */ + u_long in6p_hash; /* hash value */ +#if 1 /*IPSEC*/ + struct inpcbpolicy *in6p_sp; /* security policy. */ +#endif + struct icmp6_filter *in6p_icmp6filt; + int in6p_cksum; /* IPV6_CHECKSUM setsockopt */ +}; + +#define in6p_ip6_nxt in6p_ip6.ip6_nxt /* for KAME src sync over BSD*'s */ + +/* flags in in6p_flags */ +#define IN6P_RECVOPTS 0x01 /* receive incoming IP6 options */ +#define IN6P_RECVRETOPTS 0x02 /* receive IP6 options for reply */ +#define IN6P_RECVDSTADDR 0x04 /* receive IP6 dst address */ +#define IN6P_HIGHPORT 0x10 /* user wants "high" port binding */ +#define IN6P_LOWPORT 0x20 /* user wants "low" port binding */ +#define IN6P_ANONPORT 0x40 /* port chosen for user */ +#define IN6P_FAITH 0x80 /* accept FAITH'ed connections */ +#define IN6P_PKTINFO 0x010000 +#define IN6P_HOPLIMIT 0x020000 +#define IN6P_NEXTHOP 0x040000 +#define IN6P_HOPOPTS 0x080000 +#define IN6P_DSTOPTS 0x100000 +#define IN6P_RTHDR 0x200000 +#define IN6P_CONTROLOPTS (0x3f0000 | IN6P_RECVOPTS | IN6P_RECVRETOPTS | IN6P_RECVDSTADDR) + +#define IN6PLOOKUP_WILDCARD 1 +#define IN6PLOOKUP_SETLOCAL 2 + +/* compute hash value for foreign and local in6_addr and port */ +#define IN6_HASH(faddr, fport, laddr, lport) \ + (((faddr)->s6_addr32[0] ^ (faddr)->s6_addr32[1] ^ \ + (faddr)->s6_addr32[2] ^ (faddr)->s6_addr32[3] ^ \ + (laddr)->s6_addr32[0] ^ (laddr)->s6_addr32[1] ^ \ + (laddr)->s6_addr32[2] ^ (laddr)->s6_addr32[3]) \ + + (fport) + (lport)) + +#define sotoin6pcb(so) ((struct in6pcb *)(so)->so_pcb) + +#ifdef _KERNEL +void in6_losing __P((struct in6pcb *)); +int in6_pcballoc __P((struct socket *, struct in6pcb *)); +int in6_pcbbind __P((struct in6pcb *, struct mbuf *)); +int in6_pcbconnect __P((struct in6pcb *, struct mbuf *)); +void in6_pcbdetach __P((struct in6pcb *)); +void in6_pcbdisconnect __P((struct in6pcb *)); +struct in6pcb * + in6_pcblookup __P((struct in6pcb *, + struct in6_addr *, u_int, struct in6_addr *, + u_int, int)); +int in6_pcbnotify __P((struct in6pcb *, struct sockaddr *, + u_int, struct in6_addr *, u_int, int, + void (*)(struct in6pcb *, int))); +int in6_pcbsetport __P((struct in6_addr *, struct in6pcb *)); +void in6_rtchange __P((struct in6pcb *, int)); +void in6_setpeeraddr __P((struct in6pcb *, struct mbuf *)); +void in6_setsockaddr __P((struct in6pcb *, struct mbuf *)); +struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *, + struct ip6_pktopts *, + struct ip6_moptions *, + struct route_in6 *, + struct in6_addr *, int *)); +int in6_selecthlim __P((struct in6pcb *, struct ifnet *)); + +#ifndef TCP6 +extern struct rtentry * + in6_pcbrtentry __P((struct in6pcb *)); +extern struct in6pcb *in6_pcblookup_connect __P((struct in6pcb *, + struct in6_addr *, u_int, struct in6_addr *, u_int, int)); +extern struct in6pcb *in6_pcblookup_bind __P((struct in6pcb *, + struct in6_addr *, u_int, int)); +#endif +#endif /* _KERNEL */ + +#endif /* !_NETINET6_IN6_PCB_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/in6_prefix.h b/ecos/packages/net/tcpip/current/include/netinet6/in6_prefix.h new file mode 100644 index 0000000..1b3781a --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/in6_prefix.h @@ -0,0 +1,121 @@ +//========================================================================== +// +// include/netinet6_in6_prefix.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in6_prefix.h,v 1.1 1999/12/08 06:50:21 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, 1998 and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETINET6_IN6_PREFIX_H_ +#define _NETINET6_IN6_PREFIX_H_ + +struct rr_prefix { + struct ifprefix rp_ifpr; + LIST_ENTRY(rr_prefix) rp_entry; + LIST_HEAD(rp_addrhead, rp_addr) rp_addrhead; + struct sockaddr_in6 rp_prefix; /* prefix */ + u_int32_t rp_vltime; /* advertised valid lifetime */ + u_int32_t rp_pltime; /* advertised preferred lifetime */ + time_t rp_expire; /* expiration time of the prefix */ + time_t rp_preferred; /* preferred time of the prefix */ + struct in6_prflags rp_flags; + u_char rp_origin; /* from where this prefix info is obtained */ + struct rp_stateflags { + /* if some prefix should be added to this prefix */ + u_char addmark : 1; + u_char delmark : 1; /* if this prefix will be deleted */ + } rp_stateflags; +}; + +#define rp_type rp_ifpr.ifpr_type +#define rp_ifp rp_ifpr.ifpr_ifp +#define rp_plen rp_ifpr.ifpr_plen + +#define rp_raf rp_flags.prf_ra +#define rp_raf_onlink rp_flags.prf_ra.onlink +#define rp_raf_auto rp_flags.prf_ra.autonomous + +#define rp_statef_addmark rp_stateflags.addmark +#define rp_statef_delmark rp_stateflags.delmark + +#define rp_rrf rp_flags.prf_rr +#define rp_rrf_decrvalid rp_flags.prf_rr.decrvalid +#define rp_rrf_decrprefd rp_flags.prf_rr.decrprefd + +struct rp_addr { + LIST_ENTRY(rp_addr) ra_entry; + struct in6_addr ra_ifid; + struct in6_ifaddr *ra_addr; + struct ra_flags { + u_char anycast : 1; + } ra_flags; +}; + +#define ifpr2rp(ifpr) ((struct rr_prefix *)(ifpr)) +#define rp2ifpr(rp) ((struct ifprefix *)(rp)) + +#define RP_IN6(rp) (&(rp)->rp_prefix.sin6_addr) + +#define RR_INFINITE_LIFETIME 0xffffffff + + +LIST_HEAD(rr_prhead, rr_prefix); + +extern struct rr_prhead rr_prefix; + +void in6_rr_timer __P((void *)); +int delete_each_prefix __P((struct socket *so, struct rr_prefix *rpp, + u_char origin)); +#endif // _NETINET6_IN6_PREFIX_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/in6_var.h b/ecos/packages/net/tcpip/current/include/netinet6/in6_var.h new file mode 100644 index 0000000..5858346 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/in6_var.h @@ -0,0 +1,593 @@ +//========================================================================== +// +// include/netinet6_in6_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in6_var.h,v 1.6 1999/12/10 10:04:28 angelos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1985, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET6_IN6_VAR_H_ +#define _NETINET6_IN6_VAR_H_ + +/* + * Interface address, Internet version. One of these structures + * is allocated for each interface with an Internet address. + * The ifaddr structure contains the protocol-independent part + * of the structure and is assumed to be first. + */ + +/* + * pltime/vltime are just for future reference (required to implements 2 + * hour rule for hosts). they should never be modified by nd6_timeout or + * anywhere else. + * userland -> kernel: accept pltime/vltime + * kernel -> userland: throuw up everything + * in kernel: modify preferred/expire only + */ +struct in6_addrlifetime { + time_t ia6t_expire; /* valid lifetime expiration time */ + time_t ia6t_preferred; /* preferred lifetime expiration time */ + u_int32_t ia6t_vltime; /* valid lifetime */ + u_int32_t ia6t_pltime; /* prefix lifetime */ +}; + +struct in6_ifaddr { + struct ifaddr ia_ifa; /* protocol-independent info */ +#define ia_ifp ia_ifa.ifa_ifp +#define ia_flags ia_ifa.ifa_flags + struct sockaddr_in6 ia_addr; /* interface address */ + struct sockaddr_in6 ia_net; /* network number of interface */ + struct sockaddr_in6 ia_dstaddr; /* space for destination addr */ + struct sockaddr_in6 ia_prefixmask; /* prefix mask */ + u_int32_t ia_plen; /* prefix length */ + struct in6_ifaddr *ia_next; /* next in6 list of IP6 addresses */ + LIST_HEAD(in6_multihead, in6_multi) ia6_multiaddrs; + /* list of multicast addresses */ + int ia6_flags; + + struct in6_addrlifetime ia6_lifetime; /* NULL = infty */ + struct ifprefix *ia6_ifpr; /* back pointer to ifprefix */ +}; + +/* + * IPv6 interface statistics, as defined in RFC2465 Ipv6IfStatsEntry (p12). + */ +struct in6_ifstat { + u_quad_t ifs6_in_receive; /* # of total input datagram */ + u_quad_t ifs6_in_hdrerr; /* # of datagrams with invalid hdr */ + u_quad_t ifs6_in_toobig; /* # of datagrams exceeded MTU */ + u_quad_t ifs6_in_noroute; /* # of datagrams with no route */ + u_quad_t ifs6_in_addrerr; /* # of datagrams with invalid dst */ + u_quad_t ifs6_in_protounknown; /* # of datagrams with unknown proto */ + /* NOTE: increment on final dst if */ + u_quad_t ifs6_in_truncated; /* # of truncated datagrams */ + u_quad_t ifs6_in_discard; /* # of discarded datagrams */ + /* NOTE: fragment timeout is not here */ + u_quad_t ifs6_in_deliver; /* # of datagrams delivered to ULP */ + /* NOTE: increment on final dst if */ + u_quad_t ifs6_out_forward; /* # of datagrams forwarded */ + /* NOTE: increment on outgoing if */ + u_quad_t ifs6_out_request; /* # of outgoing datagrams from ULP */ + /* NOTE: does not include forwrads */ + u_quad_t ifs6_out_discard; /* # of discarded datagrams */ + u_quad_t ifs6_out_fragok; /* # of datagrams fragmented */ + u_quad_t ifs6_out_fragfail; /* # of datagrams failed on fragment */ + u_quad_t ifs6_out_fragcreat; /* # of fragment datagrams */ + /* NOTE: this is # after fragment */ + u_quad_t ifs6_reass_reqd; /* # of incoming fragmented packets */ + /* NOTE: increment on final dst if */ + u_quad_t ifs6_reass_ok; /* # of reassembled packets */ + /* NOTE: this is # after reass */ + /* NOTE: increment on final dst if */ + u_quad_t ifs6_reass_fail; /* # of reass failures */ + /* NOTE: may not be packet count */ + /* NOTE: increment on final dst if */ + u_quad_t ifs6_in_mcast; /* # of inbound multicast datagrams */ + u_quad_t ifs6_out_mcast; /* # of outbound multicast datagrams */ +}; + +/* + * ICMPv6 interface statistics, as defined in RFC2466 Ipv6IfIcmpEntry. + * XXX: I'm not sure if this file is the right place for this structure... + */ +struct icmp6_ifstat { + /* + * Input statistics + */ + /* ipv6IfIcmpInMsgs, total # of input messages */ + u_quad_t ifs6_in_msg; + /* ipv6IfIcmpInErrors, # of input error messages */ + u_quad_t ifs6_in_error; + /* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */ + u_quad_t ifs6_in_dstunreach; + /* ipv6IfIcmpInAdminProhibs, # of input administratively prohibited errs */ + u_quad_t ifs6_in_adminprohib; + /* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */ + u_quad_t ifs6_in_timeexceed; + /* ipv6IfIcmpInParmProblems, # of input parameter problem errors */ + u_quad_t ifs6_in_paramprob; + /* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */ + u_quad_t ifs6_in_pkttoobig; + /* ipv6IfIcmpInEchos, # of input echo requests */ + u_quad_t ifs6_in_echo; + /* ipv6IfIcmpInEchoReplies, # of input echo replies */ + u_quad_t ifs6_in_echoreply; + /* ipv6IfIcmpInRouterSolicits, # of input router solicitations */ + u_quad_t ifs6_in_routersolicit; + /* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */ + u_quad_t ifs6_in_routeradvert; + /* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */ + u_quad_t ifs6_in_neighborsolicit; + /* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advertisements */ + u_quad_t ifs6_in_neighboradvert; + /* ipv6IfIcmpInRedirects, # of input redirects */ + u_quad_t ifs6_in_redirect; + /* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */ + u_quad_t ifs6_in_mldquery; + /* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */ + u_quad_t ifs6_in_mldreport; + /* ipv6IfIcmpInGroupMembReductions, # of input MLD done */ + u_quad_t ifs6_in_mlddone; + + /* + * Output statistics. We should solve unresolved routing problem... + */ + /* ipv6IfIcmpOutMsgs, total # of output messages */ + u_quad_t ifs6_out_msg; + /* ipv6IfIcmpOutErrors, # of output error messages */ + u_quad_t ifs6_out_error; + /* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */ + u_quad_t ifs6_out_dstunreach; + /* ipv6IfIcmpOutAdminProhibs, # of output administratively prohibited errs */ + u_quad_t ifs6_out_adminprohib; + /* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */ + u_quad_t ifs6_out_timeexceed; + /* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */ + u_quad_t ifs6_out_paramprob; + /* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */ + u_quad_t ifs6_out_pkttoobig; + /* ipv6IfIcmpOutEchos, # of output echo requests */ + u_quad_t ifs6_out_echo; + /* ipv6IfIcmpOutEchoReplies, # of output echo replies */ + u_quad_t ifs6_out_echoreply; + /* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */ + u_quad_t ifs6_out_routersolicit; + /* ipv6IfIcmpOutRouterAdvertisements, # of output router advertisements */ + u_quad_t ifs6_out_routeradvert; + /* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */ + u_quad_t ifs6_out_neighborsolicit; + /* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advertisements */ + u_quad_t ifs6_out_neighboradvert; + /* ipv6IfIcmpOutRedirects, # of output redirects */ + u_quad_t ifs6_out_redirect; + /* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */ + u_quad_t ifs6_out_mldquery; + /* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */ + u_quad_t ifs6_out_mldreport; + /* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */ + u_quad_t ifs6_out_mlddone; +}; + +struct in6_ifreq { + char ifr_name[IFNAMSIZ]; + union { + struct sockaddr_in6 ifru_addr; + struct sockaddr_in6 ifru_dstaddr; + short ifru_flags; + int ifru_flags6; + int ifru_metric; + caddr_t ifru_data; + struct in6_addrlifetime ifru_lifetime; + struct in6_ifstat ifru_stat; + struct icmp6_ifstat ifru_icmp6stat; + } ifr_ifru; +}; + +struct in6_aliasreq { + char ifra_name[IFNAMSIZ]; + struct sockaddr_in6 ifra_addr; + struct sockaddr_in6 ifra_dstaddr; + struct sockaddr_in6 ifra_prefixmask; + int ifra_flags; + struct in6_addrlifetime ifra_lifetime; +}; + +/* prefix type macro */ +#define IN6_PREFIX_ND 1 +#define IN6_PREFIX_RR 2 + +/* + * prefix related flags passed between kernel(NDP related part) and + * user land command(ifconfig) and daemon(rtadvd). + */ +struct in6_prflags { + struct prf_ra { + u_char onlink : 1; + u_char autonomous : 1; + u_char reserved : 6; + } prf_ra; + u_char prf_reserved1; + u_short prf_reserved2; + /* want to put this on 4byte offset */ + struct prf_rr { + u_char decrvalid : 1; + u_char decrprefd : 1; + u_char reserved : 6; + } prf_rr; + u_char prf_reserved3; + u_short prf_reserved4; +}; + +struct in6_prefixreq { + char ipr_name[IFNAMSIZ]; + u_char ipr_origin; + u_char ipr_plen; + u_int32_t ipr_vltime; + u_int32_t ipr_pltime; + struct in6_prflags ipr_flags; + struct sockaddr_in6 ipr_prefix; +}; + +#define PR_ORIG_RA 0 +#define PR_ORIG_RR 1 +#define PR_ORIG_STATIC 2 +#define PR_ORIG_KERNEL 3 + +#define ipr_raf_onlink ipr_flags.prf_ra.onlink +#define ipr_raf_auto ipr_flags.prf_ra.autonomous + +#define ipr_statef_onlink ipr_flags.prf_state.onlink + +#define ipr_rrf_decrvalid ipr_flags.prf_rr.decrvalid +#define ipr_rrf_decrprefd ipr_flags.prf_rr.decrprefd + +struct in6_rrenumreq { + char irr_name[IFNAMSIZ]; + u_char irr_origin; + u_char irr_m_len; /* match len for matchprefix */ + u_char irr_m_minlen; /* minlen for matching prefix */ + u_char irr_m_maxlen; /* maxlen for matching prefix */ + u_char irr_u_uselen; /* uselen for adding prefix */ + u_char irr_u_keeplen; /* keeplen from matching prefix */ + struct irr_raflagmask { + u_char onlink : 1; + u_char autonomous : 1; + u_char reserved : 6; + } irr_raflagmask; + u_int32_t irr_vltime; + u_int32_t irr_pltime; + struct in6_prflags irr_flags; + struct sockaddr_in6 irr_matchprefix; + struct sockaddr_in6 irr_useprefix; +}; + +#define irr_raf_mask_onlink irr_raflagmask.onlink +#define irr_raf_mask_auto irr_raflagmask.autonomous +#define irr_raf_mask_reserved irr_raflagmask.reserved + +#define irr_raf_onlink irr_flags.prf_ra.onlink +#define irr_raf_auto irr_flags.prf_ra.autonomous + +#define irr_statef_onlink irr_flags.prf_state.onlink + +#define irr_rrf irr_flags.prf_rr +#define irr_rrf_decrvalid irr_flags.prf_rr.decrvalid +#define irr_rrf_decrprefd irr_flags.prf_rr.decrprefd + +/* + * Given a pointer to an in6_ifaddr (ifaddr), + * return a pointer to the addr as a sockaddr_in6 + */ +#define IA6_IN6(ia) (&((ia)->ia_addr.sin6_addr)) +#define IA6_DSTIN6(ia) (&((ia)->ia_dstaddr.sin6_addr)) +#define IA6_MASKIN6(ia) (&((ia)->ia_prefixmask.sin6_addr)) +#define IA6_SIN6(ia) (&((ia)->ia_addr)) +#define IA6_DSTSIN6(ia) (&((ia)->ia_dstaddr)) +#define IFA_IN6(x) (&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr) +#define IFA_DSTIN6(x) (&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr) + +#define IFPR_IN6(x) (&((struct sockaddr_in6 *)((x)->ifpr_prefix))->sin6_addr) + +#ifdef _KERNEL +#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \ + (((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \ + (((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \ + (((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \ + (((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 ) +#endif + +#define SIOCSIFADDR_IN6 _IOW('i', 12, struct in6_ifreq) +#define SIOCGIFADDR_IN6 _IOWR('i', 33, struct in6_ifreq) +#define SIOCSIFDSTADDR_IN6 _IOW('i', 14, struct in6_ifreq) +#define SIOCGIFDSTADDR_IN6 _IOWR('i', 34, struct in6_ifreq) +#define SIOCSIFNETMASK_IN6 _IOW('i', 22, struct in6_ifreq) +#define SIOCGIFNETMASK_IN6 _IOWR('i', 37, struct in6_ifreq) + +#define SIOCDIFADDR_IN6 _IOW('i', 25, struct in6_ifreq) +#define SIOCAIFADDR_IN6 _IOW('i', 26, struct in6_aliasreq) + +#define SIOCSIFPHYADDR_IN6 _IOW('i', 70, struct in6_aliasreq) +#define SIOCGIFPSRCADDR_IN6 _IOWR('i', 71, struct in6_ifreq) +#define SIOCGIFPDSTADDR_IN6 _IOWR('i', 72, struct in6_ifreq) + +#define SIOCGIFAFLAG_IN6 _IOWR('i', 73, struct in6_ifreq) + +#define SIOCGDRLST_IN6 _IOWR('i', 74, struct in6_drlist) +#define SIOCGPRLST_IN6 _IOWR('i', 75, struct in6_prlist) +#define SIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ndireq) +#define SIOCSNDFLUSH_IN6 _IOWR('i', 77, struct in6_ifreq) +#define SIOCGNBRINFO_IN6 _IOWR('i', 78, struct in6_nbrinfo) +#define SIOCSPFXFLUSH_IN6 _IOWR('i', 79, struct in6_ifreq) +#define SIOCSRTRFLUSH_IN6 _IOWR('i', 80, struct in6_ifreq) + +#define SIOCGIFALIFETIME_IN6 _IOWR('i', 81, struct in6_ifreq) +#define SIOCSIFALIFETIME_IN6 _IOWR('i', 82, struct in6_ifreq) +#define SIOCGIFSTAT_IN6 _IOWR('i', 83, struct in6_ifreq) +#define SIOCGIFSTAT_ICMP6 _IOWR('i', 84, struct in6_ifreq) + +#define SIOCSIFPREFIX_IN6 _IOW('i', 100, struct in6_prefixreq) /* set */ +#define SIOCGIFPREFIX_IN6 _IOWR('i', 101, struct in6_prefixreq) /* get */ +#define SIOCDIFPREFIX_IN6 _IOW('i', 102, struct in6_prefixreq) /* del */ +#define SIOCAIFPREFIX_IN6 _IOW('i', 103, struct in6_rrenumreq) /* add */ +#define SIOCCIFPREFIX_IN6 _IOW('i', 104, \ + struct in6_rrenumreq) /* change */ +#define SIOCSGIFPREFIX_IN6 _IOW('i', 105, \ + struct in6_rrenumreq) /* set global */ + +#define SIOCGETSGCNT_IN6 _IOWR('u', 106, \ + struct sioc_sg_req6) /* get s,g pkt cnt */ +#define SIOCGETMIFCNT_IN6 _IOWR('u', 107, \ + struct sioc_mif_req6) /* get pkt cnt per if */ + +#define IN6_IFF_ANYCAST 0x01 /* anycast address */ +#define IN6_IFF_TENTATIVE 0x02 /* tentative address */ +#define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */ +#define IN6_IFF_DETACHED 0x08 /* may be detached from the link */ +#define IN6_IFF_DEPRECATED 0x10 /* deprecated address */ + +/* do not input/output */ +#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED) + +#ifdef _KERNEL +extern struct in6_ifaddr *in6_ifaddr; + +extern struct in6_ifstat **in6_ifstat; +extern size_t in6_ifstatmax; +extern struct icmp6stat icmp6stat; +extern struct icmp6_ifstat **icmp6_ifstat; +extern size_t icmp6_ifstatmax; +#define in6_ifstat_inc(ifp, tag) \ +do { \ + if ((ifp) && (ifp)->if_index <= if_index \ + && (ifp)->if_index < in6_ifstatmax \ + && in6_ifstat && in6_ifstat[(ifp)->if_index]) { \ + in6_ifstat[(ifp)->if_index]->tag++; \ + } \ +} while (0) + +extern struct ifqueue ip6intrq; /* IP6 packet input queue */ +extern struct in6_addr zeroin6_addr; +extern u_char inet6ctlerrmap[]; +extern unsigned long in6_maxmtu; + +/* + * Macro for finding the internet address structure (in6_ifaddr) corresponding + * to a given interface (ifnet structure). + */ +#define IFP_TO_IA6(ifp, ia) \ +/* struct ifnet *ifp; */ \ +/* struct in6_ifaddr *ia; */ \ +do { \ + struct ifaddr *ifa; \ + for (ifa = (ifp)->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) { \ + if (!ifa->ifa_addr) \ + continue; \ + if (ifa->ifa_addr->sa_family == AF_INET6) \ + break; \ + } \ + (ia) = (struct in6_ifaddr *)ifa; \ +} while (0) +#endif /* _KERNEL */ + +/* + * Multi-cast membership entry. One for each group/ifp that a PCB + * belongs to. + */ +struct in6_multi_mship { + struct in6_multi *i6mm_maddr; /* Multicast address pointer */ + LIST_ENTRY(in6_multi_mship) i6mm_chain; /* multicast options chain */ +}; + +struct in6_multi { + LIST_ENTRY(in6_multi) in6m_entry; /* list glue */ + struct in6_addr in6m_addr; /* IP6 multicast address */ + struct ifnet *in6m_ifp; /* back pointer to ifnet */ + struct in6_ifaddr *in6m_ia; /* back pointer to in6_ifaddr */ + u_int in6m_refcount; /* # membership claims by sockets */ + u_int in6m_state; /* state of the membership */ + u_int in6m_timer; /* MLD6 listener report timer */ +}; + +#ifdef _KERNEL +/* + * Structure used by macros below to remember position when stepping through + * all of eht in6_multi records. + */ +struct in6_multistep { + struct in6_ifaddr *i_ia; + struct in6_multi *i_in6m; +}; + +/* + * Macros for looking up the in6_multi record for a given IP6 multicast + * address on a given interface. If no matching record is found, "in6m" + * returns NLL. + */ + +#define IN6_LOOKUP_MULTI(addr, ifp, in6m) \ +/* struct in6_addr addr; */ \ +/* struct ifnet *ifp; */ \ +/* struct in6_multi *in6m; */ \ +do { \ + register struct in6_ifaddr *ia; \ + \ + IFP_TO_IA6((ifp), ia); \ + if (ia == NULL) \ + (in6m) = NULL; \ + else \ + for ((in6m) = ia->ia6_multiaddrs.lh_first; \ + (in6m) != NULL && \ + !IN6_ARE_ADDR_EQUAL(&(in6m)->in6m_addr, &(addr)); \ + (in6m) = in6m->in6m_entry.le_next) \ + continue; \ +} while (0) + +/* + * Macro to step through all of the in6_multi records, one at a time. + * The current position is remembered in "step", which the caller must + * provide. IN6_FIRST_MULTI(), below, must be called to initialize "step" + * and get the first record. Both macros return a NULL "in6m" when there + * are no remaining records. + */ +#define IN6_NEXT_MULTI(step, in6m) \ +/* struct in6_multistep step; */ \ +/* struct in6_multi *in6m; */ \ +do { \ + if (((in6m) = (step).i_in6m) != NULL) \ + (step).i_in6m = (in6m)->in6m_entry.le_next; \ + else \ + while ((step).i_ia != NULL) { \ + (in6m) = (step).i_ia->ia6_multiaddrs.lh_first; \ + (step).i_ia = (step).i_ia->ia_next; \ + if ((in6m) != NULL) { \ + (step).i_in6m = (in6m)->in6m_entry.le_next; \ + break; \ + } \ + } \ +} while (0) + +#define IN6_FIRST_MULTI(step, in6m) \ +/* struct in6_multistep step; */ \ +/* struct in6_multi *in6m */ \ +do { \ + (step).i_ia = in6_ifaddr; \ + (step).i_in6m = NULL; \ + IN6_NEXT_MULTI((step), (in6m)); \ +} while (0) + +int in6_ifinit __P((struct ifnet *, + struct in6_ifaddr *, struct sockaddr_in6 *, int)); +struct in6_multi *in6_addmulti __P((struct in6_addr *, struct ifnet *, + int *)); +void in6_delmulti __P((struct in6_multi *)); +void in6_ifscrub __P((struct ifnet *, struct in6_ifaddr *)); +extern int in6_ifindex2scopeid __P((int)); +extern int in6_mask2len __P((struct in6_addr *)); +extern void in6_len2mask __P((struct in6_addr *, int)); +int in6_control __P((struct socket *, + u_long, caddr_t, struct ifnet *, struct proc *)); +void in6_savemkludge __P((struct in6_ifaddr *)); +void in6_setmaxmtu __P((void)); +void in6_restoremkludge __P((struct in6_ifaddr *, struct ifnet *)); +struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *)); +struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *, + struct in6_addr *)); +char *ip6_sprintf __P((struct in6_addr *)); +int in6_matchlen __P((struct in6_addr *, struct in6_addr *)); +int in6_are_prefix_equal __P((struct in6_addr *p1, struct in6_addr *p2, + int len)); +void in6_prefixlen2mask __P((struct in6_addr *maskp, int len)); +int in6_prefix_ioctl __P((struct socket *so, u_long cmd, caddr_t data, + struct ifnet *ifp)); +int in6_prefix_add_ifid __P((int iilen, struct in6_ifaddr *ia)); +void in6_prefix_remove_ifid __P((int iilen, struct in6_ifaddr *ia)); +#endif /* _KERNEL */ + +#endif /* _NETINET6_IN6_VAR_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ip6.h b/ecos/packages/net/tcpip/current/include/netinet6/ip6.h new file mode 100644 index 0000000..7c923cc --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ip6.h @@ -0,0 +1,316 @@ +//========================================================================== +// +// include/netinet6_ipv6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip6.h,v 1.1 1999/12/08 06:50:21 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET6_IPV6_H_ +#define _NETINET6_IPV6_H_ + +/* + * Definition for internet protocol version 6. + * RFC 2460 + */ + +struct ip6_hdr { + union { + struct ip6_hdrctl { + u_int32_t ip6_un1_flow; /* 20 bits of flow-ID */ + u_int16_t ip6_un1_plen; /* payload length */ + u_int8_t ip6_un1_nxt; /* next header */ + u_int8_t ip6_un1_hlim; /* hop limit */ + } ip6_un1; + u_int8_t ip6_un2_vfc; /* 4 bits version, 4 bits class */ + } ip6_ctlun; + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ +}; + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +#define IPV6_VERSION 0x60 +#define IPV6_VERSION_MASK 0xf0 + +#if BYTE_ORDER == BIG_ENDIAN +#define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */ +#define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */ +#else +#if BYTE_ORDER == LITTLE_ENDIAN +#define IPV6_FLOWINFO_MASK 0xffffff0f /* flow info (28 bits) */ +#define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */ +#endif /* LITTLE_ENDIAN */ +#endif +#if 1 +/* ECN bits proposed by Sally Floyd */ +#define IP6TOS_CE 0x01 /* congestion experienced */ +#define IP6TOS_ECT 0x02 /* ECN-capable transport */ +#endif + +/* + * Extension Headers + */ + +struct ip6_ext { + u_char ip6e_nxt; + u_char ip6e_len; +}; + +/* Hop-by-Hop options header */ +/* XXX should we pad it to force alignment on an 8-byte boundary? */ +struct ip6_hbh { + u_int8_t ip6h_nxt; /* next header */ + u_int8_t ip6h_len; /* length in units of 8 octets */ + /* followed by options */ +}; + +/* Destination options header */ +/* XXX should we pad it to force alignment on an 8-byte boundary? */ +struct ip6_dest { + u_int8_t ip6d_nxt; /* next header */ + u_int8_t ip6d_len; /* length in units of 8 octets */ + /* followed by options */ +}; + +/* Option types and related macros */ +#define IP6OPT_PAD1 0x00 /* 00 0 00000 */ +#define IP6OPT_PADN 0x01 /* 00 0 00001 */ +#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ +#define IP6OPT_JUMBO_LEN 6 +#define IP6OPT_RTALERT 0x05 /* 00 0 00101 */ +#define IP6OPT_RTALERT_LEN 4 +#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ +#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ +#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ +#define IP6OPT_MINLEN 2 + +#define IP6OPT_TYPE(o) ((o) & 0xC0) +#define IP6OPT_TYPE_SKIP 0x00 +#define IP6OPT_TYPE_DISCARD 0x40 +#define IP6OPT_TYPE_FORCEICMP 0x80 +#define IP6OPT_TYPE_ICMP 0xC0 + +#define IP6OPT_MUTABLE 0x20 + +/* Routing header */ +struct ip6_rthdr { + u_int8_t ip6r_nxt; /* next header */ + u_int8_t ip6r_len; /* length in units of 8 octets */ + u_int8_t ip6r_type; /* routing type */ + u_int8_t ip6r_segleft; /* segments left */ + /* followed by routing type specific data */ +}; + +/* Type 0 Routing header */ +struct ip6_rthdr0 { + u_int8_t ip6r0_nxt; /* next header */ + u_int8_t ip6r0_len; /* length in units of 8 octets */ + u_int8_t ip6r0_type; /* always zero */ + u_int8_t ip6r0_segleft; /* segments left */ + u_int8_t ip6r0_reserved; /* reserved field */ + u_int8_t ip6r0_slmap[3]; /* strict/loose bit map */ + struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */ +}; + +/* Fragment header */ +struct ip6_frag { + u_int8_t ip6f_nxt; /* next header */ + u_int8_t ip6f_reserved; /* reserved field */ + u_int16_t ip6f_offlg; /* offset, reserved, and flag */ + u_int32_t ip6f_ident; /* identification */ +}; + +#if BYTE_ORDER == BIG_ENDIAN +#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */ +#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ +#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ +#else /* BYTE_ORDER == LITTLE_ENDIAN */ +#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */ +#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */ +#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */ +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +/* + * Internet implementation parameters. + */ +#define IPV6_MAXHLIM 255 /* maximun hoplimit */ +#define IPV6_DEFHLIM 64 /* default hlim */ +#define IPV6_FRAGTTL 120 /* ttl for fragment packets, in slowtimo tick */ +#define IPV6_HLIMDEC 1 /* subtracted when forwaeding */ + +#define IPV6_MMTU 1280 /* minimal MTU and reassembly. 1024 + 256 */ +#define IPV6_MAXPACKET 65535 /* ip6 max packet size without Jumbo payload*/ + +/* + * IP6_EXTHDR_CHECK ensures that region between the IP6 header and the + * target header (including IPv6 itself, extension headers and + * TCP/UDP/ICMP6 headers) are continuous. KAME requires drivers + * to store incoming data into one internal mbuf or one or more external + * mbufs(never into two or more internal mbufs). Thus, the third case is + * supposed to never be matched but is prepared just in case. + */ + +#define IP6_EXTHDR_CHECK(m, off, hlen, ret) \ +do { \ + if ((m)->m_next != NULL) { \ + if (((m)->m_flags & M_LOOP) && \ + ((m)->m_len < (off) + (hlen)) && \ + (((m) = m_pullup((m), (off) + (hlen))) == NULL)) { \ + ip6stat.ip6s_exthdrtoolong++; \ + return ret; \ + } else if ((m)->m_flags & M_EXT) { \ + if ((m)->m_len < (off) + (hlen)) { \ + ip6stat.ip6s_exthdrtoolong++; \ + m_freem(m); \ + return ret; \ + } \ + } else { \ + if ((m)->m_len < (off) + (hlen)) { \ + ip6stat.ip6s_exthdrtoolong++; \ + m_freem(m); \ + return ret; \ + } \ + } \ + } \ + else { \ + if ((m)->m_len < (off) + (hlen)) { \ + ip6stat.ip6s_tooshort++; \ + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); \ + m_freem(m); \ + return ret; \ + } \ + } \ +} while (0) + +#ifdef __NetBSD__ +/* + * IP6_EXTHDR_GET ensures that intermediate protocol header (from "off" to + * "len") is located in single mbuf, on contiguous memory region. + * The pointer to the region will be returned to pointer variable "val", + * with type "typ". + * IP6_EXTHDR_GET0 does the same, except that it aligns the structure at the + * very top of mbuf. GET0 is likely to make memory copy than GET. + * + * XXX we're now testing this, needs m_pulldown() + */ +#define IP6_EXTHDR_GET(val, typ, m, off, len) \ +do { \ + struct mbuf *t; \ + int tmp; \ + t = m_pulldown((m), (off), (len), &tmp); \ + if (t) { \ + if (t->m_len < tmp + (len)) \ + panic("m_pulldown malfunction"); \ + (val) = (typ)(mtod(t, caddr_t) + tmp); \ + } else \ + (val) = (typ)NULL; \ +} while (0) + +#define IP6_EXTHDR_GET0(val, typ, m, off, len) \ +do { \ + struct mbuf *t; \ + t = m_pulldown((m), (off), (len), NULL); \ + if (t) { \ + if (t->m_len < (len)) \ + panic("m_pulldown malfunction"); \ + (val) = (typ)mtod(t, caddr_t); \ + } else \ + (val) = (typ)NULL; \ +} while (0) + +#endif /*NetBSD*/ + +#endif /* not _NETINET_IPV6_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ip6_mroute.h b/ecos/packages/net/tcpip/current/include/netinet6/ip6_mroute.h new file mode 100644 index 0000000..b50f1a1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ip6_mroute.h @@ -0,0 +1,277 @@ +//========================================================================== +// +// include/netinet6_ip6_mroute.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* $OpenBSD: ip6_mroute.h,v 1.2 1999/12/10 10:04:28 angelos Exp $ */ + +/* + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* BSDI ip_mroute.h,v 2.5 1996/10/11 16:01:48 pjd Exp */ + +/* + * Definitions for IP multicast forwarding. + * + * Written by David Waitzman, BBN Labs, August 1988. + * Modified by Steve Deering, Stanford, February 1989. + * Modified by Ajit Thyagarajan, PARC, August 1993. + * Modified by Ajit Thyagarajan, PARC, August 1994. + * Modified by Ahmed Helmy, USC, September 1996. + * + * MROUTING Revision: 1.2 + */ + +#ifndef _NETINET6_IP6_MROUTE_H_ +#define _NETINET6_IP6_MROUTE_H_ + +/* + * Multicast Routing set/getsockopt commands. + */ +#define MRT6_INIT 100 /* initialize forwarder */ +#define MRT6_DONE 101 /* shut down forwarder */ +#define MRT6_ADD_MIF 102 /* add multicast interface */ +#define MRT6_DEL_MIF 103 /* delete multicast interface */ +#define MRT6_ADD_MFC 104 /* insert forwarding cache entry */ +#define MRT6_DEL_MFC 105 /* delete forwarding cache entry */ +#define MRT6_PIM 107 /* enable pim code */ + +#if BSD >= 199103 +#define GET_TIME(t) microtime(&t) +#elif defined(sun) +#define GET_TIME(t) uniqtime(&t) +#else +#define GET_TIME(t) ((t) = time) +#endif + +/* + * Types and macros for handling bitmaps with one bit per multicast interface. + */ +typedef u_short mifi_t; /* type of a mif index */ +#define MAXMIFS 64 + +#ifndef IF_SETSIZE +#define IF_SETSIZE 256 +#endif + +typedef long if_mask; +#define NIFBITS (sizeof(if_mask) * NBBY) /* bits per mask */ + +#ifndef howmany +#define howmany(x, y) (((x) + ((y) - 1)) / (y)) +#endif + +typedef struct if_set { + fd_mask ifs_bits[howmany(IF_SETSIZE, NIFBITS)]; +} if_set; + +#define IF_SET(n, p) ((p)->ifs_bits[(n)/NIFBITS] |= (1 << ((n) % NIFBITS))) +#define IF_CLR(n, p) ((p)->ifs_bits[(n)/NIFBITS] &= ~(1 << ((n) % NIFBITS))) +#define IF_ISSET(n, p) ((p)->ifs_bits[(n)/NIFBITS] & (1 << ((n) % NIFBITS))) +#define IF_COPY(f, t) bcopy(f, t, sizeof(*(f))) +#define IF_ZERO(p) bzero(p, sizeof(*(p))) + +/* + * Argument structure for MRT6_ADD_IF. + */ +struct mif6ctl { + mifi_t mif6c_mifi; /* the index of the mif to be added */ + u_char mif6c_flags; /* MIFF_ flags defined below */ + u_short mif6c_pifi; /* the index of the physical IF */ +#ifdef notyet + u_int mif6c_rate_limit; /* max rate */ +#endif +}; + +#define MIFF_REGISTER 0x1 /* mif represents a register end-point */ + +/* + * Argument structure for MRT6_ADD_MFC and MRT6_DEL_MFC + */ +struct mf6cctl { + struct sockaddr_in6 mf6cc_origin; /* IPv6 origin of mcasts */ + struct sockaddr_in6 mf6cc_mcastgrp; /* multicast group associated */ + mifi_t mf6cc_parent; /* incoming ifindex */ + struct if_set mf6cc_ifset; /* set of forwarding ifs */ +}; + +/* + * The kernel's multicast routing statistics. + */ +struct mrt6stat { + u_quad_t mrt6s_mfc_lookups; /* # forw. cache hash table hits */ + u_quad_t mrt6s_mfc_misses; /* # forw. cache hash table misses */ + u_quad_t mrt6s_upcalls; /* # calls to mrouted */ + u_quad_t mrt6s_no_route; /* no route for packet's origin */ + u_quad_t mrt6s_bad_tunnel; /* malformed tunnel options */ + u_quad_t mrt6s_cant_tunnel; /* no room for tunnel options */ + u_quad_t mrt6s_wrong_if; /* arrived on wrong interface */ + u_quad_t mrt6s_upq_ovflw; /* upcall Q overflow */ + u_quad_t mrt6s_cache_cleanups; /* # entries with no upcalls */ + u_quad_t mrt6s_drop_sel; /* pkts dropped selectively */ + u_quad_t mrt6s_q_overflow; /* pkts dropped - Q overflow */ + u_quad_t mrt6s_pkt2large; /* pkts dropped - size > BKT SIZE */ + u_quad_t mrt6s_upq_sockfull; /* upcalls dropped - socket full */ +}; + +/* + * Struct used to communicate from kernel to multicast router + * note the convenient similarity to an IPv6 header. + */ +struct mrt6msg { + u_long unused1; + u_char im6_msgtype; /* what type of message */ +#define MRT6MSG_NOCACHE 1 +#define MRT6MSG_WRONGMIF 2 +#define MRT6MSG_WHOLEPKT 3 /* used for user level encap*/ + u_char im6_mbz; /* must be zero */ + u_char im6_mif; /* mif rec'd on */ + u_char unused2; + struct in6_addr im6_src, im6_dst; +}; + +/* + * Argument structure used by multicast routing daemon to get src-grp + * packet counts + */ +struct sioc_sg_req6 { + struct sockaddr_in6 src; + struct sockaddr_in6 grp; + u_quad_t pktcnt; + u_quad_t bytecnt; + u_quad_t wrong_if; +}; + +/* + * Argument structure used by mrouted to get mif pkt counts + */ +struct sioc_mif_req6 { + mifi_t mifi; /* mif number */ + u_quad_t icount; /* Input packet count on mif */ + u_quad_t ocount; /* Output packet count on mif */ + u_quad_t ibytes; /* Input byte count on mif */ + u_quad_t obytes; /* Output byte count on mif */ +}; + +#if defined(_KERNEL) || defined(KERNEL) +/* + * The kernel's multicast-interface structure. + */ +struct mif6 { + u_char m6_flags; /* MIFF_ flags defined above */ + u_int m6_rate_limit; /* max rate */ +#ifdef notyet + struct tbf *m6_tbf; /* token bucket structure at intf. */ +#endif + struct in6_addr m6_lcl_addr; /* local interface address */ + struct ifnet *m6_ifp; /* pointer to interface */ + u_quad_t m6_pkt_in; /* # pkts in on interface */ + u_quad_t m6_pkt_out; /* # pkts out on interface */ + u_quad_t m6_bytes_in; /* # bytes in on interface */ + u_quad_t m6_bytes_out; /* # bytes out on interface */ + struct route_in6 m6_route;/* cached route if this is a tunnel */ +#ifdef notyet + u_int m6_rsvp_on; /* RSVP listening on this vif */ + struct socket *m6_rsvpd; /* RSVP daemon socket */ +#endif +}; + +/* + * The kernel's multicast forwarding cache entry structure + */ +struct mf6c { + struct sockaddr_in6 mf6c_origin; /* IPv6 origin of mcasts */ + struct sockaddr_in6 mf6c_mcastgrp; /* multicast group associated*/ + mifi_t mf6c_parent; /* incoming IF */ + struct if_set mf6c_ifset; /* set of outgoing IFs */ + + u_quad_t mf6c_pkt_cnt; /* pkt count for src-grp */ + u_quad_t mf6c_byte_cnt; /* byte count for src-grp */ + u_quad_t mf6c_wrong_if; /* wrong if for src-grp */ + int mf6c_expire; /* time to clean entry up */ + struct timeval mf6c_last_assert; /* last time I sent an assert*/ + struct rtdetq *mf6c_stall; /* pkts waiting for route */ + struct mf6c *mf6c_next; /* hash table linkage */ +}; + +#define MF6C_INCOMPLETE_PARENT ((mifi_t)-1) + +/* + * Argument structure used for pkt info. while upcall is made + */ +#ifndef _NETINET_IP_MROUTE_H_ +struct rtdetq { /* XXX: rtdetq is also defined in ip_mroute.h */ + struct mbuf *m; /* A copy of the packet */ + struct ifnet *ifp; /* Interface pkt came in on */ +#ifdef UPCALL_TIMING + struct timeval t; /* Timestamp */ +#endif /* UPCALL_TIMING */ + struct rtdetq *next; +}; +#endif /* _NETINET_IP_MROUTE_H_ */ + +#define MF6CTBLSIZ 256 +#if (MF6CTBLSIZ & (MF6CTBLSIZ - 1)) == 0 /* from sys:route.h */ +#define MF6CHASHMOD(h) ((h) & (MF6CTBLSIZ - 1)) +#else +#define MF6CHASHMOD(h) ((h) % MF6CTBLSIZ) +#endif + +#define MAX_UPQ6 4 /* max. no of pkts in upcall Q */ + +int ip6_mrouter_set __P((int, struct socket *, struct mbuf *)); +int ip6_mrouter_get __P((int, struct socket *, struct mbuf **)); +int ip6_mrouter_done __P((void)); +int mrt6_ioctl __P((int, caddr_t)); +#endif /* _KERNEL */ + +#endif /* !_NETINET6_IP6_MROUTE_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ip6_var.h b/ecos/packages/net/tcpip/current/include/netinet6/ip6_var.h new file mode 100644 index 0000000..4496c60 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ip6_var.h @@ -0,0 +1,287 @@ +//========================================================================== +// +// include/netinet6_ip6_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* $OpenBSD: ip6_var.h,v 1.2 1999/12/10 10:04:28 angelos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET6_IP6_VAR_H_ +#define _NETINET6_IP6_VAR_H_ + +/* + * IP6 reassembly queue structure. Each fragment + * being reassembled is attached to one of these structures. + */ +struct ip6q { + u_long ip6q_head; + u_short ip6q_len; + u_char ip6q_nxt; + u_char ip6q_hlim; + struct ip6asfrag *ip6q_down; + struct ip6asfrag *ip6q_up; + u_long ip6q_ident; + u_char ip6q_arrive; + u_char ip6q_ttl; + struct in6_addr ip6q_src, ip6q_dst; + struct ip6q *ip6q_next; + struct ip6q *ip6q_prev; + int ip6q_unfrglen; +#ifdef notyet + u_char *ip6q_nxtp; +#endif +}; + +struct ip6asfrag { + u_long ip6af_head; + u_short ip6af_len; + u_char ip6af_nxt; + u_char ip6af_hlim; + /* must not override the above members during reassembling */ + struct ip6asfrag *ip6af_down; + struct ip6asfrag *ip6af_up; + u_short ip6af_mff; + u_short ip6af_off; + struct mbuf *ip6af_m; + u_long ip6af_offset; /* offset where next header starts */ + u_short ip6af_frglen; /* fragmentable part length */ + u_char ip6af_x1[10]; +}; + +#define IP6_REASS_MBUF(ip6af) (*(struct mbuf **)&((ip6af)->ip6af_m)) + +struct ip6_moptions { + struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */ + u_char im6o_multicast_hlim; /* hoplimit for outgoing multicasts */ + u_char im6o_multicast_loop; /* 1 >= hear sends if a member */ + LIST_HEAD(, in6_multi_mship) im6o_memberships; +}; + +/* + * Control options for outgoing packets + */ + +/* Routing header related info */ +struct ip6po_rhinfo { + struct ip6_rthdr *ip6po_rhi_rthdr; /* Routing header */ + struct route_in6 ip6po_rhi_route; /* Route to the 1st hop */ +}; +#define ip6po_rthdr ip6po_rhinfo.ip6po_rhi_rthdr +#define ip6po_route ip6po_rhinfo.ip6po_rhi_route + +struct ip6_pktopts { + struct mbuf *ip6po_m; /* Pointer to mbuf storing the data */ + int ip6po_hlim; /* Hoplimit for outgoing packets */ + struct in6_pktinfo *ip6po_pktinfo; /* Outgoing IF/address information */ + struct sockaddr *ip6po_nexthop; /* Next-hop address */ + struct ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */ + struct ip6_dest *ip6po_dest1; /* Destination options header(1st part) */ + struct ip6po_rhinfo ip6po_rhinfo; /* Routing header related info. */ + struct ip6_dest *ip6po_dest2; /* Destination options header(2nd part) */ +}; + +struct ip6stat { + u_quad_t ip6s_total; /* total packets received */ + u_quad_t ip6s_tooshort; /* packet too short */ + u_quad_t ip6s_toosmall; /* not enough data */ + u_quad_t ip6s_fragments; /* fragments received */ + u_quad_t ip6s_fragdropped; /* frags dropped(dups, out of space) */ + u_quad_t ip6s_fragtimeout; /* fragments timed out */ + u_quad_t ip6s_fragoverflow; /* fragments that exceeded limit */ + u_quad_t ip6s_forward; /* packets forwarded */ + u_quad_t ip6s_cantforward; /* packets rcvd for unreachable dest */ + u_quad_t ip6s_redirectsent; /* packets forwarded on same net */ + u_quad_t ip6s_delivered; /* datagrams delivered to upper level*/ + u_quad_t ip6s_localout; /* total ip packets generated here */ + u_quad_t ip6s_odropped; /* lost packets due to nobufs, etc. */ + u_quad_t ip6s_reassembled; /* total packets reassembled ok */ + u_quad_t ip6s_fragmented; /* datagrams sucessfully fragmented */ + u_quad_t ip6s_ofragments; /* output fragments created */ + u_quad_t ip6s_cantfrag; /* don't fragment flag was set, etc. */ + u_quad_t ip6s_badoptions; /* error in option processing */ + u_quad_t ip6s_noroute; /* packets discarded due to no route */ + u_quad_t ip6s_badvers; /* ip6 version != 6 */ + u_quad_t ip6s_rawout; /* total raw ip packets generated */ + u_quad_t ip6s_badscope; /* scope error */ + u_quad_t ip6s_notmember; /* don't join this multicast group */ + u_quad_t ip6s_nxthist[256]; /* next header history */ + u_quad_t ip6s_m1; /* one mbuf */ + u_quad_t ip6s_m2m[32]; /* two or more mbuf */ + u_quad_t ip6s_mext1; /* one ext mbuf */ + u_quad_t ip6s_mext2m; /* two or more ext mbuf */ + u_quad_t ip6s_exthdrtoolong; /* ext hdr are not continuous */ + u_quad_t ip6s_nogif; /* no match gif found */ + u_quad_t ip6s_toomanyhdr; /* discarded due to too many headers */ + /* XXX the following two items are not really AF_INET6 thing */ + u_quad_t ip6s_pulldown; /* # of calls to m_pulldown */ + u_quad_t ip6s_pulldown_copy; /* # of mbuf copies in m_pulldown */ + u_quad_t ip6s_pulldown_alloc; /* # of mbuf allocs in m_pulldown */ +}; + +#ifdef _KERNEL +/* flags passed to ip6_output as last parameter */ +#define IPV6_DADOUTPUT 0x01 /* DAD */ +#define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */ + +extern struct ip6stat ip6stat; /* statistics */ +extern u_int32_t ip6_id; /* fragment identifier */ +extern int ip6_defhlim; /* default hop limit */ +extern int ip6_defmcasthlim; /* default multicast hop limit */ +extern int ip6_forwarding; /* act as router? */ +extern int ip6_forward_srcrt; /* forward src-routed? */ +extern int ip6_gif_hlim; /* Hop limit for gif encap packet */ +extern int ip6_use_deprecated; /* allow deprecated addr as source */ +extern int ip6_rr_prune; /* router renumbering prefix + * walk list every 5 sec. */ +#ifdef MAPPED_ADDR_ENABLED +extern int ip6_mapped_addr_on; +#endif /* MAPPED_ADDR_ENABLED */ + +extern struct socket *ip6_mrouter; /* multicast routing daemon */ +extern int ip6_sendredirects; /* send IP redirects when forwarding? */ +extern int ip6_maxfragpackets; /* Maximum packets in reassembly queue */ +extern int ip6_sourcecheck; /* Verify source interface */ +extern int ip6_sourcecheck_interval; /* Interval between log messages */ +extern int ip6_accept_rtadv; /* Acts as a host not a router */ +extern int ip6_keepfaith; /* Firewall Aided Internet Translator */ +extern int ip6_log_interval; +extern time_t ip6_log_time; +extern int ip6_hdrnestlimit; /* upper limit of # of extension headers */ +extern int ip6_dad_count; /* DupAddrDetectionTransmits */ + +extern u_int32_t ip6_flow_seq; +extern int ip6_auto_flowlabel; + +struct in6pcb; +struct inpcb; + +int icmp6_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); + +void ip6_init __P((void)); +void ip6intr __P((void)); +void ip6_input __P((struct mbuf *)); +void ip6_freemoptions __P((struct ip6_moptions *)); +int ip6_unknown_opt __P((u_int8_t *, struct mbuf *, int)); +char * ip6_get_prevhdr __P((struct mbuf *, int)); +int ip6_mforward __P((struct ip6_hdr *, struct ifnet *, struct mbuf *)); +int ip6_process_hopopts __P((struct mbuf *, u_int8_t *, int, u_int32_t *, + u_int32_t *)); +void ip6_savecontrol __P((struct inpcb *, struct mbuf **, struct ip6_hdr *, + struct mbuf *)); +int ip6_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); + +void ip6_forward __P((struct mbuf *, int)); + +void ip6_mloopback __P((struct ifnet *, struct mbuf *, struct sockaddr_in6 *)); +int ip6_output __P((struct mbuf *, struct ip6_pktopts *, + struct route_in6 *, int, + struct ip6_moptions *, struct ifnet **)); +int ip6_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); +int ip6_setpktoptions __P((struct mbuf *, struct ip6_pktopts *, int)); +int ip6_optlen __P((struct inpcb *)); + +int route6_input __P((struct mbuf **, int *, int)); + +void frag6_init __P((void)); +int frag6_input __P((struct mbuf **, int *, int)); +void frag6_slowtimo __P((void)); +void frag6_drain __P((void)); + +void rip6_init __P((void)); +int rip6_input __P((struct mbuf **mp, int *offp, int proto)); +int rip6_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); +int rip6_output __P((struct mbuf *, ...)); +int rip6_usrreq __P((struct socket *, + int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *)); + +int dest6_input __P((struct mbuf **, int *, int)); +int none_input __P((struct mbuf **, int *, int)); +#endif /* _KERNEL */ + +#endif /* !_NETINET6_IP6_VAR_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ip6protosw.h b/ecos/packages/net/tcpip/current/include/netinet6/ip6protosw.h new file mode 100644 index 0000000..17e9644 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ip6protosw.h @@ -0,0 +1,158 @@ +//========================================================================== +// +// include/netinet6_ip6protosw.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* $OpenBSD: ip6protosw.h,v 1.2 1999/12/10 10:04:28 angelos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* BSDI protosw.h,v 2.3 1996/10/11 16:02:40 pjd Exp */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)protosw.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _NETINET6_IP6PROTOSW_H_ +#define _NETINET6_IP6PROTOSW_H_ + +/* + * Protocol switch table for IPv6. + * All other definitions should refer to sys/protosw.h + */ + +struct mbuf; +struct sockaddr; +struct socket; +struct domain; +struct proc; +struct ip6_hdr; + +/* + * argument type for the last arg of pr_ctlinput(). + * should be consulted only with AF_INET6 family. + */ +struct ip6ctlparam { + struct mbuf *ip6c_m; /* start of mbuf chain */ + struct ip6_hdr *ip6c_ip6; /* ip6 header of target packet */ + int ip6c_off; /* offset of the target proto header */ +}; + +struct ip6protosw { + short pr_type; /* socket type used for */ + struct domain *pr_domain; /* domain protocol a member of */ + short pr_protocol; /* protocol number */ + short pr_flags; /* see below */ + +/* protocol-protocol hooks */ + int (*pr_input) /* input to protocol (from below) */ + __P((struct mbuf **, int *, int)); + int (*pr_output) /* output to protocol (from above) */ + __P((struct mbuf *, ...)); + void (*pr_ctlinput) /* control input (from below) */ + __P((int, struct sockaddr *, void *)); + int (*pr_ctloutput) /* control output (from above) */ + __P((int, struct socket *, int, int, struct mbuf **)); + +/* user-protocol hook */ + int (*pr_usrreq) /* user request: see list below */ + __P((struct socket *, int, struct mbuf *, + struct mbuf *, struct mbuf *, struct proc *)); + +/* utility hooks */ + void (*pr_init) /* initialization hook */ + __P((void)); + + void (*pr_fasttimo) /* fast timeout (200ms) */ + __P((void)); + void (*pr_slowtimo) /* slow timeout (500ms) */ + __P((void)); + void (*pr_drain) /* flush any excess space possible */ + __P((void)); + int (*pr_sysctl) /* sysctl for protocol */ + __P((int *, u_int, void *, size_t *, void *, size_t)); +}; + +#endif /* !_NETINET6_IP6PROTOSW_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ipv6.h b/ecos/packages/net/tcpip/current/include/netinet6/ipv6.h new file mode 100644 index 0000000..4926182 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ipv6.h @@ -0,0 +1,153 @@ +//========================================================================== +// +// include/netinet6_ipv6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% copyright-nrl-95 +This software is Copyright 1995-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_IPV6_H +#define _NETINET6_IPV6_H 1 + +#define IPV6VERSION 6 + +/* + * Header structures. + */ + +struct ipv6 +{ + uint32_t ipv6_versfl; /* Version and flow label word. */ + + uint16_t ipv6_length; /* Datagram length (not including the length + of this header). */ + uint8_t ipv6_nexthdr; /* Next header type. */ + uint8_t ipv6_hoplimit; /* Hop limit. */ + + struct in6_addr ipv6_src; /* Source address. */ + struct in6_addr ipv6_dst; /* Destination address. */ +}; + +#if __linux__ +#include <endian.h> +#else /* __linux__ */ +#include <machine/endian.h> +#endif /* __linux__ */ + +struct ipv6hdr { +#if BYTE_ORDER == LITTLE_ENDIAN + uint8_t ipv6_priority:4; /* going away? */ + uint8_t ipv6_version:4; + uint32_t ipv6_flowid:24; +#elif BYTE_ORDER == BIG_ENDIAN + uint32_t ipv6_flowid:24; + uint8_t ipv6_priority:4; /* going away? */ + uint8_t ipv6_version:4; +#else +#error "Don't know what endian to use." +#endif + uint16_t ipv6_len; + uint8_t ipv6_nextheader; + uint8_t ipv6_hoplimit; + struct in6_addr ipv6_src; /* source address */ + struct in6_addr ipv6_dst; /* destination address */ +}; + +/* + * Macros and defines for header fields, and values thereof. + * Assume things are in host order for these three macros. + */ + +#define IPV6_VERSION(h) ((h)->ipv6_versfl >> 28) +#define IPV6_PRIORITY(h) (((h)->ipv6_versfl & 0x0f000000) >> 24) +#define IPV6_FLOWID(h) ((h)->ipv6_versfl & 0x00ffffff) + +#define MAXHOPLIMIT 64 +#define IPV6_MINMTU 576 + +/* + * Other IPv6 header definitions. + */ + +/* Fragmentation header & macros for it. NOTE: Host order assumption. */ + +struct ipv6_fraghdr +{ + uint8_t frag_nexthdr; /* Next header type. */ + uint8_t frag_reserved; + uint16_t frag_bitsoffset; /* More bit and fragment offset. */ + uint32_t frag_id; /* Fragment identifier. */ +}; + +#define FRAG_MOREMASK 0x1 +#define FRAG_OFFMASK 0xFFF8 +#define FRAG_MORE_BIT(fh) ((fh)->frag_bitsoffset & FRAG_MOREMASK) +#define FRAG_OFFSET(fh) ((fh)->frag_bitsoffset & FRAG_OFFMASK) + +/* Source routing header. Host order assumption for macros. */ + +struct ipv6_srcroute0 +{ + uint8_t i6sr_nexthdr; /* Next header type. */ + uint8_t i6sr_len; /* RH len in 8-byte addrs, !incl this structure */ + uint8_t i6sr_type; /* Routing type, should be 0 */ + uint8_t i6sr_left; /* Segments left */ + uint32_t i6sr_reserved; /* 8 bits of reserved padding. */ +}; + +#define I6SR_BITMASK(i6sr) ((i6sr)->i6sr_reserved & 0xffffff) + +/* Options header. For "ignoreable" options. */ + +struct ipv6_opthdr +{ + uint8_t oh_nexthdr; /* Next header type. */ + uint8_t oh_extlen; /* Header extension length. */ + uint8_t oh_data[6]; /* Option data, may be reserved for + alignment purposes. */ +}; + +#define OPT_PAD1 0 +#define OPT_PADN 1 +#define OPT_JUMBO 194 + +struct ipv6_option +{ + uint8_t opt_type; /* Option type. */ + uint8_t opt_datalen; /* Option data length. */ + uint8_t opt_data[1]; /* Option data. */ +}; +#endif /* _NETINET6_IPV6_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ipv6_addrconf.h b/ecos/packages/net/tcpip/current/include/netinet6/ipv6_addrconf.h new file mode 100644 index 0000000..7764eb4 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ipv6_addrconf.h @@ -0,0 +1,52 @@ +//========================================================================== +// +// include/netinet6_ipv6_addrconf.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% copyright-nrl-95 +This software is Copyright 1995-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_IPV6_ADDRCONF_H +#define _NETINET6_IPV6_ADDRCONF_H 1 + +/* + * Function definitions. + */ +void addrconf_init __P((void)); +void addrconf_timer __P((void *)); +void addrconf_dad __P((struct in6_ifaddr *)); + +#endif /* _NETINET6_IPV6_ADDRCONF_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ipv6_icmp.h b/ecos/packages/net/tcpip/current/include/netinet6/ipv6_icmp.h new file mode 100644 index 0000000..856f65b --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ipv6_icmp.h @@ -0,0 +1,287 @@ +//========================================================================== +// +// include/netinet6_ipv6_icmp.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% copyright-nrl-95 +This software is Copyright 1995-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_IPV6_ICMP_H +#define _NETINET6_IPV6_ICMP_H 1 + +/* + * ICMPv6 header. + */ + +struct ipv6_icmp +{ + uint8_t icmp_type; + uint8_t icmp_code; + uint16_t icmp_cksum; + union + { + uint32_t ih_reserved; + struct + { + uint16_t ihs_id; + uint16_t ihs_seq; + } ih_idseq; + struct + { + uint8_t ihr_hoplimit; + uint8_t ihr_bits; + uint16_t ihr_lifetime; + } ih_radv; + } icmp_hun; +#define icmp_unused icmp_hun.ih_reserved +#define icmp_nexthopmtu icmp_hun.ih_reserved +#define icmp_paramptr icmp_hun.ih_reserved +#define icmp_echoid icmp_hun.ih_idseq.ihs_id +#define icmp_echoseq icmp_hun.ih_idseq.ihs_seq +#define icmp_grpdelay icmp_hun.ih_idseq.ihs_id +#define icmp_grpunused icmp_hun.ih_idseq.ihs_seq +#define icmp_nadvbits icmp_hun.ih_reserved +#define icmp_radvhop icmp_hun.ih_radv.ihr_hoplimit +#define icmp_radvbits icmp_hun.ih_radv.ihr_bits +#define icmp_radvlifetime icmp_hun.ih_radv.ihr_lifetime + union + { + struct + { + struct ipv6 ido_ipv6; + uint8_t ido_remaining[1]; + } id_offending; + uint8_t id_data[1]; + struct + { + struct in6_addr idn_addr; + uint8_t idn_ext[1]; + } id_neighbor; + struct + { + struct in6_addr idr_addr1; + struct in6_addr idr_addr2; + uint8_t idr_ext[1]; + } id_redirect; + struct + { + uint32_t ida_reachable; + uint32_t ida_retrans; + uint8_t ida_opt[1]; + } id_radv; + } icmp_dun; +#define icmp_offending icmp_dun.id_offending +#define icmp_ipv6 icmp_dun.id_offending.ido_ipv6 + +#define icmp_echodata icmp_dun.id_data + +#define icmp_grpaddr icmp_dun.id_neighbor.idn_addr + +#define icmp_radvreach icmp_dun.id_radv.ida_reachable +#define icmp_radvretrans icmp_dun.id_radv.ida_retrans +#define icmp_radvext icmp_dun.id_radv.ida_opt + +#define icmp_nsoltarg icmp_dun.id_neighbor.idn_addr +#define icmp_nsolext icmp_dun.id_neighbor.idn_ext +#define icmp_nadvaddr icmp_dun.id_neighbor.idn_addr +#define icmp_nadvext icmp_dun.id_neighbor.idn_ext + +#define icmp_redirtarg icmp_dun.id_redirect.idr_addr1 +#define icmp_redirdest icmp_dun.id_redirect.idr_addr2 +#define icmp_redirext icmp_dun.id_redirect.idr_ext +}; + +/* + * ICMPv6 extension constants. + */ + +#define EXT_SOURCELINK 1 +#define EXT_TARGETLINK 2 +#define EXT_PREFIX 3 +#define EXT_REDIR 4 +#define EXT_MTU 5 + +/* + * Extension structures for IPv6 discovery messages. + */ + +struct icmp_exthdr /* Generic extension */ +{ + uint8_t ext_id; + uint8_t ext_length; /* Length is 8 * this field, 0 is invalid. */ + uint8_t ext_data[6]; /* Padded to 8 bytes. */ +}; + +struct ext_prefinfo /* Prefix information */ +{ + uint8_t pre_extid; + uint8_t pre_length; + + uint8_t pre_prefixsize; + uint8_t pre_bits; + + uint32_t pre_valid; + uint32_t pre_preferred; + uint32_t pre_reserved; + + struct in6_addr pre_prefix; +}; + +/* + * Values for pre_bits + */ +#define ICMPV6_PREFIX_ONLINK 0x80 +#define ICMPV6_PREFIX_AUTO 0x40 + +struct ext_redir /* Redirected header */ +{ + uint8_t rd_extid; + uint8_t rd_length; + uint8_t rd_reserved[6]; + struct ipv6 rd_header; +}; + +struct ext_mtu /* Recommended link MTU. */ +{ + uint8_t mtu_extid; + uint8_t mtu_length; + uint16_t mtu_reserved; + uint32_t mtu_mtu; +}; + +/* + * Constants + */ + +/* + * Lower bounds on packet lengths for various types. + * For the error advice packets must first insure that the + * packet is large enought to contain the returned ip header. + * Only then can we do the check to see if enough bits of packet + * data have been returned, since we need to check the returned + * ipv6 header length. + */ +#define ICMPV6_MINLEN 8 /* abs minimum */ +#define ICMPV6_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ +#define ICMPV6_NADVMINLEN 24 /* min neighbor advertisement */ +#define ICMPV6_NSOLMINLEN 24 /* min neighbor solicit */ +#define ICMPV6_RADVMINLEN 16 /* min router advertisement */ +#define ICMPV6_RSOLMINLEN 8 /* min router solicit */ +#define ICMPV6_REDIRMINLEN 40 /* min redirect */ +#define ICMPV6_HLPMINLEN (8 + sizeof(struct ipv6) + 8) /* HLP demux len. */ +#define ICMPV6_MAXLEN 576 /* This should be whatever IPV6_MINMTU + will be. I take this to be the WHOLE + packet, including IPv6 header, and any + IPv6 options before the ICMP message. */ + +/* + * Definition of type and code field values. + * ICMPv6 fixes things so that info messages are >= 128. + */ + +/* Error messages and codes. */ + +#define ICMPV6_UNREACH 1 /* dest unreachable, codes: */ +#define ICMPV6_UNREACH_NOROUTE 0 /* No route to dest. */ +#define ICMPV6_UNREACH_ADMIN 1 /* Admin. prohibited */ +#define ICMPV6_UNREACH_NOTNEIGHBOR 2 /* For strict source + routing. */ +#define ICMPV6_UNREACH_ADDRESS 3 /* Address unreach. */ +#define ICMPV6_UNREACH_PORT 4 /* Port unreachable */ +#define ICMPV6_TOOBIG 2 /* Packet too big. */ +#define ICMPV6_TIMXCEED 3 /* time exceeded, code: */ +#define ICMPV6_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMPV6_TIMXCEED_REASS 1 /* Reassembly t.o. */ +#define ICMPV6_PARAMPROB 4 /* ip header bad */ +#define ICMPV6_PARAMPROB_PROB 0 /* Actual incorrect + parameter. */ +#define ICMPV6_PARAMPROB_NEXTHDR 1 /* Bad next hdr. */ +#define ICMPV6_PARAMPROB_BADOPT 2 /* Unrec. option */ + +/* Info messages. */ + +#define ICMPV6_ECHO 128 /* echo service */ +#define ICMPV6_ECHOREPLY 129 /* echo reply */ +#define ICMPV6_GRPQUERY 130 /* Query group membership. */ +#define ICMPV6_GRPREPORT 131 /* Join mcast group. */ +#define ICMPV6_GRPTERM 132 /* Leave mcast group. */ + +#define ICMPV6_ROUTERSOL 133 /* Router solicit. */ +#define ICMPV6_ROUTERADV 134 /* Router advertisement. */ +#define ICMPV6_NEIGHBORSOL 135 /* Neighbor solicit. */ +#define ICMPV6_NEIGHBORADV 136 /* Neighbor advertisement. */ + +#define ICMPV6_REDIRECT 137 /* ICMPv6 redirect. */ + +/* Defined this way to save some HTONL cycles on little-endian boxes. */ +#if BYTE_ORDER == BIG_ENDIAN +#define ICMPV6_NEIGHBORADV_RTR 0x80000000 /* Router flag. */ +#define ICMPV6_NEIGHBORADV_SOL 0x40000000 /* Solicited flag. */ +#define ICMPV6_NEIGHBORADV_OVERRIDE 0x20000000 /* Override flag. */ +#else /* BYTE_ORDER == LITTLE_ENDIAN */ +#define ICMPV6_NEIGHBORADV_RTR 0x80 /* Router flag. */ +#define ICMPV6_NEIGHBORADV_SOL 0x40 /* Solicited flag. */ +#define ICMPV6_NEIGHBORADV_OVERRIDE 0x20 /* Override flag. */ +#endif + +#define ICMPV6_MAXTYPE 137 + +#define ICMPV6_INFOTYPE(type) ((type) >= 128) + +#if defined(_KERNEL) || defined(KERNEL) +#include <netinet6/ipv6_var.h> + +/* Function prototypes */ +void ipv6_icmp_error(struct mbuf *, int, int, uint32_t); +void ipv6_icmp_input(struct mbuf *, int); +void ipv6_gsolicit(struct ifnet *, struct mbuf *, struct rtentry *); +void ipv6_rtrequest(int, struct rtentry *, struct sockaddr *); +int ipv6_icmp_output(struct mbuf *,struct socket *, struct in6_addr *); +int ipv6_icmp_sysctl(int *, u_int, void *, size_t *, void *, size_t); +#if __NetBSD__ || __FreeBSD__ +int ipv6_icmp_usrreq(struct socket *,int, struct mbuf *,struct mbuf *, struct mbuf *, struct proc *); +#else /* __NetBSD__ || __FreeBSD__ */ +int ipv6_icmp_usrreq(struct socket *,int, struct mbuf *,struct mbuf *, struct mbuf *); +#endif /* __NetBSD__ || __FreeBSD__ */ + +void ipv6_routersol_input(struct mbuf *, int); +void ipv6_routeradv_input(struct mbuf *, int); +void ipv6_neighborsol_input(struct mbuf *, int); +void ipv6_neighboradv_input(struct mbuf *, int); +void ipv6_redirect_input(struct mbuf *, int); +#endif /* defined(_KERNEL) || defined(KERNEL) */ + +#endif /* _NETINET6_IPV6_ICMP_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ipv6_trans.h b/ecos/packages/net/tcpip/current/include/netinet6/ipv6_trans.h new file mode 100644 index 0000000..69fd520 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ipv6_trans.h @@ -0,0 +1,56 @@ +//========================================================================== +// +// include/netinet6_ipv6_trans.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% copyright-nrl-95 +This software is Copyright 1995-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_IPV6_TRANS_H +#define _NETINET6_IPV6_TRANS_H 1 + +/* I don't include any #includes, as I'm using this for our (NRL) + * modified netinet/ip_output() function; thus, this #include should be + * used/stuck-in after all the other necessary includes. + * + * And yes, I only put one declaration here. There's no real need + * to stick the other prototypes in here and have ip_output() fluffed + * during preprocessing time. + */ + +int ipv4_tunnel_output __P((struct mbuf *, struct sockaddr_in *, struct rtentry *)); + +#endif /* _NETINET6_IPV6_TRANS_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/ipv6_var.h b/ecos/packages/net/tcpip/current/include/netinet6/ipv6_var.h new file mode 100644 index 0000000..ba48ed8 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/ipv6_var.h @@ -0,0 +1,385 @@ +//========================================================================== +// +// include/netinet6_ipv6_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% copyright-nrl-95 +This software is Copyright 1995-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ +#ifndef _NETINET6_IPV6_VAR_H +#define _NETINET6_IPV6_VAR_H 1 + +#include <netinet6/in6.h> + +/* + * IPv6 multicast "options". Session state for multicast, including + * weird per-session multicast things. + */ + +struct ipv6_moptions +{ + struct ifnet *i6mo_multicast_ifp; /* ifp for outgoing multicasts */ + u_char i6mo_multicast_ttl; /* TTL for outgoing multicasts. + Does this matter in IPv6? */ + u_char i6mo_multicast_loop; /* 1 => hear sends if a member */ + u_short i6mo_num_memberships; /* no. memberships this socket */ + struct in6_multi *i6mo_membership[IN6_MAX_MEMBERSHIPS]; +}; + +/* + * IPv6 stats. + */ + +#if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802 +#define _IPV6STAT_TYPE u_quad_t +#else /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802 */ +#define _IPV6STAT_TYPE u_long +#endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802 */ + +struct ipv6stat { + _IPV6STAT_TYPE ips_total; /* total packets received */ + _IPV6STAT_TYPE ips_tooshort; /* packet too short */ + _IPV6STAT_TYPE ips_toosmall; /* not enough data */ + _IPV6STAT_TYPE ips_fragments; /* fragments received */ + _IPV6STAT_TYPE ips_fragdropped; /* frags dropped (dups, out of space) */ + _IPV6STAT_TYPE ips_fragtimeout; /* fragments timed out */ + _IPV6STAT_TYPE ips_forward; /* packets forwarded */ + _IPV6STAT_TYPE ips_cantforward; /* packets rcvd for unreachable dest */ + _IPV6STAT_TYPE ips_redirectsent; /* packets forwarded on same net */ + _IPV6STAT_TYPE ips_noproto; /* unknown or unsupported protocol */ + _IPV6STAT_TYPE ips_delivered; /* datagrams delivered to upper level*/ + _IPV6STAT_TYPE ips_localout; /* total ip packets generated here */ + _IPV6STAT_TYPE ips_odropped; /* lost packets due to nobufs, etc. */ + _IPV6STAT_TYPE ips_reassembled; /* total packets reassembled ok */ + _IPV6STAT_TYPE ips_fragmented; /* datagrams sucessfully fragmented */ + _IPV6STAT_TYPE ips_ofragments; /* output fragments created */ + _IPV6STAT_TYPE ips_cantfrag; /* don't fragment flag was set, etc. */ + _IPV6STAT_TYPE ips_badoptions; /* error in option processing */ + _IPV6STAT_TYPE ips_noroute; /* packets discarded due to no route */ + _IPV6STAT_TYPE ips_badvers; /* IPv6 version != 6 */ + _IPV6STAT_TYPE ips_rawout; /* total raw ip packets generated */ +}; + +#if defined(_KERNEL) || defined(KERNEL) +/* + * The IPv6 fragment queue entry structure. + * Notes: + * Nodes are stored in ttl order. + * prefix comes from whichever packet gets here first. + * data contains a chain of chains of mbufs (m_next down a chain, m_nextpkt + * chaining chains together) where the chains are ordered by assembly + * position. When two chains are contiguous for reassembly, they are + * combined and the frag header disappears. + * The structure is deliberately sized so MALLOC will round up on the order + * of much less than the total size instead of doubling the size. + */ + +struct ipv6_fragment +{ + struct ipv6_fragment *next; /* Next fragment chain */ + struct mbuf *prefix; /* Headers before frag header(s) */ + struct mbuf *data; /* Frag headers + whatever data */ + u_char ttl; /* Fragment chain TTL. */ + u_char flags; /* Bit 0 indicates got end of chain */ +}; + +/* + * Structures and definitions for discovery mechanisms in IPv6. + */ + +/* + * Neighbor cache: + * + * Number of unanswered probes is in discq. + * "Time of next event" will be in rt->rt_rmx.rmx_expire + * (rmx_expire will actually be quite overloaded, actually.) + * Status REACHABLE will be dq_unanswered < 0 + * Status PROBE will be dq_unanswered >= 0 + * Status INCOMPLETE will be link addr length of 0 if held, + * or deleted if not held. + * + * If held, but INCOMPLETE fails set RTF_REJECT and make sure + * IPv6 and HLP's know how to deal with RTF_REJECT being set. + */ + +struct discq /* Similar to v4's llinfo_arp, discovery's "neighbor entry". */ +{ + struct discq *dq_next,*dq_prev; /* For {ins,rem}que(). */ + struct rtentry *dq_rt; /* Back pointer to routing entry for + an address that may be dead. */ + struct mbuf *dq_queue; /* Queue of outgoing messages. */ + int dq_unanswered; /* Number of unanswered probes. */ +}; + +#if !defined(_BSDI_VERSION) || (_BSDI_VERSION < 199802) +/* Routing flag redefinitions */ +#define RTF_ISAROUTER RTF_PROTO2 /* Neighbor is a router. */ +#define RTF_DEFAULT RTF_PROTO1 /* Default route. */ +#endif /* !defined(_BSDI_VERSION) || (_BSDI_VERSION < 199802) */ + +/* + * These should be configurable parameters, see ipv6_discovery.c. + * All units are in comments besides constants. + */ + +#define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 /* seconds */ +#define MAX_INITIAL_RTR_ADVERTISEMENTS 3 /* transmissions */ +#define MAX_RTR_RESPONSE_DELAY 2 /* seconds */ + +#define MAX_RTR_SOLICITATION_DELAY 1 /* second */ +#define RTR_SOLICITATION_INTERVAL 3 /* seconds */ +#define MAX_RTR_SOLICITATIONS 3 /* transmissions */ + +#define MAX_MULTICAST_SOLICIT 3 /* transmissions */ +#define MAX_UNICAST_SOLICIT 3 /* transmissions */ +#define MAX_ANYCAST_DELAY_TIME 1 /* seconds */ +#define MAX_NEIGHBOR_ADVERTISEMENTS 3 /* transmissions */ +#define MIN_NEIGHBOR_ADVERT_INTERVAL 16 /* seconds */ +#define REACHABLE_TIME 30 /* seconds */ +#define RETRANS_TIMER 3 /* seconds */ +#define DELAY_FIRST_PROBE_TIME 3 /* seconds */ +/* Need to somehow define random factors. */ + +#define NEXTHOP_CLEAN_INTERVAL 600 /* seconds */ +#define REJECT_TIMER 20 /* seconds */ + +/* + * Child of a router or tunnel. Is a "meta-entry" for garbage collection. + */ + +struct v6child +{ + struct v6child *v6c_next,*v6c_prev; /* For {ins,rem}que() */ + struct v6router *v6c_parent; /* Parent router. I'm null if + I'm the router, or a tunnel + child. */ + struct rtentry *v6c_route; /* Next-hop cache entry. I won't + be holding it, but I'm attached + to it, like discq is to neighbor + cache entries. */ +}; + +/* + * Default router list entry. Should be inserted + * in priority order. Will also have entries for non- + * default routers, because I may be a router myself. + */ + +struct v6router +{ + struct v6router *v6r_next,*v6r_prev; /* For {ins,rem}que() */ + struct rtentry *v6r_rt; /* Route for this. Could be neighbor, + could be tunnel. */ + struct v6child v6r_children; /* Children of this router. */ + + /* Metric information? */ + uint32_t v6r_expire; /* Expiration time. */ +}; +#define V6R_SIN6(v6r) ((struct sockaddr_in6 *)rt_key((v6r)->v6r_rt)) + +/* + * Flags for "flags" argument in ipv6_output(). + */ + +#define IPV6_FORWARDING 0x1 /* Most of IPv6 header exists? */ +#define IPV6_RAWOUTPUT 0x2 /* Raw IPv6 packet! */ +#define IPV6_ROUTETOIF SO_DONTROUTE /* Include sys/socket.h... */ + +void ipv6_init __P((void)); +void ipv6_drain __P((void)); +void ipv6_slowtimo __P((void)); +int ipv6_sysctl __P((int *, uint, void *, size_t *, void *, size_t)); +struct route6; + +#if __FreeBSD__ +int ipv6_ctloutput __P((struct socket *, struct sockopt *)); +int ripv6_ctloutput __P((struct socket *, struct sockopt *)); +#else /* __FreeBSD__ */ +int ipv6_ctloutput __P((int, struct socket *,int,int, struct mbuf **)); +int ripv6_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); +#endif /* __FreeBSD__ */ +void ripv6_init __P((void)); +#if __OpenBSD__ +void ripv6_input __P((struct mbuf *, ...)); +int ripv6_output __P((struct mbuf *, ...)); +#else /* __OpenBSD__ */ +void ripv6_input __P((struct mbuf *, int)); +int ripv6_output __P((struct mbuf *, struct socket *, struct in6_addr *, struct mbuf *)); +#endif /* __OpenBSD__ */ + +#if __NetBSD__ || __FreeBSD__ +int ripv6_usrreq_send(struct socket *, int, struct mbuf *, struct sockaddr *, + struct mbuf *, struct proc *); +#else /* __NetBSD__ || __FreeBSD__ */ +int ripv6_usrreq_send(struct socket *, int, struct mbuf *, struct sockaddr *, + struct mbuf *); +#endif /* __NetBSD__ || __FreeBSD__ */ + +#if __FreeBSD__ +int ripv6_usrreq_abort(struct socket *); +int ripv6_usrreq_attach(struct socket *, int , struct proc *); +int ripv6_usrreq_bind(struct socket *, struct sockaddr *, struct proc *); +int ripv6_usrreq_connect(struct socket *, struct sockaddr *, struct proc *); +int ripv6_usrreq_control(struct socket *, u_long, caddr_t, struct ifnet *, + struct proc *); +int ripv6_usrreq_detach(struct socket *); +int ripv6_usrreq_peeraddr(struct socket *, struct sockaddr **); +int ripv6_usrreq_sense(struct socket *, struct stat *); +int ripv6_usrreq_shutdown(struct socket *); +int ripv6_usrreq_sockaddr(struct socket *, struct sockaddr **); +#else /* __FreeBSD__ */ +#if __NetBSD__ +int ripv6_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *, + struct mbuf *, struct proc *)); +#else /* __NetBSD__ */ +int ripv6_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *, + struct mbuf *)); +#endif /* __NetBSD__ */ +#endif /* __FreeBSD__ */ + +#if __OpenBSD__ +void ipv6_input __P((struct mbuf *, ...)); +int ipv6_output __P((struct mbuf *, ...)); +#else /* __OpenBSD__ */ +void ipv6_input __P((struct mbuf *, int)); +int ipv6_output __P((struct mbuf *, struct route6 *, int, struct ipv6_moptions *, struct ifnet *, struct socket *)); +#endif /* __OpenBSD__ */ +void ipv6_reasm __P((struct mbuf *, int)); +void ipv6_hop __P((struct mbuf *, int)); + +#if __FreeBSD__ +int in6_control __P((struct socket *,int, caddr_t, struct ifnet *,int, struct proc *)); +#else /* __FreeBSD__ */ +#if __NetBSD__ +int in6_control __P((struct socket *,u_long, caddr_t, struct ifnet *,int, struct proc *)); +#else /* __NetBSD__ */ +int in6_control __P((struct socket *,int, caddr_t, struct ifnet *,int)); +#endif /* __NetBSD__ */ +#endif /* __FreeBSD__ */ +void ipv6_stripoptions __P((struct mbuf *, int)); +struct in6_multi *in6_addmulti __P((struct in6_addr *,struct ifnet *)); +void in6_delmulti __P((struct in6_multi *)); + +#if __FreeBSD__ +/* ripv6_usrreq and ipv6_icmp_usrreq functions */ +extern struct pr_usrreqs ripv6_usrreqs; +extern struct pr_usrreqs ipv6_icmp_usrreqs; + +extern int ripv6_usr_attach(struct socket *, int , struct proc *); +extern int ripv6_usr_disconnect(struct socket *); +extern int ripv6_usr_abort(struct socket *); +extern int ripv6_usr_detach(struct socket *); +extern int ripv6_usr_bind(struct socket *, struct sockaddr *, struct proc *); +extern int ripv6_usr_connect(struct socket *, struct sockaddr *, struct proc *); +extern int ripv6_usr_shutdown(struct socket *); +extern int ripv6_usr_send(struct socket *, int, struct mbuf *, + struct sockaddr *, struct mbuf *, struct proc *); +extern int ripv6_usr_control(struct socket *, int, caddr_t, + struct ifnet *, struct proc *); +extern int ripv6_usr_sense(struct socket *, struct stat *); +extern int ripv6_usr_sockaddr(struct socket *, struct sockaddr **); +extern int ripv6_usr_peeraddr(struct socket *, struct sockaddr **); +#endif /* __FreeBSD__ */ + +extern int ipv6_icmp_send(struct socket *, int, struct mbuf *, + struct sockaddr *, struct mbuf *, struct proc *); + +#if __OpenBSD__ +#ifdef NRL_IPSEC +void *ipv6_trans_ctlinput __P((int, struct sockaddr *, void *, struct mbuf *)); +#else /* NRL_IPSEC */ +void *ipv6_trans_ctlinput __P((int, struct sockaddr *, void *)); +#endif /* NRL_IPSEC */ +#else /* __OpenBSD__ */ +struct ip; +#ifdef NRL_IPSEC +void ipv6_trans_ctlinput __P((int, struct sockaddr *, struct ip *, struct mbuf *)); +#else /* NRL_IPSEC */ +void ipv6_trans_ctlinput __P((int, struct sockaddr *, struct ip *)); +#endif /* NRL_IPSEC */ +#endif /* __OpenBSD__ */ + +/* These might belong in in_pcb.h */ +struct inpcb; +#if __FreeBSD__ +/* + * FreeBSD, having done away with the *_usrreq() functions no longer needs to + * pass mbufs to these functions. Thus they pass in sockaddrs instead. + */ +int in6_pcbbind(struct inpcb *, struct sockaddr *); +int in6_pcbconnect(struct inpcb *, struct sockaddr *); +int in6_setsockaddr(struct inpcb *, struct sockaddr **); +int in6_setpeeraddr(struct inpcb *, struct sockaddr **); +#else /* __FreeBSD__ */ +int in6_pcbbind(struct inpcb *, struct mbuf *); +int in6_pcbconnect(struct inpcb *, struct mbuf *); +int in6_setsockaddr(struct inpcb *, struct mbuf *); +int in6_setpeeraddr(struct inpcb *, struct mbuf *); +#endif /* __FreeBSD__ */ +void ipv6_onlink_query(struct sockaddr_in6 *); +int ipv6_verify_onlink(struct sockaddr_in6 *); + +#if __FreeBSD__ +struct inpcbhead; /* XXX? Forward declaration needed. */ +#define __IN6_PCBNOTIFY_FIRSTARG struct inpcbhead * +#endif /* __FreeBSD__ */ +#if __NetBSD__ || __OpenBSD__ +struct inpcbtable; +#define __IN6_PCBNOTIFY_FIRSTARG struct inpcbtable * +#endif /* __NetBSD__ || __OpenBSD__ */ +#if __bsdi__ +struct inpcb; +#define __IN6_PCBNOTIFY_FIRSTARG struct inpcb * +#endif /* __bsdi__ */ + +#if (!__OpenBSD__ && defined(IPSEC)) || (__OpenBSD__ && defined(NRL_IPSEC)) +int in6_pcbnotify __P((__IN6_PCBNOTIFY_FIRSTARG, struct sockaddr *, uint, + struct in6_addr *, uint, int, void (*)(struct inpcb *, + int), struct mbuf *, int)); +#else /* (!__OpenBSD__ && defined(IPSEC)) || (__OpenBSD__ && defined(NRL_IPSEC)) */ +int in6_pcbnotify __P((__IN6_PCBNOTIFY_FIRSTARG, struct sockaddr *, uint, + struct in6_addr *, uint, int, void (*)(struct inpcb *, + int))); +#endif /* (!__OpenBSD__ && defined(IPSEC)) || (__OpenBSD__ && defined(NRL_IPSEC)) */ + +#undef __IN6_PCBNOTIFY_FIRSTARG + +void ipv6_freemoptions __P((struct ipv6_moptions *)); + +int ipv6_controltoheader(struct mbuf **m, struct mbuf *control, struct ifnet **forceifp, int *); +struct mbuf *ipv6_headertocontrol(struct mbuf *m, int extra, int inp_flags); +#endif /* defined(_KERNEL) || defined(KERNEL) */ + +#endif /* _NETINET6_IPV6_VAR_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/mld6_var.h b/ecos/packages/net/tcpip/current/include/netinet6/mld6_var.h new file mode 100644 index 0000000..655e104 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/mld6_var.h @@ -0,0 +1,80 @@ +//========================================================================== +// +// include/netinet6_mld6_var.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* $OpenBSD: mld6_var.h,v 1.1 1999/12/08 06:50:23 itojun Exp $ */ + +/* + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETINET6_MLD6_VAR_H_ +#define _NETINET6_MLD6_VAR_H_ + +#ifdef _KERNEL + +#define MLD6_RANDOM_DELAY(X) (random() % (X) + 1) + +/* + * States for MLD stop-listening processing + */ +#define MLD6_OTHERLISTENER 0 +#define MLD6_IREPORTEDLAST 1 + +void mld6_init __P((void)); +void mld6_input __P((struct mbuf *, int)); +void mld6_start_listening __P((struct in6_multi *)); +void mld6_stop_listening __P((struct in6_multi *)); +void mld6_fasttimeo __P((void)); +#endif /* _KERNEL */ + +#endif /* _NETINET6_MLD6_VAR_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/nd6.h b/ecos/packages/net/tcpip/current/include/netinet6/nd6.h new file mode 100644 index 0000000..5e5e70c --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/nd6.h @@ -0,0 +1,335 @@ +//========================================================================== +// +// include/netinet6.nd6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* $OpenBSD: nd6.h,v 1.1 1999/12/08 06:50:23 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETINET6_ND6_H_ +#define _NETINET6_ND6_H_ + +#include <sys/queue.h> + +struct llinfo_nd6 { + struct llinfo_nd6 *ln_next; + struct llinfo_nd6 *ln_prev; + struct rtentry *ln_rt; + struct mbuf *ln_hold; /* last packet until resolved/timeout */ + long ln_asked; /* number of queries already sent for this addr */ + u_long ln_expire; /* lifetime for NDP state transition */ + short ln_state; /* reachability state */ + short ln_router; /* 2^0: ND6 router bit */ +}; + +#define ND6_LLINFO_NOSTATE -2 +#define ND6_LLINFO_WAITDELETE -1 +#define ND6_LLINFO_INCOMPLETE 0 +#define ND6_LLINFO_REACHABLE 1 +#define ND6_LLINFO_STALE 2 +#define ND6_LLINFO_DELAY 3 +#define ND6_LLINFO_PROBE 4 + +struct nd_ifinfo { + u_int32_t linkmtu; /* LinkMTU */ + u_int32_t maxmtu; /* Upper bound of LinkMTU */ + u_int32_t basereachable; /* BaseReachableTime */ + u_int32_t reachable; /* Reachable Time */ + u_int32_t retrans; /* Retrans Timer */ + int recalctm; /* BaseReacable re-calculation timer */ + u_int8_t chlim; /* CurHopLimit */ + u_int8_t receivedra; +}; + +struct in6_nbrinfo { + char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */ + struct in6_addr addr; /* IPv6 address of the neighbor */ + long asked; /* number of queries already sent for this addr */ + int isrouter; /* if it acts as a router */ + int state; /* reachability state */ + int expire; /* lifetime for NDP state transition */ +}; + +#define DRLSTSIZ 10 +#define PRLSTSIZ 10 +struct in6_drlist { + char ifname[IFNAMSIZ]; + struct { + struct in6_addr rtaddr; + u_char flags; + u_short rtlifetime; + u_long expire; + u_short if_index; + } defrouter[DRLSTSIZ]; +}; + +struct in6_prlist { + char ifname[IFNAMSIZ]; + struct { + struct in6_addr prefix; + struct prf_ra raflags; + u_char prefixlen; + u_long vltime; + u_long pltime; + u_long expire; + u_short if_index; + u_short advrtrs; /* number of advertisement routers */ + struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ + } prefix[PRLSTSIZ]; +}; + +struct in6_ndireq { + char ifname[IFNAMSIZ]; + struct nd_ifinfo ndi; +}; + +/* protocol constants */ +#define MAX_RTR_SOLICITATION_DELAY 1 /*1sec*/ +#define RTR_SOLICITATION_INTERVAL 4 /*4sec*/ +#define MAX_RTR_SOLICITATIONS 3 + +#define ND6_INFINITE_LIFETIME 0xffffffff + +#ifdef _KERNEL +/* node constants */ +#define MAX_REACHABLE_TIME 3600000 /* msec */ +#define REACHABLE_TIME 30000 /* msec */ +#define RETRANS_TIMER 1000 /* msec */ +#define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */ +#define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */ +#define ND_COMPUTE_RTIME(x) \ + (((MIN_RANDOM_FACTOR * (x >> 10)) + (random() & \ + ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000) + +struct nd_defrouter { + LIST_ENTRY(nd_defrouter) dr_entry; +#define dr_next dr_entry.le_next + struct in6_addr rtaddr; + u_char flags; + u_short rtlifetime; + u_long expire; + struct ifnet *ifp; +}; + +struct nd_prefix { + struct ifnet *ndpr_ifp; + LIST_ENTRY(nd_prefix) ndpr_entry; + struct sockaddr_in6 ndpr_prefix; /* prefix */ + struct in6_addr ndpr_mask; /* netmask derived from the prefix */ + struct in6_addr ndpr_addr; /* address that is derived from the prefix */ + u_int32_t ndpr_vltime; /* advertised valid lifetime */ + u_int32_t ndpr_pltime; /* advertised preferred lifetime */ + time_t ndpr_expire; /* expiration time of the prefix */ + time_t ndpr_preferred; /* preferred time of the prefix */ + struct prf_ra ndpr_flags; + /* list of routers that advertise the prefix: */ + LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs; + u_char ndpr_plen; + struct ndpr_stateflags { + /* if this prefix can be regarded as on-link */ + u_char onlink : 1; + } ndpr_stateflags; +}; + +#define ndpr_next ndpr_entry.le_next + +#define ndpr_raf ndpr_flags +#define ndpr_raf_onlink ndpr_flags.onlink +#define ndpr_raf_auto ndpr_flags.autonomous + +#define ndpr_statef_onlink ndpr_stateflags.onlink +#define ndpr_statef_addmark ndpr_stateflags.addmark + +/* + * We keep expired prefix for certain amount of time, for validation purposes. + * 1800s = MaxRtrAdvInterval + */ +#define NDPR_KEEP_EXPIRED (1800 * 2) + +/* + * Message format for use in obtaining information about prefixes + * from inet6 sysctl function + */ +struct inet6_ndpr_msghdr { + u_short inpm_msglen; /* to skip over non-understood messages */ + u_char inpm_version; /* future binary compatability */ + u_char inpm_type; /* message type */ + struct in6_addr inpm_prefix; + u_long prm_vltim; + u_long prm_pltime; + u_long prm_expire; + u_long prm_preferred; + struct in6_prflags prm_flags; + u_short prm_index; /* index for associated ifp */ + u_char prm_plen; /* length of prefix in bits */ +}; + +#define prm_raf_onlink prm_flags.prf_ra.onlink +#define prm_raf_auto prm_flags.prf_ra.autonomous + +#define prm_statef_onlink prm_flags.prf_state.onlink + +#define prm_rrf_decrvalid prm_flags.prf_rr.decrvalid +#define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd + +#define ifpr2ndpr(ifpr) ((struct nd_prefix *)(ifpr)) +#define ndpr2ifpr(ndpr) ((struct ifprefix *)(ndpr)) + +struct nd_pfxrouter { + LIST_ENTRY(nd_pfxrouter) pfr_entry; +#define pfr_next pfr_entry.le_next + struct nd_defrouter *router; +}; + +LIST_HEAD(nd_drhead, nd_defrouter); +LIST_HEAD(nd_prhead, nd_prefix); + +/* nd6.c */ +extern int nd6_prune; +extern int nd6_delay; +extern int nd6_umaxtries; +extern int nd6_mmaxtries; +extern int nd6_useloopback; +extern int nd6_proxyall; +extern struct llinfo_nd6 llinfo_nd6; +extern struct nd_ifinfo *nd_ifinfo; +extern struct nd_drhead nd_defrouter; +extern struct nd_prhead nd_prefix; + +union nd_opts { + struct nd_opt_hdr *nd_opt_array[9]; + struct { + struct nd_opt_hdr *zero; + struct nd_opt_hdr *src_lladdr; + struct nd_opt_hdr *tgt_lladdr; + struct nd_opt_prefix_info *pi_beg;/* multiple opts, start */ + struct nd_opt_rd_hdr *rh; + struct nd_opt_mtu *mtu; + struct nd_opt_hdr *search; /* multiple opts */ + struct nd_opt_hdr *last; /* multiple opts */ + int done; + struct nd_opt_prefix_info *pi_end;/* multiple opts, end */ + } nd_opt_each; +}; +#define nd_opts_src_lladdr nd_opt_each.src_lladdr +#define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr +#define nd_opts_pi nd_opt_each.pi_beg +#define nd_opts_pi_end nd_opt_each.pi_end +#define nd_opts_rh nd_opt_each.rh +#define nd_opts_mtu nd_opt_each.mtu +#define nd_opts_search nd_opt_each.search +#define nd_opts_last nd_opt_each.last +#define nd_opts_done nd_opt_each.done + +/* XXX: need nd6_var.h?? */ +/* nd6.c */ +void nd6_init __P((void)); +void nd6_ifattach __P((struct ifnet *)); +int nd6_is_addr_neighbor __P((struct in6_addr *, struct ifnet *)); +void nd6_option_init __P((void *, int, union nd_opts *)); +struct nd_opt_hdr *nd6_option __P((union nd_opts *)); +int nd6_options __P((union nd_opts *)); +struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *)); +void nd6_setmtu __P((struct ifnet *)); +void nd6_timer __P((void *)); +void nd6_free __P((struct rtentry *)); +void nd6_nud_hint __P((struct rtentry *, struct in6_addr *)); +int nd6_resolve __P((struct ifnet *, struct rtentry *, + struct mbuf *, struct sockaddr *, u_char *)); +#if defined(__bsdi__) && _BSDI_VERSION >= 199802 +void nd6_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *)); +void nd6_p2p_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *)); +#else +void nd6_rtrequest __P((int, struct rtentry *, struct sockaddr *)); +void nd6_p2p_rtrequest __P((int, struct rtentry *, struct sockaddr *)); +#endif +int nd6_ioctl __P((u_long, caddr_t, struct ifnet *)); +struct rtentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *, + char *, int, int, int)); +/* for test */ +int nd6_output __P((struct ifnet *, struct mbuf *, struct sockaddr_in6 *, + struct rtentry *)); +int nd6_storelladdr __P((struct ifnet *, struct rtentry *, struct mbuf *, + struct sockaddr *, u_char *)); + +/* nd6_nbr.c */ +void nd6_na_input __P((struct mbuf *, int, int)); +void nd6_na_output __P((struct ifnet *, struct in6_addr *, + struct in6_addr *, u_long, int)); +void nd6_ns_input __P((struct mbuf *, int, int)); +void nd6_ns_output __P((struct ifnet *, struct in6_addr *, + struct in6_addr *, struct llinfo_nd6 *, int)); +caddr_t nd6_ifptomac __P((struct ifnet *)); +void nd6_dad_start __P((struct ifaddr *, int *)); +void nd6_dad_duplicated __P((struct ifaddr *)); + +/* nd6_rtr.c */ +void nd6_rs_input __P((struct mbuf *, int, int)); +void nd6_ra_input __P((struct mbuf *, int, int)); +void prelist_del __P((struct nd_prefix *)); +void defrouter_addreq __P((struct nd_defrouter *)); +void defrouter_delreq __P((struct nd_defrouter *, int)); +void defrtrlist_del __P((struct nd_defrouter *)); +void prelist_remove __P((struct nd_prefix *)); +int prelist_update __P((struct nd_prefix *, struct nd_defrouter *, + struct mbuf *)); +struct nd_defrouter *defrouter_lookup __P((struct in6_addr *, + struct ifnet *)); +int in6_ifdel __P((struct ifnet *, struct in6_addr *)); +int in6_init_prefix_ltimes __P((struct nd_prefix *ndpr)); +void rt6_flush __P((struct in6_addr *, struct ifnet *)); + +#endif /* _KERNEL */ + +#endif /* _NETINET6_ND6_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/nd6_protocol.h b/ecos/packages/net/tcpip/current/include/netinet6/nd6_protocol.h new file mode 100644 index 0000000..be22293 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/nd6_protocol.h @@ -0,0 +1,129 @@ +//========================================================================== +// +// include/netinet6_nd6_protocol.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* +%%% portions-copyright-nrl-97 +Portions of this software are Copyright 1997-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_ND6_PROTOCOL_H +#define _NETINET6_ND6_PROTOCOL_H 1 + +#include <netinet6/icmpv6.h> + +#define ND6_ROUTER_SOLICITATION 133 +#define ND6_ROUTER_ADVERTISEMENT 134 +#define ND6_NEIGHBOR_SOLICITATION 135 +#define ND6_NEIGHBOR_ADVERTISEMENT 136 +#define ND6_REDIRECT 137 + +enum nd6_option { + ND6_OPT_SOURCE_LINKADDR=1, + ND6_OPT_TARGET_LINKADDR=2, + ND6_OPT_PREFIX_INFORMATION=3, + ND6_OPT_REDIRECTED_HEADER=4, + ND6_OPT_MTU=5, + ND6_OPT_ENDOFLIST=256 +}; + +struct nd_router_solicit { /* router solicitation */ + struct icmpv6hdr rsol_hdr; +}; + +#define rsol_type rsol_hdr.icmpv6_type +#define rsol_code rsol_hdr.icmpv6_code +#define rsol_cksum rsol_hdr.icmpv6_cksum +#define rsol_reserved rsol_hdr.icmpv6_data32[0] + +struct nd_router_advert { /* router advertisement */ + struct icmpv6hdr radv_hdr; + uint32_t radv_reachable; /* reachable time */ + uint32_t radv_retransmit; /* reachable retransmit time */ +}; + +#define radv_type radv_hdr.icmpv6_type +#define radv_code radv_hdr.icmpv6_code +#define radv_cksum radv_hdr.icmpv6_cksum +#define radv_maxhoplimit radv_hdr.icmpv6_data8[0] +#define radv_m_o_res radv_hdr.icmpv6_data8[1] +#define ND6_RADV_M_BIT 0x80 +#define ND6_RADV_O_BIT 0x40 +#define radv_router_lifetime radv_hdr.icmpv6_data16[1] + +struct nd6_nsolicitation { /* neighbor solicitation */ + struct icmpv6hdr nsol6_hdr; + struct in6_addr nsol6_target; +}; + +struct nd6_nadvertisement { /* neighbor advertisement */ + struct icmpv6hdr nadv6_hdr; + struct in6_addr nadv6_target; +}; + +#define nadv6_flags nadv6_hdr.icmpv6_data32[0] +#define ND6_NADVERFLAG_ISROUTER 0x80 +#define ND6_NADVERFLAG_SOLICITED 0x40 +#define ND6_NADVERFLAG_OVERRIDE 0x20 + +struct nd6_redirect { /* redirect */ + struct icmpv6hdr redirect_hdr; + struct in6_addr redirect_target; + struct in6_addr redirect_destination; +}; + +struct nd6_opt_prefix_info { /* prefix information */ + uint8_t opt_type; + uint8_t opt_length; + uint8_t opt_prefix_length; + uint8_t opt_l_a_res; + uint32_t opt_valid_life; + uint32_t opt_preferred_life; + uint32_t opt_reserved2; + struct in6_addr opt_prefix; +}; + +#define ND6_OPT_PI_L_BIT 0x80 +#define ND6_OPT_PI_A_BIT 0x40 + +struct nd6_opt_mtu { /* MTU option */ + uint8_t opt_type; + uint8_t opt_length; + uint16_t opt_reserved; + uint32_t opt_mtu; +}; + +#endif /* _NETINET6_ND6_PROTOCOL_H */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/osdep.h b/ecos/packages/net/tcpip/current/include/netinet6/osdep.h new file mode 100644 index 0000000..b61a997 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/osdep.h @@ -0,0 +1,147 @@ +//========================================================================== +// +// include/netinet6_osdep.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: osdep.h,v 1.3 1999/12/10 08:53:18 angelos Exp $ */ +/* +%%% copyright-nrl-97 +This software is Copyright 1997-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +%%% copyright-cmetz-97 +This software is Copyright 1997-1998 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from <license@inner.net>. + +*/ +#ifndef _NETINET6_OSDEP_H_ +#define _NETINET6_OSDEP_H_ + +#define OSDEP_BSD 1 + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#ifdef KERNEL +#ifndef ATSH_ADD +#include <sys/systm.h> +#endif /* ATSH_ADD */ +#ifndef MLEN +#include <sys/mbuf.h> +#endif /* MLEN */ +#include <sys/kernel.h> +#include <sys/malloc.h> +#ifndef SB_MAX +#include <sys/socketvar.h> +#endif /* SB_MAX */ +#include <sys/proc.h> +#ifndef RTM_RTTUNIT +#include <net/route.h> +#endif /* RTM_RTTUNIT */ +#endif /* KERNEL */ +struct ifnet; +struct mbuf; +#include <netinet/in.h> +struct route6; + +#ifdef KERNEL +/* XXX */ +#define OSDEP_CRITICALDCL int __s; +#define OSDEP_CRITICALSTART __s = splnet() +#define OSDEP_CRITICALEND splx(__s) +#define OSDEP_TIMESECONDS (time.tv_sec) +#define OSDEP_PROCESS struct proc +#define OSDEP_PROCESSCURRENT (curproc) +#define OSDEP_PROCESSPARENT(x) ((x)->p_pptr) +#define OSDEP_PROCESSPID(x) ((x)->p_pid) + +#ifdef SS_PRIV +#define OSDEP_SOCKETPRIVELEGED(socket) (socket->so_state & SS_PRIV) +#else /* SS_PRIV */ +/* XXX? */ +#define OSDEP_SOCKETPRIVELEGED(socket) (!curproc || !curproc->p_ucred || !curproc->p_ucred->cr_uid) +#endif /* SS_PRIV */ +#define OSDEP_PCAST(x) ((unsigned int)(x) & 0xffffffff) +#define OSDEP_SOCKET struct socket +#define OSDEP_PACKET struct mbuf +struct mbuf; + +#define OSDEP_REAL_MALLOC(n) malloc((unsigned long)(n), M_TEMP, M_DONTWAIT) +#define OSDEP_REAL_FREE(p) free((void *)p, M_TEMP) +#define OSDEP_FAMILY(socket) (socket->so_proto->pr_domain->dom_family) +#define OSDEP_PSEUDORANDOM (uint32_t)random() + +struct ifnet; +struct mbuf *m_devget(char *, int, int, struct ifnet *, void (*)(const void *, void *, size_t)); + +static __inline__ int __osdep_datatopacket(void *data, int len, OSDEP_PACKET **packet) +{ + if (!(*packet = m_devget(data, len, 0, NULL, NULL))) + return -ENOMEM; + + return 0; +}; + +#define OSDEP_DATATOPACKET(data, len, packet) __osdep_datatopacket(data, len, packet) + +#define OSDEP_ZEROPACKET(packet) m_zero(packet) +#define OSDEP_FREEPACKET(packet) m_freem(packet) + +#define memcpy(dst, src, len) bcopy(src, dst, len) +#define memmove(dst, src, len) bcopy(src, dst, len) +#define memset(p, zero, len) bzero(p, len) /* XXX */ +#define memcmp(p1, p2, len) bcmp(p1, p2, len) + +#define OSDEP_COPYFROMUSER(dst, src, len) copyin(src, dst, len) +#define OSDEP_COPYTOUSER(dst, src, len) copyout(src, dst, len) + +#endif /* KERNEL */ +#define OSDEP_SALEN 1 +#define OSDEP_ERROR(x) (x) + +#define ENETSECURITYPOLICY -ECOMM + +#ifdef DEBUG_MALLOC +#undef OSDEP_MALLOC +#undef OSDEP_FREE +#define OSDEP_MALLOC(n) debug_malloc_malloc(n, DEBUG_STATUS) +#define OSDEP_FREE(p) debug_malloc_free(p) +#else /* DEBUG_MALLOC */ +#undef OSDEP_MALLOC +#define OSDEP_MALLOC(n) OSDEP_REAL_MALLOC(n) +#undef OSDEP_FREE +#define OSDEP_FREE(p) OSDEP_REAL_FREE(p) +#endif /* DEBUG_MALLOC */ + +#endif // _NETINET6_OSDEP_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/pim6.h b/ecos/packages/net/tcpip/current/include/netinet6/pim6.h new file mode 100644 index 0000000..21e5932 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/pim6.h @@ -0,0 +1,102 @@ +//========================================================================== +// +// include/netinet/pim6.h +// +// IPv6 protocol independent multicast +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* $OpenBSD: pim6.h,v 1.1 1999/12/08 06:50:23 itojun Exp $ */ + +/* + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETINET_PIM6_H_ +#define _NETINET_PIM6_H_ + +/* + * Protocol Independent Multicast (PIM) definitions + * + * Written by Ahmed Helmy, SGI, July 1996 + * + * MULTICAST + */ + +/* + * PIM packet header + */ +#define PIM_VERSION 2 +struct pim { +#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN) + u_char pim_type:4, /* the PIM message type, currently they are: + * Hello, Register, Register-Stop, Join/Prune, + * Bootstrap, Assert, Graft (PIM-DM only), + * Graft-Ack (PIM-DM only), C-RP-Adv + */ + pim_ver:4; /* PIM version number; 2 for PIMv2 */ +#else + u_char pim_ver:4, /* PIM version */ + pim_type:4; /* PIM type */ +#endif + u_char pim_rsv; /* Reserved */ + u_short pim_cksum; /* IP style check sum */ +}; + +#define PIM_MINLEN 8 /* The header min. length is 8 */ +#define PIM6_REG_MINLEN (PIM_MINLEN+40) /* Register message + inner IP6 header */ + +/* + * Message types + */ +#define PIM_REGISTER 1 /* PIM Register type is 1 */ + +/* second bit in reg_head is the null bit */ +#define PIM_NULL_REGISTER 0x40000000 + +#endif // _NETINET_PIM6_H_ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/pim6_var.h b/ecos/packages/net/tcpip/current/include/netinet6/pim6_var.h new file mode 100644 index 0000000..fdc705a --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/pim6_var.h @@ -0,0 +1,99 @@ +//========================================================================== +// +// include/netinet/pim6_var.h +// +// IPv6 protocol independent multicast +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* $OpenBSD: pim6_var.h,v 1.1 1999/12/08 06:50:23 itojun Exp $ */ + +/* + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* KAME Id: pim6_var.h,v 1.2 1999/08/01 15:58:13 itojun Exp */ + +#ifndef _NETINET6_PIM6_VAR_H_ +#define _NETINET6_PIM6_VAR_H_ + +/* + * Protocol Independent Multicast (PIM), + * implementation-specific definitions. + * + * Written by George Edmond Eddy (Rusty), ISI, February 1998 + * Modified by Pavlin Ivanov Radoslavov, USC/ISI, May 1998 + */ + +struct pim6stat { + u_quad_t pim6s_rcv_total; /* total PIM messages received */ + u_quad_t pim6s_rcv_tooshort; /* received with too few bytes */ + u_quad_t pim6s_rcv_badsum; /* received with bad checksum */ + u_quad_t pim6s_rcv_badversion; /* received bad PIM version */ + u_quad_t pim6s_rcv_registers; /* received registers */ + u_quad_t pim6s_rcv_badregisters; /* received invalid registers */ + u_quad_t pim6s_snd_registers; /* sent registers */ +}; + +#if (defined(KERNEL)) || (defined(_KERNEL)) +extern struct pim6stat pim6stat; + +int pim6_input __P((struct mbuf **, int*, int)); +#endif /* KERNEL */ + +/* + * Names for PIM sysctl objects + */ +#define PIMCTL_STATS 1 /* statistics (read-only) */ +#define PIMCTL_MAXID 2 + +#define PIMCTL_NAMES { \ + { 0, 0 }, \ + { 0, 0 }, \ +} + +#endif /* _NETINET6_PIM6_VAR_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/netinet6/tcpipv6.h b/ecos/packages/net/tcpip/current/include/netinet6/tcpipv6.h new file mode 100644 index 0000000..4446032 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/netinet6/tcpipv6.h @@ -0,0 +1,68 @@ +//========================================================================== +// +// include/netinet6_tcpipv6.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcpipv6.h,v 1.4 1999/12/10 08:53:18 angelos Exp $ */ + +/* +%%% copyright-nrl-95 +This software is Copyright 1995-1998 by Randall Atkinson, Ronald Lee, +Daniel McDonald, Bao Phan, and Chris Winters. All Rights Reserved. All +rights under this copyright have been assigned to the US Naval Research +Laboratory (NRL). The NRL Copyright Notice and License Agreement Version +1.1 (January 17, 1995) applies to this software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. + +*/ + +#ifndef _NETINET6_TCPIPV6_H +#define _NETINET6_TCPIPV6_H 1 + +#include <netinet6/ip6.h> +#include <netinet/tcp.h> + +struct tcpipv6hdr { + struct ip6_hdr ti6_i; + struct tcphdr ti6_t; +}; + +#define ti6_src ti6_i.ipv6_src +#define ti6_dst ti6_i.ipv6_dst +#define ti6_sport ti6_t.th_sport +#define ti6_dport ti6_t.th_dport +#define ti6_seq ti6_t.th_seq +#define ti6_ack ti6_t.th_ack +#define ti6_x2 ti6_t.th_x2 +#define ti6_off ti6_t.th_off +#define ti6_flags ti6_t.th_flags +#define ti6_win ti6_t.th_win +#define ti6_sum ti6_t.th_sum +#define ti6_urp ti6_t.th_urp + +#endif /* _NETINET6_TCPIPV6_H */ diff --git a/ecos/packages/net/tcpip/current/include/sys/bsdselect.h b/ecos/packages/net/tcpip/current/include/sys/bsdselect.h new file mode 100644 index 0000000..127f07c --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/bsdselect.h @@ -0,0 +1,55 @@ +//========================================================================== +// +// include/sys/select.h +// +// Support for 'select()' system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#ifndef _SYS_SELECT_H_ +#define _SYS_SELECT_H_ + +#include <pkgconf/system.h> + +#ifdef CYGPKG_IO_FILEIO + +#include <cyg/io/file.h> + +void selwakeup __P((struct selinfo *)); + +#else + +/* + * Used to maintain information about processes that wish to be + * notified when I/O becomes possible. + */ +struct selinfo { + void *unused; +}; + +void selrecord __P((void *selector, struct selinfo *)); +void selwakeup __P((struct selinfo *)); + +#endif + +#endif /* !_SYS_SELECT_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/bsdtypes.h b/ecos/packages/net/tcpip/current/include/sys/bsdtypes.h new file mode 100644 index 0000000..2a5d597 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/bsdtypes.h @@ -0,0 +1,194 @@ +//========================================================================== +// +// include/sys/types.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: types.h,v 1.15 1999/02/15 18:53:57 millert Exp $ */ +/* $NetBSD: types.h,v 1.29 1996/11/15 22:48:25 jtc Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.4 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_TYPES_H_ +#define _SYS_TYPES_H_ + +/* Machine type dependent parameters. */ +#include <machine/types.h> + +#include <machine/ansi.h> +#include <machine/endian.h> + +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +typedef unsigned char unchar; /* Sys V compatibility */ +typedef unsigned short ushort; /* Sys V compatibility */ +typedef unsigned int uint; /* Sys V compatibility */ +typedef unsigned long ulong; /* Sys V compatibility */ +#endif + +typedef u_int64_t u_quad_t; /* quads */ +typedef int64_t quad_t; +typedef quad_t * qaddr_t; + +typedef char * caddr_t; /* core address */ +typedef int32_t daddr_t; /* disk address */ +typedef u_int32_t fixpt_t; /* fixed point number */ +typedef long key_t; /* IPC key (for Sys V IPC) */ +typedef quad_t rlim_t; /* resource limit */ +typedef int32_t segsz_t; /* segment size */ +typedef int32_t swblk_t; /* swap offset */ +typedef u_int32_t useconds_t; /* microseconds */ +typedef int32_t suseconds_t; /* microseconds (signed) */ + +/* + * XPG4.2 states that inclusion of <netinet/in.h> must pull these + * in and that inclusion of <sys/socket.h> must pull in sa_family_t. + * We put there here because there are other headers that require + * these types and <sys/socket.h> and <netinet/in.h> will indirectly + * include <sys/types.h>. Thus we are compliant without too many hoops. + */ +typedef u_int32_t in_addr_t; /* base type for internet address */ +typedef u_int16_t in_port_t; /* IP port type */ +typedef u_int8_t sa_family_t; /* sockaddr address family type */ +typedef u_int32_t socklen_t; /* length type for network syscalls */ + +/* + * These belong in unistd.h, but are placed here too to ensure that + * long arguments will be promoted to off_t if the program fails to + * include that header or explicitly cast them to off_t. + */ +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +#ifndef _KERNEL +#include <sys/cdefs.h> +__BEGIN_DECLS +off_t lseek __P((int, off_t, int)); +int ftruncate __P((int, off_t)); +int truncate __P((const char *, off_t)); +__END_DECLS +#endif /* !_KERNEL */ +#endif /* !defined(_POSIX_SOURCE) ... */ + +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +/* Major, minor numbers, dev_t's. */ +#define major(x) ((int32_t)(((u_int32_t)(x) >> 8) & 0xff)) +#define minor(x) ((int32_t)((x) & 0xff)) +#define makedev(x,y) ((dev_t)(((x) << 8) | (y))) +#endif + +#if 0 //def _BSD_CLOCK_T_ +typedef _BSD_CLOCK_T_ clock_t; +#undef _BSD_CLOCK_T_ +#endif + +#ifndef __ECOS +#if 0 //def _BSD_SIZE_T_ +typedef _BSD_SIZE_T_ size_t; +#undef _BSD_SIZE_T_ +#endif +#endif + +#if 0 //def _BSD_SSIZE_T_ +typedef _BSD_SSIZE_T_ ssize_t; +#undef _BSD_SSIZE_T_ +#endif + +#if 0 //def _BSD_TIME_T_ +typedef _BSD_TIME_T_ time_t; +#undef _BSD_TIME_T_ +#endif + +#if 0 //def _BSD_CLOCKID_T_ +typedef _BSD_CLOCKID_T_ clockid_t; +#undef _BSD_CLOCKID_T_ +#endif + +#if 0 //def _BSD_TIMER_T_ +typedef _BSD_TIMER_T_ timer_t; +#undef _BSD_TIMER_T_ +#endif + +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) + +#if defined(__STDC__) && defined(_KERNEL) +/* + * Forward structure declarations for function prototypes. We include the + * common structures that cross subsystem boundaries here; others are mostly + * used in the same place that the structure is defined. + */ +struct proc; +struct pgrp; +struct ucred; +struct rusage; +struct file; +struct buf; +struct tty; +struct uio; +#endif + +#endif /* !defined(_POSIX_SOURCE) ... */ +#endif /* !_SYS_TYPES_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/cdefs.h b/ecos/packages/net/tcpip/current/include/sys/cdefs.h new file mode 100644 index 0000000..c26bb31 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/cdefs.h @@ -0,0 +1,170 @@ +//========================================================================== +// +// include/sys/cdefs.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: cdefs.h,v 1.5 1996/09/27 17:34:44 maja Exp $ */ +/* $NetBSD: cdefs.h,v 1.16 1996/04/03 20:46:39 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.7 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_CDEFS_H_ +#define _SYS_CDEFS_H_ + +/* + * Gratuitous NetBSD gcc extensions we can do without. + */ + +#ifdef __KPRINTF_ATTRIBUTE__ +#undef __KPRINTF_ATTRIBUTE__ +#endif + +#include <machine/cdefs.h> + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS }; +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. __CONCAT can also concatenate double-quoted + * strings produced by the __STRING macro, but this only works with ANSI C. + */ +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) +#define __inline inline /* convert to C++ keyword */ +#else +#if !defined(__GNUC__) && !defined(lint) +#define __inline /* delete GCC keyword */ +#endif /* !__GNUC__ && !lint */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#if !defined(__GNUC__) && !defined(lint) +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +#endif /* !__GNUC__ && !lint */ + +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * Programs using the ANSI C keywords const, inline etc. as normal + * identifiers should define -DNO_ANSI_KEYWORDS. + */ +#ifndef NO_ANSI_KEYWORDS +#define const __const /* convert ANSI C keywords */ +#define inline __inline +#define signed __signed +#define volatile __volatile +#endif /* !NO_ANSI_KEYWORDS */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of + * these work for GNU C++ (modulo a slight glitch in the C++ grammar + * in the distribution version of 2.5.5). + */ +#if !defined(__GNUC__) || __GNUC__ < 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define __dead __volatile +#define __pure __const +#endif +#endif + +#ifdef __KPRINTF_ATTRIBUTE__ +#define __kprintf_attribute__(a) __attribute__(a) +#else +#define __kprintf_attribute__(a) +#endif + +/* Delete pseudo-keywords wherever they are not available or needed. */ +#ifndef __dead +#define __dead +#define __pure +#endif + +#endif /* !_SYS_CDEFS_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/domain.h b/ecos/packages/net/tcpip/current/include/sys/domain.h new file mode 100644 index 0000000..e4062a4 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/domain.h @@ -0,0 +1,102 @@ +//========================================================================== +// +// include/sys/domain.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: domain.h,v 1.2 1996/03/03 12:11:38 niklas Exp $ */ +/* $NetBSD: domain.h,v 1.10 1996/02/09 18:25:07 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)domain.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_DOMAIN_H_ +#define _SYS_DOMAIN_H_ + +/* + * Structure per communications domain. + */ + +/* + * Forward structure declarations for function prototypes [sic]. + */ +struct mbuf; + +struct domain { + int dom_family; /* AF_xxx */ + char *dom_name; + void (*dom_init) /* initialize domain data structures */ + __P((void)); + int (*dom_externalize) /* externalize access rights */ + __P((struct mbuf *)); + void (*dom_dispose) /* dispose of internalized rights */ + __P((struct mbuf *)); + struct protosw *dom_protosw, *dom_protoswNPROTOSW; + struct domain *dom_next; + int (*dom_rtattach) /* initialize routing table */ + __P((void **, int)); + int dom_rtoffset; /* an arg to rtattach, in bits */ + int dom_maxrtkey; /* for routing layer */ +}; + +#ifdef _KERNEL +struct domain *domains; +void domaininit __P((void)); +#endif + +#endif // _SYS_DOMAIN_H_ diff --git a/ecos/packages/net/tcpip/current/include/sys/endian.h b/ecos/packages/net/tcpip/current/include/sys/endian.h new file mode 100644 index 0000000..f11fd32 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/endian.h @@ -0,0 +1,222 @@ +//========================================================================== +// +// include/sys/endian.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: endian.h,v 1.4 1999/07/21 05:58:25 csapuntz Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niklas Hallqvist. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Generic definitions for little- and big-endian systems. Other endianesses + * has to be dealt with in the specific machine/endian.h file for that port. + * + * This file is meant to be included from a little- or big-endian port's + * machine/endian.h after setting BYTE_ORDER to either 1234 for little endian + * or 4321 for big.. + */ + +#ifndef _SYS_ENDIAN_H_ +#define _SYS_ENDIAN_H_ + +#ifndef _POSIX_SOURCE + +#include <sys/cdefs.h> + +#define LITTLE_ENDIAN 1234 + + +#define BIG_ENDIAN 4321 +#define PDP_ENDIAN 3412 + +#ifdef __GNUC__ + +#define __swap16gen(x) ({ \ + u_int16_t __swap16gen_x = (x); \ + \ + (u_int16_t)((__swap16gen_x & 0xff) << 8 | \ + (__swap16gen_x & 0xff00) >> 8); \ +}) + +#define __swap32gen(x) ({ \ + u_int32_t __swap32gen_x = (x); \ + \ + (u_int32_t)((__swap32gen_x & 0xff) << 24 | \ + (__swap32gen_x & 0xff00) << 8 | \ + (__swap32gen_x & 0xff0000) >> 8 | \ + (__swap32gen_x & 0xff000000) >> 24); \ +}) + +#else /* __GNUC__ */ + +/* Note that these macros evaluate their arguments several times. */ +#define __swap16gen(x) \ + (u_int16_t)(((u_int16_t)(x) & 0xff) << 8 | ((u_int16_t)(x) & 0xff00) >> 8) + +#define __swap32gen(x) \ + (u_int32_t)(((u_int32_t)(x) & 0xff) << 24 | \ + ((u_int32_t)(x) & 0xff00) << 8 | ((u_int32_t)(x) & 0xff0000) >> 8 | \ + ((u_int32_t)(x) & 0xff000000) >> 24) + +#endif /* __GNUC__ */ + +/* + * Define MD_SWAP if you provide swap{16,32}md functions/macros that are + * optimized for your architecture, These will be used for swap{16,32} + * unless the argument is a constant and we are using GCC, where we can + * take advantage of the CSE phase much better by using the generic version. + */ +#ifdef MD_SWAP +#if __GNUC__ + +#define swap16(x) ({ \ + u_int16_t __swap16_x = (x); \ + \ + __builtin_constant_p(x) ? __swap16gen(__swap16_x) : \ + __swap16md(__swap16_x); \ +}) + +#define swap32(x) ({ \ + u_int32_t __swap32_x = (x); \ + \ + __builtin_constant_p(x) ? __swap32gen(__swap32_x) : \ + __swap32md(__swap32_x); \ +}) + +#endif /* __GNUC__ */ + +#else /* MD_SWAP */ +#define swap16 __swap16gen +#define swap32 __swap32gen +#endif /* MD_SWAP */ + +#define swap16_multi(v, n) do { \ + size_t __swap16_multi_n = (n); \ + u_int16_t *__swap16_multi_v = (v); \ + \ + while (__swap16_multi_n) { \ + *__swap16_multi_v = swap16(*__swap16_multi_v); \ + __swap16_multi_v++; \ + __swap16_multi_n--; \ + } \ +} while (0) + +__BEGIN_DECLS +u_int32_t htobe32 __P((u_int32_t)); +u_int16_t htobe16 __P((u_int16_t)); +u_int32_t betoh32 __P((u_int32_t)); +u_int16_t betoh16 __P((u_int16_t)); + +u_int32_t htole32 __P((u_int32_t)); +u_int16_t htole16 __P((u_int16_t)); +u_int32_t letoh32 __P((u_int32_t)); +u_int16_t letoh16 __P((u_int16_t)); +__END_DECLS + +#if BYTE_ORDER == LITTLE_ENDIAN + +/* Can be overridden by machine/endian.h before inclusion of this file. */ +#ifndef _QUAD_HIGHWORD +#define _QUAD_HIGHWORD 1 +#endif +#ifndef _QUAD_LOWWORD +#define _QUAD_LOWWORD 0 +#endif + +#define htobe16 swap16 +#define htobe32 swap32 +#define betoh16 swap16 +#define betoh32 swap32 + +#define htole16(x) (x) +#define htole32(x) (x) +#define letoh16(x) (x) +#define letoh32(x) (x) + +#endif /* BYTE_ORDER */ + +#if BYTE_ORDER == BIG_ENDIAN + +/* Can be overridden by machine/endian.h before inclusion of this file. */ +#ifndef _QUAD_HIGHWORD +#define _QUAD_HIGHWORD 0 +#endif +#ifndef _QUAD_LOWWORD +#define _QUAD_LOWWORD 1 +#endif + +#define htole16 swap16 +#define htole32 swap32 +#define letoh16 swap16 +#define letoh32 swap32 + +#define htobe16(x) (x) +#define htobe32(x) (x) +#define betoh16(x) (x) +#define betoh32(x) (x) + +#endif /* BYTE_ORDER */ + +#define htons htobe16 +#define htonl htobe32 +#define ntohs betoh16 +#define ntohl betoh32 + +#define NTOHL(x) (x) = ntohl((u_int32_t)(x)) +#define NTOHS(x) (x) = ntohs((u_int16_t)(x)) +#define HTONL(x) (x) = htonl((u_int32_t)(x)) +#define HTONS(x) (x) = htons((u_int16_t)(x)) + +#endif /* _POSIX_SOURCE */ +#endif /* _SYS_ENDIAN_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/errno.h b/ecos/packages/net/tcpip/current/include/sys/errno.h new file mode 100644 index 0000000..3c15f86 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/errno.h @@ -0,0 +1,30 @@ +//========================================================================== +// +// include/sys/errno.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// Just another name for the standard file +#include <errno.h> diff --git a/ecos/packages/net/tcpip/current/include/sys/ioccom.h b/ecos/packages/net/tcpip/current/include/sys/ioccom.h new file mode 100644 index 0000000..76f8eb6 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/ioccom.h @@ -0,0 +1,103 @@ +//========================================================================== +// +// include/sys/ioccom.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ioccom.h,v 1.2 1996/03/03 12:11:49 niklas Exp $ */ +/* $NetBSD: ioccom.h,v 1.4 1994/10/30 21:49:56 cgd Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ioccom.h 8.2 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_IOCCOM_H_ +#define _SYS_IOCCOM_H_ + +/* + * Ioctl's have the command encoded in the lower word, and the size of + * any in or out parameters in the upper word. The high 3 bits of the + * upper word are used to encode the in/out status of the parameter. + */ +#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */ +#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) +#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16)) +#define IOCGROUP(x) (((x) >> 8) & 0xff) + +#ifndef __ECOS +#define IOCPARM_MAX NBPG /* max size of ioctl args, mult. of NBPG */ +#endif + /* no parameters */ +#define IOC_VOID (unsigned long)0x20000000 + /* copy parameters out */ +#define IOC_OUT (unsigned long)0x40000000 + /* copy parameters in */ +#define IOC_IN (unsigned long)0x80000000 + /* copy paramters in and out */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* mask for IN/OUT/VOID */ +#define IOC_DIRMASK (unsigned long)0xe0000000 + +#define _IOC(inout,group,num,len) \ + (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) +#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0) +#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) +#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) +/* this should be _IORW, but stdio got there first */ +#define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) + +#endif /* !_SYS_IOCCOM_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/ioctl.h b/ecos/packages/net/tcpip/current/include/sys/ioctl.h new file mode 100644 index 0000000..15ee2f8 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/ioctl.h @@ -0,0 +1,122 @@ +//========================================================================== +// +// include/sys/ioctl.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ioctl.h,v 1.3 1996/03/03 12:11:50 niklas Exp $ */ +/* $NetBSD: ioctl.h,v 1.20 1996/01/30 18:21:47 thorpej Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ioctl.h 8.6 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_IOCTL_H_ +#define _SYS_IOCTL_H_ + +#ifndef __ECOS +#include <sys/ttycom.h> + +/* + * Pun for SunOS prior to 3.2. SunOS 3.2 and later support TIOCGWINSZ + * and TIOCSWINSZ (yes, even 3.2-3.5, the fact that it wasn't documented + * nonwithstanding). + */ +struct ttysize { + unsigned short ts_lines; + unsigned short ts_cols; + unsigned short ts_xxx; + unsigned short ts_yyy; +}; +#define TIOCGSIZE TIOCGWINSZ +#define TIOCSSIZE TIOCSWINSZ +#endif + +#include <sys/ioccom.h> + +#ifndef __ECOS +#include <sys/dkio.h> +#include <sys/filio.h> +#endif +#include <sys/sockio.h> + +#ifndef _KERNEL + +#include <sys/cdefs.h> + +__BEGIN_DECLS +int ioctl __P((int, unsigned long, ...)); +__END_DECLS +#endif /* !_KERNEL */ +#endif /* !_SYS_IOCTL_H_ */ + +/* + * Keep outside _SYS_IOCTL_H_ + * Compatability with old terminal driver + * + * Source level -> #define USE_OLD_TTY + * Kernel level -> options COMPAT_43 or COMPAT_SUNOS or ... + */ +#if defined(USE_OLD_TTY) || defined(COMPAT_43) || defined(COMPAT_SUNOS) || \ + defined(COMPAT_SVR4) || defined(COMPAT_FREEBSD) +#include <sys/ioctl_compat.h> +#endif diff --git a/ecos/packages/net/tcpip/current/include/sys/kernel.h b/ecos/packages/net/tcpip/current/include/sys/kernel.h new file mode 100644 index 0000000..ef28665 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/kernel.h @@ -0,0 +1,101 @@ +//========================================================================== +// +// include/sys/kernel.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: kernel.h,v 1.5 1996/08/11 20:39:07 niklas Exp $ */ +/* $NetBSD: kernel.h,v 1.11 1995/03/03 01:24:16 cgd Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kernel.h 8.3 (Berkeley) 1/21/94 + */ + +/* Global variables for the kernel. */ + +/* 1.1 */ +extern long hostid; +extern char hostname[MAXHOSTNAMELEN]; +extern int hostnamelen; +extern char domainname[MAXHOSTNAMELEN]; +extern int domainnamelen; + +/* 1.2 */ +extern volatile struct timeval mono_time; +extern struct timeval boottime; +extern struct timeval runtime; +extern volatile struct timeval ktime; +#define time ktime +extern struct timezone tz; /* XXX */ + +extern int tick; /* usec per tick (1000000 / hz) */ +extern int tickfix; /* periodic tick adj. tick not integral */ +extern int tickfixinterval; /* interval at which to apply adjustment */ +extern int tickadj; /* "standard" clock skew, us./tick */ +extern int hz; /* system clock's frequency */ +extern int stathz; /* statistics clock's frequency */ +extern int profhz; /* profiling clock's frequency */ +extern int lbolt; /* once a second sleep address */ +extern int tickdelta; +extern long timedelta; + + diff --git a/ecos/packages/net/tcpip/current/include/sys/malloc.h b/ecos/packages/net/tcpip/current/include/sys/malloc.h new file mode 100644 index 0000000..98054bd --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/malloc.h @@ -0,0 +1,469 @@ +//========================================================================== +// +// include/sys/malloc.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: malloc.h,v 1.27 1999/12/08 06:50:24 itojun Exp $ */ +/* $NetBSD: malloc.h,v 1.39 1998/07/12 19:52:01 augustss Exp $ */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)malloc.h 8.5 (Berkeley) 5/3/95 + */ + +#ifndef _SYS_MALLOC_H_ +#define _SYS_MALLOC_H_ + +/* + * flags to malloc + */ +#define M_WAITOK 0x0000 +#define M_NOWAIT 0x0001 + +/* + * Types of memory to be allocated + */ +#define M_FREE 0 /* should be on free list */ +#define M_MBUF 1 /* mbuf */ +#define M_DEVBUF 2 /* device driver memory */ +#define M_SOCKET 3 /* socket structure */ +#define M_PCB 4 /* protocol control block */ +#define M_RTABLE 5 /* routing tables */ +#define M_HTABLE 6 /* IMP host tables */ +#define M_FTABLE 7 /* fragment reassembly header */ +#define M_ZOMBIE 8 /* zombie proc status */ +#define M_IFADDR 9 /* interface address */ +#define M_SOOPTS 10 /* socket options */ +#define M_SONAME 11 /* socket name */ +#define M_NAMEI 12 /* namei path name buffer */ +#define M_GPROF 13 /* kernel profiling buffer */ +#define M_IOCTLOPS 14 /* ioctl data buffer */ +#define M_MAPMEM 15 /* mapped memory descriptors */ +#define M_CRED 16 /* credentials */ +#define M_PGRP 17 /* process group header */ +#define M_SESSION 18 /* session header */ +#define M_IOV 19 /* large iov's */ +#define M_MOUNT 20 /* vfs mount struct */ +#define M_FHANDLE 21 /* network file handle */ +#define M_NFSREQ 22 /* NFS request header */ +#define M_NFSMNT 23 /* NFS mount structure */ +#define M_NFSNODE 24 /* NFS vnode private part */ +#define M_VNODE 25 /* Dynamically allocated vnodes */ +#define M_CACHE 26 /* Dynamically allocated cache entries */ +#define M_DQUOT 27 /* UFS quota entries */ +#define M_UFSMNT 28 /* UFS mount structure */ +#define M_SHM 29 /* SVID compatible shared memory segments */ +#define M_VMMAP 30 /* VM map structures */ +#define M_VMMAPENT 31 /* VM map entry structures */ +#define M_VMOBJ 32 /* VM object structure */ +#define M_VMOBJHASH 33 /* VM object hash structure */ +#define M_VMPMAP 34 /* VM pmap */ +#define M_VMPVENT 35 /* VM phys-virt mapping entry */ +#define M_VMPAGER 36 /* XXX: VM pager struct */ +#define M_VMPGDATA 37 /* XXX: VM pager private data */ +#define M_FILE 38 /* Open file structure */ +#define M_FILEDESC 39 /* Open file descriptor table */ +#define M_LOCKF 40 /* Byte-range locking structures */ +#define M_PROC 41 /* Proc structures */ +#define M_SUBPROC 42 /* Proc sub-structures */ +#define M_SEGMENT 43 /* Segment for LFS */ +#define M_LFSNODE 44 /* LFS vnode private part */ +#define M_FFSNODE 45 /* FFS vnode private part */ +#define M_MFSNODE 46 /* MFS vnode private part */ +#define M_NQLEASE 47 /* Nqnfs lease */ +#define M_NQMHOST 48 /* Nqnfs host address table */ +#define M_NETADDR 49 /* Export host address structure */ +#define M_NFSSVC 50 /* Nfs server structure */ +#define M_NFSUID 51 /* Nfs uid mapping structure */ +#define M_NFSD 52 /* Nfs server daemon structure */ +#define M_IPMOPTS 53 /* internet multicast options */ +#define M_IPMADDR 54 /* internet multicast address */ +#define M_IFMADDR 55 /* link-level multicast address */ +#define M_MRTABLE 56 /* multicast routing tables */ +#define M_ISOFSMNT 57 /* ISOFS mount structure */ +#define M_ISOFSNODE 58 /* ISOFS vnode private part */ +#define M_MSDOSFSMNT 59 /* MSDOS FS mount structure */ +#define M_MSDOSFSFAT 60 /* MSDOS FS fat table */ +#define M_MSDOSFSNODE 61 /* MSDOS FS vnode private part */ +#define M_TTYS 62 /* allocated tty structures */ +#define M_EXEC 63 /* argument lists & other mem used by exec */ +#define M_MISCFSMNT 64 /* miscfs mount structures */ +#define M_MISCFSNODE 65 /* miscfs vnode private part */ +#define M_ADOSFSMNT 66 /* adosfs mount structures */ +#define M_ADOSFSNODE 67 /* adosfs vnode private part */ +#define M_ANODE 68 /* adosfs anode structures and tables. */ +#define M_IPQ 69 /* IP packet queue entry */ +#define M_AFS 70 /* Andrew File System */ +#define M_ADOSFSBITMAP 71 /* adosfs bitmap */ +#define M_EXT2FSNODE 72 /* EXT2FS vnode private part */ +#define M_PFIL 73 /* packer filter */ +#define M_PFKEY 74 /* pfkey data */ +#define M_TDB 75 /* Transforms database */ +#define M_XDATA 76 /* IPsec data */ +#define M_VFS 77 /* VFS file systems */ + +#define M_PAGEDEP 78 /* File page dependencies */ +#define M_INODEDEP 79 /* Inode dependencies */ +#define M_NEWBLK 80 /* New block allocation */ +#define M_BMSAFEMAP 81 /* Block or frag allocated from cyl group map */ +#define M_ALLOCDIRECT 82 /* Block or frag dependency for an inode */ +#define M_INDIRDEP 83 /* Indirect block dependencies */ +#define M_ALLOCINDIR 84 /* Block dependency for an indirect block */ +#define M_FREEFRAG 85 /* Previously used frag for an inode */ +#define M_FREEBLKS 86 /* Blocks freed from an inode */ +#define M_FREEFILE 87 /* Inode deallocated */ +#define M_DIRADD 88 /* New directory entry */ +#define M_MKDIR 89 /* New directory */ +#define M_DIRREM 90 /* Directory entry deleted */ +#define M_VMPBUCKET 91 /* VM page buckets */ +#define M_VMSWAP 92 /* VM swap structures */ + +#define M_DISCQ 93 /* IPv6 discq */ +#define M_FRAGQ 94 /* IPv6 fragq */ +#define M_SECA 95 /* Sec Assoc */ +#if 0 /* NRL IPv6 */ +#define M_I6IFP 96 /* IPv6 if info */ +#endif + +#define M_RAIDFRAME 97 /* Raidframe data */ + +#define M_UVMAMAP 98 /* UVM amap and realted */ +#define M_UVMAOBJ 99 /* UVM aobj and realted */ +#define M_POOL 100 /* Pool memory */ + +#define M_USB 101 /* USB general */ +#define M_USBDEV 102 /* USB device driver */ +#define M_USBHC 103 /* USB host controller */ + + +/* KAME IPv6 */ +#define M_IP6OPT 123 /* IPv6 options */ +#define M_IP6NDP 124 /* IPv6 Neighbour Discovery */ +#define M_IP6RR 125 /* IPv6 Router Renumbering Prefix */ +#define M_RR_ADDR 126 /* IPv6 Router Renumbering Ifid */ + +#define M_PIPE 104 /* Pipe structures */ + +#define M_MEMDESC 105 /* Memory range */ + +#define M_TEMP 127 /* misc temporary data buffers */ +#define M_LAST 128 /* Must be last type + 1 */ + + +#define INITKMEMNAMES { \ + "free", /* 0 M_FREE */ \ + "mbuf", /* 1 M_MBUF */ \ + "devbuf", /* 2 M_DEVBUF */ \ + "socket", /* 3 M_SOCKET */ \ + "pcb", /* 4 M_PCB */ \ + "routetbl", /* 5 M_RTABLE */ \ + "hosttbl", /* 6 M_HTABLE */ \ + "fragtbl", /* 7 M_FTABLE */ \ + "zombie", /* 8 M_ZOMBIE */ \ + "ifaddr", /* 9 M_IFADDR */ \ + "soopts", /* 10 M_SOOPTS */ \ + "soname", /* 11 M_SONAME */ \ + "namei", /* 12 M_NAMEI */ \ + "gprof", /* 13 M_GPROF */ \ + "ioctlops", /* 14 M_IOCTLOPS */ \ + "mapmem", /* 15 M_MAPMEM */ \ + "cred", /* 16 M_CRED */ \ + "pgrp", /* 17 M_PGRP */ \ + "session", /* 18 M_SESSION */ \ + "iov", /* 19 M_IOV */ \ + "mount", /* 20 M_MOUNT */ \ + "fhandle", /* 21 M_FHANDLE */ \ + "NFS req", /* 22 M_NFSREQ */ \ + "NFS mount", /* 23 M_NFSMNT */ \ + "NFS node", /* 24 M_NFSNODE */ \ + "vnodes", /* 25 M_VNODE */ \ + "namecache", /* 26 M_CACHE */ \ + "UFS quota", /* 27 M_DQUOT */ \ + "UFS mount", /* 28 M_UFSMNT */ \ + "shm", /* 29 M_SHM */ \ + "VM map", /* 30 M_VMMAP */ \ + "VM mapent", /* 31 M_VMMAPENT */ \ + "VM object", /* 32 M_VMOBJ */ \ + "VM objhash", /* 33 M_VMOBJHASH */ \ + "VM pmap", /* 34 M_VMPMAP */ \ + "VM pvmap", /* 35 M_VMPVENT */ \ + "VM pager", /* 36 M_VMPAGER */ \ + "VM pgdata", /* 37 M_VMPGDATA */ \ + "file", /* 38 M_FILE */ \ + "file desc", /* 39 M_FILEDESC */ \ + "lockf", /* 40 M_LOCKF */ \ + "proc", /* 41 M_PROC */ \ + "subproc", /* 42 M_SUBPROC */ \ + "LFS segment", /* 43 M_SEGMENT */ \ + "LFS node", /* 44 M_LFSNODE */ \ + "FFS node", /* 45 M_FFSNODE */ \ + "MFS node", /* 46 M_MFSNODE */ \ + "NQNFS Lease", /* 47 M_NQLEASE */ \ + "NQNFS Host", /* 48 M_NQMHOST */ \ + "Export Host", /* 49 M_NETADDR */ \ + "NFS srvsock", /* 50 M_NFSSVC */ \ + "NFS uid", /* 51 M_NFSUID */ \ + "NFS daemon", /* 52 M_NFSD */ \ + "ip_moptions", /* 53 M_IPMOPTS */ \ + "in_multi", /* 54 M_IPMADDR */ \ + "ether_multi", /* 55 M_IFMADDR */ \ + "mrt", /* 56 M_MRTABLE */ \ + "ISOFS mount", /* 57 M_ISOFSMNT */ \ + "ISOFS node", /* 58 M_ISOFSNODE */ \ + "MSDOSFS mount", /* 59 M_MSDOSFSMNT */ \ + "MSDOSFS fat", /* 60 M_MSDOSFSFAT */ \ + "MSDOSFS node", /* 61 M_MSDOSFSNODE */ \ + "ttys", /* 62 M_TTYS */ \ + "exec", /* 63 M_EXEC */ \ + "miscfs mount", /* 64 M_MISCFSMNT */ \ + "miscfs node", /* 65 M_MISCFSNODE */ \ + "adosfs mount", /* 66 M_ADOSFSMNT */ \ + "adosfs node", /* 67 M_ADOSFSNODE */ \ + "adosfs anode", /* 68 M_ANODE */ \ + "IP queue ent", /* 69 M_IPQ */ \ + "afs", /* 70 M_AFS */ \ + "adosfs bitmap", /* 71 M_ADOSFSBITMAP */ \ + "EXT2FS node", /* 72 M_EXT2FSNODE */ \ + "pfil", /* 73 M_PFIL */ \ + "pfkey data", /* 74 M_PFKEY */ \ + "tdb", /* 75 M_TDB */ \ + "xform_data", /* 76 M_XDATA */ \ + "vfs", /* 77 M_VFS */ \ + "pagedep", /* 78 M_PAGEDEP */ \ + "inodedep", /* 79 M_INODEDEP */ \ + "newblk", /* 80 M_NEWBLK */ \ + "bmsafemap", /* 81 M_BMSAFEMAP */ \ + "allocdirect", /* 82 M_ALLOCDIRECT */ \ + "indirdep", /* 83 M_INDIRDEP */ \ + "allocindir", /* 84 M_ALLOCINDIR */ \ + "freefrag", /* 85 M_FREEFRAG */ \ + "freeblks", /* 86 M_FREEBLKS */ \ + "freefile", /* 87 M_FREEFILE */ \ + "diradd", /* 88 M_DIRADD */ \ + "mkdir", /* 89 M_MKDIR */ \ + "dirrem", /* 90 M_DIRREM */ \ + "VM page bucket", /* 91 M_VMPBUCKET */ \ + "VM swap", /* 92 M_VMSWAP */ \ + "IPv6 discq", /* 93 M_DISCQ */ \ + "IPv6 fragq", /* 94 M_FRAGQ */ \ + "Sec Assoc", /* 95 M_SECA */ \ + "IPv6 if info", /* 96 M_I6IFP */ \ + "RaidFrame data", /* 97 M_RAIDFRAME */ \ + "UVM amap", /* 98 M_UVMAMAP */ \ + "UVM aobj", /* 99 M_UVMAOBJ */ \ + "pool", /* 100 M_POOL */ \ + "USB", /* 101 M_USB */ \ + "USB device", /* 102 M_USBDEV */ \ + "USB HC", /* 103 M_USBHC */ \ + "pipe", /* 104 M_PIPE */ \ + "memdesc", /* 105 M_MEMDESC */ \ + NULL, \ + NULL, NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, NULL, \ + NULL, \ + "ip6_options", /* 123 M_IP6OPT */ \ + "NDP", /* 124 M_IP6NDP */ \ + "ip6rr", /* 125 M_IP6RR */ \ + "rp_addr", /* 126 M_RR_ADDR */ \ + "temp", /* 127 M_TEMP */ \ +} + +#ifndef __ECOS +struct kmemstats { + long ks_inuse; /* # of packets of this type currently in use */ + long ks_calls; /* total packets of this type ever allocated */ + long ks_memuse; /* total memory held in bytes */ + u_short ks_limblocks; /* number of times blocked for hitting limit */ + u_short ks_mapblocks; /* number of times blocked for kernel map */ + long ks_maxused; /* maximum number ever used */ + long ks_limit; /* most that are allowed to exist */ + long ks_size; /* sizes of this thing that are allocated */ + long ks_spare; +}; + +/* + * Array of descriptors that describe the contents of each page + */ +struct kmemusage { + short ku_indx; /* bucket index */ + union { + u_short freecnt;/* for small allocations, free pieces in page */ + u_short pagecnt;/* for large allocations, pages alloced */ + } ku_un; +}; +#define ku_freecnt ku_un.freecnt +#define ku_pagecnt ku_un.pagecnt + +/* + * Set of buckets for each size of memory block that is retained + */ +struct kmembuckets { + caddr_t kb_next; /* list of free blocks */ + caddr_t kb_last; /* last free block */ + long kb_calls; /* total calls to allocate this size */ + long kb_total; /* total number of blocks allocated */ + long kb_totalfree; /* # of free elements in this bucket */ + long kb_elmpercl; /* # of elements in this sized allocation */ + long kb_highwat; /* high water mark */ + long kb_couldfree; /* over high water mark and could free */ +}; + +#ifdef _KERNEL +#define MINALLOCSIZE (1 << MINBUCKET) +#define BUCKETINDX(size) \ + ((size) <= (MINALLOCSIZE * 128) \ + ? (size) <= (MINALLOCSIZE * 8) \ + ? (size) <= (MINALLOCSIZE * 2) \ + ? (size) <= (MINALLOCSIZE * 1) \ + ? (MINBUCKET + 0) \ + : (MINBUCKET + 1) \ + : (size) <= (MINALLOCSIZE * 4) \ + ? (MINBUCKET + 2) \ + : (MINBUCKET + 3) \ + : (size) <= (MINALLOCSIZE* 32) \ + ? (size) <= (MINALLOCSIZE * 16) \ + ? (MINBUCKET + 4) \ + : (MINBUCKET + 5) \ + : (size) <= (MINALLOCSIZE * 64) \ + ? (MINBUCKET + 6) \ + : (MINBUCKET + 7) \ + : (size) <= (MINALLOCSIZE * 2048) \ + ? (size) <= (MINALLOCSIZE * 512) \ + ? (size) <= (MINALLOCSIZE * 256) \ + ? (MINBUCKET + 8) \ + : (MINBUCKET + 9) \ + : (size) <= (MINALLOCSIZE * 1024) \ + ? (MINBUCKET + 10) \ + : (MINBUCKET + 11) \ + : (size) <= (MINALLOCSIZE * 8192) \ + ? (size) <= (MINALLOCSIZE * 4096) \ + ? (MINBUCKET + 12) \ + : (MINBUCKET + 13) \ + : (size) <= (MINALLOCSIZE * 16384) \ + ? (MINBUCKET + 14) \ + : (MINBUCKET + 15)) + +/* + * Turn virtual addresses into kmem map indicies + */ +#define kmemxtob(alloc) (kmembase + (alloc) * NBPG) +#define btokmemx(addr) (((caddr_t)(addr) - kmembase) / NBPG) +#define btokup(addr) (&kmemusage[((caddr_t)(addr) - kmembase) >> CLSHIFT]) + +/* + * Macro versions for the usual cases of malloc/free + */ +#if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(_LKM) +#define MALLOC(space, cast, size, type, flags) \ + (space) = (cast)malloc((u_long)(size), type, flags) +#define FREE(addr, type) free((caddr_t)(addr), type) + +#else /* do not collect statistics */ +#define MALLOC(space, cast, size, type, flags) do { \ + register struct kmembuckets *kbp = &bucket[BUCKETINDX(size)]; \ + long s = splimp(); \ + if (kbp->kb_next == NULL) { \ + (space) = (cast)malloc((u_long)(size), type, flags); \ + } else { \ + (space) = (cast)kbp->kb_next; \ + kbp->kb_next = *(caddr_t *)(space); \ + } \ + splx(s); \ +} while (0) + +#define FREE(addr, type) do { \ + register struct kmembuckets *kbp; \ + register struct kmemusage *kup = btokup(addr); \ + long s = splimp(); \ + if (1 << kup->ku_indx > MAXALLOCSAVE) { \ + free((caddr_t)(addr), type); \ + } else { \ + kbp = &bucket[kup->ku_indx]; \ + if (kbp->kb_next == NULL) \ + kbp->kb_next = (caddr_t)(addr); \ + else \ + *(caddr_t *)(kbp->kb_last) = (caddr_t)(addr); \ + *(caddr_t *)(addr) = NULL; \ + kbp->kb_last = (caddr_t)(addr); \ + } \ + splx(s); \ +} while(0) +#endif /* do not collect statistics */ + +extern struct kmemstats kmemstats[]; +extern struct kmemusage *kmemusage; +extern char *kmembase; +extern struct kmembuckets bucket[]; + +extern void *malloc __P((unsigned long size, int type, int flags)); +extern void free __P((void *addr, int type)); + +#endif /* _KERNEL */ +#endif // __ECOS + +#if defined(__ECOS) && defined(_KERNEL) +extern void *cyg_net_malloc(u_long size, int type, int flags); +extern void cyg_net_free(caddr_t addr, int type); +#define MALLOC(space, cast, size, type, flags) \ + (space) = (cast)cyg_net_malloc((u_long)(size), type, flags) +#define malloc(size, type, flags) cyg_net_malloc((u_long)size, type, flags) +#define FREE(addr, type) cyg_net_free((caddr_t)(addr), type) +#define free(addr, type) FREE(addr, type) +#endif + +#endif /* !_SYS_MALLOC_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/mbuf.h b/ecos/packages/net/tcpip/current/include/sys/mbuf.h new file mode 100644 index 0000000..2ca6bee --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/mbuf.h @@ -0,0 +1,473 @@ +//========================================================================== +// +// include/sys/mbuf.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: mbuf.h,v 1.14 1999/12/08 06:50:24 itojun Exp $ */ +/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mbuf.h 8.5 (Berkeley) 2/19/95 + */ + +#ifndef _SYS_MBUF_H_ +#define _SYS_MBUF_H_ + +#ifndef M_WAITOK +#include <sys/malloc.h> +#endif + +/* + * Mbufs are of a single size, MSIZE (machine/param.h), which + * includes overhead. An mbuf may add a single "mbuf cluster" of size + * MCLBYTES (also in machine/param.h), which has no additional overhead + * and is used instead of the internal data area; this is done when + * at least MINCLSIZE of data must be stored. + */ + +#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */ +#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */ + +#define MINCLSIZE (MHLEN + 1) /* smallest amount to put in cluster */ +#define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */ + +/* + * Macros for type conversion + * mtod(m,t) - convert mbuf pointer to data pointer of correct type + * dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX) + * mtocl(x) - convert pointer within cluster to cluster index # + * cltom(x) - convert cluster # to ptr to beginning of cluster + */ +#define mtod(m,t) ((t)((m)->m_data)) +#define dtom(x) ((struct mbuf *)((long)(x) & ~(MSIZE-1))) +#ifdef __ECOS +extern int cyg_mtocl(u_long); +extern struct mbuf *cyg_cltom(u_long); +#define mtocl(x) cyg_mtocl((u_long)x) +#define cltom(x) cyg_cltom((u_long)x) +#else +#define mtocl(x) (((u_long)(x) - (u_long)mbutl) >> MCLSHIFT) +#define cltom(x) ((caddr_t)((u_long)mbutl + ((u_long)(x) << MCLSHIFT))) +#endif + +/* header at beginning of each mbuf: */ +struct m_hdr { + struct mbuf *mh_next; /* next buffer in chain */ + struct mbuf *mh_nextpkt; /* next chain in queue/record */ + caddr_t mh_data; /* location of data */ + u_int mh_len; /* amount of data in this mbuf */ + short mh_type; /* type of data in this mbuf */ + short mh_flags; /* flags; see below */ +}; + +/* record/packet header in first mbuf of chain; valid if M_PKTHDR set */ +struct pkthdr { + struct ifnet *rcvif; /* rcv interface */ + int len; /* total packet length */ + void *tdbi; /* pointer to struct tdb_ident */ + /* XXX - pull in ip_ipsp.h */ +}; + +/* description of external storage mapped into mbuf, valid if M_EXT set */ +struct m_ext { + caddr_t ext_buf; /* start of buffer */ + void (*ext_free) /* free routine if not the usual */ + __P((struct mbuf *)); + u_int ext_size; /* size of buffer, for ext_free */ + void (*ext_ref) /* add a reference to the ext object */ + __P((struct mbuf *)); + void *ext_handle; /* handle for storage manager */ +}; + +struct mbuf { + struct m_hdr m_hdr; + union { + struct { + struct pkthdr MH_pkthdr; /* M_PKTHDR set */ + union { + struct m_ext MH_ext; /* M_EXT set */ + char MH_databuf[MHLEN]; + } MH_dat; + } MH; + char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */ + } M_dat; +}; +#define m_next m_hdr.mh_next +#define m_len m_hdr.mh_len +#define m_data m_hdr.mh_data +#define m_type m_hdr.mh_type +#define m_flags m_hdr.mh_flags +#define m_nextpkt m_hdr.mh_nextpkt +#define m_act m_nextpkt +#define m_pkthdr M_dat.MH.MH_pkthdr +#define m_ext M_dat.MH.MH_dat.MH_ext +#define m_pktdat M_dat.MH.MH_dat.MH_databuf +#define m_dat M_dat.M_databuf + +/* mbuf flags */ +#define M_EXT 0x0001 /* has associated external storage */ +#define M_PKTHDR 0x0002 /* start of record */ +#define M_EOR 0x0004 /* end of record */ + +/* mbuf pkthdr flags, also in m_flags */ +#define M_BCAST 0x0100 /* send/received as link-level broadcast */ +#define M_MCAST 0x0200 /* send/received as link-level multicast */ +#define M_CONF 0x0400 /* packet was encrypted (ESP-transport) */ +#define M_AUTH 0x0800 /* packet was authenticated (AH) */ +#if 0 /* NRL IPv6 */ +#define M_TUNNEL 0x1000 /* packet was tunneled */ +#define M_DAD 0x2000 /* Used on outbound packets to indicate that + * this is for duplicate address detection */ +#endif + +/* KAME IPv6 */ +#define M_ANYCAST6 0x4000 /* received as IPv6 anycast */ +#if 0 /*KAME IPSEC*/ +#define M_AUTHIPHDR 0x0010 /* data origin authentication for IP header */ +#define M_DECRYPTED 0x0020 /* confidentiality */ +#endif +#define M_LOOP 0x0040 /* for Mbuf statistics */ +#if 0 /*KAME IPSEC*/ +#define M_AUTHIPDGM 0x0080 /* data origin authentication */ +#endif + +/* flags copied when copying m_pkthdr */ +#define M_COPYFLAGS (M_PKTHDR|M_EOR|M_BCAST|M_MCAST|M_CONF|M_AUTH|M_ANYCAST6|M_LOOP) + +/* mbuf types */ +#define MT_FREE 0 /* should be on free list */ +#define MT_DATA 1 /* dynamic (data) allocation */ +#define MT_HEADER 2 /* packet header */ +#define MT_SOCKET 3 /* socket structure */ +#define MT_PCB 4 /* protocol control block */ +#define MT_RTABLE 5 /* routing tables */ +#define MT_HTABLE 6 /* IMP host tables */ +#define MT_ATABLE 7 /* address resolution tables */ +#define MT_SONAME 8 /* socket name */ +#define MT_SOOPTS 10 /* socket options */ +#define MT_FTABLE 11 /* fragment reassembly header */ +#define MT_RIGHTS 12 /* access rights */ +#define MT_IFADDR 13 /* interface address */ +#define MT_CONTROL 14 /* extra-data protocol message */ +#define MT_OOBDATA 15 /* expedited data */ + +/* flags to m_get/MGET */ +#define M_DONTWAIT M_NOWAIT +#define M_WAIT M_WAITOK + +#ifdef __ECOS +extern void *cyg_net_mbuf_alloc(int type, int flags); +extern void cyg_net_mbuf_free(caddr_t addr, int type); +#define MBUF_ALLOC(space, cast, size, type, flags) \ + (space) = (cast)cyg_net_mbuf_alloc(type, flags) +#define MBUF_FREE(addr, type) cyg_net_mbuf_free((caddr_t)(addr), type) +#else +#define MBUF_ALLOC(space, cast, size, type, flags) \ + MALLOC(space, cast, size, type, flags) +#define MBUF_FREE(addr, type) \ + MFREE(addr, type) +#endif + +/* + * mbuf utility macros: + * + * MBUFLOCK(code) + * prevents a section of code from from being interrupted by network + * drivers. + */ +#define MBUFLOCK(code) \ + { int ms = splimp(); \ + { code } \ + splx(ms); \ + } + +/* + * mbuf allocation/deallocation macros: + * + * MGET(struct mbuf *m, int how, int type) + * allocates an mbuf and initializes it to contain internal data. + * + * MGETHDR(struct mbuf *m, int how, int type) + * allocates an mbuf and initializes it to contain a packet header + * and internal data. + */ +#define MGET(m, how, type) { \ + MBUF_ALLOC((m), struct mbuf *, MSIZE, mbtypes[type], (how)); \ + if (m) { \ + (m)->m_type = (type); \ + MBUFLOCK(mbstat.m_mtypes[type]++;) \ + (m)->m_next = (struct mbuf *)NULL; \ + (m)->m_nextpkt = (struct mbuf *)NULL; \ + (m)->m_data = (m)->m_dat; \ + (m)->m_flags = 0; \ + } else \ + (m) = m_retry((how), (type)); \ +} + +#define MGETHDR(m, how, type) { \ + MBUF_ALLOC((m), struct mbuf *, MSIZE, mbtypes[type], (how)); \ + if (m) { \ + (m)->m_type = (type); \ + MBUFLOCK(mbstat.m_mtypes[type]++;) \ + (m)->m_next = (struct mbuf *)NULL; \ + (m)->m_nextpkt = (struct mbuf *)NULL; \ + (m)->m_data = (m)->m_pktdat; \ + (m)->m_flags = M_PKTHDR; \ + } else \ + (m) = m_retryhdr((how), (type)); \ +} + +/* + * Mbuf cluster macros. + * MCLALLOC(caddr_t p, int how) allocates an mbuf cluster. + * MCLGET adds such clusters to a normal mbuf; + * the flag M_EXT is set upon success. + * MCLFREE releases a reference to a cluster allocated by MCLALLOC, + * freeing the cluster if the reference count has reached 0. + * + * Normal mbuf clusters are normally treated as character arrays + * after allocation, but use the first word of the buffer as a free list + * pointer while on the free list. + */ +union mcluster { + union mcluster *mcl_next; + char mcl_buf[MCLBYTES]; +}; + +#define MCLALLOC(p, how) \ + MBUFLOCK( \ + if (mclfree == 0) \ + (void)m_clalloc(1, (how)); \ + if (((p) = (caddr_t)mclfree) != 0) { \ + ++mclrefcnt[mtocl(p)]; \ + mbstat.m_clfree--; \ + mclfree = ((union mcluster *)(p))->mcl_next; \ + } \ + ) + +#define MCLGET(m, how) \ + { MCLALLOC((m)->m_ext.ext_buf, (how)); \ + if ((m)->m_ext.ext_buf != NULL) { \ + (m)->m_data = (m)->m_ext.ext_buf; \ + (m)->m_flags |= M_EXT; \ + (m)->m_ext.ext_size = MCLBYTES; \ + (m)->m_ext.ext_free = NULL; \ + (m)->m_ext.ext_ref = NULL; \ + (m)->m_ext.ext_handle = NULL; \ + } \ + } + +#define MCLFREE(p) \ + MBUFLOCK ( \ + if (--mclrefcnt[mtocl(p)] == 0) { \ + ((union mcluster *)(p))->mcl_next = mclfree; \ + mclfree = (union mcluster *)(p); \ + mbstat.m_clfree++; \ + } \ + ) + +/* + * For cluster mbufs (regardless of header or not). + */ +#define MCL_ALIGN(m, len) \ + { (m)->m_data += (MCLBYTES - (len)) &~ (sizeof(long) -1); } + +/* + * MFREE(struct mbuf *m, struct mbuf *n) + * Free a single mbuf and associated external storage. + * Place the successor, if any, in n. + */ +#define MFREE(m, n) \ + { MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--;) \ + if ((m)->m_flags & M_EXT) { \ + if ((m)->m_ext.ext_free) \ + (*((m)->m_ext.ext_free))(m); \ + else \ + MCLFREE((m)->m_ext.ext_buf); \ + } \ + (n) = (m)->m_next; \ + MBUF_FREE((m), mbtypes[(m)->m_type]); \ + } + +/* + * Copy mbuf pkthdr from from to to. + * from must have M_PKTHDR set, and to must be empty. + */ +#define M_COPY_PKTHDR(to, from) { \ + (to)->m_pkthdr = (from)->m_pkthdr; \ + (to)->m_flags = (from)->m_flags & M_COPYFLAGS; \ + (to)->m_data = (to)->m_pktdat; \ +} + +/* + * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place + * an object of the specified size at the end of the mbuf, longword aligned. + */ +#define M_ALIGN(m, len) \ + { (m)->m_data += (MLEN - (len)) &~ (sizeof(long) - 1); } +/* + * As above, for mbufs allocated with m_gethdr/MGETHDR + * or initialized by M_COPY_PKTHDR. + */ +#define MH_ALIGN(m, len) \ + { (m)->m_data += (MHLEN - (len)) &~ (sizeof(long) - 1); } + +/* + * Compute the amount of space available + * before the current start of data in an mbuf. + */ +#define M_LEADINGSPACE(m) \ + ((m)->m_flags & M_EXT ? /* (m)->m_data - (m)->m_ext.ext_buf */ 0 : \ + (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat : \ + (m)->m_data - (m)->m_dat) + +/* + * Compute the amount of space available + * after the end of data in an mbuf. + */ +#define M_TRAILINGSPACE(m) \ + ((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf + (m)->m_ext.ext_size - \ + ((m)->m_data + (m)->m_len) : \ + &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len)) + +/* + * Arrange to prepend space of size plen to mbuf m. + * If a new mbuf must be allocated, how specifies whether to wait. + * If how is M_DONTWAIT and allocation fails, the original mbuf chain + * is freed and m is set to NULL. + */ +#define M_PREPEND(m, plen, how) { \ + if (M_LEADINGSPACE(m) >= (plen)) { \ + (m)->m_data -= (plen); \ + (m)->m_len += (plen); \ + } else \ + (m) = m_prepend((m), (plen), (how)); \ + if ((m) && (m)->m_flags & M_PKTHDR) \ + (m)->m_pkthdr.len += (plen); \ +} + +/* change mbuf to new type */ +#define MCHTYPE(m, t) { \ + MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--; mbstat.m_mtypes[t]++;) \ + (m)->m_type = t;\ +} + +/* length to m_copy to copy all */ +#define M_COPYALL 1000000000 + +/* compatiblity with 4.3 */ +#define m_copy(m, o, l) m_copym((m), (o), (l), M_DONTWAIT) + +/* + * Mbuf statistics. + */ +struct mbstat { + u_long m_mbufs; /* mbufs obtained from page pool */ + u_long m_clusters; /* clusters obtained from page pool */ + u_long m_spare; /* spare field */ + u_long m_clfree; /* free clusters */ + u_long m_drops; /* times failed to find space */ + u_long m_wait; /* times waited for space */ + u_long m_drain; /* times drained protocols for space */ + u_short m_mtypes[256]; /* type specific mbuf allocations */ +}; + +#ifdef _KERNEL +extern struct mbuf *mbutl; /* virtual address of mclusters */ +extern char *mclrefcnt; /* cluster reference counts */ +extern struct mbstat mbstat; +extern int nmbclusters; +union mcluster *mclfree; +extern int max_linkhdr; /* largest link-level header */ +extern int max_protohdr; /* largest protocol header */ +extern int max_hdr; /* largest link+protocol header */ +extern int max_datalen; /* MHLEN - max_hdr */ +extern int mbtypes[]; /* XXX */ +extern int needqueuedrain; /* True if allocation failed at */ + /* interrupt level */ + +void mbinit __P((void)); +struct mbuf *m_copym2 __P((struct mbuf *, int, int, int)); +struct mbuf *m_copym __P((struct mbuf *, int, int, int)); +struct mbuf *m_free __P((struct mbuf *)); +struct mbuf *m_get __P((int, int)); +struct mbuf *m_getclr __P((int, int)); +struct mbuf *m_gethdr __P((int, int)); +struct mbuf *m_prepend __P((struct mbuf *, int, int)); +struct mbuf *m_pullup __P((struct mbuf *, int)); +struct mbuf *m_pullup2 __P((struct mbuf *, int)); +struct mbuf *m_retry __P((int, int)); +struct mbuf *m_retryhdr __P((int, int)); +struct mbuf *m_split __P((struct mbuf *, int, int)); +struct mbuf *m_inject __P((struct mbuf *, int, int, int)); +void m_adj __P((struct mbuf *, int)); +int m_clalloc __P((int, int)); +void m_copyback __P((struct mbuf *, int, int, caddr_t)); +void m_freem __P((struct mbuf *)); +void m_reclaim __P((void)); +void m_copydata __P((struct mbuf *, int, int, caddr_t)); +void m_cat __P((struct mbuf *, struct mbuf *)); +struct mbuf *m_devget __P((char *, int, int, struct ifnet *, + void (*) __P((const void *, void *, size_t)))); +void m_zero __P((struct mbuf *)); +int m_apply __P((struct mbuf *, int, int, + int (*)(caddr_t, caddr_t, unsigned int), caddr_t)); + +#endif + +#endif // _SYS_MBUF_H_ diff --git a/ecos/packages/net/tcpip/current/include/sys/param.h b/ecos/packages/net/tcpip/current/include/sys/param.h new file mode 100644 index 0000000..89952cf --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/param.h @@ -0,0 +1,344 @@ +//========================================================================== +// +// include/sys/param.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: param.h,v 1.25 1999/09/23 08:25:01 deraadt Exp $ */ +/* $NetBSD: param.h,v 1.23 1996/03/17 01:02:29 thorpej Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)param.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_PARAM_H_ +#define _SYS_PARAM_H_ + +#define BSD 199306 /* System version (year & month). */ +#define BSD4_3 1 +#define BSD4_4 1 + +#define OpenBSD 199912 /* OpenBSD version (year & month). */ +#define OpenBSD2_6 1 /* OpenBSD 2.6 */ + +#ifndef NULL +#ifdef __GNUG__ +#define NULL __null +#else +#define NULL 0 +#endif +#endif + +#ifndef _LOCORE +#include <sys/types.h> +#ifndef __ECOS +#include <sys/simplelock.h> +#endif +#endif + +#ifndef __ECOS +/* + * Machine-independent constants (some used in following include files). + * Redefined constants are from POSIX 1003.1 limits file. + * + * MAXCOMLEN should be >= sizeof(ac_comm) (see <acct.h>) + * MAXLOGNAME should be >= UT_NAMESIZE (see <utmp.h>) + */ +#include <sys/syslimits.h> + +#define MAXCOMLEN 16 /* max command name remembered */ +#define MAXINTERP 64 /* max interpreter file name length */ +#define MAXLOGNAME 12 /* max login name length */ +#define MAXUPRC CHILD_MAX /* max simultaneous processes */ +#define NCARGS ARG_MAX /* max bytes for an exec function */ +#define NGROUPS NGROUPS_MAX /* max number groups */ +#define NOFILE OPEN_MAX /* max open files per process (soft) */ +#define NOFILE_MAX 1024 /* max open files per process (hard) */ +#define NOGROUP 65535 /* marker for empty group set member */ +#endif +#define MAXHOSTNAMELEN 256 /* max hostname size */ + +/* More types and definitions used throughout the kernel. */ +#ifdef _KERNEL +#include <sys/cdefs.h> +#include <sys/errno.h> +#include <sys/time.h> +#ifdef __ECOS +#include <cyg/io/file.h> +#else +#include <sys/resource.h> +#include <sys/ucred.h> +#include <sys/uio.h> +#endif +#endif + +#ifndef __ECOS +/* Signals. */ +#include <sys/signal.h> +#endif + +#ifndef __ECOS +/* + * Priorities. Note that with 32 run queues, differences less than 4 are + * insignificant. + */ +#define PSWP 0 +#define PVM 4 +#define PINOD 8 +#define PRIBIO 16 +#define PVFS 20 +#define PZERO 22 /* No longer magic, shouldn't be here. XXX */ +#define PSOCK 24 +#define PWAIT 32 +#define PLOCK 36 +#define PPAUSE 40 +#define PUSER 50 +#define MAXPRI 127 /* Priorities range from 0 through MAXPRI. */ + +#define PRIMASK 0x0ff +#define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */ +#endif + +#define NBPW sizeof(int) /* number of bytes per word (integer) */ + +#ifndef __ECOS +#define CMASK 022 /* default file mask: S_IWGRP|S_IWOTH */ +#define NODEV (dev_t)(-1) /* non-existent device */ + +/* + * Clustering of hardware pages on machines with ridiculously small + * page sizes is done here. The paging subsystem deals with units of + * CLSIZE pte's describing NBPG (from machine/machparam.h) pages each. + */ +#define CLBYTES (CLSIZE*NBPG) +#define CLOFSET (CLSIZE*NBPG-1) /* for clusters, like PGOFSET */ +#define claligned(x) ((((int)(x))&CLOFSET)==0) +#define CLOFF CLOFSET +#define CLSHIFT (PGSHIFT+CLSIZELOG2) + +#if CLSIZE==1 +#define clbase(i) (i) +#define clrnd(i) (i) +#else +/* Give the base virtual address (first of CLSIZE). */ +#define clbase(i) ((i) &~ (CLSIZE-1)) +/* Round a number of clicks up to a whole cluster. */ +#define clrnd(i) (((i) + (CLSIZE-1)) &~ (CLSIZE-1)) +#endif + +#define CBLOCK 64 /* Clist block size, must be a power of 2. */ +#define CBQSIZE (CBLOCK/NBBY) /* Quote bytes/cblock - can do better. */ + /* Data chars/clist. */ +#define CBSIZE (CBLOCK - sizeof(struct cblock *) - CBQSIZE) +#define CROUND (CBLOCK - 1) /* Clist rounding. */ + +/* + * File system parameters and macros. + * + * The file system is made out of blocks of at most MAXBSIZE units, with + * smaller units (fragments) only in the last direct block. MAXBSIZE + * primarily determines the size of buffers in the buffer pool. It may be + * made larger without any effect on existing file systems; however making + * it smaller makes some file systems unmountable. + */ +#ifndef MAXBSIZE /* XXX temp until sun3 DMA chaining */ +#define MAXBSIZE MAXPHYS +#endif +#define MAXFRAG 8 + +/* + * MAXPATHLEN defines the longest permissable path length after expanding + * symbolic links. It is used to allocate a temporary buffer from the buffer + * pool in which to do the name expansion, hence should be a power of two, + * and must be less than or equal to MAXBSIZE. MAXSYMLINKS defines the + * maximum number of symbolic links that may be expanded in a path name. + * It should be set high enough to allow all legitimate uses, but halt + * infinite loops reasonably quickly. + */ +#define MAXPATHLEN PATH_MAX +#define MAXSYMLINKS 32 + +#endif // __ECOS + +/* Bit map related macros. */ +#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) +#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) +#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) +#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) + +/* Macros for counting and rounding. */ +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#define powerof2(x) ((((x)-1)&(x))==0) + +/* Macros for min/max. */ +#ifndef _KERNEL +# ifndef MIN +# define MIN(a,b) (((a)<(b))?(a):(b)) +# endif +# ifndef MAX +# define MAX(a,b) (((a)>(b))?(a):(b)) +# endif +#endif + +#ifndef __ECOS +/* + * Constants for setting the parameters of the kernel memory allocator. + * + * 2 ** MINBUCKET is the smallest unit of memory that will be + * allocated. It must be at least large enough to hold a pointer. + * + * Units of memory less or equal to MAXALLOCSAVE will permanently + * allocate physical memory; requests for these size pieces of + * memory are quite fast. Allocations greater than MAXALLOCSAVE must + * always allocate and free physical memory; requests for these + * size allocations should be done infrequently as they will be slow. + * + * Constraints: CLBYTES <= MAXALLOCSAVE <= 2 ** (MINBUCKET + 14), and + * MAXALLOCSIZE must be a power of two. + */ +#define MINBUCKET 4 /* 4 => min allocation of 16 bytes */ +#define MAXALLOCSAVE (2 * CLBYTES) + +/* + * Scale factor for scaled integers used to count %cpu time and load avgs. + * + * The number of CPU `tick's that map to a unique `%age' can be expressed + * by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that + * can be calculated (assuming 32 bits) can be closely approximated using + * the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15). + * + * For the scheduler to maintain a 1:1 mapping of CPU `tick' to `%age', + * FSHIFT must be at least 11; this gives us a maximum load avg of ~1024. + */ +#define FSHIFT 11 /* bits to right of fixed binary point */ +#define FSCALE (1<<FSHIFT) + +/* + * rfork() options. + * + * XXX currently, operations without RFPROC set are not supported. + */ +#define RFNAMEG (1<<0) /* UNIMPL new plan9 `name space' */ +#define RFENVG (1<<1) /* UNIMPL copy plan9 `env space' */ +#define RFFDG (1<<2) /* copy fd table */ +#define RFNOTEG (1<<3) /* UNIMPL create new plan9 `note group' */ +#define RFPROC (1<<4) /* change child (else changes curproc) */ +#define RFMEM (1<<5) /* share `address space' */ +#define RFNOWAIT (1<<6) /* parent need not wait() on child */ +#define RFCNAMEG (1<<10) /* UNIMPL zero plan9 `name space' */ +#define RFCENVG (1<<11) /* UNIMPL zero plan9 `env space' */ +#define RFCFDG (1<<12) /* zero fd table */ +#endif // __ECOS + +#ifdef __ECOS +// Function mappings + +extern int cyg_tsleep(void *, int, char *, int); +extern void cyg_wakeup(void *); +#define tsleep(e,p,w,t) cyg_tsleep(e,0,w,t) +#define wakeup(e) cyg_wakeup(e) + +#ifdef CYGIMPL_TRACE_SPLX +extern cyg_uint32 cyg_splimp(const char *file, const int line); +extern cyg_uint32 cyg_splnet(const char *file, const int line); +extern cyg_uint32 cyg_splclock(const char *file, const int line); +extern cyg_uint32 cyg_splsoftnet(const char *file, const int line); +extern void cyg_splx(cyg_uint32, const char *file, const int line); +#define splimp() cyg_splimp(__FUNCTION__, __LINE__) +#define splnet() cyg_splnet(__FUNCTION__, __LINE__) +#define splclock() cyg_splclock(__FUNCTION__, __LINE__) +#define splsoftnet() cyg_splsoftnet(__FUNCTION__, __LINE__) +#define splx(x) cyg_splx(x, __FUNCTION__, __LINE__) +#define cyg_scheduler_lock() _cyg_scheduler_lock(__FUNCTION__, __LINE__) +#define cyg_scheduler_safe_lock() _cyg_scheduler_safe_lock(__FUNCTION__, __LINE__) +#define cyg_scheduler_unlock() _cyg_scheduler_unlock(__FUNCTION__, __LINE__) +#else +extern cyg_uint32 cyg_splimp(void); +extern cyg_uint32 cyg_splnet(void); +extern cyg_uint32 cyg_splclock(void); +extern cyg_uint32 cyg_splsoftnet(void); +extern cyg_uint32 cyg_splhigh(void); +extern void cyg_splx(cyg_uint32); +#define splimp cyg_splimp +#define splnet cyg_splnet +#define splclock cyg_splclock +#define splsoftnet cyg_splsoftnet +#define splhigh cyg_splhigh +#define splx cyg_splx +#endif + +extern void cyg_panic(const char *msg, ...); +#define panic cyg_panic + +// Namespace changes +#define route_reinit cyg_route_reinit +#define arc4random cyg_arc4random +#endif + +/* Machine type dependent parameters. */ +#include <machine/param.h> +#include <machine/limits.h> + +#endif // __SYS_PARAM_H_ diff --git a/ecos/packages/net/tcpip/current/include/sys/protosw.h b/ecos/packages/net/tcpip/current/include/sys/protosw.h new file mode 100644 index 0000000..9afe2b4 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/protosw.h @@ -0,0 +1,271 @@ +//========================================================================== +// +// include/sys/protosw.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: protosw.h,v 1.3 1996/04/21 22:31:54 deraadt Exp $ */ +/* $NetBSD: protosw.h,v 1.10 1996/04/09 20:55:32 cgd Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)protosw.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_PROTOSW_H_ +#define _SYS_PROTOSW_H_ + +/* + * Protocol switch table. + * + * Each protocol has a handle initializing one of these structures, + * which is used for protocol-protocol and system-protocol communication. + * + * A protocol is called through the pr_init entry before any other. + * Thereafter it is called every 200ms through the pr_fasttimo entry and + * every 500ms through the pr_slowtimo for timer based actions. + * The system will call the pr_drain entry if it is low on space and + * this should throw away any non-critical data. + * + * Protocols pass data between themselves as chains of mbufs using + * the pr_input and pr_output hooks. Pr_input passes data up (towards + * UNIX) and pr_output passes it down (towards the imps); control + * information passes up and down on pr_ctlinput and pr_ctloutput. + * The protocol is responsible for the space occupied by any the + * arguments to these entries and must dispose it. + * + * The userreq routine interfaces protocols to the system and is + * described below. + */ + +struct mbuf; +struct sockaddr; +struct socket; +struct domain; + +struct protosw { + short pr_type; /* socket type used for */ + struct domain *pr_domain; /* domain protocol a member of */ + short pr_protocol; /* protocol number */ + short pr_flags; /* see below */ + +/* protocol-protocol hooks */ + void (*pr_input) /* input to protocol (from below) */ + __P((struct mbuf *, ...)); + int (*pr_output) /* output to protocol (from above) */ + __P((struct mbuf *, ...)); + void *(*pr_ctlinput) /* control input (from below) */ + __P((int, struct sockaddr *, void *)); + int (*pr_ctloutput) /* control output (from above) */ + __P((int, struct socket *, int, int, struct mbuf **)); + +/* user-protocol hook */ + int (*pr_usrreq) /* user request: see list below */ + __P((struct socket *, int, struct mbuf *, + struct mbuf *, struct mbuf *)); + +/* utility hooks */ + void (*pr_init) /* initialization hook */ + __P((void)); + + void (*pr_fasttimo) /* fast timeout (200ms) */ + __P((void)); + void (*pr_slowtimo) /* slow timeout (500ms) */ + __P((void)); + void (*pr_drain) /* flush any excess space possible */ + __P((void)); + int (*pr_sysctl) /* sysctl for protocol */ + __P((int *, u_int, void *, size_t *, void *, size_t)); +}; + +#define PR_SLOWHZ 2 /* 2 slow timeouts per second */ +#define PR_FASTHZ 5 /* 5 fast timeouts per second */ + +/* + * Values for pr_flags. + * PR_ADDR requires PR_ATOMIC; + * PR_ADDR and PR_CONNREQUIRED are mutually exclusive. + */ +#define PR_ATOMIC 0x01 /* exchange atomic messages only */ +#define PR_ADDR 0x02 /* addresses given with messages */ +#define PR_CONNREQUIRED 0x04 /* connection required by protocol */ +#define PR_WANTRCVD 0x08 /* want PRU_RCVD calls */ +#define PR_RIGHTS 0x10 /* passes capabilities */ + +/* + * The arguments to usrreq are: + * (*protosw[].pr_usrreq)(up, req, m, nam, opt); + * where up is a (struct socket *), req is one of these requests, + * m is a optional mbuf chain containing a message, + * nam is an optional mbuf chain containing an address, + * and opt is a pointer to a socketopt structure or nil. + * The protocol is responsible for disposal of the mbuf chain m, + * the caller is responsible for any space held by nam and opt. + * A non-zero return from usrreq gives an + * UNIX error number which should be passed to higher level software. + */ +#define PRU_ATTACH 0 /* attach protocol to up */ +#define PRU_DETACH 1 /* detach protocol from up */ +#define PRU_BIND 2 /* bind socket to address */ +#define PRU_LISTEN 3 /* listen for connection */ +#define PRU_CONNECT 4 /* establish connection to peer */ +#define PRU_ACCEPT 5 /* accept connection from peer */ +#define PRU_DISCONNECT 6 /* disconnect from peer */ +#define PRU_SHUTDOWN 7 /* won't send any more data */ +#define PRU_RCVD 8 /* have taken data; more room now */ +#define PRU_SEND 9 /* send this data */ +#define PRU_ABORT 10 /* abort (fast DISCONNECT, DETATCH) */ +#define PRU_CONTROL 11 /* control operations on protocol */ +#define PRU_SENSE 12 /* return status into m */ +#define PRU_RCVOOB 13 /* retrieve out of band data */ +#define PRU_SENDOOB 14 /* send out of band data */ +#define PRU_SOCKADDR 15 /* fetch socket's address */ +#define PRU_PEERADDR 16 /* fetch peer's address */ +#define PRU_CONNECT2 17 /* connect two sockets */ +/* begin for protocols internal use */ +#define PRU_FASTTIMO 18 /* 200ms timeout */ +#define PRU_SLOWTIMO 19 /* 500ms timeout */ +#define PRU_PROTORCV 20 /* receive from below */ +#define PRU_PROTOSEND 21 /* send to below */ + +#define PRU_NREQ 21 + +#ifdef PRUREQUESTS +char *prurequests[] = { + "ATTACH", "DETACH", "BIND", "LISTEN", + "CONNECT", "ACCEPT", "DISCONNECT", "SHUTDOWN", + "RCVD", "SEND", "ABORT", "CONTROL", + "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR", + "PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO", + "PROTORCV", "PROTOSEND", +}; +#endif + +/* + * The arguments to the ctlinput routine are + * (*protosw[].pr_ctlinput)(cmd, sa, arg); + * where cmd is one of the commands below, sa is a pointer to a sockaddr, + * and arg is an optional caddr_t argument used within a protocol family. + */ +#define PRC_IFDOWN 0 /* interface transition */ +#define PRC_ROUTEDEAD 1 /* select new route if possible ??? */ +#define PRC_QUENCH2 3 /* DEC congestion bit says slow down */ +#define PRC_QUENCH 4 /* some one said to slow down */ +#define PRC_MSGSIZE 5 /* message size forced drop */ +#define PRC_HOSTDEAD 6 /* host appears to be down */ +#define PRC_HOSTUNREACH 7 /* deprecated (use PRC_UNREACH_HOST) */ +#define PRC_UNREACH_NET 8 /* no route to network */ +#define PRC_UNREACH_HOST 9 /* no route to host */ +#define PRC_UNREACH_PROTOCOL 10 /* dst says bad protocol */ +#define PRC_UNREACH_PORT 11 /* bad port # */ +/* was PRC_UNREACH_NEEDFRAG 12 (use PRC_MSGSIZE) */ +#define PRC_UNREACH_SRCFAIL 13 /* source route failed */ +#define PRC_REDIRECT_NET 14 /* net routing redirect */ +#define PRC_REDIRECT_HOST 15 /* host routing redirect */ +#define PRC_REDIRECT_TOSNET 16 /* redirect for type of service & net */ +#define PRC_REDIRECT_TOSHOST 17 /* redirect for tos & host */ +#define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */ +#define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */ +#define PRC_PARAMPROB 20 /* header incorrect */ + +#define PRC_NCMDS 21 + +#define PRC_IS_REDIRECT(cmd) \ + ((cmd) >= PRC_REDIRECT_NET && (cmd) <= PRC_REDIRECT_TOSHOST) + +#ifdef PRCREQUESTS +char *prcrequests[] = { + "IFDOWN", "ROUTEDEAD", "#2", "DEC-BIT-QUENCH2", + "QUENCH", "MSGSIZE", "HOSTDEAD", "#7", + "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH", + "#12", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT", + "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS", + "PARAMPROB" +}; +#endif + +/* + * The arguments to ctloutput are: + * (*protosw[].pr_ctloutput)(req, so, level, optname, optval); + * req is one of the actions listed below, so is a (struct socket *), + * level is an indication of which protocol layer the option is intended. + * optname is a protocol dependent socket option request, + * optval is a pointer to a mbuf-chain pointer, for value-return results. + * The protocol is responsible for disposal of the mbuf chain *optval + * if supplied, + * the caller is responsible for any space held by *optval, when returned. + * A non-zero return from usrreq gives an + * UNIX error number which should be passed to higher level software. + */ +#define PRCO_GETOPT 0 +#define PRCO_SETOPT 1 + +#define PRCO_NCMDS 2 + +#ifdef PRCOREQUESTS +char *prcorequests[] = { + "GETOPT", "SETOPT", +}; +#endif + +#ifdef _KERNEL +struct sockaddr; +struct protosw *pffindproto __P((int, int, int)); +struct protosw *pffindtype __P((int, int)); +void pfctlinput __P((int, struct sockaddr *)); +#endif + +#endif // _SYS_PROTOSW_H_ diff --git a/ecos/packages/net/tcpip/current/include/sys/queue.h b/ecos/packages/net/tcpip/current/include/sys/queue.h new file mode 100644 index 0000000..2358b86 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/queue.h @@ -0,0 +1,514 @@ +//========================================================================== +// +// include/sys/queue.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: queue.h,v 1.14 1999/09/08 08:20:04 espie Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ + if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.le_next; \ + else \ + (head).tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ +} while (0) + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue access methods + */ +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_END(head) ((void *)(head)) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define CIRCLEQ_EMPTY(head) \ + (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for((var) = CIRCLEQ_FIRST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_NEXT(var, field)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = CIRCLEQ_LAST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_PREV(var, field)) + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = CIRCLEQ_END(head); \ + (head)->cqh_last = CIRCLEQ_END(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = CIRCLEQ_END(head); \ + if ((head)->cqh_last == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = CIRCLEQ_END(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (0) + +#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ + CIRCLEQ_END(head)) \ + (head).cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ + CIRCLEQ_END(head)) \ + (head).cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/socket.h b/ecos/packages/net/tcpip/current/include/sys/socket.h new file mode 100644 index 0000000..fe9fb38 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/socket.h @@ -0,0 +1,454 @@ +//========================================================================== +// +// include/sys/socket.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: socket.h,v 1.30 1999/12/08 06:50:24 itojun Exp $ */ +/* $NetBSD: socket.h,v 1.14 1996/02/09 18:25:36 christos Exp $ */ + +/* + * Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)socket.h 8.4 (Berkeley) 2/21/94 + */ + +#ifndef _SYS_SOCKET_H_ +#define _SYS_SOCKET_H_ + +/* + * Definitions related to sockets: types, address families, options. + */ + +/* + * Types + */ +#define SOCK_STREAM 1 /* stream socket */ +#define SOCK_DGRAM 2 /* datagram socket */ +#define SOCK_RAW 3 /* raw-protocol interface */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequenced packet stream */ + +/* + * Option flags per-socket. + */ +#define SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ +#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */ + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF 0x1001 /* send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_NETPROC 0x1020 /* multiplex; network processing */ + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xffff /* options for socket level */ + +/* + * Address families. + */ +#define AF_UNSPEC 0 /* unspecified */ +#define AF_LOCAL 1 /* local to host (pipes, portals) */ +#define AF_UNIX AF_LOCAL /* backward compatibility */ +#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ +#define AF_IMPLINK 3 /* arpanet imp addresses */ +#define AF_PUP 4 /* pup protocols: e.g. BSP */ +#define AF_CHAOS 5 /* mit CHAOS protocols */ +#define AF_NS 6 /* XEROX NS protocols */ +#define AF_ISO 7 /* ISO protocols */ +#define AF_OSI AF_ISO +#define AF_ECMA 8 /* european computer manufacturers */ +#define AF_DATAKIT 9 /* datakit protocols */ +#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ +#define AF_SNA 11 /* IBM SNA */ +#define AF_DECnet 12 /* DECnet */ +#define AF_DLI 13 /* DEC Direct data link interface */ +#define AF_LAT 14 /* LAT */ +#define AF_HYLINK 15 /* NSC Hyperchannel */ +#define AF_APPLETALK 16 /* Apple Talk */ +#define AF_ROUTE 17 /* Internal Routing Protocol */ +#define AF_LINK 18 /* Link layer interface */ +#define pseudo_AF_XTP 19 /* eXpress Transfer Protocol (no AF) */ +#define AF_COIP 20 /* connection-oriented IP, aka ST II */ +#define AF_CNT 21 /* Computer Network Technology */ +#define pseudo_AF_RTIP 22 /* Help Identify RTIP packets */ +#define AF_IPX 23 /* Novell Internet Protocol */ +#define AF_INET6 24 /* IPv6 */ +#define pseudo_AF_PIP 25 /* Help Identify PIP packets */ +#define AF_ISDN 26 /* Integrated Services Digital Network*/ +#define AF_E164 AF_ISDN /* CCITT E.164 recommendation */ +#define AF_NATM 27 /* native ATM access */ +#define AF_ENCAP 28 +#define AF_SIP 29 /* Simple Internet Protocol */ +#define AF_KEY 30 +#define AF_MAX 31 + +/* + * Structure used by kernel to store most + * addresses. + */ +struct sockaddr { + u_int8_t sa_len; /* total length */ + sa_family_t sa_family; /* address family */ + char sa_data[14]; /* actually longer; address value */ +}; + +/* + * Sockaddr type which can hold any sockaddr type available + * in the system. + * + * Note: __ss_{len,family} is defined in RFC2553. During RFC2553 discussion + * the field name went back and forth between ss_len and __ss_len, + * and RFC2553 specifies it to be __ss_len. openbsd picked ss_len. + * For maximum portability, userland programmer would need to + * (1) make the code never touch ss_len portion (cast it into sockaddr and + * touch sa_len), or (2) add "-Dss_len=__ss_len" into CFLAGS to unify all + * occurences (including header file) to __ss_len. + */ +struct sockaddr_storage { + u_int8_t ss_len; /* total length */ + sa_family_t ss_family; /* address family */ + u_char __ss_pad1[6]; /* align to quad */ + u_int64_t __ss_pad2; /* force alignment for stupid compilers */ + u_char __ss_pad3[240]; /* pad to a total of 256 bytes */ +}; + +/* + * Structure used by kernel to pass protocol + * information in raw sockets. + */ +struct sockproto { + u_short sp_family; /* address family */ + u_short sp_protocol; /* protocol */ +}; + +/* + * Protocol families, same as address families for now. + */ +#define PF_UNSPEC AF_UNSPEC +#define PF_LOCAL AF_LOCAL +#define PF_UNIX PF_LOCAL /* backward compatibility */ +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_IMPLINK AF_IMPLINK +#define PF_PUP AF_PUP +#define PF_CHAOS AF_CHAOS +#define PF_NS AF_NS +#define PF_ISO AF_ISO +#define PF_OSI AF_ISO +#define PF_ECMA AF_ECMA +#define PF_DATAKIT AF_DATAKIT +#define PF_CCITT AF_CCITT +#define PF_SNA AF_SNA +#define PF_DECnet AF_DECnet +#define PF_DLI AF_DLI +#define PF_LAT AF_LAT +#define PF_HYLINK AF_HYLINK +#define PF_APPLETALK AF_APPLETALK +#define PF_ROUTE AF_ROUTE +#define PF_LINK AF_LINK +#define PF_XTP pseudo_AF_XTP /* really just proto family, no AF */ +#define PF_COIP AF_COIP +#define PF_CNT AF_CNT +#define PF_IPX AF_IPX /* same format as AF_NS */ +#define PF_INET6 AF_INET6 +#define PF_RTIP pseudo_AF_FTIP /* same format as AF_INET */ +#define PF_PIP pseudo_AF_PIP +#define PF_ISDN AF_ISDN +#define PF_NATM AF_NATM +#define PF_ENCAP AF_ENCAP +#define PF_SIP AF_SIP +#define PF_KEY AF_KEY +#define PF_MAX AF_MAX + +/* + * These are the valid values for the "how" field used by shutdown(2). + */ +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 + +/* + * Socket credentials. + */ +struct sockcred { + uid_t sc_uid; /* real user id */ + uid_t sc_euid; /* effective user id */ + gid_t sc_gid; /* real group id */ + gid_t sc_egid; /* effective group id */ + int sc_ngroups; /* number of supplemental groups */ + gid_t sc_groups[1]; /* variable length */ +}; + +/* + * Compute size of a sockcred structure with groups. + */ +#define SOCKCREDSIZE(ngrps) \ + (sizeof(struct sockcred) + (sizeof(gid_t) * ((ngrps) - 1))) + +/* + * Definitions for network related sysctl, CTL_NET. + * + * Second level is protocol family. + * Third level is protocol number. + * + * Further levels are defined by the individual families below. + */ +#define NET_MAXID AF_MAX + +#define CTL_NET_NAMES { \ + { 0, 0 }, \ + { "unix", CTLTYPE_NODE }, \ + { "inet", CTLTYPE_NODE }, \ + { "implink", CTLTYPE_NODE }, \ + { "pup", CTLTYPE_NODE }, \ + { "chaos", CTLTYPE_NODE }, \ + { "xerox_ns", CTLTYPE_NODE }, \ + { "iso", CTLTYPE_NODE }, \ + { "emca", CTLTYPE_NODE }, \ + { "datakit", CTLTYPE_NODE }, \ + { "ccitt", CTLTYPE_NODE }, \ + { "ibm_sna", CTLTYPE_NODE }, \ + { "decnet", CTLTYPE_NODE }, \ + { "dec_dli", CTLTYPE_NODE }, \ + { "lat", CTLTYPE_NODE }, \ + { "hylink", CTLTYPE_NODE }, \ + { "appletalk", CTLTYPE_NODE }, \ + { "route", CTLTYPE_NODE }, \ + { "link_layer", CTLTYPE_NODE }, \ + { "xtp", CTLTYPE_NODE }, \ + { "coip", CTLTYPE_NODE }, \ + { "cnt", CTLTYPE_NODE }, \ + { "rtip", CTLTYPE_NODE }, \ + { "ipx", CTLTYPE_NODE }, \ + { "inet6", CTLTYPE_NODE }, \ + { "pip", CTLTYPE_NODE }, \ + { "isdn", CTLTYPE_NODE }, \ + { "natm", CTLTYPE_NODE }, \ + { "encap", CTLTYPE_NODE }, \ + { "sip", CTLTYPE_NODE }, \ + { "key", CTLTYPE_NODE }, \ +} + +/* + * PF_ROUTE - Routing table + * + * Three additional levels are defined: + * Fourth: address family, 0 is wildcard + * Fifth: type of info, defined below + * Sixth: flag(s) to mask with for NET_RT_FLAGS + */ +#define NET_RT_DUMP 1 /* dump; may limit to a.f. */ +#define NET_RT_FLAGS 2 /* by flags, e.g. RESOLVING */ +#define NET_RT_IFLIST 3 /* survey interface list */ +#define NET_RT_MAXID 4 + +#define CTL_NET_RT_NAMES { \ + { 0, 0 }, \ + { "dump", CTLTYPE_STRUCT }, \ + { "flags", CTLTYPE_STRUCT }, \ + { "iflist", CTLTYPE_STRUCT }, \ +} + +/* + * Maximum queue length specifiable by listen(2). + */ +#define SOMAXCONN 128 + +/* + * Message header for recvmsg and sendmsg calls. + * Used value-result for recvmsg, value only for sendmsg. + */ +struct msghdr { + caddr_t msg_name; /* optional address */ + socklen_t msg_namelen; /* size of address */ + struct iovec *msg_iov; /* scatter/gather array */ + u_int msg_iovlen; /* # elements in msg_iov */ + caddr_t msg_control; /* ancillary data, see below */ + socklen_t msg_controllen; /* ancillary data buffer len */ + int msg_flags; /* flags on received message */ +}; + +#define MSG_OOB 0x1 /* process out-of-band data */ +#define MSG_PEEK 0x2 /* peek at incoming message */ +#define MSG_DONTROUTE 0x4 /* send without using routing tables */ +#define MSG_EOR 0x8 /* data completes record */ +#define MSG_TRUNC 0x10 /* data discarded before delivery */ +#define MSG_CTRUNC 0x20 /* control data lost before delivery */ +#define MSG_WAITALL 0x40 /* wait for full request or error */ +#define MSG_DONTWAIT 0x80 /* this message should be nonblocking */ +#define MSG_BCAST 0x100 /* this message rec'd as broadcast */ +#define MSG_MCAST 0x200 /* this message rec'd as multicast */ + +/* + * Header for ancillary data objects in msg_control buffer. + * Used for additional information with/about a datagram + * not expressible by flags. The format is a sequence + * of message elements headed by cmsghdr structures. + */ +struct cmsghdr { + socklen_t cmsg_len; /* data byte count, including hdr */ + int cmsg_level; /* originating protocol */ + int cmsg_type; /* protocol-specific type */ +/* followed by u_char cmsg_data[]; */ +}; + +/* given pointer to struct cmsghdr, return pointer to data */ +#define CMSG_DATA(cmsg) ((u_char *)((cmsg) + 1)) + +/* given pointer to struct cmsghdr, return pointer to next cmsghdr */ +#define CMSG_NXTHDR(mhdr, cmsg) \ + (((caddr_t)(cmsg) + (cmsg)->cmsg_len + sizeof(struct cmsghdr) > \ + (mhdr)->msg_control + (mhdr)->msg_controllen) ? \ + (struct cmsghdr *)NULL : \ + (struct cmsghdr *)((caddr_t)(cmsg) + CMSG_ALIGN((cmsg)->cmsg_len))) + +#define CMSG_FIRSTHDR(mhdr) ((struct cmsghdr *)(mhdr)->msg_control) + +/* Round len up to next alignment boundary */ +#define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1)) + +/* Length of the contents of a control message of length len */ +#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) + +/* Length of the space taken up by a padded control message of length len */ +#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len)) + +/* "Socket"-level control message types: */ +#define SCM_RIGHTS 0x01 /* access rights (array of int) */ +#define SCM_CREDS 0x02 /* credientials (struct sockcred) */ + +/* + * 4.3 compat sockaddr, move to compat file later + */ +struct osockaddr { + u_short sa_family; /* address family */ + char sa_data[14]; /* up to 14 bytes of direct address */ +}; + +/* + * 4.3-compat message header (move to compat file later). + */ +struct omsghdr { + caddr_t msg_name; /* optional address */ + int msg_namelen; /* size of address */ + struct iovec *msg_iov; /* scatter/gather array */ + int msg_iovlen; /* # elements in msg_iov */ + caddr_t msg_accrights; /* access rights sent/received */ + int msg_accrightslen; +}; + +#define SA_LEN(x) ((x)->sa_len) + +#ifndef _KERNEL + +#include <sys/cdefs.h> + +__BEGIN_DECLS +int accept __P((int, struct sockaddr *, socklen_t *)); +int bind __P((int, const struct sockaddr *, socklen_t)); +int connect __P((int, const struct sockaddr *, socklen_t)); +int getpeername __P((int, struct sockaddr *, socklen_t *)); +int getsockname __P((int, struct sockaddr *, socklen_t *)); +int getsockopt __P((int, int, int, void *, socklen_t *)); +int listen __P((int, int)); +ssize_t recv __P((int, void *, size_t, int)); +ssize_t recvfrom __P((int, void *, size_t, int, struct sockaddr *, socklen_t *)); +ssize_t recvmsg __P((int, struct msghdr *, int)); +ssize_t send __P((int, const void *, size_t, int)); +ssize_t sendto __P((int, const void *, + size_t, int, const struct sockaddr *, socklen_t)); +ssize_t sendmsg __P((int, const struct msghdr *, int)); +int setsockopt __P((int, int, int, const void *, socklen_t)); +int shutdown __P((int, int)); +int socket __P((int, int, int)); +int socketpair __P((int, int, int, int *)); +__END_DECLS +#else +# if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) || \ + defined(COMPAT_HPUX) || defined(COMPAT_FREEBSD) +# define COMPAT_OLDSOCK +# define MSG_COMPAT 0x8000 +# endif + +void pfctlinput __P((int, struct sockaddr *)); +#endif /* !_KERNEL */ + +#endif /* !_SYS_SOCKET_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/socketvar.h b/ecos/packages/net/tcpip/current/include/sys/socketvar.h new file mode 100644 index 0000000..4f63689 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/socketvar.h @@ -0,0 +1,338 @@ +//========================================================================== +// +// include/sys/socketvar.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: socketvar.h,v 1.17 1999/12/08 06:50:24 itojun Exp $ */ +/* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)socketvar.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_SOCKETVAR_H_ +#define _SYS_SOCKETVAR_H_ + +#include <sys/bsdselect.h> /* for struct selinfo */ + +/* + * Kernel structure per socket. + * Contains send and receive buffer queues, + * handle on protocol and pointer to protocol + * private data and error information. + */ +struct socket { + short so_type; /* generic type, see socket.h */ + short so_options; /* from socket call, see socket.h */ + short so_linger; /* time to linger while closing */ + short so_state; /* internal state flags SS_*, below */ + void *so_pcb; /* protocol control block */ + struct protosw *so_proto; /* protocol handle */ +/* + * Variables for connection queueing. + * Socket where accepts occur is so_head in all subsidiary sockets. + * If so_head is 0, socket is not related to an accept. + * For head socket so_q0 queues partially completed connections, + * while so_q is a queue of connections ready to be accepted. + * If a connection is aborted and it has so_head set, then + * it has to be pulled out of either so_q0 or so_q. + * We allow connections to queue up based on current queue lengths + * and limit on number of queued connections for this socket. + */ + struct socket *so_head; /* back pointer to accept socket */ + struct socket *so_q0; /* queue of partial connections */ + struct socket *so_q; /* queue of incoming connections */ + short so_q0len; /* partials on so_q0 */ + short so_qlen; /* number of connections on so_q */ + short so_qlimit; /* max number queued connections */ + short so_timeo; /* connection timeout */ + u_short so_error; /* error affecting connection */ + pid_t so_pgid; /* pgid for signals */ + uid_t so_siguid; /* uid of process who set so_pgid */ + uid_t so_sigeuid; /* euid of process who set so_pgid */ + u_long so_oobmark; /* chars to oob mark */ +/* + * Variables for socket buffering. + */ + struct sockbuf { + u_long sb_cc; /* actual chars in buffer */ + u_long sb_hiwat; /* max actual char count */ + u_long sb_mbcnt; /* chars of mbufs used */ + u_long sb_mbmax; /* max chars of mbufs to use */ + long sb_lowat; /* low water mark */ + struct mbuf *sb_mb; /* the mbuf chain */ + struct selinfo sb_sel; /* process selecting read/write */ + short sb_flags; /* flags, see below */ + short sb_timeo; /* timeout for read/write */ + } so_rcv, so_snd; +#define SB_MAX (256*1024) /* default for max chars in sockbuf */ +#define SB_LOCK 0x01 /* lock on data queue */ +#define SB_WANT 0x02 /* someone is waiting to lock */ +#define SB_WAIT 0x04 /* someone is waiting for data/space */ +#define SB_SEL 0x08 /* someone is selecting */ +#define SB_ASYNC 0x10 /* ASYNC I/O, need signals */ +#define SB_NOINTR 0x40 /* operations not interruptible */ + + void *so_internal; /* Space for svr4 stream data */ + void (*so_upcall) __P((struct socket *so, caddr_t arg, int waitf)); + caddr_t so_upcallarg; /* Arg for above */ + uid_t so_euid; /* who opened the socket */ + uid_t so_ruid; /* who opened the socket */ +}; + +/* + * Socket state bits. + */ +#define SS_NOFDREF 0x001 /* no file table ref any more */ +#define SS_ISCONNECTED 0x002 /* socket connected to a peer */ +#define SS_ISCONNECTING 0x004 /* in process of connecting to peer */ +#define SS_ISDISCONNECTING 0x008 /* in process of disconnecting */ +#define SS_CANTSENDMORE 0x010 /* can't send more data to peer */ +#define SS_CANTRCVMORE 0x020 /* can't receive more data from peer */ +#define SS_RCVATMARK 0x040 /* at mark on input */ +#define SS_ISDISCONNECTED 0x800 /* socket disconnected from peer */ + +#define SS_PRIV 0x080 /* privileged for broadcast, raw... */ +#define SS_NBIO 0x100 /* non-blocking ops */ +#define SS_ASYNC 0x200 /* async i/o notify */ +#define SS_ISCONFIRMING 0x400 /* deciding to accept connection req */ +#define SS_CONNECTOUT 0x1000 /* connect, not accept, at this end */ + +/* + * Macros for sockets and socket buffering. + */ + +/* + * Do we need to notify the other side when I/O is possible? + */ +#define sb_notify(sb) (((sb)->sb_flags & (SB_WAIT|SB_SEL|SB_ASYNC)) != 0) + +/* + * How much space is there in a socket buffer (so->so_snd or so->so_rcv)? + * This is problematical if the fields are unsigned, as the space might + * still be negative (cc > hiwat or mbcnt > mbmax). Should detect + * overflow and return 0. Should use "lmin" but it doesn't exist now. + */ +#define sbspace(sb) \ + ((long) imin((int)((sb)->sb_hiwat - (sb)->sb_cc), \ + (int)((sb)->sb_mbmax - (sb)->sb_mbcnt))) + +/* do we have to send all at once on a socket? */ +#define sosendallatonce(so) \ + ((so)->so_proto->pr_flags & PR_ATOMIC) + +/* can we read something from so? */ +#define soreadable(so) \ + ((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat || \ + ((so)->so_state & SS_CANTRCVMORE) || \ + (so)->so_qlen || (so)->so_error) + +/* can we write something to so? */ +#define sowriteable(so) \ + ((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \ + (((so)->so_state&SS_ISCONNECTED) || \ + ((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || \ + ((so)->so_state & SS_CANTSENDMORE) || \ + (so)->so_error) + +/* adjust counters in sb reflecting allocation of m */ +#define sballoc(sb, m) { \ + (sb)->sb_cc += (m)->m_len; \ + (sb)->sb_mbcnt += MSIZE; \ + if ((m)->m_flags & M_EXT) \ + (sb)->sb_mbcnt += (m)->m_ext.ext_size; \ +} + +/* adjust counters in sb reflecting freeing of m */ +#define sbfree(sb, m) { \ + (sb)->sb_cc -= (m)->m_len; \ + (sb)->sb_mbcnt -= MSIZE; \ + if ((m)->m_flags & M_EXT) \ + (sb)->sb_mbcnt -= (m)->m_ext.ext_size; \ +} + +/* + * Set lock on sockbuf sb; sleep if lock is already held. + * Unless SB_NOINTR is set on sockbuf, sleep is interruptible. + * Returns error without lock if sleep is interrupted. + */ +#ifdef __ECOS +extern int sblock(struct sockbuf *sb, int wf); +extern void sbunlock(struct sockbuf *sb); +#else +#define sblock(sb, wf) ((sb)->sb_flags & SB_LOCK ? \ + (((wf) == M_WAITOK) ? sb_lock(sb) : EWOULDBLOCK) : \ + ((sb)->sb_flags |= SB_LOCK), 0) + +/* release lock on sockbuf sb */ +#define sbunlock(sb) { \ + (sb)->sb_flags &= ~SB_LOCK; \ + if ((sb)->sb_flags & SB_WANT) { \ + (sb)->sb_flags &= ~SB_WANT; \ + wakeup((caddr_t)&(sb)->sb_flags); \ + } \ +} +#endif + +#define sorwakeup(so) { sowakeup((so), &(so)->so_rcv); \ + if ((so)->so_upcall) \ + (*((so)->so_upcall))((so), (so)->so_upcallarg, M_DONTWAIT); \ + } + +#define sowwakeup(so) sowakeup((so), &(so)->so_snd) + +#ifdef _KERNEL +u_long sb_max; +/* to catch callers missing new second argument to sonewconn: */ +#define sonewconn(head, connstatus) sonewconn1((head), (connstatus)) +struct socket *sonewconn1 __P((struct socket *head, int connstatus)); + +/* strings for sleep message: */ +extern char netio[], netcon[], netcls[]; + +struct mbuf; +struct sockaddr; +struct proc; +struct msghdr; +struct stat; + +/* + * File operations on sockets. + */ +#ifdef __ECOS +int soo_read __P((struct file *fp, struct uio *uio)); +int soo_write __P((struct file *fp, struct uio *uio)); +int soo_ioctl __P((struct file *fp, CYG_ADDRWORD cmd, CYG_ADDRWORD data)); +int soo_select __P((struct file *fp, int which)); +int soo_close __P((struct file *fp)); +#else +int soo_read __P((struct file *fp, struct uio *uio, struct ucred *cred)); +int soo_write __P((struct file *fp, struct uio *uio, struct ucred *cred)); +int soo_ioctl __P((struct file *fp, u_long cmd, caddr_t data, + struct proc *p)); +int soo_select __P((struct file *fp, int which, struct proc *p)); +int soo_close __P((struct file *fp, struct proc *p)); +#endif + +int soo_stat __P((struct socket *, struct stat *)); +int uipc_usrreq __P((struct socket *, int , struct mbuf *, + struct mbuf *, struct mbuf *)); +void sbappend __P((struct sockbuf *sb, struct mbuf *m)); +int sbappendaddr __P((struct sockbuf *sb, struct sockaddr *asa, + struct mbuf *m0, struct mbuf *control)); +int sbappendcontrol __P((struct sockbuf *sb, struct mbuf *m0, + struct mbuf *control)); +void sbappendrecord __P((struct sockbuf *sb, struct mbuf *m0)); +void sbcheck __P((struct sockbuf *sb)); +void sbcompress __P((struct sockbuf *sb, struct mbuf *m, struct mbuf *n)); +struct mbuf * + sbcreatecontrol __P((caddr_t p, int size, int type, int level)); +void sbdrop __P((struct sockbuf *sb, int len)); +void sbdroprecord __P((struct sockbuf *sb)); +void sbflush __P((struct sockbuf *sb)); +void sbinsertoob __P((struct sockbuf *sb, struct mbuf *m0)); +void sbrelease __P((struct sockbuf *sb)); +int sbreserve __P((struct sockbuf *sb, u_long cc)); +int sbwait __P((struct sockbuf *sb)); +int sb_lock __P((struct sockbuf *sb)); +int soabort __P((struct socket *so)); +int soaccept __P((struct socket *so, struct mbuf *nam)); +int sobind __P((struct socket *so, struct mbuf *nam)); +void socantrcvmore __P((struct socket *so)); +void socantsendmore __P((struct socket *so)); +int soclose __P((struct socket *so)); +int soconnect __P((struct socket *so, struct mbuf *nam)); +int soconnect2 __P((struct socket *so1, struct socket *so2)); +int socreate __P((int dom, struct socket **aso, int type, int proto)); +int sodisconnect __P((struct socket *so)); +void sofree __P((struct socket *so)); +int sogetopt __P((struct socket *so, int level, int optname, + struct mbuf **mp)); +void sohasoutofband __P((struct socket *so)); +void soisconnected __P((struct socket *so)); +void soisconnecting __P((struct socket *so)); +void soisdisconnected __P((struct socket *so)); +void soisdisconnecting __P((struct socket *so)); +int solisten __P((struct socket *so, int backlog)); +struct socket * + sonewconn1 __P((struct socket *head, int connstatus)); +void soqinsque __P((struct socket *head, struct socket *so, int q)); +int soqremque __P((struct socket *so, int q)); +int soreceive __P((struct socket *so, struct mbuf **paddr, struct uio *uio, + struct mbuf **mp0, struct mbuf **controlp, int *flagsp)); +int soreserve __P((struct socket *so, u_long sndcc, u_long rcvcc)); +void sorflush __P((struct socket *so)); +int sosend __P((struct socket *so, struct mbuf *addr, struct uio *uio, + struct mbuf *top, struct mbuf *control, int flags)); +int sosetopt __P((struct socket *so, int level, int optname, + struct mbuf *m0)); +int soshutdown __P((struct socket *so, int how)); +void sowakeup __P((struct socket *so, struct sockbuf *sb)); +int sockargs __P((struct mbuf **, caddr_t, socklen_t, int)); + +#ifdef __ECOS +int sendit __P((int, struct msghdr *, int, register_t *)); +int recvit __P((int, struct msghdr *, caddr_t, register_t *)); +#else +int sendit __P((struct proc *, int, struct msghdr *, int, register_t *)); +int recvit __P((struct proc *, int, struct msghdr *, caddr_t, + register_t *)); +#endif +#endif /* _KERNEL */ + +#endif // _SYS_SOCKETVAR_H_ diff --git a/ecos/packages/net/tcpip/current/include/sys/sockio.h b/ecos/packages/net/tcpip/current/include/sys/sockio.h new file mode 100644 index 0000000..211e501 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/sockio.h @@ -0,0 +1,179 @@ +//========================================================================== +// +// include/sys/sockio.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: sockio.h,v 1.10 1999/12/08 06:50:24 itojun Exp $ */ +/* $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sockio.h 8.1 (Berkeley) 3/28/94 + */ + +#ifndef _SYS_SOCKIO_H_ +#define _SYS_SOCKIO_H_ + +#include <sys/ioccom.h> + +/* Socket ioctl's. */ +#define SIOCSHIWAT _IOW('s', 0, int) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, int) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, int) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, int) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */ +#define SIOCSPGRP _IOW('s', 8, int) /* set process group */ +#define SIOCGPGRP _IOR('s', 9, int) /* get process group */ + +#ifdef __ECOS +#define SIOCADDRT _IOW('r', 10, struct ecos_rtentry) /* add route */ +#define SIOCDELRT _IOW('r', 11, struct ecos_rtentry) /* delete route */ +#else +#define SIOCADDRT _IOW('r', 10, struct ortentry) /* add route */ +#define SIOCDELRT _IOW('r', 11, struct ortentry) /* delete route */ +#endif + +#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ +#define OSIOCGIFADDR _IOWR('i', 13, struct ifreq) /* get ifnet address */ +#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */ +#define SIOCGIFHWADDR _IOWR('i', 15, struct ifreq) /* get MAC address */ +#ifdef __ECOS +#define SIOCSIFHWADDR _IOW('i',101, struct ifreq) /* set MAC address */ +/* NB these two take a struct ifreq followed by the useful data */ +#define SIOCGIFSTATSUD _IOWR('i',102, struct ifreq) /* get uptodate if stats */ +#define SIOCGIFSTATS _IOWR('i',103, struct ifreq) /* get interface stats */ +#endif +#define SIOCSIFDSTADDR _IOW('i', 14, struct ifreq) /* set p-p address */ +#define OSIOCGIFDSTADDR _IOWR('i', 15, struct ifreq) /* get p-p address */ +#define SIOCGIFDSTADDR _IOWR('i', 34, struct ifreq) /* get p-p address */ +#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */ +#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */ +#define OSIOCGIFBRDADDR _IOWR('i', 18, struct ifreq) /* get broadcast addr */ +#define SIOCGIFBRDADDR _IOWR('i', 35, struct ifreq) /* get broadcast addr */ +#define SIOCSIFBRDADDR _IOW('i', 19, struct ifreq) /* set broadcast addr */ +#define OSIOCGIFCONF _IOWR('i', 20, struct ifconf) /* get ifnet list */ +#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */ +#define OSIOCGIFNETMASK _IOWR('i', 21, struct ifreq) /* get net addr mask */ +#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */ +#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */ +#define SIOCGIFMETRIC _IOWR('i', 23, struct ifreq) /* get IF metric */ +#define SIOCSIFMETRIC _IOW('i', 24, struct ifreq) /* set IF metric */ +#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */ +#define SIOCAIFADDR _IOW('i', 26, struct ifaliasreq)/* add/chg IF alias */ +#define SIOCGIFDATA _IOWR('i', 27, struct ifreq) /* get if_data */ + +/* KAME IPv6 */ +/* SIOCAIFALIAS? */ +#define SIOCALIFADDR _IOW('i', 28, struct if_laddrreq) /* add IF addr */ +#define SIOCGLIFADDR _IOWR('i', 29, struct if_laddrreq) /* get IF addr */ +#define SIOCDLIFADDR _IOW('i', 30, struct if_laddrreq) /* delete IF addr */ + +#define SIOCADDMULTI _IOW('i', 49, struct ifreq) /* add m'cast addr */ +#define SIOCDELMULTI _IOW('i', 50, struct ifreq) /* del m'cast addr */ +#define SIOCGETVIFCNT _IOWR('u', 51, struct sioc_vif_req)/* vif pkt cnt */ +#define SIOCGETSGCNT _IOWR('u', 52, struct sioc_sg_req) /* sg pkt cnt */ + +#define SIOCSIFMEDIA _IOWR('i', 53, struct ifreq) /* set net media */ +#define SIOCGIFMEDIA _IOWR('i', 54, struct ifmediareq) /* get net media */ + +#define SIOCSIFPHYADDR _IOW('i', 70, struct ifaliasreq) /* set gif addres */ +#define SIOCGIFPSRCADDR _IOWR('i', 71, struct ifreq) /* get gif psrc addr */ +#define SIOCGIFPDSTADDR _IOWR('i', 72, struct ifreq) /* get gif pdst addr */ + +#define SIOCBRDGADD _IOWR('i', 60, struct ifbreq) /* add bridge ifs */ +#define SIOCBRDGDEL _IOWR('i', 61, struct ifbreq) /* del bridge ifs */ +#define SIOCBRDGGIFFLGS _IOWR('i', 62, struct ifbreq) /* get brdg if flags */ +#define SIOCBRDGSIFFLGS _IOWR('i', 63, struct ifbreq) /* set brdg if flags */ +#define SIOCBRDGSCACHE _IOWR('i', 64, struct ifbcachereq) /* set cache size */ +#define SIOCBRDGGCACHE _IOWR('i', 65, struct ifbcachereq) /* get cache size */ +#define SIOCBRDGADDS _IOW('i', 65, struct ifbreq) /* add span port */ +#define SIOCBRDGIFS _IOWR('i', 66, struct ifbreq) /* get member ifs */ +#define SIOCBRDGDELS _IOW('i', 66, struct ifbreq) /* del span port */ +#define SIOCBRDGRTS _IOWR('i', 67, struct ifbaconf) /* get addresses */ +#define SIOCBRDGSADDR _IOWR('i', 68, struct ifbareq) /* set addr flags */ +#define SIOCBRDGSTO _IOWR('i', 69, struct ifbcachetoreq) /* cache timeout */ +#define SIOCBRDGGTO _IOWR('i', 70, struct ifbcachetoreq) /* cache timeout */ +#define SIOCBRDGDADDR _IOWR('i', 71, struct ifbareq) /* delete addr */ +#define SIOCBRDGFLUSH _IOWR('i', 72, struct ifbreq) /* flush addr cache */ + +#define SIOCBRDGARL _IOWR('i', 77, struct ifbrlreq) /* add bridge rule */ +#define SIOCBRDGFRL _IOWR('i', 78, struct ifbrlreq) /* flush brdg rules */ +#define SIOCBRDGGRL _IOWR('i', 79, struct ifbrlconf)/* get bridge rules */ + +#define SIOCBRDGGPRI _IOWR('i', 80, struct ifbrparam) /* get priority */ +#define SIOCBRDGSPRI _IOW('i', 80, struct ifbrparam) /* set priority */ +#define SIOCBRDGGHT _IOWR('i', 81, struct ifbrparam) /* get hello time */ +#define SIOCBRDGSHT _IOW('i', 81, struct ifbrparam) /* set hello time */ +#define SIOCBRDGGFD _IOWR('i', 82, struct ifbrparam) /* get forward delay */ +#define SIOCBRDGSFD _IOW('i', 82, struct ifbrparam) /* set forward delay */ +#define SIOCBRDGGMA _IOWR('i', 83, struct ifbrparam) /* get max age */ +#define SIOCBRDGSMA _IOW('i', 83, struct ifbrparam) /* set max age */ +#define SIOCBRDGSIFPRIO _IOWR('i', 84, struct ifbreq) /* set if priority */ +#define SIOCBRDGSIFCOST _IOWR('i', 85, struct ifbreq) /* set if cost */ + +#define SIOCSIFMTU _IOW('i', 127, struct ifreq) /* set ifnet mtu */ +#define SIOCGIFMTU _IOWR('i', 126, struct ifreq) /* get ifnet mtu */ +#define SIOCSIFASYNCMAP _IOW('i', 125, struct ifreq) /* set ppp asyncmap */ +#define SIOCGIFASYNCMAP _IOWR('i', 124, struct ifreq) /* get ppp asyncmap */ + +#ifdef __ECOS +#define FIONBIO _IOW('s', 80, int) /* set non-blocking I/O */ +#define FIOASYNC _IOW('s', 81, int) /* set async I/O */ +#define FIONREAD _IOR('s', 82, int) /* get number of avail chars */ +#endif + +#endif /* !_SYS_SOCKIO_H_ */ diff --git a/ecos/packages/net/tcpip/current/include/sys/syscallargs.h b/ecos/packages/net/tcpip/current/include/sys/syscallargs.h new file mode 100644 index 0000000..b1a3872 --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/syscallargs.h @@ -0,0 +1,1411 @@ +//========================================================================== +// +// include/sys/syscallargs.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: syscallargs.h,v 1.41 1999/08/08 00:32:22 niklas Exp $ */ + +/* + * System call argument lists. + * + * DO NOT EDIT-- this file is automatically generated. + * created from; OpenBSD: syscalls.master,v 1.37 1999/06/07 07:17:42 deraadt Exp + */ + +#ifndef _SYS_SYSCALLARGS_H_ +#define _SYS_SYSCALLARGS_H_ + +#define syscallarg(x) union { x datum; register_t pad; } + +#ifdef __ECOS +#define SYSCALLARG(a,t) a.t.datum +#endif + +#ifndef __ECOS +struct sys_exit_args { + syscallarg(int) rval; +}; +#endif + +struct sys_read_args { + syscallarg(int) fd; + syscallarg(void *) buf; + syscallarg(size_t) nbyte; +}; +extern int sys_read(struct sys_read_args *, register_t *); + +struct sys_write_args { + syscallarg(int) fd; + syscallarg(const void *) buf; + syscallarg(size_t) nbyte; +}; +extern int sys_write(struct sys_write_args *, register_t *); + +struct sys_open_args { + syscallarg(const char *) path; + syscallarg(int) flags; + syscallarg(int) mode; +}; + +struct sys_close_args { + syscallarg(int) fd; +}; + +#ifndef __ECOS +struct sys_wait4_args { + syscallarg(int) pid; + syscallarg(int *) status; + syscallarg(int) options; + syscallarg(struct rusage *) rusage; +}; + +struct compat_43_sys_creat_args { + syscallarg(const char *) path; + syscallarg(int) mode; +}; + +struct sys_link_args { + syscallarg(const char *) path; + syscallarg(const char *) link; +}; + +struct sys_unlink_args { + syscallarg(const char *) path; +}; + +struct sys_chdir_args { + syscallarg(const char *) path; +}; + +struct sys_fchdir_args { + syscallarg(int) fd; +}; + +struct sys_mknod_args { + syscallarg(const char *) path; + syscallarg(int) mode; + syscallarg(dev_t) dev; +}; + +struct sys_chmod_args { + syscallarg(const char *) path; + syscallarg(int) mode; +}; + +struct sys_chown_args { + syscallarg(const char *) path; + syscallarg(uid_t) uid; + syscallarg(gid_t) gid; +}; + +struct sys_obreak_args { + syscallarg(char *) nsize; +}; + +struct sys_ogetfsstat_args { + syscallarg(struct statfs *) buf; + syscallarg(long) bufsize; + syscallarg(int) flags; +}; + +struct compat_43_sys_lseek_args { + syscallarg(int) fd; + syscallarg(long) offset; + syscallarg(int) whence; +}; + +struct sys_mount_args { + syscallarg(const char *) type; + syscallarg(const char *) path; + syscallarg(int) flags; + syscallarg(void *) data; +}; + +struct sys_unmount_args { + syscallarg(const char *) path; + syscallarg(int) flags; +}; + +struct sys_setuid_args { + syscallarg(uid_t) uid; +}; + +struct sys_ptrace_args { + syscallarg(int) req; + syscallarg(pid_t) pid; + syscallarg(caddr_t) addr; + syscallarg(int) data; +}; + +struct sys_recvmsg_args { + syscallarg(int) s; + syscallarg(struct msghdr *) msg; + syscallarg(int) flags; +}; + +struct sys_sendmsg_args { + syscallarg(int) s; + syscallarg(const struct msghdr *) msg; + syscallarg(int) flags; +}; +#endif + +struct sys_recvfrom_args { + syscallarg(int) s; + syscallarg(void *) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(struct sockaddr *) from; + syscallarg(socklen_t *) fromlenaddr; +}; +extern int sys_recvfrom(struct sys_recvfrom_args *, register_t *); + +struct sys_accept_args { + syscallarg(int) s; + syscallarg(struct sockaddr *) name; + syscallarg(socklen_t *) anamelen; +}; +extern int sys_accept(struct sys_accept_args *, register_t *); + +struct sys_getpeername_args { + syscallarg(int) fdes; + syscallarg(struct sockaddr *) asa; + syscallarg(int *) alen; +}; +extern int sys_getpeername(struct sys_getpeername_args *, register_t *); + +struct sys_getsockname_args { + syscallarg(int) fdes; + syscallarg(struct sockaddr *) asa; + syscallarg(socklen_t *) alen; +}; +extern int sys_getsockname(struct sys_getsockname_args *, register_t *); + +struct sys_access_args { + syscallarg(const char *) path; + syscallarg(int) flags; +}; + +#ifndef __ECOS +struct sys_chflags_args { + syscallarg(const char *) path; + syscallarg(u_int) flags; +}; + +struct sys_fchflags_args { + syscallarg(int) fd; + syscallarg(u_int) flags; +}; + +struct sys_kill_args { + syscallarg(int) pid; + syscallarg(int) signum; +}; + +struct compat_43_sys_stat_args { + syscallarg(const char *) path; + syscallarg(struct ostat *) ub; +}; + +struct compat_43_sys_lstat_args { + syscallarg(char *) path; + syscallarg(struct ostat *) ub; +}; + +struct sys_dup_args { + syscallarg(int) fd; +}; + +struct sys_profil_args { + syscallarg(caddr_t) samples; + syscallarg(size_t) size; + syscallarg(u_long) offset; + syscallarg(u_int) scale; +}; + +struct sys_ktrace_args { + syscallarg(const char *) fname; + syscallarg(int) ops; + syscallarg(int) facs; + syscallarg(pid_t) pid; +}; + +struct sys_sigaction_args { + syscallarg(int) signum; + syscallarg(const struct sigaction *) nsa; + syscallarg(struct sigaction *) osa; +}; + +struct sys_sigprocmask_args { + syscallarg(int) how; + syscallarg(sigset_t) mask; +}; + +struct sys_getlogin_args { + syscallarg(char *) namebuf; + syscallarg(u_int) namelen; +}; + +struct sys_setlogin_args { + syscallarg(const char *) namebuf; +}; + +struct sys_acct_args { + syscallarg(const char *) path; +}; + +struct sys_sigaltstack_args { + syscallarg(const struct sigaltstack *) nss; + syscallarg(struct sigaltstack *) oss; +}; +#endif + +struct sys_ioctl_args { + syscallarg(int) fd; + syscallarg(u_long) com; + syscallarg(void *) data; +}; +extern int sys_ioctl(struct sys_ioctl_args *, register_t *); + +#ifndef __ECOS +struct sys_reboot_args { + syscallarg(int) opt; +}; + +struct sys_revoke_args { + syscallarg(const char *) path; +}; + +struct sys_symlink_args { + syscallarg(const char *) path; + syscallarg(const char *) link; +}; + +struct sys_readlink_args { + syscallarg(const char *) path; + syscallarg(char *) buf; + syscallarg(size_t) count; +}; + +struct sys_execve_args { + syscallarg(const char *) path; + syscallarg(char *const *) argp; + syscallarg(char *const *) envp; +}; + +struct sys_umask_args { + syscallarg(int) newmask; +}; + +struct sys_chroot_args { + syscallarg(const char *) path; +}; + +struct compat_43_sys_fstat_args { + syscallarg(int) fd; + syscallarg(struct ostat *) sb; +}; + +struct compat_43_sys_getkerninfo_args { + syscallarg(int) op; + syscallarg(char *) where; + syscallarg(int *) size; + syscallarg(int) arg; +}; + +struct sys_omsync_args { + syscallarg(caddr_t) addr; + syscallarg(size_t) len; +}; + +struct sys_sbrk_args { + syscallarg(int) incr; +}; + +struct sys_sstk_args { + syscallarg(int) incr; +}; + +struct compat_43_sys_mmap_args { + syscallarg(caddr_t) addr; + syscallarg(size_t) len; + syscallarg(int) prot; + syscallarg(int) flags; + syscallarg(int) fd; + syscallarg(long) pos; +}; + +struct sys_ovadvise_args { + syscallarg(int) anom; +}; + +struct sys_munmap_args { + syscallarg(void *) addr; + syscallarg(size_t) len; +}; + +struct sys_mprotect_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) prot; +}; + +struct sys_madvise_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) behav; +}; + +struct sys_mincore_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(char *) vec; +}; + +struct sys_getgroups_args { + syscallarg(int) gidsetsize; + syscallarg(gid_t *) gidset; +}; + +struct sys_setgroups_args { + syscallarg(int) gidsetsize; + syscallarg(const gid_t *) gidset; +}; + +struct sys_setpgid_args { + syscallarg(pid_t) pid; + syscallarg(int) pgid; +}; + +struct sys_setitimer_args { + syscallarg(int) which; + syscallarg(const struct itimerval *) itv; + syscallarg(struct itimerval *) oitv; +}; + +struct sys_swapon_args { + syscallarg(const char *) name; +}; + +struct sys_getitimer_args { + syscallarg(int) which; + syscallarg(struct itimerval *) itv; +}; + +struct compat_43_sys_gethostname_args { + syscallarg(char *) hostname; + syscallarg(u_int) len; +}; + +struct compat_43_sys_sethostname_args { + syscallarg(char *) hostname; + syscallarg(u_int) len; +}; + +struct sys_dup2_args { + syscallarg(int) from; + syscallarg(int) to; +}; + +struct sys_fcntl_args { + syscallarg(int) fd; + syscallarg(int) cmd; + syscallarg(void *) arg; +}; +#endif + +struct sys_select_args { + syscallarg(int) nd; + syscallarg(fd_set *) in; + syscallarg(fd_set *) ou; + syscallarg(fd_set *) ex; + syscallarg(struct timeval *) tv; +}; +extern int sys_select(struct sys_select_args *, register_t *); + +#ifndef __ECOS +struct sys_fsync_args { + syscallarg(int) fd; +}; + +struct sys_setpriority_args { + syscallarg(int) which; + syscallarg(int) who; + syscallarg(int) prio; +}; +#endif + +struct sys_socket_args { + syscallarg(int) domain; + syscallarg(int) type; + syscallarg(int) protocol; +}; +extern int sys_socket(struct sys_socket_args *, register_t *); + +struct sys_connect_args { + syscallarg(int) s; + syscallarg(const struct sockaddr *) name; + syscallarg(socklen_t) namelen; +}; +extern int sys_connect(struct sys_connect_args *, register_t *); + +#ifndef __ECOS +struct compat_43_sys_accept_args { + syscallarg(int) s; + syscallarg(caddr_t) name; + syscallarg(int *) anamelen; +}; + +struct sys_getpriority_args { + syscallarg(int) which; + syscallarg(int) who; +}; + +struct compat_43_sys_send_args { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(int) len; + syscallarg(int) flags; +}; + +struct compat_43_sys_recv_args { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(int) len; + syscallarg(int) flags; +}; + +struct sys_sigreturn_args { + syscallarg(struct sigcontext *) sigcntxp; +}; +#endif + +struct sys_bind_args { + syscallarg(int) s; + syscallarg(const struct sockaddr *) name; + syscallarg(socklen_t) namelen; +}; +extern int sys_bind(struct sys_bind_args *, register_t *); + +struct sys_setsockopt_args { + syscallarg(int) s; + syscallarg(int) level; + syscallarg(int) name; + syscallarg(const void *) val; + syscallarg(socklen_t) valsize; +}; +extern int sys_setsockopt(struct sys_setsockopt_args *, register_t *); + +struct sys_listen_args { + syscallarg(int) s; + syscallarg(int) backlog; +}; +extern int sys_listen(struct sys_listen_args *, register_t *); + +#ifndef __ECOS +struct compat_43_sys_sigvec_args { + syscallarg(int) signum; + syscallarg(struct sigvec *) nsv; + syscallarg(struct sigvec *) osv; +}; + +struct compat_43_sys_sigblock_args { + syscallarg(int) mask; +}; + +struct compat_43_sys_sigsetmask_args { + syscallarg(int) mask; +}; + +struct sys_sigsuspend_args { + syscallarg(int) mask; +}; + +struct compat_43_sys_sigstack_args { + syscallarg(struct sigstack *) nss; + syscallarg(struct sigstack *) oss; +}; + +struct compat_43_sys_recvmsg_args { + syscallarg(int) s; + syscallarg(struct omsghdr *) msg; + syscallarg(int) flags; +}; + +struct compat_43_sys_sendmsg_args { + syscallarg(int) s; + syscallarg(caddr_t) msg; + syscallarg(int) flags; +}; + +struct sys_vtrace_args { + syscallarg(int) request; + syscallarg(int) value; +}; + +struct sys_gettimeofday_args { + syscallarg(struct timeval *) tp; + syscallarg(struct timezone *) tzp; +}; + +struct sys_getrusage_args { + syscallarg(int) who; + syscallarg(struct rusage *) rusage; +}; +#endif + +struct sys_getsockopt_args { + syscallarg(int) s; + syscallarg(int) level; + syscallarg(int) name; + syscallarg(void *) val; + syscallarg(socklen_t *) avalsize; +}; +extern int sys_getsockopt(struct sys_getsockopt_args *, register_t *); + +struct sys_readv_args { + syscallarg(int) fd; + syscallarg(const struct iovec *) iovp; + syscallarg(int) iovcnt; +}; + +struct sys_writev_args { + syscallarg(int) fd; + syscallarg(const struct iovec *) iovp; + syscallarg(int) iovcnt; +}; + +#ifndef __ECOS +struct sys_settimeofday_args { + syscallarg(const struct timeval *) tv; + syscallarg(const struct timezone *) tzp; +}; + +struct sys_fchown_args { + syscallarg(int) fd; + syscallarg(uid_t) uid; + syscallarg(gid_t) gid; +}; + +struct sys_fchmod_args { + syscallarg(int) fd; + syscallarg(int) mode; +}; + +struct compat_43_sys_recvfrom_args { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(caddr_t) from; + syscallarg(int *) fromlenaddr; +}; + +struct compat_43_sys_setreuid_args { + syscallarg(int) ruid; + syscallarg(int) euid; +}; + +struct compat_43_sys_setregid_args { + syscallarg(int) rgid; + syscallarg(int) egid; +}; + +struct sys_rename_args { + syscallarg(const char *) from; + syscallarg(const char *) to; +}; + +struct compat_43_sys_truncate_args { + syscallarg(const char *) path; + syscallarg(long) length; +}; + +struct compat_43_sys_ftruncate_args { + syscallarg(int) fd; + syscallarg(long) length; +}; + +struct sys_flock_args { + syscallarg(int) fd; + syscallarg(int) how; +}; + +struct sys_mkfifo_args { + syscallarg(const char *) path; + syscallarg(int) mode; +}; +#endif + +struct sys_sendto_args { + syscallarg(int) s; + syscallarg(const void *) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(const struct sockaddr *) to; + syscallarg(socklen_t) tolen; +}; +extern int sys_sendto(struct sys_sendto_args *, register_t *); + +struct sys_shutdown_args { + syscallarg(int) s; + syscallarg(int) how; +}; +extern int sys_shutdown(struct sys_shutdown_args *, register_t *); + +struct sys_socketpair_args { + syscallarg(int) domain; + syscallarg(int) type; + syscallarg(int) protocol; + syscallarg(int *) rsv; +}; + +#ifndef __ECOS +struct sys_mkdir_args { + syscallarg(const char *) path; + syscallarg(int) mode; +}; + +struct sys_rmdir_args { + syscallarg(const char *) path; +}; + +struct sys_utimes_args { + syscallarg(const char *) path; + syscallarg(const struct timeval *) tptr; +}; + +struct sys_adjtime_args { + syscallarg(const struct timeval *) delta; + syscallarg(struct timeval *) olddelta; +}; + +struct compat_43_sys_getpeername_args { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(socklen_t *) alen; +}; + +struct compat_43_sys_sethostid_args { + syscallarg(int32_t) hostid; +}; + +struct compat_43_sys_getrlimit_args { + syscallarg(int) which; + syscallarg(struct ogetrlimit *) rlp; +}; + +struct compat_43_sys_setrlimit_args { + syscallarg(int) which; + syscallarg(struct ogetrlimit *) rlp; +}; + +struct compat_43_sys_killpg_args { + syscallarg(int) pgid; + syscallarg(int) signum; +}; + +struct sys_quotactl_args { + syscallarg(const char *) path; + syscallarg(int) cmd; + syscallarg(int) uid; + syscallarg(char *) arg; +}; + +struct compat_43_sys_getsockname_args { + syscallarg(int) fdec; + syscallarg(caddr_t) asa; + syscallarg(int *) alen; +}; + +struct sys_nfssvc_args { + syscallarg(int) flag; + syscallarg(void *) argp; +}; + +struct compat_43_sys_getdirentries_args { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(int) count; + syscallarg(long *) basep; +}; + +struct sys_ostatfs_args { + syscallarg(const char *) path; + syscallarg(struct ostatfs *) buf; +}; + +struct sys_ofstatfs_args { + syscallarg(int) fd; + syscallarg(struct ostatfs *) buf; +}; + +struct sys_getfh_args { + syscallarg(const char *) fname; + syscallarg(fhandle_t *) fhp; +}; + +struct compat_09_sys_getdomainname_args { + syscallarg(char *) domainname; + syscallarg(int) len; +}; + +struct compat_09_sys_setdomainname_args { + syscallarg(char *) domainname; + syscallarg(int) len; +}; + +struct compat_09_sys_uname_args { + syscallarg(struct outsname *) name; +}; + +struct sys_sysarch_args { + syscallarg(int) op; + syscallarg(char *) parms; +}; + +struct compat_10_sys_semsys_args { + syscallarg(int) which; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(int) a4; + syscallarg(int) a5; +}; + +struct compat_10_sys_msgsys_args { + syscallarg(int) which; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(int) a4; + syscallarg(int) a5; + syscallarg(int) a6; +}; + +struct compat_10_sys_shmsys_args { + syscallarg(int) which; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(int) a4; +}; + +struct sys_ntp_gettime_args { + syscallarg(struct ntptimeval *) ntvp; +}; + +struct sys_ntp_adjtime_args { + syscallarg(struct timex *) tp; +}; + +struct sys_setgid_args { + syscallarg(gid_t) gid; +}; + +struct sys_setegid_args { + syscallarg(gid_t) egid; +}; + +struct sys_seteuid_args { + syscallarg(uid_t) euid; +}; + +struct lfs_bmapv_args { + syscallarg(fsid_t *) fsidp; + syscallarg(struct block_info *) blkiov; + syscallarg(int) blkcnt; +}; + +struct lfs_markv_args { + syscallarg(fsid_t *) fsidp; + syscallarg(struct block_info *) blkiov; + syscallarg(int) blkcnt; +}; + +struct lfs_segclean_args { + syscallarg(fsid_t *) fsidp; + syscallarg(u_long) segment; +}; + +struct lfs_segwait_args { + syscallarg(fsid_t *) fsidp; + syscallarg(struct timeval *) tv; +}; + +struct sys_stat_args { + syscallarg(const char *) path; + syscallarg(struct stat *) ub; +}; + +struct sys_fstat_args { + syscallarg(int) fd; + syscallarg(struct stat *) sb; +}; + +struct sys_lstat_args { + syscallarg(const char *) path; + syscallarg(struct stat *) ub; +}; + +struct sys_pathconf_args { + syscallarg(const char *) path; + syscallarg(int) name; +}; + +struct sys_fpathconf_args { + syscallarg(int) fd; + syscallarg(int) name; +}; + +struct sys_swapctl_args { + syscallarg(int) cmd; + syscallarg(const void *) arg; + syscallarg(int) misc; +}; + +struct sys_getrlimit_args { + syscallarg(int) which; + syscallarg(struct rlimit *) rlp; +}; + +struct sys_setrlimit_args { + syscallarg(int) which; + syscallarg(const struct rlimit *) rlp; +}; + +struct sys_getdirentries_args { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(int) count; + syscallarg(long *) basep; +}; + +struct sys_mmap_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) prot; + syscallarg(int) flags; + syscallarg(int) fd; + syscallarg(long) pad; + syscallarg(off_t) pos; +}; + +struct sys_lseek_args { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) offset; + syscallarg(int) whence; +}; + +struct sys_truncate_args { + syscallarg(const char *) path; + syscallarg(int) pad; + syscallarg(off_t) length; +}; + +struct sys_ftruncate_args { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) length; +}; + +struct sys___sysctl_args { + syscallarg(int *) name; + syscallarg(u_int) namelen; + syscallarg(void *) old; + syscallarg(size_t *) oldlenp; + syscallarg(void *) new; + syscallarg(size_t) newlen; +}; + +struct sys_mlock_args { + syscallarg(const void *) addr; + syscallarg(size_t) len; +}; + +struct sys_munlock_args { + syscallarg(const void *) addr; + syscallarg(size_t) len; +}; + +struct sys_undelete_args { + syscallarg(const char *) path; +}; + +struct sys_futimes_args { + syscallarg(int) fd; + syscallarg(const struct timeval *) tptr; +}; + +struct sys_getpgid_args { + syscallarg(pid_t) pid; +}; + +struct sys_xfspioctl_args { + syscallarg(int) operation; + syscallarg(char *) a_pathP; + syscallarg(int) a_opcode; + syscallarg(struct ViceIoctl *) a_paramsP; + syscallarg(int) a_followSymlinks; +}; + +struct sys___osemctl_args { + syscallarg(int) semid; + syscallarg(int) semnum; + syscallarg(int) cmd; + syscallarg(union semun *) arg; +}; + +struct sys_semget_args { + syscallarg(key_t) key; + syscallarg(int) nsems; + syscallarg(int) semflg; +}; + +struct sys_semop_args { + syscallarg(int) semid; + syscallarg(struct sembuf *) sops; + syscallarg(u_int) nsops; +}; + +struct sys_semconfig_args { + syscallarg(int) flag; +}; + +struct sys_omsgctl_args { + syscallarg(int) msqid; + syscallarg(int) cmd; + syscallarg(struct omsqid_ds *) buf; +}; + +struct sys_msgget_args { + syscallarg(key_t) key; + syscallarg(int) msgflg; +}; + +struct sys_msgsnd_args { + syscallarg(int) msqid; + syscallarg(const void *) msgp; + syscallarg(size_t) msgsz; + syscallarg(int) msgflg; +}; + +struct sys_msgrcv_args { + syscallarg(int) msqid; + syscallarg(void *) msgp; + syscallarg(size_t) msgsz; + syscallarg(long) msgtyp; + syscallarg(int) msgflg; +}; + +struct sys_shmat_args { + syscallarg(int) shmid; + syscallarg(const void *) shmaddr; + syscallarg(int) shmflg; +}; + +struct sys_oshmctl_args { + syscallarg(int) shmid; + syscallarg(int) cmd; + syscallarg(struct oshmid_ds *) buf; +}; + +struct sys_shmdt_args { + syscallarg(const void *) shmaddr; +}; + +struct sys_shmget_args { + syscallarg(key_t) key; + syscallarg(int) size; + syscallarg(int) shmflg; +}; + +struct sys_clock_gettime_args { + syscallarg(clockid_t) clock_id; + syscallarg(struct timespec *) tp; +}; + +struct sys_clock_settime_args { + syscallarg(clockid_t) clock_id; + syscallarg(const struct timespec *) tp; +}; + +struct sys_clock_getres_args { + syscallarg(clockid_t) clock_id; + syscallarg(struct timespec *) tp; +}; + +struct sys_nanosleep_args { + syscallarg(const struct timespec *) rqtp; + syscallarg(struct timespec *) rmtp; +}; + +struct sys_minherit_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) inherit; +}; + +struct sys_rfork_args { + syscallarg(int) flags; +}; + +struct sys_poll_args { + syscallarg(struct pollfd *) fds; + syscallarg(unsigned long) nfds; + syscallarg(int) timeout; +}; + +struct sys_lchown_args { + syscallarg(const char *) path; + syscallarg(uid_t) uid; + syscallarg(gid_t) gid; +}; + +struct sys_getsid_args { + syscallarg(pid_t) pid; +}; + +struct sys_msync_args { + syscallarg(void *) addr; + syscallarg(size_t) len; + syscallarg(int) flags; +}; + +struct sys___semctl_args { + syscallarg(int) semid; + syscallarg(int) semnum; + syscallarg(int) cmd; + syscallarg(union semun *) arg; +}; + +struct sys_shmctl_args { + syscallarg(int) shmid; + syscallarg(int) cmd; + syscallarg(struct shmid_ds *) buf; +}; + +struct sys_msgctl_args { + syscallarg(int) msqid; + syscallarg(int) cmd; + syscallarg(struct msqid_ds *) buf; +}; + +struct sys_getfsstat_args { + syscallarg(struct statfs *) buf; + syscallarg(size_t) bufsize; + syscallarg(int) flags; +}; + +struct sys_statfs_args { + syscallarg(const char *) path; + syscallarg(struct statfs *) buf; +}; + +struct sys_fstatfs_args { + syscallarg(int) fd; + syscallarg(struct statfs *) buf; +}; + +struct sys_pipe_args { + syscallarg(int *) fdp; +}; + +/* + * System call prototypes. + */ + +int sys_exit __P((struct proc *, void *, register_t *)); +int sys_fork __P((struct proc *, void *, register_t *)); +int sys_read __P((struct proc *, void *, register_t *)); +int sys_write __P((struct proc *, void *, register_t *)); +int sys_open __P((struct proc *, void *, register_t *)); +int sys_close __P((struct proc *, void *, register_t *)); +int sys_wait4 __P((struct proc *, void *, register_t *)); +int compat_43_sys_creat __P((struct proc *, void *, register_t *)); +int sys_link __P((struct proc *, void *, register_t *)); +int sys_unlink __P((struct proc *, void *, register_t *)); +int sys_chdir __P((struct proc *, void *, register_t *)); +int sys_fchdir __P((struct proc *, void *, register_t *)); +int sys_mknod __P((struct proc *, void *, register_t *)); +int sys_chmod __P((struct proc *, void *, register_t *)); +int sys_chown __P((struct proc *, void *, register_t *)); +int sys_obreak __P((struct proc *, void *, register_t *)); +int sys_ogetfsstat __P((struct proc *, void *, register_t *)); +int compat_43_sys_lseek __P((struct proc *, void *, register_t *)); +int sys_getpid __P((struct proc *, void *, register_t *)); +int sys_mount __P((struct proc *, void *, register_t *)); +int sys_unmount __P((struct proc *, void *, register_t *)); +int sys_setuid __P((struct proc *, void *, register_t *)); +int sys_getuid __P((struct proc *, void *, register_t *)); +int sys_geteuid __P((struct proc *, void *, register_t *)); +int sys_ptrace __P((struct proc *, void *, register_t *)); +int sys_recvmsg __P((struct proc *, void *, register_t *)); +int sys_sendmsg __P((struct proc *, void *, register_t *)); +int sys_recvfrom __P((struct proc *, void *, register_t *)); +int sys_accept __P((struct proc *, void *, register_t *)); +int sys_getpeername __P((struct proc *, void *, register_t *)); +int sys_getsockname __P((struct proc *, void *, register_t *)); +int sys_access __P((struct proc *, void *, register_t *)); +int sys_chflags __P((struct proc *, void *, register_t *)); +int sys_fchflags __P((struct proc *, void *, register_t *)); +int sys_sync __P((struct proc *, void *, register_t *)); +int sys_kill __P((struct proc *, void *, register_t *)); +int compat_43_sys_stat __P((struct proc *, void *, register_t *)); +int sys_getppid __P((struct proc *, void *, register_t *)); +int compat_43_sys_lstat __P((struct proc *, void *, register_t *)); +int sys_dup __P((struct proc *, void *, register_t *)); +int sys_opipe __P((struct proc *, void *, register_t *)); +int sys_getegid __P((struct proc *, void *, register_t *)); +int sys_profil __P((struct proc *, void *, register_t *)); +#ifdef KTRACE +int sys_ktrace __P((struct proc *, void *, register_t *)); +#else +#endif +int sys_sigaction __P((struct proc *, void *, register_t *)); +int sys_getgid __P((struct proc *, void *, register_t *)); +int sys_sigprocmask __P((struct proc *, void *, register_t *)); +int sys_getlogin __P((struct proc *, void *, register_t *)); +int sys_setlogin __P((struct proc *, void *, register_t *)); +int sys_acct __P((struct proc *, void *, register_t *)); +int sys_sigpending __P((struct proc *, void *, register_t *)); +int sys_sigaltstack __P((struct proc *, void *, register_t *)); +int sys_ioctl __P((struct proc *, void *, register_t *)); +int sys_reboot __P((struct proc *, void *, register_t *)); +int sys_revoke __P((struct proc *, void *, register_t *)); +int sys_symlink __P((struct proc *, void *, register_t *)); +int sys_readlink __P((struct proc *, void *, register_t *)); +int sys_execve __P((struct proc *, void *, register_t *)); +int sys_umask __P((struct proc *, void *, register_t *)); +int sys_chroot __P((struct proc *, void *, register_t *)); +int compat_43_sys_fstat __P((struct proc *, void *, register_t *)); +int compat_43_sys_getkerninfo __P((struct proc *, void *, register_t *)); +int compat_43_sys_getpagesize __P((struct proc *, void *, register_t *)); +int sys_omsync __P((struct proc *, void *, register_t *)); +int sys_vfork __P((struct proc *, void *, register_t *)); +int sys_sbrk __P((struct proc *, void *, register_t *)); +int sys_sstk __P((struct proc *, void *, register_t *)); +int compat_43_sys_mmap __P((struct proc *, void *, register_t *)); +int sys_ovadvise __P((struct proc *, void *, register_t *)); +int sys_munmap __P((struct proc *, void *, register_t *)); +int sys_mprotect __P((struct proc *, void *, register_t *)); +int sys_madvise __P((struct proc *, void *, register_t *)); +int sys_mincore __P((struct proc *, void *, register_t *)); +int sys_getgroups __P((struct proc *, void *, register_t *)); +int sys_setgroups __P((struct proc *, void *, register_t *)); +int sys_getpgrp __P((struct proc *, void *, register_t *)); +int sys_setpgid __P((struct proc *, void *, register_t *)); +int sys_setitimer __P((struct proc *, void *, register_t *)); +int compat_43_sys_wait __P((struct proc *, void *, register_t *)); +int sys_swapon __P((struct proc *, void *, register_t *)); +int sys_getitimer __P((struct proc *, void *, register_t *)); +int compat_43_sys_gethostname __P((struct proc *, void *, register_t *)); +int compat_43_sys_sethostname __P((struct proc *, void *, register_t *)); +int compat_43_sys_getdtablesize __P((struct proc *, void *, register_t *)); +int sys_dup2 __P((struct proc *, void *, register_t *)); +int sys_fcntl __P((struct proc *, void *, register_t *)); +int sys_select __P((struct proc *, void *, register_t *)); +int sys_fsync __P((struct proc *, void *, register_t *)); +int sys_setpriority __P((struct proc *, void *, register_t *)); +int sys_socket __P((struct proc *, void *, register_t *)); +int sys_connect __P((struct proc *, void *, register_t *)); +int compat_43_sys_accept __P((struct proc *, void *, register_t *)); +int sys_getpriority __P((struct proc *, void *, register_t *)); +int compat_43_sys_send __P((struct proc *, void *, register_t *)); +int compat_43_sys_recv __P((struct proc *, void *, register_t *)); +int sys_sigreturn __P((struct proc *, void *, register_t *)); +int sys_bind __P((struct proc *, void *, register_t *)); +int sys_setsockopt __P((struct proc *, void *, register_t *)); +int sys_listen __P((struct proc *, void *, register_t *)); +int compat_43_sys_sigvec __P((struct proc *, void *, register_t *)); +int compat_43_sys_sigblock __P((struct proc *, void *, register_t *)); +int compat_43_sys_sigsetmask __P((struct proc *, void *, register_t *)); +int sys_sigsuspend __P((struct proc *, void *, register_t *)); +int compat_43_sys_sigstack __P((struct proc *, void *, register_t *)); +int compat_43_sys_recvmsg __P((struct proc *, void *, register_t *)); +int compat_43_sys_sendmsg __P((struct proc *, void *, register_t *)); +#ifdef TRACE +int sys_vtrace __P((struct proc *, void *, register_t *)); +#else +#endif +int sys_gettimeofday __P((struct proc *, void *, register_t *)); +int sys_getrusage __P((struct proc *, void *, register_t *)); +int sys_getsockopt __P((struct proc *, void *, register_t *)); +int sys_readv __P((struct proc *, void *, register_t *)); +int sys_writev __P((struct proc *, void *, register_t *)); +int sys_settimeofday __P((struct proc *, void *, register_t *)); +int sys_fchown __P((struct proc *, void *, register_t *)); +int sys_fchmod __P((struct proc *, void *, register_t *)); +int compat_43_sys_recvfrom __P((struct proc *, void *, register_t *)); +int compat_43_sys_setreuid __P((struct proc *, void *, register_t *)); +int compat_43_sys_setregid __P((struct proc *, void *, register_t *)); +int sys_rename __P((struct proc *, void *, register_t *)); +int compat_43_sys_truncate __P((struct proc *, void *, register_t *)); +int compat_43_sys_ftruncate __P((struct proc *, void *, register_t *)); +int sys_flock __P((struct proc *, void *, register_t *)); +int sys_mkfifo __P((struct proc *, void *, register_t *)); +int sys_sendto __P((struct proc *, void *, register_t *)); +int sys_shutdown __P((struct proc *, void *, register_t *)); +int sys_socketpair __P((struct proc *, void *, register_t *)); +int sys_mkdir __P((struct proc *, void *, register_t *)); +int sys_rmdir __P((struct proc *, void *, register_t *)); +int sys_utimes __P((struct proc *, void *, register_t *)); +int sys_adjtime __P((struct proc *, void *, register_t *)); +int compat_43_sys_getpeername __P((struct proc *, void *, register_t *)); +int compat_43_sys_gethostid __P((struct proc *, void *, register_t *)); +int compat_43_sys_sethostid __P((struct proc *, void *, register_t *)); +int compat_43_sys_getrlimit __P((struct proc *, void *, register_t *)); +int compat_43_sys_setrlimit __P((struct proc *, void *, register_t *)); +int compat_43_sys_killpg __P((struct proc *, void *, register_t *)); +int sys_setsid __P((struct proc *, void *, register_t *)); +int sys_quotactl __P((struct proc *, void *, register_t *)); +int compat_43_sys_quota __P((struct proc *, void *, register_t *)); +int compat_43_sys_getsockname __P((struct proc *, void *, register_t *)); +#if defined(NFSCLIENT) || defined(NFSSERVER) +int sys_nfssvc __P((struct proc *, void *, register_t *)); +#else +#endif +int compat_43_sys_getdirentries __P((struct proc *, void *, register_t *)); +int sys_ostatfs __P((struct proc *, void *, register_t *)); +int sys_ofstatfs __P((struct proc *, void *, register_t *)); +#if defined(NFSCLIENT) || defined(NFSSERVER) +int sys_getfh __P((struct proc *, void *, register_t *)); +#else +#endif +int compat_09_sys_getdomainname __P((struct proc *, void *, register_t *)); +int compat_09_sys_setdomainname __P((struct proc *, void *, register_t *)); +int compat_09_sys_uname __P((struct proc *, void *, register_t *)); +int sys_sysarch __P((struct proc *, void *, register_t *)); +#if defined(SYSVSEM) && !defined(alpha) +int compat_10_sys_semsys __P((struct proc *, void *, register_t *)); +#else +#endif +#if defined(SYSVMSG) && !defined(alpha) +int compat_10_sys_msgsys __P((struct proc *, void *, register_t *)); +#else +#endif +#if defined(SYSVSHM) && !defined(alpha) +int compat_10_sys_shmsys __P((struct proc *, void *, register_t *)); +#else +#endif +#ifdef NTP +int sys_ntp_gettime __P((struct proc *, void *, register_t *)); +int sys_ntp_adjtime __P((struct proc *, void *, register_t *)); +#else +#endif +int sys_setgid __P((struct proc *, void *, register_t *)); +int sys_setegid __P((struct proc *, void *, register_t *)); +int sys_seteuid __P((struct proc *, void *, register_t *)); +#ifdef LFS +int lfs_bmapv __P((struct proc *, void *, register_t *)); +int lfs_markv __P((struct proc *, void *, register_t *)); +int lfs_segclean __P((struct proc *, void *, register_t *)); +int lfs_segwait __P((struct proc *, void *, register_t *)); +#else +#endif +int sys_stat __P((struct proc *, void *, register_t *)); +int sys_fstat __P((struct proc *, void *, register_t *)); +int sys_lstat __P((struct proc *, void *, register_t *)); +int sys_pathconf __P((struct proc *, void *, register_t *)); +int sys_fpathconf __P((struct proc *, void *, register_t *)); +int sys_swapctl __P((struct proc *, void *, register_t *)); +int sys_getrlimit __P((struct proc *, void *, register_t *)); +int sys_setrlimit __P((struct proc *, void *, register_t *)); +int sys_getdirentries __P((struct proc *, void *, register_t *)); +int sys_mmap __P((struct proc *, void *, register_t *)); +int sys_lseek __P((struct proc *, void *, register_t *)); +int sys_truncate __P((struct proc *, void *, register_t *)); +int sys_ftruncate __P((struct proc *, void *, register_t *)); +int sys___sysctl __P((struct proc *, void *, register_t *)); +int sys_mlock __P((struct proc *, void *, register_t *)); +int sys_munlock __P((struct proc *, void *, register_t *)); +int sys_undelete __P((struct proc *, void *, register_t *)); +int sys_futimes __P((struct proc *, void *, register_t *)); +int sys_getpgid __P((struct proc *, void *, register_t *)); +int sys_xfspioctl __P((struct proc *, void *, register_t *)); +#ifdef LKM +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +int sys_lkmnosys __P((struct proc *, void *, register_t *)); +#else /* !LKM */ +#endif /* !LKM */ +#ifdef SYSVSEM +int sys___osemctl __P((struct proc *, void *, register_t *)); +int sys_semget __P((struct proc *, void *, register_t *)); +int sys_semop __P((struct proc *, void *, register_t *)); +int sys_semconfig __P((struct proc *, void *, register_t *)); +#else +#endif +#ifdef SYSVMSG +int sys_omsgctl __P((struct proc *, void *, register_t *)); +int sys_msgget __P((struct proc *, void *, register_t *)); +int sys_msgsnd __P((struct proc *, void *, register_t *)); +int sys_msgrcv __P((struct proc *, void *, register_t *)); +#else +#endif +#ifdef SYSVSHM +int sys_shmat __P((struct proc *, void *, register_t *)); +int sys_oshmctl __P((struct proc *, void *, register_t *)); +int sys_shmdt __P((struct proc *, void *, register_t *)); +int sys_shmget __P((struct proc *, void *, register_t *)); +#else +#endif +int sys_clock_gettime __P((struct proc *, void *, register_t *)); +int sys_clock_settime __P((struct proc *, void *, register_t *)); +int sys_clock_getres __P((struct proc *, void *, register_t *)); +int sys_nanosleep __P((struct proc *, void *, register_t *)); +int sys_minherit __P((struct proc *, void *, register_t *)); +int sys_rfork __P((struct proc *, void *, register_t *)); +int sys_poll __P((struct proc *, void *, register_t *)); +int sys_issetugid __P((struct proc *, void *, register_t *)); +int sys_lchown __P((struct proc *, void *, register_t *)); +int sys_getsid __P((struct proc *, void *, register_t *)); +int sys_msync __P((struct proc *, void *, register_t *)); +#ifdef SYSVSEM +int sys___semctl __P((struct proc *, void *, register_t *)); +#else +#endif +#ifdef SYSVSHM +int sys_shmctl __P((struct proc *, void *, register_t *)); +#else +#endif +#ifdef SYSVMSG +int sys_msgctl __P((struct proc *, void *, register_t *)); +#else +#endif +int sys_getfsstat __P((struct proc *, void *, register_t *)); +int sys_statfs __P((struct proc *, void *, register_t *)); +int sys_fstatfs __P((struct proc *, void *, register_t *)); +int sys_pipe __P((struct proc *, void *, register_t *)); +#endif + +#endif // _SYS_SYSCALLARGS_H_ diff --git a/ecos/packages/net/tcpip/current/include/sys/time.h b/ecos/packages/net/tcpip/current/include/sys/time.h new file mode 100644 index 0000000..775817a --- /dev/null +++ b/ecos/packages/net/tcpip/current/include/sys/time.h @@ -0,0 +1,239 @@ +//========================================================================== +// +// include/sys/time.h +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: time.h,v 1.9 1999/12/06 19:36:42 aaron Exp $ */ +/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 8.2 (Berkeley) 7/10/94 + */ + +#ifndef _SYS_TIME_H_ +#define _SYS_TIME_H_ + +#include <sys/types.h> +#include <time.h> + +#if 0 //ndef __time_t_defined +typedef int time_t; +# define __time_t_defined +#endif + +#if 0 + +/* + * Structure returned by gettimeofday(2) system call, + * and used in other calls. + */ +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; + +#endif + +#if 0 +/* + * Structure defined by POSIX.1b to be like a timeval. + */ +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* and nanoseconds */ +}; +#endif + +#define TIMEVAL_TO_TIMESPEC(tv, ts) { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ +} +#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ +} + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; +#define DST_NONE 0 /* not on dst */ +#define DST_USA 1 /* USA style dst */ +#define DST_AUST 2 /* Australian style dst */ +#define DST_WET 3 /* Western European dst */ +#define DST_MET 4 /* Middle European dst */ +#define DST_EET 5 /* Eastern European dst */ +#define DST_CAN 6 /* Canada */ + +/* Operations on timevals. */ +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) +#define timeradd(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ + if ((vvp)->tv_usec >= 1000000) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_usec -= 1000000; \ + } \ + } while (0) +#define timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) + +/* Operations on timespecs. */ +#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 +#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec) +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#define timespecadd(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ + if ((vsp)->tv_nsec >= 1000000000L) { \ + (vsp)->tv_sec++; \ + (vsp)->tv_nsec -= 1000000000L; \ + } \ + } while (0) +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (0) + +/* + * Names of the interval timers, and structure + * defining a timer setting. + */ +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 +#define ITIMER_PROF 2 + +struct itimerval { + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; + +/* + * Getkerninfo clock information structure + */ +struct clockinfo { + int hz; /* clock frequency */ + int tick; /* micro-seconds per hz tick */ + int tickadj; /* clock skew rate for adjtime() */ + int stathz; /* statistics clock frequency */ + int profhz; /* profiling clock frequency */ +}; + +#define CLOCK_REALTIME 0 +#define CLOCK_VIRTUAL 1 +#define CLOCK_PROF 2 + +#define TIMER_RELTIME 0x0 /* relative timer */ +#ifndef TIMER_ABSTIME +#define TIMER_ABSTIME 0x1 /* absolute timer */ +#endif + +#if defined(_KERNEL) || defined(_STANDALONE) +int itimerfix __P((struct timeval *tv)); +int itimerdecr __P((struct itimerval *itp, int usec)); +void microtime __P((struct timeval *tv)); +void settime __P((struct timeval *tv)); +#else /* !_KERNEL */ + +#ifndef __ECOS +#include <time.h> +#endif + +#if 0 //ndef _POSIX_SOURCE +#include <sys/cdefs.h> + +__BEGIN_DECLS +int adjtime __P((const struct timeval *, struct timeval *)); +int clock_getres __P((clockid_t, struct timespec *)); +int clock_gettime __P((clockid_t, struct timespec *)); +int clock_settime __P((clockid_t, const struct timespec *)); +int futimes __P((int, const struct timeval *)); +int getitimer __P((int, struct itimerval *)); +int gettimeofday __P((struct timeval *, struct timezone *)); +int nanosleep __P((const struct timespec *, struct timespec *)); +int setitimer __P((int, const struct itimerval *, struct itimerval *)); +int settimeofday __P((const struct timeval *, const struct timezone *)); +int utimes __P((const char *, const struct timeval *)); +__END_DECLS +#endif /* !POSIX */ + +#endif /* !_KERNEL */ + +#endif /* !_SYS_TIME_H_ */ diff --git a/ecos/packages/net/tcpip/current/src/ecos/init.cxx b/ecos/packages/net/tcpip/current/src/ecos/init.cxx new file mode 100644 index 0000000..0c2c5f0 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/ecos/init.cxx @@ -0,0 +1,59 @@ +//========================================================================== +// +// ecos/init.cxx +// +// Networking package initializer class +// +//========================================================================== +// ####ECOSPDCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. +// +// Permission is granted to use, copy, modify and redistribute this +// file. +// +// ------------------------------------------- +// ####ECOSPDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +// Network initialization + +#include <pkgconf/system.h> +#include <pkgconf/hal.h> +#include <cyg/infra/cyg_type.h> + +#define NET_INIT CYGBLD_ATTRIB_INIT_AFTER(CYG_INIT_LIBC) + +// This is a dummy class just so we can execute the network package +// initialization at it's proper priority + +externC void cyg_net_init(void); + +class net_init_class { +public: + net_init_class(void) { + cyg_net_init(); + } +}; + +// And here's an instance of the class just to make the code run +static net_init_class _net_init NET_INIT; + +externC void +cyg_do_net_init(void) +{ +} diff --git a/ecos/packages/net/tcpip/current/src/ecos/support.c b/ecos/packages/net/tcpip/current/src/ecos/support.c new file mode 100644 index 0000000..4bce185 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/ecos/support.c @@ -0,0 +1,728 @@ +//========================================================================== +// +// ecos/support.c +// +// eCos wrapper and support functions +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas, hmt +// Contributors: gthomas, hmt +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +// Support routines, etc., used by network code + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/kernel.h> +#include <sys/domain.h> +#include <sys/protosw.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <net/if.h> +#include <net/route.h> +#include <net/netisr.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <arpa/inet.h> + +#include <machine/cpu.h> + +#include <pkgconf/net.h> + +#include <cyg/infra/diag.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/kernel/kapi.h> + +#include <cyg/infra/cyg_ass.h> + +#if !CYGPKG_NET_DRIVER_FRAMEWORK // Interface +#error At least one network driver framework must be defined! +#else +#include <cyg/io/eth/netdev.h> + +// Define table boundaries +CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev ); +CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev ); + +// Used for system-wide "ticks per second" +int hz = 100; +int tick = 10000; // usec per "tick" + +volatile struct timeval mono_time; +volatile struct timeval ktime; + +// Low-level network debugging +int net_debug = 0; + +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +static char netint_stack[STACK_SIZE]; +static cyg_thread netint_thread_data; +static cyg_handle_t netint_thread_handle; + +cyg_flag_t netint_flags; +#define NETISR_ANY 0xFFFFFFFF // Any possible bit... + +extern void cyg_test_exit(void); // TEMP +void +cyg_panic(const char *msg, ...) +{ + cyg_uint32 old_ints; + CYG_FAIL( msg ); + HAL_DISABLE_INTERRUPTS(old_ints); + diag_printf("PANIC: %s\n", msg); + cyg_test_exit(); // FIXME +} + + +// Round a number 'n' up to a multiple of 'm' +#define round(n,m) ((((n)+((m)-1))/(m))*(m)) + +#define NET_MEMPOOL_SIZE round(CYGPKG_NET_MEM_USAGE/4,MSIZE) +#define NET_MBUFS_SIZE round(CYGPKG_NET_MEM_USAGE/4,MSIZE) +#define NET_CLUSTERS_SIZE round(CYGPKG_NET_MEM_USAGE/2,MCLBYTES) + +static unsigned char net_mempool_area[NET_MEMPOOL_SIZE]; +static cyg_mempool_var net_mem_pool; +static cyg_handle_t net_mem; +static unsigned char net_mbufs_area[NET_MBUFS_SIZE]; +static cyg_mempool_fix net_mbufs_pool; +static cyg_handle_t net_mbufs; +static unsigned char net_clusters_area[NET_CLUSTERS_SIZE]; +static cyg_mempool_fix net_clusters_pool; +static cyg_handle_t net_clusters; +static char net_clusters_refcnt[(NET_CLUSTERS_SIZE/MCLBYTES)+1]; + +#ifdef CYGDBG_NET_TIMING_STATS +static struct net_stats stats_malloc, stats_free, + stats_memcpy, stats_memset, + stats_mbuf_alloc, stats_mbuf_free, stats_cluster_alloc; +extern struct net_stats stats_in_cksum; + +// Display a number of ticks as microseconds +// Note: for improved calculation significance, values are kept in ticks*1000 +static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION; +static long ns_per_system_clock; + +static void +show_ticks_in_us(cyg_uint32 ticks) +{ + long long ns; + ns_per_system_clock = 1000000/rtc_resolution[1]; + ns = (ns_per_system_clock * ((long long)ticks * 1000)) / + CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; + ns += 5; // for rounding to .01us + diag_printf("%7d.%02d", (int)(ns/1000), (int)((ns%1000)/10)); +} + +void +show_net_stats(struct net_stats *stats, const char *title) +{ + int ave; + ave = stats->total_time / stats->count; + diag_printf("%s:\n", title); + diag_printf(" count: %6d", stats->count); + diag_printf(", min: "); + show_ticks_in_us(stats->min_time); + diag_printf(", max: "); + show_ticks_in_us(stats->max_time); + diag_printf(", total: "); + show_ticks_in_us(stats->total_time); + diag_printf(", ave: "); + show_ticks_in_us(ave); + diag_printf("\n"); + // Reset stats + memset(stats, 0, sizeof(*stats)); +} + +void +show_net_times(void) +{ + show_net_stats(&stats_malloc, "Net malloc"); + show_net_stats(&stats_free, "Net free"); + show_net_stats(&stats_mbuf_alloc, "Mbuf alloc"); + show_net_stats(&stats_mbuf_free, "Mbuf free"); + show_net_stats(&stats_cluster_alloc, "Cluster alloc"); + show_net_stats(&stats_in_cksum, "Checksum"); + show_net_stats(&stats_memcpy, "Net memcpy"); + show_net_stats(&stats_memset, "Net memset"); +} +#endif /* CYGDBG_NET_TIMING_STATS */ + +void * +cyg_net_malloc(u_long size, int type, int flags) +{ + void *res; + START_STATS(); + if (flags & M_NOWAIT) { + res = cyg_mempool_var_try_alloc(net_mem, size); + } else { + res = cyg_mempool_var_alloc(net_mem, size); + } + FINISH_STATS(stats_malloc); + return (res); +} + +void +cyg_net_free(caddr_t addr, int type) +{ + START_STATS(); + cyg_mempool_var_free(net_mem, addr); + FINISH_STATS(stats_free); +} + +void * +cyg_net_mbuf_alloc(int type, int flags) +{ + void *res; + START_STATS(); + mbstat.m_mbufs++; + if (flags & M_NOWAIT) { + res = cyg_mempool_fix_try_alloc(net_mbufs); + } else { + res = cyg_mempool_fix_alloc(net_mbufs); + } + FINISH_STATS(stats_mbuf_alloc); + // Check that this nastiness works OK + CYG_ASSERT( dtom(res) == res, "dtom failed, base of mbuf" ); + CYG_ASSERT( dtom((char *)res + MSIZE/2) == res, "dtom failed, mid mbuf" ); + return (res); +} + +void +cyg_net_mbuf_free(caddr_t addr, int type) +{ + START_STATS(); + mbstat.m_mbufs--; + cyg_mempool_fix_free(net_mbufs, addr); + FINISH_STATS(stats_mbuf_free); +} + +void * +cyg_net_cluster_alloc(void) +{ + void *res; + START_STATS(); + res = cyg_mempool_fix_try_alloc(net_clusters); + FINISH_STATS(stats_cluster_alloc); + return res; +} + +static void +cyg_kmem_init(void) +{ + unsigned char *p; +#ifdef CYGPKG_NET_DEBUG + diag_printf("Network stack using %d bytes for misc space\n", NET_MEMPOOL_SIZE); + diag_printf(" %d bytes for mbufs\n", NET_MBUFS_SIZE); + diag_printf(" %d bytes for mbuf clusters\n", NET_CLUSTERS_SIZE); +#endif + cyg_mempool_var_create(&net_mempool_area, + NET_MEMPOOL_SIZE, + &net_mem, + &net_mem_pool); + // Align the mbufs on MSIZE boudaries so that dtom() can work. + p = (unsigned char *)(((long)(&net_mbufs_area) + MSIZE - 1) & ~(MSIZE-1)); + cyg_mempool_fix_create(p, + ((&(net_mbufs_area[NET_MBUFS_SIZE])) - p) & ~(MSIZE-1), + MSIZE, + &net_mbufs, + &net_mbufs_pool); + cyg_mempool_fix_create(&net_clusters_area, + NET_CLUSTERS_SIZE, + MCLBYTES, + &net_clusters, + &net_clusters_pool); + mbutl = (struct mbuf *)&net_clusters_area; + mclrefcnt = net_clusters_refcnt; +} + +void cyg_kmem_print_stats( void ) +{ + cyg_mempool_info info; + + diag_printf( "Network stack mbuf stats:\n" ); + diag_printf( " mbufs %d, clusters %d, free clusters %d\n", + mbstat.m_mbufs, /* mbufs obtained from page pool */ + mbstat.m_clusters, /* clusters obtained from page pool */ + /* mbstat.m_spare, */ /* spare field */ + mbstat.m_clfree /* free clusters */ + ); + diag_printf( " Failed to get %d times\n" + " Waited to get %d times\n" + " Drained queues to get %d times\n", + mbstat.m_drops, /* times failed to find space */ + mbstat.m_wait, /* times waited for space */ + mbstat.m_drain /* times drained protocols for space */ + /* mbstat.m_mtypes[256]; type specific mbuf allocations */ + ); + + cyg_mempool_var_get_info( net_mem, &info ); + diag_printf( "Misc mpool: total %7d, free %7d, max free block %d\n", + info.totalmem, + info.freemem, + info.maxfree + ); + + cyg_mempool_fix_get_info( net_mbufs, &info ); + diag_printf( "Mbufs pool: total %7d, free %7d, blocksize %4d\n", + info.totalmem, + info.freemem, + info.blocksize + ); + + + cyg_mempool_fix_get_info( net_clusters, &info ); + diag_printf( "Clust pool: total %7d, free %7d, blocksize %4d\n", + info.totalmem, + info.freemem, + info.blocksize + ); +} + +// This API is for our own automated network tests. It's not in any header +// files because it's not at all supported. +int cyg_net_get_mem_stats( int which, cyg_mempool_info *p ) +{ + CYG_CHECK_DATA_PTR( p, "Bad pointer to mempool_info" ); + CYG_ASSERT( 0 <= which, "Mempool selector underflow" ); + CYG_ASSERT( 2 >=which, "Mempool selector overflow" ); + + if ( p ) + switch ( which ) { + case 0: + cyg_mempool_var_get_info( net_mem, p ); + break; + case 1: + cyg_mempool_fix_get_info( net_mbufs, p ); + break; + case 2: + cyg_mempool_fix_get_info( net_clusters, p ); + break; + default: + return 0; + } + return (int)p; +} + +int +cyg_mtocl(u_long x) +{ + int res; + res = (((u_long)(x) - (u_long)mbutl) >> MCLSHIFT); + return res; +} + +struct mbuf * +cyg_cltom(u_long x) +{ + struct mbuf *res; + res = (struct mbuf *)((caddr_t)((u_long)mbutl + ((u_long)(x) << MCLSHIFT))); + return res; +} + +externC void +net_memcpy(void *d, void *s, int n) +{ + START_STATS(); + memcpy(d, s, n); + FINISH_STATS(stats_memcpy); +} + +externC void +net_memset(void *s, int v, int n) +{ + START_STATS(); + memset(s, v, n); + FINISH_STATS(stats_memset); +} + +// Rather than bring in the whole BSD 'random' code... +int +arc4random(void) +{ + cyg_uint32 res; + static unsigned long seed = 0xDEADB00B; + HAL_CLOCK_READ(&res); // Not so bad... (but often 0..N where N is small) + seed = ((seed & 0x007F00FF) << 7) ^ + ((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits + (res << 13) ^ (res >> 9); // using the clock too! + return (int)seed; +} + +void +get_random_bytes(void *buf, size_t len) +{ + unsigned long ranbuf, *lp; + lp = (unsigned long *)buf; + while (len > 0) { + ranbuf = arc4random(); + *lp++ = ranbuf; + len -= sizeof(ranbuf); + } +} + +void +microtime(struct timeval *tp) +{ + panic("microtime"); +} + +void +get_mono_time(void) +{ + panic("get_mono_time"); +} + +void +csignal(pid_t pgid, int signum, uid_t uid, uid_t euid) +{ + panic("csignal"); +} + +int +bcmp(const void *_p1, const void *_p2, size_t len) +{ + int res = 0; + unsigned char *p1 = (unsigned char *)_p1; + unsigned char *p2 = (unsigned char *)_p2; + while (len-- > 0) { + res = *p1++ - *p2++; + if (res) break; + } + return res; +} + +int +copyout(const void *s, void *d, size_t len) +{ + memcpy(d, s, len); + return 0; +} + +int +copyin(const void *s, void *d, size_t len) +{ + memcpy(d, s, len); + return 0; +} + +void +ovbcopy(const void *s, void *d, size_t len) +{ + memcpy(d, s, len); +} + +// ------------------------------------------------------------------------ +// THE NETWORK THREAD ITSELF +// +// Network software interrupt handler +// This function is run as a separate thread to allow +// processing of network events (mostly incoming packets) +// at "user level" instead of at interrupt time. +// +static void +cyg_netint(cyg_addrword_t param) +{ + cyg_flag_value_t curisr; + int spl; + while (true) { + curisr = cyg_flag_wait(&netint_flags, NETISR_ANY, + CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR); + spl = splsoftnet(); // Prevent any overlapping "stack" processing +#ifdef INET + if (curisr & (1 << NETISR_ARP)) { + // Pending ARP requests + arpintr(); + } + if (curisr & (1 << NETISR_IP)) { + // Pending IPv4 input + ipintr(); + } +#endif +#ifdef INET6 + if (curisr & (1 << NETISR_IPV6)) { + // Pending IPv6 input + ip6intr(); + } +#endif +#if NBRIDGE > 0 + if (curisr & (1 << NETISR_BRIDGE)) { + // Pending bridge input + bridgeintr(); + } +#endif + splx(spl); + } +} + + +// This just sets one of the pseudo-ISR bits used above. +void +setsoftnet(void) +{ + // This is called if we are out of MBUFs - it doesn't do anything, and + // that situation is handled OK, so don't bother with the diagnostic: + + // diag_printf("setsoftnet\n"); + + // No need to do this because it is ignored anyway: + // schednetisr(NETISR_SOFTNET); +} + + +/* Update the kernel globel ktime. */ +static void +cyg_ktime_func(cyg_handle_t alarm,cyg_addrword_t data) +{ + cyg_tick_count_t now = cyg_current_time(); + + ktime.tv_usec = (now % hz) * tick; + ktime.tv_sec = 1 + now / hz; +} + +static void +cyg_ktime_init(void) +{ + cyg_handle_t ktime_alarm_handle; + static cyg_alarm ktime_alarm; + cyg_handle_t counter; + + // Do not start at 0 - net stack thinks 0 an invalid time; + // Have a valid time available from right now: + ktime.tv_usec = 0; + ktime.tv_sec = 1; + + cyg_clock_to_counter(cyg_real_time_clock(),&counter); + cyg_alarm_create(counter, + cyg_ktime_func, + 0, + &ktime_alarm_handle, + &ktime_alarm); + + /* We want one alarm every 10ms. */ + cyg_alarm_initialize(ktime_alarm_handle,cyg_current_time()+1,1); + cyg_alarm_enable(ktime_alarm_handle); +} + +// +// Network initialization +// This function is called during system initialization to setup the whole +// networking environment. + +// Linker magic to execute this function as 'init' +extern void cyg_do_net_init(void); + +extern void ifinit(void); +extern void loopattach(int); +extern void bridgeattach(int); + +// Internal init functions: +extern void cyg_alarm_timeout_init(void); +extern void cyg_tsleep_init(void); + +void +cyg_net_init(void) +{ + static int _init = false; + cyg_netdevtab_entry_t *t; + + if (_init) return; + + cyg_do_net_init(); // Just forces linking in the initializer/constructor + // Initialize interrupt "flags" + cyg_flag_init(&netint_flags); + // Initialize timeouts and net service thread (pseudo-DSRs) + cyg_alarm_timeout_init(); + // Initialize tsleep/wakeup support + cyg_tsleep_init(); + // Initialize network memory system + cyg_kmem_init(); + mbinit(); + cyg_ktime_init(); + + // Create network background thread + cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY, // Priority + cyg_netint, // entry + 0, // entry parameter + "Network support", // Name + &netint_stack[0], // Stack + STACK_SIZE, // Size + &netint_thread_handle, // Handle + &netint_thread_data // Thread data structure + ); + cyg_thread_resume(netint_thread_handle); // Start it + + // Initialize all network devices + for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) { +// diag_printf("Init device '%s'\n", t->name); + if (t->init(t)) { + t->status = CYG_NETDEVTAB_STATUS_AVAIL; + } else { + // What to do if device init fails? + t->status = 0; // Device not [currently] available + } + } + // And attach the loopback interface +#ifdef CYGPKG_NET_NLOOP +#if 0 < CYGPKG_NET_NLOOP + loopattach(0); +#endif +#endif +#if NBRIDGE > 0 + bridgeattach(0); +#endif + // Start up the network processing + ifinit(); + domaininit(); + + // Done + _init = true; +} + +// Copyright (C) 2002 Gary Thomas + +#include <net/if.h> +#include <net/route.h> +#include <net/netdb.h> +externC void if_indextoname(int indx, char *buf, int len); + +typedef void pr_fun(char *fmt, ...); + +static void +_mask(struct sockaddr *sa, char *buf, int _len) +{ + char *cp = ((char *)sa) + 4; + int len = sa->sa_len - 4; + int tot = 0; + + while (len-- > 0) { + if (tot) *buf++ = '.'; + buf += diag_sprintf(buf, "%d", *cp++); + tot++; + } + + while (tot < 4) { + if (tot) *buf++ = '.'; + buf += diag_sprintf(buf, "%d", 0); + tot++; + } +} + +static void +_show_ifp(struct ifnet *ifp, pr_fun *pr) +{ + struct ifaddr *ifa; + char addr[64], netmask[64], broadcast[64]; + + (*pr)("%-8s", ifp->if_xname); + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr->sa_family != AF_LINK) { + getnameinfo (ifa->ifa_addr, ifa->ifa_addr->sa_len, addr, sizeof(addr), 0, 0, 0); + getnameinfo (ifa->ifa_dstaddr, ifa->ifa_dstaddr->sa_len, broadcast, sizeof(broadcast), 0, 0, 0); + _mask(ifa->ifa_netmask, netmask, 64); + (*pr)("IP: %s, Broadcast: %s, Netmask: %s\n", addr, broadcast, netmask); + (*pr)(" "); + if ((ifp->if_flags & IFF_UP)) (*pr)("UP "); + if ((ifp->if_flags & IFF_BROADCAST)) (*pr)("BROADCAST "); + if ((ifp->if_flags & IFF_LOOPBACK)) (*pr)("LOOPBACK "); + if ((ifp->if_flags & IFF_RUNNING)) (*pr)("RUNNING "); + if ((ifp->if_flags & IFF_PROMISC)) (*pr)("PROMISC "); + if ((ifp->if_flags & IFF_MULTICAST)) (*pr)("MULTICAST "); + if ((ifp->if_flags & IFF_ALLMULTI)) (*pr)("ALLMULTI "); + (*pr)("MTU: %d, Metric: %d\n", ifp->if_mtu, ifp->if_metric); + (*pr)(" Rx - Packets: %d, Bytes: %d", ifp->if_data.ifi_ipackets, ifp->if_data.ifi_ibytes); + (*pr)(", Tx - Packets: %d, Bytes: %d\n", ifp->if_data.ifi_opackets, ifp->if_data.ifi_obytes); + } + } +} + +static int +_dumpentry(struct radix_node *rn, void *vw) +{ + struct rtentry *rt = (struct rtentry *)rn; + struct sockaddr *dst, *gate, *netmask, *genmask; + char addr[32], *cp; + pr_fun *pr = (pr_fun *)vw; + + dst = rt_key(rt); + gate = rt->rt_gateway; + netmask = rt_mask(rt); + genmask = rt->rt_genmask; + if ((rt->rt_flags & (RTF_UP | RTF_LLINFO)) == RTF_UP) { + if (netmask == NULL) { + return 0; + } + _inet_ntop(dst, addr, sizeof(addr)); + (*pr)("%-15s ", addr); + if (gate != NULL) { + _inet_ntop(gate, addr, sizeof(addr)); + (*pr)("%-15s ", addr); + } else { + (*pr)("%-15s ", " "); + } + if (netmask != NULL) { + _mask(netmask, addr, sizeof(addr)); + (*pr)("%-15s ", addr); + } else { + (*pr)("%-15s ", " "); + } + cp = addr; + if ((rt->rt_flags & RTF_UP)) *cp++ = 'U'; + if ((rt->rt_flags & RTF_GATEWAY)) *cp++ = 'G'; + if ((rt->rt_flags & RTF_STATIC)) *cp++ = 'S'; + if ((rt->rt_flags & RTF_DYNAMIC)) *cp++ = 'D'; + *cp = '\0'; + (*pr)("%-8s ", addr); // Flags + if_indextoname(rt->rt_ifp->if_index, addr, 64); + (*pr)("%-8s ", addr); + (*pr)("\n"); + } + return 0; +} + +void +show_network_tables(pr_fun *pr) +{ + int i, error; + struct radix_node_head *rnh; + struct ifnet *ifp; + + cyg_scheduler_lock(); + (*pr)("Routing tables\n"); + (*pr)("Destination Gateway Mask Flags Interface\n"); + for (i = 1; i <= AF_MAX; i++) { + if ((rnh = rt_tables[i]) != NULL) { + error = rnh->rnh_walktree(rnh, _dumpentry, pr); + } + } + + (*pr)("Interface statistics\n"); + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) { + _show_ifp(ifp, pr); + } + cyg_scheduler_unlock(); +} + +#endif // CYGPKG_NET_DRIVER_FRAMEWORK + +// EOF support.c diff --git a/ecos/packages/net/tcpip/current/src/ecos/synch.c b/ecos/packages/net/tcpip/current/src/ecos/synch.c new file mode 100644 index 0000000..972c832 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/ecos/synch.c @@ -0,0 +1,416 @@ +//========================================================================== +// +// ecos/synch.c +// +// eCos wrapper and synch functions +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas, hmt +// Contributors: gthomas, hmt +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +// Synch routines, etc., used by network code + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/kernel.h> +#include <sys/domain.h> +#include <sys/protosw.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <net/if.h> +#include <net/route.h> +#include <net/netisr.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <arpa/inet.h> + +#include <machine/cpu.h> + +#include <pkgconf/net.h> + +#include <cyg/infra/diag.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/kernel/kapi.h> + +#include <cyg/infra/cyg_ass.h> + +#include <cyg/io/eth/netdev.h> + +//---------------------------- splx() emulation ------------------------------ +// This contains both the SPLX stuff and tsleep/wakeup - because those must +// be SPLX aware. They release the SPLX lock when sleeping, and reclaim it +// (if needs be) at wakeup. +// +// The variable spl_state (and the associated bit patterns) is used to keep +// track of the "splx()" level. This is an artifact of the original stack, +// based on the BSD interrupt world (interrupts and processing could be +// masked based on a level value, supported by hardware). This is not very +// real-time, so the emulation uses proper eCos tools and techniques to +// accomplish the same result. The key here is in the analysis of the +// various "levels", why they are used, etc. +// +// SPL_IMP is called in order to protect internal data structures +// short-term, primarily so that interrupt processing does not interfere +// with them. +// +// SPL_CLOCK is called in order to ensure that a timestamp is valid i.e. no +// time passes while the stamp is being taken (since it is a potentially +// non-idempotent data structure). +// +// SPL_SOFTNET is used to prevent all other stack processing, including +// interrupts (DSRs), etc. +// +// SPL_INTERNAL is used when running the pseudo-DSR in timeout.c - this +// runs what should really be the network interface device's DSR, and any +// timeout routines that are scheduled. (They are broken out into a thread +// to isolate the network locking from the rest of the system) +// +// NB a thread in thi state can tsleep(); see below. Tsleep releases and +// reclaims the locks and so on. This necessary because of the possible +// conflict where +// I splsoft +// I tsleep +// He runs, he is lower priority +// He splsofts +// He or something else awakens me +// I want to run, but he has splsoft, so I wait +// He runs and releases splsoft +// I awaken and go. + +static volatile cyg_uint32 spl_state = 0; +#define SPL_IMP 0x01 +#define SPL_NET 0x02 +#define SPL_CLOCK 0x04 +#define SPL_SOFTNET 0x08 +#define SPL_INTERNAL 0x10 + +static cyg_mutex_t splx_mutex; +static volatile cyg_handle_t splx_thread; + + +#ifdef CYGIMPL_TRACE_SPLX +#define SPLXARGS const char *file, const int line +#define SPLXMOREARGS , const char *file, const int line +#define SPLXTRACE do_sched_event(__FUNCTION__, file, line, spl_state) +#else +#define SPLXARGS void +#define SPLXMOREARGS +#define SPLXTRACE +#endif + + +static inline cyg_uint32 +spl_any( cyg_uint32 which ) +{ + cyg_uint32 old_spl = spl_state; + if ( cyg_thread_self() != splx_thread ) { + cyg_mutex_lock( &splx_mutex ); + old_spl = 0; // Free when we unlock this context + CYG_ASSERT( 0 == splx_thread, "Thread still owned" ); + CYG_ASSERT( 0 == spl_state, "spl still set" ); + splx_thread = cyg_thread_self(); + } + CYG_ASSERT( splx_mutex.locked, "spl_any: mutex not locked" ); + CYG_ASSERT( (cyg_handle_t)splx_mutex.owner == cyg_thread_self(), + "spl_any: mutex not mine" ); + spl_state |= which; + return old_spl; +} + + +cyg_uint32 +cyg_splimp(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_IMP ); +} + +cyg_uint32 +cyg_splclock(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_CLOCK ); +} + +cyg_uint32 +cyg_splnet(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_NET ); +} + +cyg_uint32 +cyg_splhigh(SPLXARGS) +{ + SPLXTRACE; + // splhigh did SPLSOFTNET in the contrib, so this is the same + return spl_any( SPL_SOFTNET ); +} + +cyg_uint32 +cyg_splsoftnet(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_SOFTNET ); +} + +cyg_uint32 +cyg_splinternal(SPLXARGS) +{ + SPLXTRACE; + return spl_any( SPL_INTERNAL ); +} + + +// +// Return to a previous interrupt state/level. +// +void +cyg_splx(cyg_uint32 old_state SPLXMOREARGS) +{ + SPLXTRACE; + + CYG_ASSERT( 0 != spl_state, "No state set" ); + CYG_ASSERT( splx_mutex.locked, "splx: mutex not locked" ); + CYG_ASSERT( (cyg_handle_t)splx_mutex.owner == cyg_thread_self(), + "splx: mutex not mine" ); + + spl_state &= old_state; + + if ( 0 == spl_state ) { + splx_thread = 0; + cyg_mutex_unlock( &splx_mutex ); + } +} + +//------------------ tsleep() and wakeup() emulation --------------------------- +// +// Structure used to keep track of 'tsleep' style events +// +struct wakeup_event { + void *chan; + cyg_sem_t sem; +}; +static struct wakeup_event wakeup_list[CYGPKG_NET_NUM_WAKEUP_EVENTS]; + + +// Called to initialize structures used by timeout functions +void +cyg_tsleep_init(void) +{ + int i; + struct wakeup_event *ev; + // Create list of "wakeup event" semaphores + for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) { + ev->chan = 0; + cyg_semaphore_init(&ev->sem, 0); + } + // Initialize the mutex and thread id: + cyg_mutex_init( &splx_mutex ); + splx_thread = 0; +} + + +// +// Signal an event +void +cyg_wakeup(void *chan) +{ + int i; + struct wakeup_event *ev; + cyg_scheduler_lock(); // Ensure scan is safe + // NB this is broadcast semantics because a sleeper/wakee holds the + // slot until they exit. This avoids a race condition whereby the + // semaphore can get an extra post - and then the slot is freed, so the + // sem wait returns immediately, AOK, so the slot wasn't freed. + for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) + if (ev->chan == chan) + cyg_semaphore_post(&ev->sem); + + cyg_scheduler_unlock(); +} + +// ------------------------------------------------------------------------ +// Wait for an event with timeout +// tsleep(event, priority, state, timeout) +// event - the thing to wait for +// priority - unused +// state - a descriptive message +// timeout - max time (in ticks) to wait +// returns: +// 0 - event was "signalled" +// ETIMEDOUT - timeout occurred +// EINTR - thread broken out of sleep +// +int +cyg_tsleep(void *chan, int pri, char *wmesg, int timo) +{ + int i, res = 0; + struct wakeup_event *ev; + cyg_tick_count_t sleep_time; + cyg_handle_t self = cyg_thread_self(); + int old_splflags = 0; // no flags held + + cyg_scheduler_lock(); + + // Safely find a free slot: + for (i = 0, ev = wakeup_list; i < CYGPKG_NET_NUM_WAKEUP_EVENTS; i++, ev++) { + if (ev->chan == 0) { + ev->chan = chan; + break; + } + } + CYG_ASSERT( i < CYGPKG_NET_NUM_WAKEUP_EVENTS, "no sleep slots" ); + CYG_ASSERT( 1 == cyg_scheduler_read_lock(), + "Tsleep - called with scheduler locked" ); + // Defensive: + if ( i >= CYGPKG_NET_NUM_WAKEUP_EVENTS ) { + cyg_scheduler_unlock(); + return ETIMEDOUT; + } + + // If we are the owner, then we must release the mutex when + // we wait. + if ( self == splx_thread ) { + old_splflags = spl_state; // Keep them for restoration + CYG_ASSERT( spl_state, "spl_state not set" ); + // Also want to assert that the mutex is locked... + CYG_ASSERT( splx_mutex.locked, "Splx mutex not locked" ); + CYG_ASSERT( (cyg_handle_t)splx_mutex.owner == self, "Splx mutex not mine" ); + splx_thread = 0; + spl_state = 0; + cyg_mutex_unlock( &splx_mutex ); + } + + // Re-initialize the semaphore - it might have counted up arbitrarily + // in the time between a prior sleeper being signalled and them + // actually running. + cyg_semaphore_init(&ev->sem, 0); + + // This part actually does the wait: + // As of the new kernel, we can do this without unlocking the scheduler + if (timo) { + sleep_time = cyg_current_time() + timo; + if (!cyg_semaphore_timed_wait(&ev->sem, sleep_time)) { + if( cyg_current_time() >= sleep_time ) + res = ETIMEDOUT; + else + res = EINTR; + } + } else { + if (!cyg_semaphore_wait(&ev->sem) ) { + res = EINTR; + } + } + + ev->chan = 0; // Free the slot - the wakeup call cannot do this. + + if ( old_splflags ) { // restore to previous state + // As of the new kernel, we can do this with the scheduler locked + cyg_mutex_lock( &splx_mutex ); // this might wait + CYG_ASSERT( 0 == splx_thread, "Splx thread set in tsleep" ); + CYG_ASSERT( 0 == spl_state, "spl_state set in tsleep" ); + splx_thread = self; // got it now... + spl_state = old_splflags; + } + + cyg_scheduler_unlock(); + return res; +} + + + +// ------------------------------------------------------------------------ +// DEBUGGING ROUTINES +#ifdef CYGIMPL_TRACE_SPLX +#undef cyg_scheduler_lock +#undef cyg_scheduler_safe_lock +#undef cyg_scheduler_unlock + +#define MAX_SCHED_EVENTS 256 +static struct _sched_event { + char *fun, *file; + int line, lock; +} sched_event[MAX_SCHED_EVENTS]; +static int next_sched_event = 0; +static int total_sched_events = 0; + +static void +do_sched_event(char *fun, char *file, int line, int lock) +{ + struct _sched_event *se = &sched_event[next_sched_event]; + if (++next_sched_event == MAX_SCHED_EVENTS) { + next_sched_event = 0; + } + se->fun = fun; + se->file = file; + se->line = line; + se->lock = lock; + total_sched_events++; +} + +static void +show_sched_events(void) +{ + int i; + struct _sched_event *se; + if (total_sched_events < MAX_SCHED_EVENTS) { + i = 0; + } else { + i = next_sched_event + 1; + if (i == MAX_SCHED_EVENTS) i = 0; + } + diag_printf("%d total scheduler events\n", total_sched_events); + while (i != next_sched_event) { + se = &sched_event[i]; + diag_printf("%s - lock: %d, called from %s.%d\n", se->fun, se->lock, se->file, se->line); + if (++i == MAX_SCHED_EVENTS) i = 0; + } +} + +#define SPLX_TRACE_DATA() cyg_scheduler_read_lock() + +void +_cyg_scheduler_lock(char *file, int line) +{ + cyg_scheduler_lock(); + do_sched_event(__FUNCTION__, file, line, SPLX_TRACE_DATA()); +} + +void +_cyg_scheduler_safe_lock(char *file, int line) +{ + cyg_scheduler_safe_lock(); + do_sched_event(__FUNCTION__, file, line, SPLX_TRACE_DATA()); +} + +void +_cyg_scheduler_unlock(char *file, int line) +{ + cyg_scheduler_unlock(); + do_sched_event(__FUNCTION__, file, line, SPLX_TRACE_DATA()); +} +#endif // CYGIMPL_TRACE_SPLX + +// EOF synch.c diff --git a/ecos/packages/net/tcpip/current/src/ecos/timeout.c b/ecos/packages/net/tcpip/current/src/ecos/timeout.c new file mode 100644 index 0000000..7091b3e --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/ecos/timeout.c @@ -0,0 +1,314 @@ +//========================================================================== +// +// lib/timeout.c +// +// timeout support +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas, hmt +// Contributors: gthomas, hmt +// Date: 1999-02-05 +// Description: Simple timeout functions +//####DESCRIPTIONEND#### + +#include <sys/param.h> +#include <pkgconf/net.h> +#include <cyg/kernel/kapi.h> +#include <cyg/infra/cyg_ass.h> + +// Timeout support + +void alarm_timeout_init(void); + +#ifndef NTIMEOUTS +#define NTIMEOUTS 8 +#endif +typedef struct { + cyg_int32 delta; // Number of "ticks" in the future for this timeout + timeout_fun *fun; // Function to execute when it expires + void *arg; // Argument to pass when it does +} timeout_entry; +static timeout_entry timeouts[NTIMEOUTS]; +static cyg_handle_t timeout_alarm_handle; +static cyg_alarm timeout_alarm; +static cyg_int32 last_delta; +static cyg_tick_count_t last_set_time; + +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +static char alarm_stack[STACK_SIZE]; +static cyg_thread alarm_thread_data; +static cyg_handle_t alarm_thread_handle; + +static cyg_flag_t alarm_flag; + +// ------------------------------------------------------------------------ +// This routine exists so that this module can synchronize: +extern cyg_uint32 cyg_splinternal(void); + +// ------------------------------------------------------------------------ +// CALLBACK FUNCTION +// Called from the thread, this runs the alarm callbacks. +// Locking is already in place when this is called. +static void +do_timeout(void) +{ + int i; + cyg_int32 min_delta; + timeout_entry *e; + + CYG_ASSERT( 0 < last_delta, "last_delta underflow" ); + + min_delta = last_delta; // local copy + last_delta = -1; // flag recursive call underway + + for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { + if (e->delta) { + CYG_ASSERT( e->delta >= min_delta, "e->delta underflow" ); + e->delta -= min_delta; + if (e->delta <= 0) { // Defensive + // Time for this item to 'fire' + timeout_fun *fun = e->fun; + void *arg = e->arg; + // Call it *after* cleansing the record + e->fun = 0; + e->delta = 0; + (*fun)(arg); + } + } + } + + // Now scan for a new timeout *after* running all the callbacks + // (because they can add timeouts themselves) + min_delta = 0x7FFFFFFF; // Maxint + for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) + if (e->delta) + if (e->delta < min_delta) + min_delta = e->delta; + + CYG_ASSERT( 0 < min_delta, "min_delta underflow" ); + + if (min_delta != 0x7FFFFFFF) { + // Still something to do, schedule it + last_set_time = cyg_current_time(); + cyg_alarm_initialize(timeout_alarm_handle, last_set_time+min_delta, 0); + last_delta = min_delta; + } else { + last_delta = 0; // flag no activity + } +} + +// ------------------------------------------------------------------------ +// ALARM EVENT FUNCTION +// This is the DSR for the alarm firing: +static void +do_alarm(cyg_handle_t alarm, cyg_addrword_t data) +{ + cyg_flag_setbits( &alarm_flag, 1 ); +} + +void ecos_synch_eth_drv_dsr(void) +{ + cyg_flag_setbits( &alarm_flag, 2 ); +} + +// ------------------------------------------------------------------------ +// HANDLER THREAD ENTRY ROUTINE +// This waits on the DSR to tell it to run: +static void +alarm_thread(cyg_addrword_t param) +{ + // This is from the logical ethernet dev; it calls those delivery + // functions who need attention. + extern void eth_drv_run_deliveries( void ); + + // This is from the logical ethernet dev; it tickles somehow + // all ethernet devices in case one is wedged. + extern void eth_drv_tickle_devices( void ); + + while ( 1 ) { + int spl; + int x; +#ifdef CYGPKG_NET_FAST_THREAD_TICKLE_DEVS + cyg_tick_count_t later = cyg_current_time(); + later += CYGNUM_NET_FAST_THREAD_TICKLE_DEVS_DELAY; + x = cyg_flag_timed_wait( + &alarm_flag, + -1, + CYG_FLAG_WAITMODE_OR | CYG_FLAG_WAITMODE_CLR, + later ); +#else + x = cyg_flag_wait( + &alarm_flag, + -1, + CYG_FLAG_WAITMODE_OR | CYG_FLAG_WAITMODE_CLR ); + + CYG_ASSERT( 3 & x, "Lost my bits" ); +#endif // CYGPKG_NET_FAST_THREAD_TICKLE_DEVS + CYG_ASSERT( !((~3) & x), "Extra bits" ); + + spl = cyg_splinternal(); + + CYG_ASSERT( 0 == spl, "spl nonzero" ); + + if ( 2 & x ) + eth_drv_run_deliveries(); +#ifdef CYGPKG_NET_FAST_THREAD_TICKLE_DEVS + // This is in the else clause for "do we deliver" because the + // network stack might have continuous timing events anyway - so + // the timeout would not occur, x would be 1 every time. + else // Tickle the devices... + eth_drv_tickle_devices(); +#endif // CYGPKG_NET_FAST_THREAD_TICKLE_DEVS + + if ( 1 & x ) + do_timeout(); + + cyg_splx(spl); + } +} + +// ------------------------------------------------------------------------ +// INITIALIZATION FUNCTION +void +cyg_alarm_timeout_init( void ) +{ + // Init the alarm object, attached to the real time clock + cyg_handle_t h; + cyg_clock_to_counter(cyg_real_time_clock(), &h); + cyg_alarm_create(h, do_alarm, 0, &timeout_alarm_handle, &timeout_alarm); + // Init the flag of waking up + cyg_flag_init( &alarm_flag ); + // Create alarm background thread to run the callbacks + cyg_thread_create( + CYGPKG_NET_FAST_THREAD_PRIORITY, // Priority + alarm_thread, // entry + 0, // entry parameter + "Network alarm support", // Name + &alarm_stack[0], // Stack + STACK_SIZE, // Size + &alarm_thread_handle, // Handle + &alarm_thread_data // Thread data structure + ); + cyg_thread_resume(alarm_thread_handle); // Start it +} + +// ------------------------------------------------------------------------ +// EXPORTED API: SET A TIMEOUT +// This can be called from anywhere, including recursively from the timeout +// functions themselves. +cyg_uint32 +timeout(timeout_fun *fun, void *arg, cyg_int32 delta) +{ + int i; + timeout_entry *e; + cyg_uint32 stamp; + + // this needs to be atomic - recursive calls from the alarm + // handler thread itself are allowed: + int spl = cyg_splinternal(); + + CYG_ASSERT( 0 < delta, "delta is right now, or even sooner!" ); + + // Renormalize delta wrt the existing set alarm, if there is one + if ( last_delta > 0 ) + delta += (cyg_int32)(cyg_current_time() - last_set_time); + // So recorded_delta is set to either: + // alarm is active: delta + NOW - THEN + // alarm is inactive: delta + + stamp = 0; // Assume no slots available + for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { + if ((e->delta == 0) && (e->fun == 0)) { + // Free entry + e->delta = delta; + e->fun = fun; + e->arg = arg; + stamp = (cyg_uint32)e; + break; + } + } + + if ( stamp && // we did add a record AND + (0 == last_delta || // alarm was inactive OR + delta < last_delta) ) { // alarm was active but later than we need + + // (if last_delta is -1, this call is recursive from the handler so + // also do nothing in that case) + + // Here, we know the new item added is sooner than that which was + // most recently set, if any, so we can just go and set it up. + if ( 0 == last_delta ) + last_set_time = cyg_current_time(); + + // So we use, to set the alarm either: + // alarm is active: (delta + NOW - THEN) + THEN + // alarm is inactive: delta + NOW + // and in either case it is true that + // (recorded_delta + last_set_time) == (delta + NOW) + cyg_alarm_initialize(timeout_alarm_handle, last_set_time+delta, 0); + last_delta = delta; + } + // Otherwise, the alarm is active, AND it is set to fire sooner than we + // require, so when it does, that will sort out calling the item we + // just added. Or we didn't actually add a record, so nothing has + // changed. + +#ifdef CYGPKG_INFRA_DEBUG + // Do some more checking akin to that in the alarm handler: + if ( last_delta != -1 ) { // not a recursive call + cyg_tick_count_t now = cyg_current_time(); + CYG_ASSERT( last_delta >= 0, "Bad last delta" ); + delta = 0x7fffffff; + for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { + if (e->delta) { + CYG_ASSERT( e->delta >= last_delta, "e->delta underflow" ); + CYG_ASSERT( last_set_time + e->delta + 1000 > now, + "Recorded alarm not in the future!" ); + if ( e->delta < delta ) + delta = e->delta; + } else { + CYG_ASSERT( 0 == e->fun, "Function recorded for 0 delta" ); + } + } + CYG_ASSERT( delta == last_delta, "We didn't pick the smallest delta!" ); + } +#endif + + cyg_splx(spl); + return stamp; +} + +// ------------------------------------------------------------------------ +// EXPORTED API: CANCEL A TIMEOUT +// This can be called from anywhere, including recursively from the timeout +// functions themselves. +void +untimeout(timeout_fun *fun, void * arg) +{ + int i; + timeout_entry *e; + int spl = cyg_splinternal(); + + for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { + if (e->delta && (e->fun == fun) && (e->arg == arg)) { + e->delta = 0; + e->fun = 0; + break; + } + } + cyg_splx(spl); +} + +// ------------------------------------------------------------------------ + +// EOF timeout.c diff --git a/ecos/packages/net/tcpip/current/src/lib/accept.c b/ecos/packages/net/tcpip/current/src/lib/accept.c new file mode 100644 index 0000000..c2844e1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/accept.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/accept.c +// +// accept() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +accept(int s, const struct sockaddr *name, socklen_t *anamelen) +{ + struct sys_accept_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,name) = (struct sockaddr *)name; + SYSCALLARG(args,anamelen) = anamelen; + error = sys_accept(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return res; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/bind.c b/ecos/packages/net/tcpip/current/src/lib/bind.c new file mode 100644 index 0000000..994bc6c --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/bind.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/bind.c +// +// bind() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct sys_bind_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,name) = name; + SYSCALLARG(args,namelen) = namelen; + error = sys_bind(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/close.c b/ecos/packages/net/tcpip/current/src/lib/close.c new file mode 100644 index 0000000..7cf8f4e --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/close.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/close.c +// +// close() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +close(int fd) +{ + int error; + struct file *fp; + if (getfp(fd, &fp)) + return (EBADF); + error = (*fp->f_ops->fo_close)(fp); + if (error) { + errno = error; + return -1; + } else { + ffree(fp); + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/connect.c b/ecos/packages/net/tcpip/current/src/lib/connect.c new file mode 100644 index 0000000..10ec5c7 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/connect.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/connect.c +// +// connect() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct sys_connect_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,name) = name; + SYSCALLARG(args,namelen) = namelen; + error = sys_connect(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/getpeername.c b/ecos/packages/net/tcpip/current/src/lib/getpeername.c new file mode 100644 index 0000000..45eefc2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/getpeername.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/getpeername.c +// +// getpeername() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +getpeername(int s, const struct sockaddr *name, socklen_t *namelen) +{ + struct sys_getpeername_args args; + int res, error; + SYSCALLARG(args,fdes) = s; + SYSCALLARG(args,asa) = (struct sockaddr *)name; + SYSCALLARG(args,alen) = namelen; + error = sys_getpeername(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/getsockname.c b/ecos/packages/net/tcpip/current/src/lib/getsockname.c new file mode 100644 index 0000000..32044f9 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/getsockname.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/getsockname.c +// +// getsockname() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +getsockname(int s, const struct sockaddr *name, socklen_t *namelen) +{ + struct sys_getsockname_args args; + int res, error; + SYSCALLARG(args,fdes) = s; + SYSCALLARG(args,asa) = (struct sockaddr *)name; + SYSCALLARG(args,alen) = namelen; + error = sys_getsockname(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/getsockopt.c b/ecos/packages/net/tcpip/current/src/lib/getsockopt.c new file mode 100644 index 0000000..22e2b70 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/getsockopt.c @@ -0,0 +1,54 @@ +//========================================================================== +// +// lib/getsockopt.c +// +// getsockopt() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +getsockopt(int s, int level, int name, void *val, socklen_t *avalsize) +{ + struct sys_getsockopt_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,level) = level; + SYSCALLARG(args,name) = name; + SYSCALLARG(args,val) = val; + SYSCALLARG(args,avalsize) = avalsize; + error = sys_getsockopt(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/ioctl.c b/ecos/packages/net/tcpip/current/src/lib/ioctl.c new file mode 100644 index 0000000..7af846c --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/ioctl.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/ioctl.c +// +// ioctl() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +ioctl(int fd, u_long cmd, void *data) +{ + struct sys_ioctl_args args; + int res, error; + SYSCALLARG(args,fd) = fd; + SYSCALLARG(args,com) = cmd; + SYSCALLARG(args,data) = data; + error = sys_ioctl(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/listen.c b/ecos/packages/net/tcpip/current/src/lib/listen.c new file mode 100644 index 0000000..fc489da --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/listen.c @@ -0,0 +1,51 @@ +//========================================================================== +// +// lib/listen.c +// +// listen() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +listen(int s, int backlog) +{ + struct sys_listen_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,backlog) = backlog; + error = sys_listen(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/read.c b/ecos/packages/net/tcpip/current/src/lib/read.c new file mode 100644 index 0000000..a9d59ab --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/read.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/read.c +// +// read() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +read(int fd, void *buf, size_t len) +{ + struct sys_read_args args; + int res, error; + SYSCALLARG(args,fd) = fd; + SYSCALLARG(args,buf) = buf; + SYSCALLARG(args,nbyte) = len; + error = sys_read(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return res; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/recv.c b/ecos/packages/net/tcpip/current/src/lib/recv.c new file mode 100644 index 0000000..39866c1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/recv.c @@ -0,0 +1,42 @@ +//========================================================================== +// +// lib/recv.c +// +// recv() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas,andrew.lunn@ascom.ch +// Contributors: gthomas +// Date: 2001-11-01 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +extern ssize_t recvfrom (int, void *, size_t, int, struct sockaddr *, socklen_t *); + +ssize_t +recv(int s, void *buf, size_t buflen, int flags) +{ + + return(recvfrom(s,buf,buflen,flags,NULL,0)); +} diff --git a/ecos/packages/net/tcpip/current/src/lib/recvfrom.c b/ecos/packages/net/tcpip/current/src/lib/recvfrom.c new file mode 100644 index 0000000..63c1b27 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/recvfrom.c @@ -0,0 +1,56 @@ +//========================================================================== +// +// lib/recvfrom.c +// +// recvfrom() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +ssize_t +recvfrom(int s, const void *buf, size_t buflen, + int flags, const struct sockaddr *from, socklen_t *fromlen) +{ + struct sys_recvfrom_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,buf) = (void *)buf; + SYSCALLARG(args,len) = buflen; + SYSCALLARG(args,flags) = flags; + SYSCALLARG(args,from) = (struct sockaddr *)from; + SYSCALLARG(args,fromlenaddr) = fromlen; + error = sys_recvfrom(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return res; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/select.c b/ecos/packages/net/tcpip/current/src/lib/select.c new file mode 100644 index 0000000..9316913 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/select.c @@ -0,0 +1,209 @@ +//========================================================================== +// +// lib/select.c +// +// 'select()' system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: eCos implementation of 'select()' system call +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <cyg/kernel/kapi.h> +#include <sys/select.h> +#include <sys/bsdselect.h> + +static cyg_flag_t select_flag; +static cyg_bool select_flag_init = false; +#define SELECT_WAKE 0x01 +#define SELECT_ABORT 0x02 + +// +// Private function which does all the work for 'select()' +// +static int +_cyg_select(int nfd, fd_set *in, fd_set *out, fd_set *ex, + struct timeval *tv, cyg_bool_t abortable) +{ + int fd, mode, num, ticks; + struct file *fp; + fd_set in_res, out_res, ex_res; // Result sets + fd_set *selection[3], *result[3]; + cyg_tick_count_t now, then; + int mode_type[] = {FREAD, FWRITE, 0}; + cyg_flag_value_t flag, wait_flag; + + // Note: since this is called by application programs, it needs no protection + if (!select_flag_init) { + select_flag_init = true; + cyg_flag_init(&select_flag); + } + wait_flag = SELECT_WAKE; + if (abortable) wait_flag |= SELECT_ABORT; + FD_ZERO(&in_res); + FD_ZERO(&out_res); + FD_ZERO(&ex_res); + // Set up sets + selection[0] = in; result[0] = &in_res; + selection[1] = out; result[1] = &out_res; + selection[2] = ex; result[2] = &ex_res; + // Compute end time + if (tv) { + now = cyg_current_time(); + ticks = (tv->tv_sec * 100) + (tv->tv_usec / 10000); + then = now + ticks; + } else { + then = 0; // Compiler warnings :-( + ticks = 0; + } + // Scan sets for possible I/O until something found, timeout or error. + while (true) { + num = 0; // Total file descriptors "ready" + + cyg_scheduler_lock(); // Scan the list atomically wrt electing to sleep + + for (mode = 0; mode < 3; mode++) { + if (selection[mode]) { + for (fd = 0; fd < nfd; fd++) { + if (FD_ISSET(fd, selection[mode])) { + if (getfp(fd, &fp)) { + cyg_scheduler_unlock(); // return. + errno = EBADF; + return -1; + } + if ((*fp->f_ops->fo_select)(fp, mode_type[mode])) { + FD_SET(fd, result[mode]); + num++; + } + } + } + } + } + if (num) { + + cyg_scheduler_unlock(); // Happy, about to return. + + // Found something, update user's sets + if (in) { + memcpy(in, &in_res, sizeof(in_res)); + } + if (out) { + memcpy(out, &out_res, sizeof(out_res)); + } + if (ex) { + memcpy(ex, &ex_res, sizeof(ex_res)); + } + return num; + } + // Nothing found, see if we want to wait + if (tv) { + if (ticks == 0) { + // Special case of "poll" + cyg_scheduler_unlock(); // About to return. + return 0; + } + flag = cyg_flag_timed_wait(&select_flag, wait_flag, + CYG_FLAG_WAITMODE_OR, + then); + } else { + // Wait forever (until something happens) + flag = cyg_flag_wait(&select_flag, wait_flag, + CYG_FLAG_WAITMODE_OR); + } + + cyg_scheduler_unlock(); // waited atomically + + if (flag & SELECT_ABORT) { + errno = EINTR; + return -1; + } + if (!flag) { + return 0; // meaning no activity, ergo timeout occurred + } + } + errno = ENOSYS; + return -1; +} + +// +// This function is called by the lower layers to record the +// fact that a particular 'select' event is being requested. +// +void +selrecord(void *selector, struct selinfo *info) +{ + // Unused by this implementation +} + +// +// This function is called to indicate that a 'select' event +// may have occurred. +// +void +selwakeup(struct selinfo *info) +{ + // Need these ops to be atomic to make sure the clear occurs - + // otherwise a higher prio thread could hog the CPU when its fds are + // not ready, but the flag is (already) set, or set for someone else. + cyg_scheduler_lock(); + cyg_flag_setbits(&select_flag, SELECT_WAKE); + cyg_flag_maskbits(&select_flag, 0 ); // clear all + cyg_scheduler_unlock(); +} + +// +// The public function used by 'normal' programs. This interface does not allow +// the 'select()' to be externally interrupted. +// +int +select(int nfd, fd_set *in, fd_set *out, fd_set *ex, + struct timeval *tv) +{ + return _cyg_select(nfd, in, out, ex, tv, false); +} + +// +// The public function used by programs which wish to allow interruption, +// using the 'cyg_select_abort()' function below. +// +int +cyg_select_with_abort(int nfd, fd_set *in, fd_set *out, fd_set *ex, + struct timeval *tv) +{ + return _cyg_select(nfd, in, out, ex, tv, true); +} + +// +// This function can be called by the user to forceably abort any +// current selects. +// +void +cyg_select_abort(void) +{ + // See comments in selwakeup()... + cyg_scheduler_lock(); + cyg_flag_setbits(&select_flag, SELECT_ABORT); + cyg_flag_maskbits(&select_flag, 0 ); + cyg_scheduler_unlock(); +} + + diff --git a/ecos/packages/net/tcpip/current/src/lib/sendto.c b/ecos/packages/net/tcpip/current/src/lib/sendto.c new file mode 100644 index 0000000..d319150 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/sendto.c @@ -0,0 +1,56 @@ +//========================================================================== +// +// lib/sendto.c +// +// sendto() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +ssize_t +sendto(int s, const void *buf, size_t buflen, + int flags, const struct sockaddr *to, socklen_t tolen) +{ + struct sys_sendto_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,buf) = buf; + SYSCALLARG(args,len) = buflen; + SYSCALLARG(args,flags) = flags; + SYSCALLARG(args,to) = to; + SYSCALLARG(args,tolen) = tolen; + error = sys_sendto(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return res; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/setsockopt.c b/ecos/packages/net/tcpip/current/src/lib/setsockopt.c new file mode 100644 index 0000000..88902f0 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/setsockopt.c @@ -0,0 +1,54 @@ +//========================================================================== +// +// lib/setsockopt.c +// +// setsockopt() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +setsockopt(int s, int level, int name, const void *val, socklen_t valsize) +{ + struct sys_setsockopt_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,level) = level; + SYSCALLARG(args,name) = name; + SYSCALLARG(args,val) = val; + SYSCALLARG(args,valsize) = valsize; + error = sys_setsockopt(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/shutdown.c b/ecos/packages/net/tcpip/current/src/lib/shutdown.c new file mode 100644 index 0000000..a8956eb --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/shutdown.c @@ -0,0 +1,51 @@ +//========================================================================== +// +// lib/shutdown.c +// +// shutdown() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +shutdown(int s, int how) +{ + struct sys_shutdown_args args; + int res, error; + SYSCALLARG(args,s) = s; + SYSCALLARG(args,how) = how; + error = sys_shutdown(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return 0; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/socket.c b/ecos/packages/net/tcpip/current/src/lib/socket.c new file mode 100644 index 0000000..f92c225 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/socket.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/socket.c +// +// socket() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +socket(int domain, int type, int protocol) +{ + struct sys_socket_args args; + int res, error; + SYSCALLARG(args,domain) = domain; + SYSCALLARG(args,type) = type; + SYSCALLARG(args,protocol) = protocol; + error = sys_socket(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return res; + } +} diff --git a/ecos/packages/net/tcpip/current/src/lib/write.c b/ecos/packages/net/tcpip/current/src/lib/write.c new file mode 100644 index 0000000..0667631 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/lib/write.c @@ -0,0 +1,52 @@ +//========================================================================== +// +// lib/write.c +// +// write() system call +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include <sys/param.h> +#include <cyg/io/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> + +#include <sys/syscallargs.h> + +int +write(int fd, const void *buf, size_t len) +{ + struct sys_write_args args; + int res, error; + SYSCALLARG(args,fd) = fd; + SYSCALLARG(args,buf) = buf; + SYSCALLARG(args,nbyte) = len; + error = sys_write(&args, &res); + if (error) { + errno = error; + return -1; + } else { + return res; + } +} diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/kern_subr.c b/ecos/packages/net/tcpip/current/src/sys/kern/kern_subr.c new file mode 100644 index 0000000..63cf342 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/kern_subr.c @@ -0,0 +1,357 @@ +//========================================================================== +// +// sys/kern/kern_subr.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: kern_subr.c,v 1.10 1999/11/07 17:39:14 provos Exp $ */ +/* $NetBSD: kern_subr.c,v 1.15 1996/04/09 17:21:56 ragge Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 + */ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#include <sys/proc.h> +#endif // __ECOS +#include <sys/malloc.h> +#include <sys/queue.h> + +int +uiomove(cp, n, uio) + register caddr_t cp; + register int n; + register struct uio *uio; +{ + register struct iovec *iov; + u_int cnt; + int error = 0; + +#ifdef DIAGNOSTIC + if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) + panic("uiomove: mode"); + if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) + panic("uiomove proc"); +#endif + while (n > 0 && uio->uio_resid) { + iov = uio->uio_iov; + cnt = iov->iov_len; + if (cnt == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + continue; + } + if (cnt > n) + cnt = n; + switch (uio->uio_segflg) { + + case UIO_USERSPACE: + if (uio->uio_rw == UIO_READ) + error = copyout(cp, iov->iov_base, cnt); + else + error = copyin(iov->iov_base, cp, cnt); + if (error) + return (error); + break; + + case UIO_SYSSPACE: +#if defined(UVM) + if (uio->uio_rw == UIO_READ) + error = kcopy(cp, iov->iov_base, cnt); + else + error = kcopy(iov->iov_base, cp, cnt); + if (error) + return(error); +#else + if (uio->uio_rw == UIO_READ) + bcopy((caddr_t)cp, iov->iov_base, cnt); + else + bcopy(iov->iov_base, (caddr_t)cp, cnt); + break; +#endif + } + iov->iov_base = (char *)iov->iov_base + cnt; + iov->iov_len -= cnt; + uio->uio_resid -= cnt; + uio->uio_offset += cnt; + cp += cnt; + n -= cnt; + } + return (error); +} + +#ifndef __ECOS +/* + * Give next character to user as result of read. + */ +int +ureadc(c, uio) + register int c; + register struct uio *uio; +{ + register struct iovec *iov; + + if (uio->uio_resid == 0) +#ifdef DIAGNOSTIC + panic("ureadc: zero resid"); +#else + return (EINVAL); +#endif +again: + if (uio->uio_iovcnt <= 0) +#ifdef DIAGNOSTIC + panic("ureadc: non-positive iovcnt"); +#else + return (EINVAL); +#endif + iov = uio->uio_iov; + if (iov->iov_len <= 0) { + uio->uio_iovcnt--; + uio->uio_iov++; + goto again; + } + switch (uio->uio_segflg) { + + case UIO_USERSPACE: + if (subyte(iov->iov_base, c) < 0) + return (EFAULT); + break; + + case UIO_SYSSPACE: + *(char *)iov->iov_base = c; + break; + } + iov->iov_base++; + iov->iov_len--; + uio->uio_resid--; + uio->uio_offset++; + return (0); +} +#endif // __ECOS + +/* + * General routine to allocate a hash table. + */ +#ifdef __ECOS +void * +hashinit(int elements, int type, int flags, u_long *hashmask) +#else +void * +hashinit(elements, type, flags, hashmask) + int elements, type, flags; + u_long *hashmask; +#endif +{ + long hashsize; + LIST_HEAD(generic, generic) *hashtbl; + int i; + + if (elements <= 0) + panic("hashinit: bad cnt"); + for (hashsize = 1; hashsize <= elements; hashsize <<= 1) + continue; + hashsize >>= 1; + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, flags); + for (i = 0; i < hashsize; i++) + LIST_INIT(&hashtbl[i]); + *hashmask = hashsize - 1; + return (hashtbl); +} + +#ifndef __ECOS +/* + * "Shutdown hook" types, functions, and variables. + */ + +struct shutdownhook_desc { + LIST_ENTRY(shutdownhook_desc) sfd_list; + void (*sfd_fn) __P((void *)); + void *sfd_arg; +}; + +LIST_HEAD(, shutdownhook_desc) shutdownhook_list; + +int shutdownhooks_done; + +void * +shutdownhook_establish(fn, arg) + void (*fn) __P((void *)); + void *arg; +{ + struct shutdownhook_desc *ndp; + + ndp = (struct shutdownhook_desc *) + malloc(sizeof (*ndp), M_DEVBUF, M_NOWAIT); + if (ndp == NULL) + return NULL; + + ndp->sfd_fn = fn; + ndp->sfd_arg = arg; + LIST_INSERT_HEAD(&shutdownhook_list, ndp, sfd_list); + + return (ndp); +} + +void +shutdownhook_disestablish(vhook) + void *vhook; +{ +#ifdef DIAGNOSTIC + struct shutdownhook_desc *dp; + + for (dp = shutdownhook_list.lh_first; dp != NULL; + dp = dp->sfd_list.le_next) + if (dp == vhook) + break; + if (dp == NULL) + panic("shutdownhook_disestablish: hook not established"); +#endif + + LIST_REMOVE((struct shutdownhook_desc *)vhook, sfd_list); +} + +/* + * Run shutdown hooks. Should be invoked immediately before the + * system is halted or rebooted, i.e. after file systems unmounted, + * after crash dump done, etc. + */ +void +doshutdownhooks() +{ + struct shutdownhook_desc *dp; + + if (shutdownhooks_done) + return; + + for (dp = shutdownhook_list.lh_first; dp != NULL; dp = + dp->sfd_list.le_next) + (*dp->sfd_fn)(dp->sfd_arg); +} + +/* + * "Power hook" types, functions, and variables. + */ + +struct powerhook_desc { + LIST_ENTRY(powerhook_desc) sfd_list; + void (*sfd_fn) __P((int, void *)); + void *sfd_arg; +}; + +LIST_HEAD(, powerhook_desc) powerhook_list; + +void * +powerhook_establish(fn, arg) + void (*fn) __P((int, void *)); + void *arg; +{ + struct powerhook_desc *ndp; + + ndp = (struct powerhook_desc *) + malloc(sizeof(*ndp), M_DEVBUF, M_NOWAIT); + if (ndp == NULL) + return NULL; + + ndp->sfd_fn = fn; + ndp->sfd_arg = arg; + LIST_INSERT_HEAD(&powerhook_list, ndp, sfd_list); + + return (ndp); +} + +void +powerhook_disestablish(vhook) + void *vhook; +{ +#ifdef DIAGNOSTIC + struct powerhook_desc *dp; + + for (dp = powerhook_list.lh_first; dp != NULL; + dp = dp->sfd_list.le_next) + if (dp == vhook) + break; + if (dp == NULL) + panic("powerhook_disestablish: hook not established"); +#endif + + LIST_REMOVE((struct powerhook_desc *)vhook, sfd_list); + free(vhook, M_DEVBUF); +} + +/* + * Run power hooks. + */ +void +dopowerhooks(why) + int why; +{ + struct powerhook_desc *dp; + + for (dp = LIST_FIRST(&powerhook_list); + dp != NULL; + dp = LIST_NEXT(dp, sfd_list)) { + (*dp->sfd_fn)(why, dp->sfd_arg); + } +} +#endif // __ECOS diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/sockio.c b/ecos/packages/net/tcpip/current/src/sys/kern/sockio.c new file mode 100644 index 0000000..5cead64 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/sockio.c @@ -0,0 +1,950 @@ +//========================================================================== +// +// sys/kern/sockio.c +// +// Socket interface to Fileio subsystem +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-06-06 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +/* + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +//========================================================================== + +#include <pkgconf/net.h> +#include <pkgconf/io_fileio.h> + +#include <sys/types.h> + +#include <cyg/io/file.h> + +#include <cyg/fileio/fileio.h> +#include <cyg/fileio/sockio.h> + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/ioctl.h> + +#include <net/if.h> +#include <net/route.h> + +//========================================================================== +// Forward definitions + +static int bsd_init( cyg_nstab_entry *nste ); +static int bsd_socket( cyg_nstab_entry *nste, int domain, int type, + int protocol, cyg_file *file ); + +static int bsd_bind ( cyg_file *fp, const sockaddr *sa, socklen_t len ); +static int bsd_connect ( cyg_file *fp, const sockaddr *sa, socklen_t len ); +static int bsd_accept ( cyg_file *fp, cyg_file *new_fp, + struct sockaddr *name, socklen_t *anamelen ); +static int bsd_listen ( cyg_file *fp, int len ); +static int bsd_getname ( cyg_file *fp, sockaddr *sa, socklen_t *len, int peer ); +static int bsd_shutdown ( cyg_file *fp, int flags ); +static int bsd_getsockopt( cyg_file *fp, int level, int optname, + void *optval, socklen_t *optlen); +static int bsd_setsockopt( cyg_file *fp, int level, int optname, + const void *optval, socklen_t optlen); +static int bsd_sendmsg ( cyg_file *fp, const struct msghdr *m, + int flags, ssize_t *retsize ); +static int bsd_recvmsg ( cyg_file *fp, struct msghdr *m, + socklen_t *namelen, ssize_t *retsize ); + + +// File operations +static int bsd_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); +static int bsd_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); +static int bsd_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ); +static int bsd_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, + CYG_ADDRWORD data); +static int bsd_select (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info); +static int bsd_fsync (struct CYG_FILE_TAG *fp, int mode ); +static int bsd_close (struct CYG_FILE_TAG *fp); +static int bsd_fstat (struct CYG_FILE_TAG *fp, struct stat *buf ); +static int bsd_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ); +static int bsd_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ); + +static int +bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize); +static int +bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize); + + +//========================================================================== +// Table entrys + +NSTAB_ENTRY( bsd_nste, 0, + "bsd_tcpip", + "", + 0, + bsd_init, + bsd_socket); + +struct cyg_sock_ops bsd_sockops = +{ + bsd_bind, + bsd_connect, + bsd_accept, + bsd_listen, + bsd_getname, + bsd_shutdown, + bsd_getsockopt, + bsd_setsockopt, + bsd_sendmsg, + bsd_recvmsg +}; + +cyg_fileops bsd_sock_fileops = +{ + bsd_read, + bsd_write, + bsd_lseek, + bsd_ioctl, + bsd_select, + bsd_fsync, + bsd_close, + bsd_fstat, + bsd_getinfo, + bsd_setinfo +}; + +//========================================================================== +// NStab functions + + + +// ------------------------------------------------------------------------- + +static int bsd_init( cyg_nstab_entry *nste ) +{ + // Initialization already handled via constructor + + return ENOERR; +} + +// ------------------------------------------------------------------------- + +static int bsd_socket( cyg_nstab_entry *nste, int domain, int type, + int protocol, cyg_file *file ) +{ + int error = 0; + struct socket *so; + + error = socreate( domain, &so, type, protocol ); + + if( error == ENOERR ) + { + + cyg_selinit(&so->so_rcv.sb_sel); + cyg_selinit(&so->so_snd.sb_sel); + + file->f_flag |= CYG_FREAD|CYG_FWRITE; + file->f_type = CYG_FILE_TYPE_SOCKET; + file->f_ops = &bsd_sock_fileops; + file->f_offset = 0; + file->f_data = (CYG_ADDRWORD)so; + file->f_xops = (CYG_ADDRWORD)&bsd_sockops; + } + + return error; +} + + +//========================================================================== +// Sockops functions + +// ------------------------------------------------------------------------- + +static int bsd_bind ( cyg_file *fp, const sockaddr *sa, socklen_t len ) +{ + struct mbuf *nam; + int error; + + error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME); + + if (error) + return (error); + + error = sobind((struct socket *)fp->f_data, nam); + + m_freem(nam); + + return error; +} + +// ------------------------------------------------------------------------- + +static int bsd_connect ( cyg_file *fp, const sockaddr *sa, socklen_t len ) +{ + register struct socket *so; + struct mbuf *nam; + int error, s; + + so = (struct socket *)fp->f_data; + + if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) + return (EALREADY); + + error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME); + + if (error) + return (error); + + error = soconnect(so, nam); + if (error) + goto bad; + + if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { + m_freem(nam); + return (EINPROGRESS); + } + + s = splsoftnet(); + while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { + error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, + netcon, 0); + if (error) + break; + } + + if (error == 0) { + error = so->so_error; + so->so_error = 0; + } + + splx(s); + +bad: + so->so_state &= ~SS_ISCONNECTING; + m_freem(nam); + + return error; +} + +// ------------------------------------------------------------------------- + +static int bsd_accept ( cyg_file *fp, cyg_file *new_fp, + struct sockaddr *name, socklen_t *anamelen ) +{ + struct mbuf *nam; + socklen_t namelen = 0; + int error = 0, s; + register struct socket *so; + + if( anamelen != NULL ) + namelen = *anamelen; + + s = splsoftnet(); + so = (struct socket *)fp->f_data; + + if ((so->so_options & SO_ACCEPTCONN) == 0) { + splx(s); + return (EINVAL); + } + + if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { + splx(s); + return (EWOULDBLOCK); + } + + while (so->so_qlen == 0 && so->so_error == 0) { + if (so->so_state & SS_CANTRCVMORE) { + so->so_error = ECONNABORTED; + break; + } + error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, + netcon, 0); + if (error) { + splx(s); + return (error); + } + } + + if (so->so_error) { + error = so->so_error; + so->so_error = 0; + splx(s); + return (error); + } + + { + struct socket *aso = so->so_q; + if (soqremque(aso, 1) == 0) + panic("accept"); + so = aso; + } + + cyg_selinit(&so->so_rcv.sb_sel); + cyg_selinit(&so->so_snd.sb_sel); + + new_fp->f_type = DTYPE_SOCKET; + new_fp->f_flag |= FREAD|FWRITE; + new_fp->f_offset = 0; + new_fp->f_ops = &bsd_sock_fileops; + new_fp->f_data = (CYG_ADDRWORD)so; + new_fp->f_xops = (CYG_ADDRWORD)&bsd_sockops; + + nam = m_get(M_WAIT, MT_SONAME); + (void) soaccept(so, nam); + if (name) { + if (namelen > nam->m_len) + namelen = nam->m_len; + /* SHOULD COPY OUT A CHAIN HERE */ + if ((error = copyout(mtod(nam, caddr_t), + (caddr_t)name, namelen)) == 0) + *anamelen = namelen; + } + m_freem(nam); + splx(s); + + return (error); +} + +// ------------------------------------------------------------------------- + +static int bsd_listen ( cyg_file *fp, int backlog ) +{ + return (solisten((struct socket *)fp->f_data, backlog)); +} + +// ------------------------------------------------------------------------- + +static int bsd_getname ( cyg_file *fp, sockaddr *asa, socklen_t *alen, int peer ) +{ + register struct socket *so; + struct mbuf *m; + socklen_t len = 0; + int error; + int type = peer ? PRU_PEERADDR : PRU_SOCKADDR; + + if( alen != NULL ) + len = *alen; + + so = (struct socket *)fp->f_data; + + if ( peer && (so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) + return (ENOTCONN); + + m = m_getclr(M_WAIT, MT_SONAME); + if (m == NULL) + return (ENOBUFS); + + error = (*so->so_proto->pr_usrreq)(so, type, 0, m, 0); + if (error) + goto bad; + + if (len > m->m_len) + len = m->m_len; + + error = copyout(mtod(m, caddr_t), (caddr_t)asa, len); + + if (error == 0) + *alen = len; + +bad: + m_freem(m); + + return (error); +} + +// ------------------------------------------------------------------------- + +static int bsd_shutdown ( cyg_file *fp, int how ) +{ + return (soshutdown((struct socket *)fp->f_data, how)); +} + +// ------------------------------------------------------------------------- + +static int bsd_getsockopt( cyg_file *fp, int level, int optname, + void *optval, socklen_t *optlen) +{ + struct mbuf *m = NULL; + socklen_t valsize = 0; + int error; + + if( optval != NULL && optlen != NULL ) + valsize = *optlen; + + error = sogetopt((struct socket *)fp->f_data, level, optname, &m); + + if( error == ENOERR && valsize != 0 && m != NULL) + { + if (valsize > m->m_len) + valsize = m->m_len; + + error = copyout(mtod(m, caddr_t), optval, valsize); + + if( error == ENOERR ) + *optlen = valsize; + + } + + if (m != NULL) + (void) m_free(m); + return (error); +} + +// ------------------------------------------------------------------------- + +static int bsd_setsockopt( cyg_file *fp, int level, int optname, + const void *optval, socklen_t optlen) +{ + int error; + struct mbuf *m = NULL; + + if( optlen > MCLBYTES ) + return EINVAL; + + if (optval != NULL) { + m = m_get(M_WAIT, MT_SOOPTS); + if (optlen > MLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + return (ENOBUFS); + } + } + if (m == NULL) + return (ENOBUFS); + error = copyin(optval, mtod(m, caddr_t), optlen); + if (error) { + (void) m_free(m); + return (error); + } + m->m_len = optlen; + } + + return (sosetopt((struct socket *)fp->f_data, level, optname, m)); +} + +// ------------------------------------------------------------------------- + +static int bsd_sendmsg ( cyg_file *fp, const struct msghdr *m, int flags, ssize_t *retsize ) +{ + return bsd_sendit( fp, m, flags, retsize); +} + +// ------------------------------------------------------------------------- + +static int bsd_recvmsg ( cyg_file *fp, struct msghdr *m, socklen_t *namelen, ssize_t *retsize ) +{ + return bsd_recvit( fp, m, namelen, retsize); +} + +//========================================================================== +// File system call functions + +// ------------------------------------------------------------------------- + +static int bsd_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) +{ + return (soreceive((struct socket *)fp->f_data, (struct mbuf **)0, + uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0)); +} + +// ------------------------------------------------------------------------- + +static int bsd_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) +{ + return (sosend((struct socket *)fp->f_data, (struct mbuf *)0, + uio, (struct mbuf *)0, (struct mbuf *)0, 0)); +} + +// ------------------------------------------------------------------------- + +static int bsd_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ) +{ + return ESPIPE; +} + +// ------------------------------------------------------------------------- + +static int bsd_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd, + CYG_ADDRWORD data) +{ + register struct socket *so = (struct socket *)fp->f_data; + void *p = 0; + + switch (cmd) { + + case FIONBIO: + if (*(int *)data) + so->so_state |= SS_NBIO; + else + so->so_state &= ~SS_NBIO; + return (0); + + case FIOASYNC: + if (*(int *)data) { + so->so_state |= SS_ASYNC; + so->so_rcv.sb_flags |= SB_ASYNC; + so->so_snd.sb_flags |= SB_ASYNC; + } else { + so->so_state &= ~SS_ASYNC; + so->so_rcv.sb_flags &= ~SB_ASYNC; + so->so_snd.sb_flags &= ~SB_ASYNC; + } + return (0); + + case FIONREAD: + *(int *)data = so->so_rcv.sb_cc; + return (0); + + case SIOCATMARK: + *(int *)data = (so->so_state&SS_RCVATMARK) != 0; + return (0); + } + /* + * Interface/routing/protocol specific ioctls: + * interface and routing ioctls should have a + * different entry since a socket's unnecessary + */ + if (IOCGROUP(cmd) == 'i') + return (ifioctl(so, (u_long)cmd, (caddr_t)data, p)); + if (IOCGROUP(cmd) == 'r') + return (rtioctl((u_long)cmd, (caddr_t)data, p)); + return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, + (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0)); + +} + +// ------------------------------------------------------------------------- + +static int bsd_select (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info) +{ + register struct socket *so = (struct socket *)fp->f_data; + register int s = splsoftnet(); + + switch (which) { + + case FREAD: + if (soreadable(so)) { + splx(s); + return (1); + } + cyg_selrecord(info, &so->so_rcv.sb_sel); + so->so_rcv.sb_flags |= SB_SEL; + break; + + case FWRITE: + if (sowriteable(so)) { + splx(s); + return (1); + } + cyg_selrecord(info, &so->so_snd.sb_sel); + so->so_snd.sb_flags |= SB_SEL; + break; + + case 0: + if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) { + splx(s); + return (1); + } + cyg_selrecord(info, &so->so_rcv.sb_sel); + so->so_rcv.sb_flags |= SB_SEL; + break; + } + splx(s); + + return ENOERR; +} + +// ------------------------------------------------------------------------- + +static int bsd_fsync (struct CYG_FILE_TAG *fp, int mode ) +{ + // FIXME: call some sort of flush IOCTL? + return 0; +} + +// ------------------------------------------------------------------------- + +static int bsd_close (struct CYG_FILE_TAG *fp) +{ + int error = 0; + + if (fp->f_data) + error = soclose((struct socket *)fp->f_data); + fp->f_data = 0; + return (error); +} + +// ------------------------------------------------------------------------- + +static int bsd_fstat (struct CYG_FILE_TAG *fp, struct stat *buf ) +{ + register struct socket *so = (struct socket *)fp->f_data; + + bzero((caddr_t)buf, sizeof (*buf)); + + // Mark socket as a fifo for now. We need to add socket types to + // sys/stat.h. + buf->st_mode = __stat_mode_FIFO; + + return ((*so->so_proto->pr_usrreq)(so, PRU_SENSE, + (struct mbuf *)buf, + (struct mbuf *)0, + (struct mbuf *)0)); +} + +// ------------------------------------------------------------------------- + +static int bsd_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ) +{ + return ENOSYS; +} + +// ------------------------------------------------------------------------- + +static int bsd_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ) +{ + return ENOSYS; +} + + + +//========================================================================== +// Select support + +// ------------------------------------------------------------------------- +// This function is called by the lower layers to record the +// fact that a particular 'select' event is being requested. +// + +void +selrecord(void *selector, struct selinfo *info) +{ + // Unused by this implementation +} + +// ------------------------------------------------------------------------- +// This function is called to indicate that a 'select' event +// may have occurred. +// + +void +selwakeup(struct selinfo *info) +{ + cyg_selwakeup( info ); +} + +//========================================================================== +// Misc support functions + +int +sockargs(mp, buf, buflen, type) + struct mbuf **mp; + caddr_t buf; + socklen_t buflen; + int type; +{ + register struct sockaddr *sa; + register struct mbuf *m; + int error; + + if (buflen > MLEN) { +#ifdef COMPAT_OLDSOCK + if (type == MT_SONAME && buflen <= 112) + buflen = MLEN; /* unix domain compat. hack */ + else +#endif + return (EINVAL); + } + m = m_get(M_WAIT, type); + if (m == NULL) + return (ENOBUFS); + m->m_len = buflen; + error = copyin(buf, mtod(m, caddr_t), buflen); + if (error) { + (void) m_free(m); + return (error); + } + *mp = m; + if (type == MT_SONAME) { + sa = mtod(m, struct sockaddr *); + +#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN + if (sa->sa_family == 0 && sa->sa_len < AF_MAX) + sa->sa_family = sa->sa_len; +#endif + sa->sa_len = buflen; + } + return (0); +} + + +// ------------------------------------------------------------------------- +// bsd_recvit() +// Support for message reception. This is a lightly edited version of the +// recvit() function is uipc_syscalls.c. + +static int +bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize) +{ + struct uio auio; + register struct iovec *iov; + register int i; + size_t len; + int error; + struct mbuf *from = 0, *control = 0; + + auio.uio_iov = mp->msg_iov; + auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_READ; + auio.uio_offset = 0; /* XXX */ + auio.uio_resid = 0; + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++, iov++) { + /* Don't allow sum > SSIZE_MAX */ + if (iov->iov_len > SSIZE_MAX || + (auio.uio_resid += iov->iov_len) > SSIZE_MAX) + return (EINVAL); + } + + len = auio.uio_resid; + error = soreceive((struct socket *)fp->f_data, &from, &auio, + NULL, mp->msg_control ? &control : NULL, + &mp->msg_flags); + if (error) { + if (auio.uio_resid != len && + (error == EINTR || error == EWOULDBLOCK)) + error = 0; + } + if (error) + goto out; + *retsize = len - auio.uio_resid; + if (mp->msg_name) { + len = mp->msg_namelen; + if (len <= 0 || from == 0) + len = 0; + else { + /* save sa_len before it is destroyed by MSG_COMPAT */ + if (len > from->m_len) + len = from->m_len; + /* else if len < from->m_len ??? */ +#ifdef COMPAT_OLDSOCK + if (mp->msg_flags & MSG_COMPAT) + mtod(from, struct osockaddr *)->sa_family = + mtod(from, struct sockaddr *)->sa_family; +#endif + error = copyout(mtod(from, caddr_t), + (caddr_t)mp->msg_name, (unsigned)len); + if (error) + goto out; + } + mp->msg_namelen = len; + if (namelenp ) { + *namelenp = len; +#ifdef COMPAT_OLDSOCK + if (mp->msg_flags & MSG_COMPAT) + error = 0; /* old recvfrom didn't check */ + else +#endif + goto out; + } + } + if (mp->msg_control) { +#ifdef COMPAT_OLDSOCK + /* + * We assume that old recvmsg calls won't receive access + * rights and other control info, esp. as control info + * is always optional and those options didn't exist in 4.3. + * If we receive rights, trim the cmsghdr; anything else + * is tossed. + */ + if (control && mp->msg_flags & MSG_COMPAT) { + if (mtod(control, struct cmsghdr *)->cmsg_level != + SOL_SOCKET || + mtod(control, struct cmsghdr *)->cmsg_type != + SCM_RIGHTS) { + mp->msg_controllen = 0; + goto out; + } + control->m_len -= sizeof (struct cmsghdr); + control->m_data += sizeof (struct cmsghdr); + } +#endif + len = mp->msg_controllen; + if (len <= 0 || control == 0) + len = 0; + else { + struct mbuf *m = control; + caddr_t p = (caddr_t)mp->msg_control; + + do { + i = m->m_len; + if (len < i) { + mp->msg_flags |= MSG_CTRUNC; + i = len; + } + error = copyout(mtod(m, caddr_t), p, + (unsigned)i); + if (m->m_next) + i = ALIGN(i); + p += i; + len -= i; + if (error != 0 || len <= 0) + break; + } while ((m = m->m_next) != NULL); + len = p - (caddr_t)mp->msg_control; + } + mp->msg_controllen = len; + } +out: + if (from) + m_freem(from); + if (control) + m_freem(control); + return (error); +} + +// ------------------------------------------------------------------------- +// sendit() +// Support for message transmission. This is a lightly edited version of the +// synonymous function is uipc_syscalls.c. + +static int +bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize) +{ + struct uio auio; + register struct iovec *iov; + register int i; + struct mbuf *to, *control; + int len, error; + + auio.uio_iov = mp->msg_iov; + auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_offset = 0; /* XXX */ + auio.uio_resid = 0; + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++, iov++) { + /* Don't allow sum > SSIZE_MAX */ + if (iov->iov_len > SSIZE_MAX || + (auio.uio_resid += iov->iov_len) > SSIZE_MAX) + return (EINVAL); + } + if (mp->msg_name) { + error = sockargs(&to, mp->msg_name, mp->msg_namelen, + MT_SONAME); + if (error) + return (error); + } else + to = 0; + if (mp->msg_control) { + if (mp->msg_controllen < sizeof(struct cmsghdr) +#ifdef COMPAT_OLDSOCK + && mp->msg_flags != MSG_COMPAT +#endif + ) { + error = EINVAL; + goto bad; + } + error = sockargs(&control, mp->msg_control, + mp->msg_controllen, MT_CONTROL); + if (error) + goto bad; +#ifdef COMPAT_OLDSOCK + if (mp->msg_flags == MSG_COMPAT) { + register struct cmsghdr *cm; + + M_PREPEND(control, sizeof(*cm), M_WAIT); + if (control == 0) { + error = ENOBUFS; + goto bad; + } else { + cm = mtod(control, struct cmsghdr *); + cm->cmsg_len = control->m_len; + cm->cmsg_level = SOL_SOCKET; + cm->cmsg_type = SCM_RIGHTS; + } + } +#endif + } else + control = 0; + + len = auio.uio_resid; + error = sosend((struct socket *)fp->f_data, to, &auio, + NULL, control, flags); + if (error) { + if (auio.uio_resid != len && + (error == EINTR || error == EWOULDBLOCK)) + error = 0; +#ifndef __ECOS + if (error == EPIPE) + psignal(p, SIGPIPE); +#endif + } + if (error == 0) + *retsize = len - auio.uio_resid; +bad: + if (to) + m_freem(to); + return (error); +} + + +//========================================================================== +// End of sockio.c diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/sys_generic.c b/ecos/packages/net/tcpip/current/src/sys/kern/sys_generic.c new file mode 100644 index 0000000..bf0e9ed --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/sys_generic.c @@ -0,0 +1,1022 @@ +//========================================================================== +// +// sys/kern/sys_generic.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: sys_generic.c,v 1.22 1999/11/29 22:02:14 deraadt Exp $ */ +/* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ + +/* + * Copyright (c) 1996 Theo de Raadt + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94 + */ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#include <sys/filedesc.h> +#endif // __ECOS +#include <sys/ioctl.h> +#ifdef __ECOS +#include <cyg/io/file.h> +#else // __ECOS +#include <sys/file.h> +#include <sys/proc.h> +#include <sys/resourcevar.h> +#endif // __ECOS +#include <sys/socketvar.h> +#ifndef __ECOS +#include <sys/signalvar.h> +#include <sys/kernel.h> +#include <sys/uio.h> +#include <sys/stat.h> +#endif // __ECOS +#include <sys/malloc.h> +#ifndef __ECOS +#include <sys/poll.h> +#endif // __ECOS +#ifdef KTRACE +#include <sys/ktrace.h> +#endif + +#ifndef __ECOS +#include <sys/mount.h> +#endif // __ECOS +#include <sys/syscallargs.h> + +#ifndef __ECOS +int selscan __P((struct proc *, fd_set *, fd_set *, int, register_t *)); +int seltrue __P((dev_t, int, struct proc *)); +void pollscan __P((struct proc *, struct pollfd *, int, register_t *)); +#endif // __ECOS + +/* + * Read system call. + */ +#ifdef __ECOS +int +sys_read(struct sys_read_args *uap, register_t *retval) +#else +/* ARGSUSED */ +int +sys_read(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +#endif +{ +#ifndef __ECOS + register struct sys_read_args /* { + syscallarg(int) fd; + syscallarg(void *) buf; + syscallarg(size_t) nbyte; + } */ *uap = v; + register struct filedesc *fdp = p->p_fd; +#endif + struct file *fp; + struct uio auio; + struct iovec aiov; + long cnt, error = 0; +#ifdef KTRACE + struct iovec ktriov; +#endif + +#ifdef __ECOS + if (getfp((u_int)SCARG(uap, fd), &fp) || +#else + if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || +#endif + (fp->f_flag & FREAD) == 0) + return (EBADF); + /* Don't allow nbyte to be larger than max return val */ + if (SCARG(uap, nbyte) > SSIZE_MAX) + return(EINVAL); + aiov.iov_base = (caddr_t)SCARG(uap, buf); + aiov.iov_len = SCARG(uap, nbyte); + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_resid = SCARG(uap, nbyte); + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_USERSPACE; +#ifndef __ECOS + auio.uio_procp = p; +#endif +#ifdef KTRACE + /* + * if tracing, save a copy of iovec + */ + if (KTRPOINT(p, KTR_GENIO)) + ktriov = aiov; +#endif + cnt = SCARG(uap, nbyte); +#ifdef __ECOS + error = (*fp->f_ops->fo_read)(fp, &auio); +#else + error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred); +#endif + if (error) +#ifdef __ECOS + if (auio.uio_resid != cnt && ( +#else + if (auio.uio_resid != cnt && (error == ERESTART || +#endif + error == EINTR || error == EWOULDBLOCK)) + error = 0; + cnt -= auio.uio_resid; +#ifdef KTRACE + if (KTRPOINT(p, KTR_GENIO) && error == 0) + ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov, + cnt, error); +#endif + *retval = cnt; + return (error); +} + + +#ifndef __ECOS +/* + * Scatter read system call. + */ +int +sys_readv(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_readv_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(int) iovcnt; + } */ *uap = v; + register struct file *fp; + register struct filedesc *fdp = p->p_fd; + struct uio auio; + register struct iovec *iov; + struct iovec *needfree; + struct iovec aiov[UIO_SMALLIOV]; + long i, cnt, error = 0; + u_int iovlen; +#ifdef KTRACE + struct iovec *ktriov = NULL; +#endif + + if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || + (fp->f_flag & FREAD) == 0) + return (EBADF); + if (SCARG(uap, iovcnt) <= 0) + return (EINVAL); + /* note: can't use iovlen until iovcnt is validated */ + iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec); + if (SCARG(uap, iovcnt) > UIO_SMALLIOV) { + if (SCARG(uap, iovcnt) > IOV_MAX) + return (EINVAL); + MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); + needfree = iov; + } else { + iov = aiov; + needfree = NULL; + } + auio.uio_iov = iov; + auio.uio_iovcnt = SCARG(uap, iovcnt); + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_procp = p; + error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen); + if (error) + goto done; + auio.uio_resid = 0; + for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) { + /* Don't allow sum > SSIZE_MAX */ + if (iov->iov_len > SSIZE_MAX || + (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { + error = EINVAL; + goto done; + } + } +#ifdef KTRACE + /* + * if tracing, save a copy of iovec + */ + if (KTRPOINT(p, KTR_GENIO)) { + MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); + bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); + } +#endif + cnt = auio.uio_resid; + error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred); + if (error) + if (auio.uio_resid != cnt && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) + error = 0; + cnt -= auio.uio_resid; +#ifdef KTRACE + if (ktriov != NULL) { + if (error == 0) + ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov, + cnt, error); + FREE(ktriov, M_TEMP); + } +#endif + *retval = cnt; +done: + if (needfree) + FREE(needfree, M_IOV); + return (error); +} +#endif + +/* + * Write system call + */ +#ifdef __ECOS +int +sys_write(struct sys_write_args *uap, register_t *retval) +#else +int +sys_write(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +#endif +{ +#ifndef __ECOS + register struct sys_write_args /* { + syscallarg(int) fd; + syscallarg(void *) buf; + syscallarg(size_t) nbyte; + } */ *uap = v; + register struct filedesc *fdp = p->p_fd; +#endif + struct file *fp; + struct uio auio; + struct iovec aiov; + long cnt, error = 0; +#ifdef KTRACE + struct iovec ktriov; +#endif + +#ifdef __ECOS + if (getfp((u_int)SCARG(uap, fd), &fp) || +#else + if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || +#endif + (fp->f_flag & FWRITE) == 0) + return (EBADF); + /* Don't allow nbyte to be larger than max return val */ + if (SCARG(uap, nbyte) > SSIZE_MAX) + return(EINVAL); + aiov.iov_base = (caddr_t)SCARG(uap, buf); + aiov.iov_len = SCARG(uap, nbyte); + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_resid = SCARG(uap, nbyte); + auio.uio_rw = UIO_WRITE; + auio.uio_segflg = UIO_USERSPACE; +#ifndef __ECOS + auio.uio_procp = p; +#endif +#ifdef KTRACE + /* + * if tracing, save a copy of iovec + */ + if (KTRPOINT(p, KTR_GENIO)) + ktriov = aiov; +#endif + cnt = SCARG(uap, nbyte); +#ifdef __ECOS + error = (*fp->f_ops->fo_write)(fp, &auio); +#else + error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred); +#endif + if (error) { +#ifdef __ECOS + if (auio.uio_resid != cnt && + (error == EINTR || error == EWOULDBLOCK)) + error = 0; +#else + if (auio.uio_resid != cnt && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) + error = 0; + if (error == EPIPE) + psignal(p, SIGPIPE); +#endif + } + cnt -= auio.uio_resid; +#ifdef KTRACE + if (KTRPOINT(p, KTR_GENIO) && error == 0) + ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE, + &ktriov, cnt, error); +#endif + *retval = cnt; + return (error); +} + +#ifndef __ECOS +/* + * Gather write system call + */ +int +sys_writev(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_writev_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(int) iovcnt; + } */ *uap = v; + register struct file *fp; + register struct filedesc *fdp = p->p_fd; + struct uio auio; + register struct iovec *iov; + struct iovec *needfree; + struct iovec aiov[UIO_SMALLIOV]; + long i, cnt, error = 0; + u_int iovlen; +#ifdef KTRACE + struct iovec *ktriov = NULL; +#endif + + if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || + (fp->f_flag & FWRITE) == 0) + return (EBADF); + if (SCARG(uap, iovcnt) <= 0) + return (EINVAL); + /* note: can't use iovlen until iovcnt is validated */ + iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec); + if (SCARG(uap, iovcnt) > UIO_SMALLIOV) { + if (SCARG(uap, iovcnt) > IOV_MAX) + return (EINVAL); + MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); + needfree = iov; + } else { + iov = aiov; + needfree = NULL; + } + auio.uio_iov = iov; + auio.uio_iovcnt = SCARG(uap, iovcnt); + auio.uio_rw = UIO_WRITE; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_procp = p; + error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen); + if (error) + goto done; + auio.uio_resid = 0; + for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) { + /* Don't allow sum > SSIZE_MAX */ + if (iov->iov_len > SSIZE_MAX || + (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { + error = EINVAL; + goto done; + } + } +#ifdef KTRACE + /* + * if tracing, save a copy of iovec + */ + if (KTRPOINT(p, KTR_GENIO)) { + MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); + bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); + } +#endif + cnt = auio.uio_resid; + error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred); + if (error) { + if (auio.uio_resid != cnt && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) + error = 0; + if (error == EPIPE) + psignal(p, SIGPIPE); + } + cnt -= auio.uio_resid; +#ifdef KTRACE + if (ktriov != NULL) { + if (error == 0) + ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE, + ktriov, cnt, error); + FREE(ktriov, M_TEMP); + } +#endif + *retval = cnt; +done: + if (needfree) + FREE(needfree, M_IOV); + return (error); +} +#endif + +/* + * Ioctl system call + */ +#ifdef __ECOS +int +sys_ioctl(struct sys_ioctl_args *uap, register_t *retval) +#else +/* ARGSUSED */ +int +sys_ioctl(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +#endif +{ +#ifndef __ECOS + register struct sys_ioctl_args /* { + syscallarg(int) fd; + syscallarg(u_long) com; + syscallarg(caddr_t) data; + } */ *uap = v; + register struct filedesc *fdp; +#endif + int tmp; + struct file *fp; + register u_long com; + register int error; + register u_int size; + caddr_t data, memp; +#define STK_PARAMS 128 + char stkbuf[STK_PARAMS]; + +#ifdef __ECOS + if (getfp(SCARG(uap, fd), &fp)) +#else + fdp = p->p_fd; + if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) +#endif + return (EBADF); + + if ((fp->f_flag & (FREAD | FWRITE)) == 0) + return (EBADF); + +#ifdef __ECOS + com = SCARG(uap, com); +#else + switch (com = SCARG(uap, com)) { + case FIONCLEX: + fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE; + return (0); + case FIOCLEX: + fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE; + return (0); + } +#endif + + /* + * Interpret high order word to find amount of data to be + * copied to/from the user's address space. + */ + size = IOCPARM_LEN(com); +#ifndef __ECOS + if (size > IOCPARM_MAX) + return (ENOTTY); +#endif + memp = NULL; + if (size > sizeof (stkbuf)) { + memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); + data = memp; + } else + data = stkbuf; + if (com&IOC_IN) { + if (size) { + error = copyin(SCARG(uap, data), data, (u_int)size); + if (error) { + if (memp) + free(memp, M_IOCTLOPS); + return (error); + } + } else + *(caddr_t *)data = SCARG(uap, data); + } else if ((com&IOC_OUT) && size) + /* + * Zero the buffer so the user always + * gets back something deterministic. + */ + bzero(data, size); + else if (com&IOC_VOID) + *(caddr_t *)data = SCARG(uap, data); + + switch (com) { + + case FIONBIO: + if ((tmp = *(int *)data) != 0) + fp->f_flag |= FNONBLOCK; + else + fp->f_flag &= ~FNONBLOCK; +#ifdef __ECOS + error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (CYG_ADDRWORD)&tmp); +#else + error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); +#endif + break; + + case FIOASYNC: + if ((tmp = *(int *)data) != 0) + fp->f_flag |= FASYNC; + else + fp->f_flag &= ~FASYNC; +#ifdef __ECOS + error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (CYG_ADDRWORD)&tmp); +#else + error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); +#endif + break; + +#ifndef __ECOS + case FIOSETOWN: + tmp = *(int *)data; + if (fp->f_type == DTYPE_SOCKET) { + struct socket *so = (struct socket *)fp->f_data; + + so->so_pgid = tmp; + so->so_siguid = p->p_cred->p_ruid; + so->so_sigeuid = p->p_ucred->cr_uid; + error = 0; + break; + } + if (tmp <= 0) { + tmp = -tmp; + } else { + struct proc *p1 = pfind(tmp); + if (p1 == 0) { + error = ESRCH; + break; + } + tmp = p1->p_pgrp->pg_id; + } + error = (*fp->f_ops->fo_ioctl) + (fp, TIOCSPGRP, (caddr_t)&tmp, p); + break; + + case FIOGETOWN: + if (fp->f_type == DTYPE_SOCKET) { + error = 0; + *(int *)data = ((struct socket *)fp->f_data)->so_pgid; + break; + } + error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p); + *(int *)data = -*(int *)data; + break; +#endif + default: +#ifdef __ECOS + error = (*fp->f_ops->fo_ioctl)(fp, com, (CYG_ADDRWORD)data); +#else + error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); +#endif + /* + * Copy any data to user, size was + * already set and checked above. + */ + if (error == 0 && (com&IOC_OUT) && size) + error = copyout(data, SCARG(uap, data), (u_int)size); + break; + } + if (memp) + free(memp, M_IOCTLOPS); + return (error); +} + +#ifndef __ECOS +int selwait, nselcoll; + +/* + * Select system call. + */ +int +sys_select(p, v, retval) + register struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_select_args /* { + syscallarg(int) nd; + syscallarg(fd_set *) in; + syscallarg(fd_set *) ou; + syscallarg(fd_set *) ex; + syscallarg(struct timeval *) tv; + } */ *uap = v; + fd_set bits[6], *pibits[3], *pobits[3]; + struct timeval atv; + int s, ncoll, error = 0, timo; + u_int ni; + + if (SCARG(uap, nd) > p->p_fd->fd_nfiles) { + /* forgiving; slightly wrong */ + SCARG(uap, nd) = p->p_fd->fd_nfiles; + } + ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask); + if (SCARG(uap, nd) > FD_SETSIZE) { + caddr_t mbits; + + if ((mbits = malloc(ni * 6, M_TEMP, M_WAITOK)) == NULL) { + error = EINVAL; + goto cleanup; + } + bzero(mbits, ni * 6); + pibits[0] = (fd_set *)&mbits[ni * 0]; + pibits[1] = (fd_set *)&mbits[ni * 1]; + pibits[2] = (fd_set *)&mbits[ni * 2]; + pobits[0] = (fd_set *)&mbits[ni * 3]; + pobits[1] = (fd_set *)&mbits[ni * 4]; + pobits[2] = (fd_set *)&mbits[ni * 5]; + } else { + bzero((caddr_t)bits, sizeof(bits)); + pibits[0] = &bits[0]; + pibits[1] = &bits[1]; + pibits[2] = &bits[2]; + pobits[0] = &bits[3]; + pobits[1] = &bits[4]; + pobits[2] = &bits[5]; + } + +#define getbits(name, x) \ + if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \ + (caddr_t)pibits[x], ni))) \ + goto done; + getbits(in, 0); + getbits(ou, 1); + getbits(ex, 2); +#undef getbits + + if (SCARG(uap, tv)) { + error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv, + sizeof (atv)); + if (error) + goto done; + if (itimerfix(&atv)) { + error = EINVAL; + goto done; + } + s = splclock(); + timeradd(&atv, &time, &atv); + timo = hzto(&atv); + /* + * Avoid inadvertently sleeping forever. + */ + if (timo == 0) + timo = 1; + splx(s); + } else + timo = 0; +retry: + ncoll = nselcoll; + p->p_flag |= P_SELECT; + error = selscan(p, pibits[0], pobits[0], SCARG(uap, nd), retval); + if (error || *retval) + goto done; + s = splhigh(); + /* this should be timercmp(&time, &atv, >=) */ + if (SCARG(uap, tv) && (time.tv_sec > atv.tv_sec || + (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) { + splx(s); + goto done; + } + if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { + splx(s); + goto retry; + } + p->p_flag &= ~P_SELECT; + error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); + splx(s); + if (error == 0) + goto retry; +done: + p->p_flag &= ~P_SELECT; + /* select is not restarted after signals... */ + if (error == ERESTART) + error = EINTR; + if (error == EWOULDBLOCK) + error = 0; +#define putbits(name, x) \ + if (SCARG(uap, name) && (error2 = copyout((caddr_t)pobits[x], \ + (caddr_t)SCARG(uap, name), ni))) \ + error = error2; + if (error == 0) { + int error2; + + putbits(in, 0); + putbits(ou, 1); + putbits(ex, 2); +#undef putbits + } + +cleanup: + if (pibits[0] != &bits[0]) + free(pibits[0], M_TEMP); + return (error); +} + +int +selscan(p, ibits, obits, nfd, retval) + struct proc *p; + fd_set *ibits, *obits; + int nfd; + register_t *retval; +{ + caddr_t cibits = (caddr_t)ibits, cobits = (caddr_t)obits; + register struct filedesc *fdp = p->p_fd; + register int msk, i, j, fd; + register fd_mask bits; + struct file *fp; + int ni, n = 0; + static int flag[3] = { FREAD, FWRITE, 0 }; + + /* + * if nfd > FD_SETSIZE then the fd_set's contain nfd bits (rounded + * up to the next byte) otherwise the fd_set's are normal sized. + */ + ni = sizeof(fd_set); + if (nfd > FD_SETSIZE) + ni = howmany(nfd, NFDBITS) * sizeof(fd_mask); + + for (msk = 0; msk < 3; msk++) { + fd_set *pibits = (fd_set *)&cibits[msk*ni]; + fd_set *pobits = (fd_set *)&cobits[msk*ni]; + + for (i = 0; i < nfd; i += NFDBITS) { + bits = pibits->fds_bits[i/NFDBITS]; + while ((j = ffs(bits)) && (fd = i + --j) < nfd) { + bits &= ~(1 << j); + fp = fdp->fd_ofiles[fd]; + if (fp == NULL) + return (EBADF); + if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { + FD_SET(fd, pobits); + n++; + } + } + } + } + *retval = n; + return (0); +} + +/*ARGSUSED*/ +int +seltrue(dev, flag, p) + dev_t dev; + int flag; + struct proc *p; +{ + + return (1); +} + +/* + * Record a select request. + */ +void +selrecord(selector, sip) + struct proc *selector; + struct selinfo *sip; +{ + struct proc *p; + pid_t mypid; + + mypid = selector->p_pid; + if (sip->si_selpid == mypid) + return; + if (sip->si_selpid && (p = pfind(sip->si_selpid)) && + p->p_wchan == (caddr_t)&selwait) + sip->si_flags |= SI_COLL; + else + sip->si_selpid = mypid; +} + +/* + * Do a wakeup when a selectable event occurs. + */ +void +selwakeup(sip) + register struct selinfo *sip; +{ + register struct proc *p; + int s; + + if (sip->si_selpid == 0) + return; + if (sip->si_flags & SI_COLL) { + nselcoll++; + sip->si_flags &= ~SI_COLL; + wakeup((caddr_t)&selwait); + } + p = pfind(sip->si_selpid); + sip->si_selpid = 0; + if (p != NULL) { + s = splhigh(); + if (p->p_wchan == (caddr_t)&selwait) { + if (p->p_stat == SSLEEP) + setrunnable(p); + else + unsleep(p); + } else if (p->p_flag & P_SELECT) + p->p_flag &= ~P_SELECT; + splx(s); + } +} + +void +pollscan(p, pl, nfd, retval) + struct proc *p; + struct pollfd *pl; + int nfd; + register_t *retval; +{ + register struct filedesc *fdp = p->p_fd; + register int msk, i; + struct file *fp; + int x, n = 0; + static int flag[3] = { FREAD, FWRITE, 0 }; + static int pflag[3] = { POLLIN|POLLRDNORM, POLLOUT, POLLERR }; + + /* + * XXX: We need to implement the rest of the flags. + */ + for (i = 0; i < nfd; i++) { + /* Check the file descriptor. */ + if (pl[i].fd < 0) + continue; + if (pl[i].fd >= fdp->fd_nfiles) { + pl[i].revents = POLLNVAL; + n++; + continue; + } + + fp = fdp->fd_ofiles[pl[i].fd]; + if (fp == NULL) { + pl[i].revents = POLLNVAL; + n++; + continue; + } + for (x = msk = 0; msk < 3; msk++) { + if (pl[i].events & pflag[msk]) { + if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { + pl[i].revents |= pflag[msk] & + pl[i].events; + x++; + } + } + } + if (x) + n++; + } + *retval = n; +} + +/* + * We are using the same mechanism as select only we encode/decode args + * differently. + */ +int +sys_poll(p, v, retval) + register struct proc *p; + void *v; + register_t *retval; +{ + struct sys_poll_args *uap = v; + size_t sz; + struct pollfd pfds[4], *pl = pfds; + int msec = SCARG(uap, timeout); + struct timeval atv; + int timo, ncoll, i, s, error, error2; + extern int nselcoll, selwait; + + /* Standards say no more than MAX_OPEN; this is possibly better. */ + if (SCARG(uap, nfds) > min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, + maxfiles)) + return (EINVAL); + + sz = sizeof(struct pollfd) * SCARG(uap, nfds); + + /* optimize for the default case, of a small nfds value */ + if (sz > sizeof(pfds)) + pl = (struct pollfd *) malloc(sz, M_TEMP, M_WAITOK); + + if ((error = copyin(SCARG(uap, fds), pl, sz)) != 0) + goto bad; + + for (i = 0; i < SCARG(uap, nfds); i++) + pl[i].revents = 0; + + if (msec != -1) { + atv.tv_sec = msec / 1000; + atv.tv_usec = (msec - (atv.tv_sec * 1000)) * 1000; + + if (itimerfix(&atv)) { + error = EINVAL; + goto done; + } + s = splclock(); + timeradd(&atv, &time, &atv); + timo = hzto(&atv); + /* + * Avoid inadvertently sleeping forever. + */ + if (timo == 0) + timo = 1; + splx(s); + } else + timo = 0; + +retry: + ncoll = nselcoll; + p->p_flag |= P_SELECT; + pollscan(p, pl, SCARG(uap, nfds), retval); + if (*retval) + goto done; + s = splhigh(); + if (timo && timercmp(&time, &atv, >=)) { + splx(s); + goto done; + } + if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { + splx(s); + goto retry; + } + p->p_flag &= ~P_SELECT; + error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "poll", timo); + splx(s); + if (error == 0) + goto retry; + +done: + p->p_flag &= ~P_SELECT; + /* poll is not restarted after signals... */ + if (error == ERESTART) + error = EINTR; + if (error == EWOULDBLOCK) + error = 0; + if ((error2 = copyout(pl, SCARG(uap, fds), sz)) != 0) + error = error2; +bad: + if (pl != pfds) + free((char *) pl, M_TEMP); + return (error); +} +#endif diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/sys_socket.c b/ecos/packages/net/tcpip/current/src/sys/kern/sys_socket.c new file mode 100644 index 0000000..6c36169 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/sys_socket.c @@ -0,0 +1,279 @@ +//========================================================================== +// +// sys/kern/sys_socket.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: sys_socket.c,v 1.3 1997/08/31 20:42:23 deraadt Exp $ */ +/* $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/param.h> +#ifdef __ECOS +#include <cyg/io/file.h> +#else +#include <sys/systm.h> +#include <sys/file.h> +#include <sys/proc.h> +#endif +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/ioctl.h> +#ifndef __ECOS +#include <sys/stat.h> +#endif + +#include <net/if.h> +#include <net/route.h> + +struct fileops socketops = + { soo_read, soo_write, soo_ioctl, soo_select, soo_close }; + +#ifdef __ECOS +/* ARGSUSED */ +int +soo_read(struct file *fp, struct uio *uio) +#else +/* ARGSUSED */ +int +soo_read(fp, uio, cred) + struct file *fp; + struct uio *uio; + struct ucred *cred; +#endif +{ + + return (soreceive((struct socket *)fp->f_data, (struct mbuf **)0, + uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0)); +} + +#ifdef __ECOS +int +soo_write(struct file *fp, struct uio *uio) +#else +/* ARGSUSED */ +int +soo_write(fp, uio, cred) + struct file *fp; + struct uio *uio; + struct ucred *cred; +#endif +{ + + return (sosend((struct socket *)fp->f_data, (struct mbuf *)0, + uio, (struct mbuf *)0, (struct mbuf *)0, 0)); +} + +#ifdef __ECOS +int +soo_ioctl(struct file *fp, CYG_ADDRWORD cmd, CYG_ADDRWORD data) +#else +int +soo_ioctl(fp, cmd, data, p) + struct file *fp; + u_long cmd; + register caddr_t data; + struct proc *p; +#endif +{ + register struct socket *so = (struct socket *)fp->f_data; +#ifdef __ECOS + void *p = 0; +#endif + + switch (cmd) { + + case FIONBIO: + if (*(int *)data) + so->so_state |= SS_NBIO; + else + so->so_state &= ~SS_NBIO; + return (0); + + case FIOASYNC: + if (*(int *)data) { + so->so_state |= SS_ASYNC; + so->so_rcv.sb_flags |= SB_ASYNC; + so->so_snd.sb_flags |= SB_ASYNC; + } else { + so->so_state &= ~SS_ASYNC; + so->so_rcv.sb_flags &= ~SB_ASYNC; + so->so_snd.sb_flags &= ~SB_ASYNC; + } + return (0); + + case FIONREAD: + *(int *)data = so->so_rcv.sb_cc; + return (0); + +#ifndef __ECOS + case SIOCSPGRP: + so->so_pgid = *(int *)data; + so->so_siguid = p->p_cred->p_ruid; + so->so_sigeuid = p->p_ucred->cr_uid; + return (0); + + case SIOCGPGRP: + *(int *)data = so->so_pgid; + return (0); +#endif + + case SIOCATMARK: + *(int *)data = (so->so_state&SS_RCVATMARK) != 0; + return (0); + } + /* + * Interface/routing/protocol specific ioctls: + * interface and routing ioctls should have a + * different entry since a socket's unnecessary + */ + if (IOCGROUP(cmd) == 'i') + return (ifioctl(so, (u_long)cmd, (caddr_t)data, p)); + if (IOCGROUP(cmd) == 'r') + return (rtioctl((u_long)cmd, (caddr_t)data, p)); + return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, + (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0)); +} + +#ifdef __ECOS +int +soo_select(struct file *fp, int which) +#else +int +soo_select(fp, which, p) + struct file *fp; + int which; + struct proc *p; +#endif +{ + register struct socket *so = (struct socket *)fp->f_data; + register int s = splsoftnet(); +#ifdef __ECOS + void *p = 0; +#endif + + switch (which) { + + case FREAD: + if (soreadable(so)) { + splx(s); + return (1); + } + selrecord(p, &so->so_rcv.sb_sel); + so->so_rcv.sb_flags |= SB_SEL; + break; + + case FWRITE: + if (sowriteable(so)) { + splx(s); + return (1); + } + selrecord(p, &so->so_snd.sb_sel); + so->so_snd.sb_flags |= SB_SEL; + break; + + case 0: + if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) { + splx(s); + return (1); + } + selrecord(p, &so->so_rcv.sb_sel); + so->so_rcv.sb_flags |= SB_SEL; + break; + } + splx(s); + return (0); +} + +#ifndef __ECOS +int +soo_stat(so, ub) + register struct socket *so; + register struct stat *ub; +{ + + bzero((caddr_t)ub, sizeof (*ub)); + ub->st_mode = S_IFSOCK; + return ((*so->so_proto->pr_usrreq)(so, PRU_SENSE, + (struct mbuf *)ub, (struct mbuf *)0, + (struct mbuf *)0)); +} +#endif + +#ifdef __ECOS +int +soo_close(struct file *fp) +#else +/* ARGSUSED */ +int +soo_close(fp, p) + struct file *fp; + struct proc *p; +#endif +{ + int error = 0; + + if (fp->f_data) + error = soclose((struct socket *)fp->f_data); + fp->f_data = 0; + return (error); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/uipc_domain.c b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_domain.c new file mode 100644 index 0000000..be7c073 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_domain.c @@ -0,0 +1,308 @@ +//========================================================================== +// +// sys/kern/uipc_domain.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: uipc_domain.c,v 1.9 1999/12/08 06:50:17 itojun Exp $ */ +/* $NetBSD: uipc_domain.c,v 1.14 1996/02/09 19:00:44 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uipc_domain.c 8.2 (Berkeley) 10/18/93 + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#include <sys/domain.h> +#include <sys/mbuf.h> +#include <sys/time.h> +#include <sys/kernel.h> +#ifndef __ECOS +#include <sys/systm.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <sys/sysctl.h> +#endif + +void pffasttimo __P((void *)); +void pfslowtimo __P((void *)); +#if defined (KEY) || defined (IPSEC) +int pfkey_init __P((void)); +#endif /* KEY || IPSEC */ + +#define ADDDOMAIN(x) { \ + extern struct domain __CONCAT(x,domain); \ + __CONCAT(x,domain.dom_next) = domains; \ + domains = &__CONCAT(x,domain); \ +} + +void +domaininit() +{ + register struct domain *dp; + register struct protosw *pr; + +#undef unix + /* + * KAME NOTE: ADDDOMAIN(route) is moved to the last part so that + * it will be initialized as the *first* element. confusing! + */ +#ifndef lint +#ifndef __ECOS + ADDDOMAIN(unix); +#endif +#ifdef INET + ADDDOMAIN(inet); +#endif +#ifdef INET6 + ADDDOMAIN(inet6); +#endif /* INET6 */ +#if defined (KEY) || defined (IPSEC) + pfkey_init(); +#endif /* KEY || IPSEC */ +#ifdef IPX + ADDDOMAIN(ipx); +#endif +#ifdef NETATALK + ADDDOMAIN(atalk); +#endif +#ifdef NS + ADDDOMAIN(ns); +#endif +#ifdef ISO + ADDDOMAIN(iso); +#endif +#ifdef CCITT + ADDDOMAIN(ccitt); +#endif +#ifdef notdef /* XXXX */ +#include "imp.h" +#if NIMP > 0 + ADDDOMAIN(imp); +#endif +#endif +#ifdef IPSEC +#ifdef __KAME__ + ADDDOMAIN(key); +#endif +#endif + ADDDOMAIN(route); +#endif + + for (dp = domains; dp; dp = dp->dom_next) { + if (dp->dom_init) + (*dp->dom_init)(); + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) + if (pr->pr_init) + (*pr->pr_init)(); + } + +if (max_linkhdr < 16) /* XXX */ +max_linkhdr = 16; + max_hdr = max_linkhdr + max_protohdr; + max_datalen = MHLEN - max_hdr; + timeout(pffasttimo, NULL, 1); + timeout(pfslowtimo, NULL, 1); +} + +struct protosw * +pffindtype(family, type) + int family, type; +{ + register struct domain *dp; + register struct protosw *pr; + + for (dp = domains; dp; dp = dp->dom_next) + if (dp->dom_family == family) + goto found; + return (0); +found: + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) + if (pr->pr_type && pr->pr_type == type) + return (pr); + return (0); +} + +struct protosw * +pffindproto(family, protocol, type) + int family, protocol, type; +{ + register struct domain *dp; + register struct protosw *pr; + struct protosw *maybe = 0; + + if (family == 0) + return (0); + for (dp = domains; dp; dp = dp->dom_next) + if (dp->dom_family == family) + goto found; + return (0); +found: + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { + if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) + return (pr); + + if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && + pr->pr_protocol == 0 && maybe == (struct protosw *)0) + maybe = pr; + } + return (maybe); +} + +#ifndef __ECOS +int +net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; + struct proc *p; +{ + register struct domain *dp; + register struct protosw *pr; + int family, protocol; + + /* + * All sysctl names at this level are nonterminal. + * PF_KEY: next component is protocol family, and then at least one + * additional component. + * usually: next two components are protocol family and protocol + * number, then at least one addition component. + */ + if (namelen < 2) + return (EISDIR); /* overloaded */ + family = name[0]; + + if (family == 0) + return (0); + for (dp = domains; dp; dp = dp->dom_next) + if (dp->dom_family == family) + goto found; + return (ENOPROTOOPT); +found: + switch (family) { +#ifdef IPSEC +#ifdef __KAME__ + case PF_KEY: + pr = dp->dom_protosw; + if (pr->pr_sysctl) + return ((*pr->pr_sysctl)(name + 1, namelen - 1, + oldp, oldlenp, newp, newlen)); + return (ENOPROTOOPT); +#endif +#endif + default: + break; + } + if (namelen < 3) + return (EISDIR); /* overloaded */ + protocol = name[1]; + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) + if (pr->pr_protocol == protocol && pr->pr_sysctl) + return ((*pr->pr_sysctl)(name + 2, namelen - 2, + oldp, oldlenp, newp, newlen)); + return (ENOPROTOOPT); +} +#endif + +void +pfctlinput(cmd, sa) + int cmd; + struct sockaddr *sa; +{ + register struct domain *dp; + register struct protosw *pr; + + for (dp = domains; dp; dp = dp->dom_next) + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) + if (pr->pr_ctlinput) + (*pr->pr_ctlinput)(cmd, sa, NULL); +} + +void +pfslowtimo(arg) + void *arg; +{ + register struct domain *dp; + register struct protosw *pr; + + for (dp = domains; dp; dp = dp->dom_next) + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) + if (pr->pr_slowtimo) { + (*pr->pr_slowtimo)(); + } + timeout(pfslowtimo, NULL, hz/2); +} + +void +pffasttimo(arg) + void *arg; +{ + register struct domain *dp; + register struct protosw *pr; + + for (dp = domains; dp; dp = dp->dom_next) + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) + if (pr->pr_fasttimo) { + (*pr->pr_fasttimo)(); + } + timeout(pffasttimo, NULL, hz/5); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/uipc_mbuf.c b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_mbuf.c new file mode 100644 index 0000000..ddbc5bc --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_mbuf.c @@ -0,0 +1,1093 @@ +//========================================================================== +// +// sys/kern/uipc_mbuf.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: uipc_mbuf.c,v 1.18 1999/12/05 07:30:31 angelos Exp $ */ +/* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#include <sys/proc.h> +#endif +#include <sys/malloc.h> +#ifndef __ECOS +#include <sys/map.h> +#endif +#define MBTYPES +#include <sys/mbuf.h> +#include <sys/kernel.h> +#ifndef __ECOS +#include <sys/syslog.h> +#endif +#include <sys/domain.h> +#include <sys/protosw.h> + +#include <machine/cpu.h> + +#ifndef __ECOS +#include <vm/vm.h> +#endif + +#if defined(UVM) +#include <uvm/uvm_extern.h> +#endif + +#ifndef __ECOS +extern vm_map_t mb_map; +#endif +struct mbuf *mbutl; +char *mclrefcnt; +int needqueuedrain; + +#ifdef __ECOS +extern void setsoftnet(void); +extern void *cyg_net_cluster_alloc(void); +#endif + +/* Declarations of variables move from mbuf.h to keep g++ happy */ +#ifdef __ECOS +struct mbstat mbstat; +union mcluster *mclfree; +int max_linkhdr; /* largest link-level header */ +int max_protohdr; /* largest protocol header */ +int max_hdr; /* largest link+protocol header */ +int max_datalen; /* MHLEN - max_hdr */ +#ifdef MBTYPES +int mbtypes[] = { /* XXX */ + M_FREE, /* MT_FREE 0 should be on free list */ + M_MBUF, /* MT_DATA 1 dynamic (data) allocation */ + M_MBUF, /* MT_HEADER 2 packet header */ + M_SOCKET, /* MT_SOCKET 3 socket structure */ + M_PCB, /* MT_PCB 4 protocol control block */ + M_RTABLE, /* MT_RTABLE 5 routing tables */ + M_HTABLE, /* MT_HTABLE 6 IMP host tables */ + 0, /* MT_ATABLE 7 address resolution tables */ + M_MBUF, /* MT_SONAME 8 socket name */ + 0, /* 9 */ + M_SOOPTS, /* MT_SOOPTS 10 socket options */ + M_FTABLE, /* MT_FTABLE 11 fragment reassembly header */ + M_MBUF, /* MT_RIGHTS 12 access rights */ + M_IFADDR, /* MT_IFADDR 13 interface address */ + M_MBUF, /* MT_CONTROL 14 extra-data protocol message */ + M_MBUF, /* MT_OOBDATA 15 expedited data */ +#ifdef DATAKIT + 25, 26, 27, 28, 29, 30, 31, 32 /* datakit ugliness */ +#endif +}; +#endif +#endif // __ECOS + +void +mbinit() +{ + int s; + + s = splimp(); +#ifdef __ECOS + if (m_clalloc(1, M_DONTWAIT) == 0) +#else + if (m_clalloc(max(4096 / CLBYTES, 1), M_DONTWAIT) == 0) +#endif + goto bad; + splx(s); + return; +bad: + panic("mbinit"); +} + +/* + * Allocate some number of mbuf clusters + * and place on cluster free list. + * Must be called at splimp. + */ +/* ARGSUSED */ +int +m_clalloc(ncl, nowait) + register int ncl; + int nowait; +{ +#ifdef __ECOS + caddr_t p; + int i; + + if (ncl != 1) { + panic("Allocate multiple clusters!"); + } + p = (caddr_t)cyg_net_cluster_alloc(); + if (p == NULL) { + m_reclaim(); + return (mclfree != NULL); + } + for (i = 0; i < ncl; i++) { + ((union mcluster *)p)->mcl_next = mclfree; + mclfree = (union mcluster *)p; + p += MCLBYTES; + mbstat.m_clfree++; + } + mbstat.m_clusters += ncl; + return (1); +#else // __ECOS + volatile static struct timeval lastlogged; + struct timeval curtime, logdiff; + register caddr_t p; + register int i; + int npg, s; + + npg = ncl * CLSIZE; +#if defined(UVM) + p = (caddr_t)uvm_km_kmemalloc(mb_map, uvmexp.mb_object, ctob(npg), + nowait ? 0 : UVM_KMF_NOWAIT); +#else + p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait); +#endif + if (p == NULL) { + s = splclock(); + curtime = time; + splx(s); + timersub(&curtime, &lastlogged, &logdiff); + if (logdiff.tv_sec >= 60) { + lastlogged = curtime; + log(LOG_ERR, "mb_map full\n"); + } + m_reclaim(); + return (mclfree != NULL); + } + ncl = ncl * CLBYTES / MCLBYTES; + for (i = 0; i < ncl; i++) { + ((union mcluster *)p)->mcl_next = mclfree; + mclfree = (union mcluster *)p; + p += MCLBYTES; + mbstat.m_clfree++; + } + mbstat.m_clusters += ncl; + return (1); +#endif // __ECOS +} + +/* + * When MGET failes, ask protocols to free space when short of memory, + * then re-attempt to allocate an mbuf. + */ +struct mbuf * +m_retry(i, t) + int i, t; +{ + register struct mbuf *m; + + if (i & M_DONTWAIT) { + needqueuedrain = 1; + setsoftnet(); + return (NULL); + } + m_reclaim(); +#define m_retry(i, t) NULL + MGET(m, i, t); +#undef m_retry + return (m); +} + +/* + * As above; retry an MGETHDR. + */ +struct mbuf * +m_retryhdr(i, t) + int i, t; +{ + register struct mbuf *m; + + if (i & M_DONTWAIT) { + needqueuedrain = 1; + setsoftnet(); + return (NULL); + } + m_reclaim(); +#define m_retryhdr(i, t) NULL + MGETHDR(m, i, t); +#undef m_retryhdr + return (m); +} + +void +m_reclaim() +{ + register struct domain *dp; + register struct protosw *pr; + int s = splimp(); + + needqueuedrain = 0; + for (dp = domains; dp; dp = dp->dom_next) + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) + if (pr->pr_drain) + (*pr->pr_drain)(); + splx(s); + mbstat.m_drain++; +} + +/* + * Space allocation routines. + * These are also available as macros + * for critical paths. + */ +struct mbuf * +m_get(nowait, type) + int nowait, type; +{ + register struct mbuf *m; + + MGET(m, nowait, type); + return (m); +} + +struct mbuf * +m_gethdr(nowait, type) + int nowait, type; +{ + register struct mbuf *m; + + MGETHDR(m, nowait, type); + return (m); +} + +struct mbuf * +m_getclr(nowait, type) + int nowait, type; +{ + register struct mbuf *m; + + MGET(m, nowait, type); + if (m == NULL) + return (NULL); + bzero(mtod(m, caddr_t), MLEN); + return (m); +} + +struct mbuf * +m_free(m) + struct mbuf *m; +{ + register struct mbuf *n; + + MFREE(m, n); + return (n); +} + +void +m_freem(m) + register struct mbuf *m; +{ + register struct mbuf *n; + + if (m == NULL) + return; + do { + MFREE(m, n); + } while ((m = n) != NULL); +} + +/* + * Mbuffer utility routines. + */ + +/* + * Lesser-used path for M_PREPEND: + * allocate new mbuf to prepend to chain, + * copy junk along. + */ +struct mbuf * +m_prepend(m, len, how) + register struct mbuf *m; + int len, how; +{ + struct mbuf *mn; + + MGET(mn, how, m->m_type); + if (mn == NULL) { + m_freem(m); + return (NULL); + } + if (m->m_flags & M_PKTHDR) { + M_COPY_PKTHDR(mn, m); + m->m_flags &= ~M_PKTHDR; + } + mn->m_next = m; + m = mn; + if (len < MHLEN) + MH_ALIGN(m, len); + m->m_len = len; + return (m); +} + +/* + * Make a copy of an mbuf chain starting "off0" bytes from the beginning, + * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. + * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. + */ +int MCFail; + +struct mbuf * +m_copym(m, off0, len, wait) + register struct mbuf *m; + int off0, wait; + register int len; +{ + register struct mbuf *n, **np; + register int off = off0; + struct mbuf *top; + int copyhdr = 0; + + if (off < 0) + panic("m_copym: off %d < 0", off); + if (len < 0) + panic("m_copym: len %d < 0", len); + if (off == 0 && m->m_flags & M_PKTHDR) + copyhdr = 1; + while (off > 0) { + if (m == NULL) + panic("m_copym: null mbuf"); + if (off < m->m_len) + break; + off -= m->m_len; + m = m->m_next; + } + np = ⊤ + top = NULL; + while (len > 0) { + if (m == NULL) { + if (len != M_COPYALL) + panic("m_copym: %d not M_COPYALL", len); + break; + } + MGET(n, wait, m->m_type); + *np = n; + if (n == NULL) + goto nospace; + if (copyhdr) { + M_COPY_PKTHDR(n, m); + if (len == M_COPYALL) + n->m_pkthdr.len -= off0; + else + n->m_pkthdr.len = len; + copyhdr = 0; + } + n->m_len = min(len, m->m_len - off); + if (m->m_flags & M_EXT) { + n->m_data = m->m_data + off; + if (!m->m_ext.ext_ref) + mclrefcnt[mtocl(m->m_ext.ext_buf)]++; + else + (*(m->m_ext.ext_ref))(m); + n->m_ext = m->m_ext; + n->m_flags |= M_EXT; + } else + bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), + (unsigned)n->m_len); + if (len != M_COPYALL) + len -= n->m_len; + off = 0; + m = m->m_next; + np = &n->m_next; + } + if (top == NULL) + MCFail++; + return (top); +nospace: + m_freem(top); + MCFail++; + return (NULL); +} + +/* + * m_copym2() is like m_copym(), except it COPIES cluster mbufs, instead + * of merely bumping the reference count. + */ +struct mbuf * +m_copym2(m, off0, len, wait) + register struct mbuf *m; + int off0, wait; + register int len; +{ + register struct mbuf *n, **np; + register int off = off0; + struct mbuf *top; + int copyhdr = 0; + + if (len < 0) + panic("m_copym2: len %d < 0", len); + if (off < 0) + panic("m_copym2: off %d < 0", off); + if (off == 0 && m->m_flags & M_PKTHDR) + copyhdr = 1; + while (off > 0) { + if (m == NULL) + panic("m_copym2: null mbuf"); + if (off < m->m_len) + break; + off -= m->m_len; + m = m->m_next; + } + np = ⊤ + top = NULL; + while (len > 0) { + if (m == NULL) { + if (len != M_COPYALL) + panic("m_copym2: %d != M_COPYALL", len); + break; + } + MGET(n, wait, m->m_type); + *np = n; + if (n == NULL) + goto nospace; + if (copyhdr) { + M_COPY_PKTHDR(n, m); + if (len == M_COPYALL) + n->m_pkthdr.len -= off0; + else + n->m_pkthdr.len = len; + copyhdr = 0; + } + n->m_len = min(len, m->m_len - off); + if ((m->m_flags & M_EXT) && (n->m_len > MHLEN)) { + /* This is a cheesy hack. */ + MCLGET(n, wait); + if (n->m_flags & M_EXT) + bcopy(mtod(m, caddr_t) + off, mtod(n, caddr_t), + (unsigned)n->m_len); + else + goto nospace; + } else + bcopy(mtod(m, caddr_t) + off, mtod(n, caddr_t), + (unsigned)n->m_len); + if (len != M_COPYALL) + len -= n->m_len; + off = 0; + m = m->m_next; + np = &n->m_next; + } + if (top == NULL) + MCFail++; + return (top); +nospace: + m_freem(top); + MCFail++; + return (NULL); +} + +/* + * Copy data from an mbuf chain starting "off" bytes from the beginning, + * continuing for "len" bytes, into the indicated buffer. + */ +void +m_copydata(m, off, len, cp) + register struct mbuf *m; + register int off; + register int len; + caddr_t cp; +{ + register unsigned count; + + if (off < 0) + panic("m_copydata: off %d < 0", off); + if (len < 0) + panic("m_copydata: len %d < 0", len); + while (off > 0) { + if (m == NULL) + panic("m_copydata: null mbuf in skip"); + if (off < m->m_len) + break; + off -= m->m_len; + m = m->m_next; + } + while (len > 0) { + if (m == NULL) + panic("m_copydata: null mbuf"); + count = min(m->m_len - off, len); + bcopy(mtod(m, caddr_t) + off, cp, count); + len -= count; + cp += count; + off = 0; + m = m->m_next; + } +} + +/* + * Concatenate mbuf chain n to m. + * Both chains must be of the same type (e.g. MT_DATA). + * Any m_pkthdr is not updated. + */ +void +m_cat(m, n) + register struct mbuf *m, *n; +{ + while (m->m_next) + m = m->m_next; + while (n) { + if (m->m_flags & M_EXT || + m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { + /* just join the two chains */ + m->m_next = n; + return; + } + /* splat the data from one into the other */ + bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, + (u_int)n->m_len); + m->m_len += n->m_len; + n = m_free(n); + } +} + +void +m_adj(mp, req_len) + struct mbuf *mp; + int req_len; +{ + register int len = req_len; + register struct mbuf *m; + register int count; + + if ((m = mp) == NULL) + return; + if (len >= 0) { + /* + * Trim from head. + */ + while (m != NULL && len > 0) { + if (m->m_len <= len) { + len -= m->m_len; + m->m_len = 0; + m = m->m_next; + } else { + m->m_len -= len; + m->m_data += len; + len = 0; + } + } + m = mp; + if (mp->m_flags & M_PKTHDR) + m->m_pkthdr.len -= (req_len - len); + } else { + /* + * Trim from tail. Scan the mbuf chain, + * calculating its length and finding the last mbuf. + * If the adjustment only affects this mbuf, then just + * adjust and return. Otherwise, rescan and truncate + * after the remaining size. + */ + len = -len; + count = 0; + for (;;) { + count += m->m_len; + if (m->m_next == NULL) + break; + m = m->m_next; + } + if (m->m_len >= len) { + m->m_len -= len; + if (mp->m_flags & M_PKTHDR) + mp->m_pkthdr.len -= len; + return; + } + count -= len; + if (count < 0) + count = 0; + /* + * Correct length for chain is "count". + * Find the mbuf with last data, adjust its length, + * and toss data from remaining mbufs on chain. + */ + m = mp; + if (m->m_flags & M_PKTHDR) + m->m_pkthdr.len = count; + for (; m; m = m->m_next) { + if (m->m_len >= count) { + m->m_len = count; + break; + } + count -= m->m_len; + } + while ((m = m->m_next) != NULL) + m->m_len = 0; + } +} + +/* + * Rearange an mbuf chain so that len bytes are contiguous + * and in the data area of an mbuf (so that mtod and dtom + * will work for a structure of size len). Returns the resulting + * mbuf chain on success, frees it and returns null on failure. + * If there is room, it will add up to max_protohdr-len extra bytes to the + * contiguous region in an attempt to avoid being called next time. + */ +int MPFail; + +struct mbuf * +m_pullup(n, len) + register struct mbuf *n; + int len; +{ + register struct mbuf *m; + register int count; + int space; + + /* + * If first mbuf has no cluster, and has room for len bytes + * without shifting current data, pullup into it, + * otherwise allocate a new mbuf to prepend to the chain. + */ + if ((n->m_flags & M_EXT) == 0 && + n->m_data + len < &n->m_dat[MLEN] && n->m_next) { + if (n->m_len >= len) + return (n); + m = n; + n = n->m_next; + len -= m->m_len; + } else { + if (len > MHLEN) + goto bad; + MGET(m, M_DONTWAIT, n->m_type); + if (m == NULL) + goto bad; + m->m_len = 0; + if (n->m_flags & M_PKTHDR) { + M_COPY_PKTHDR(m, n); + n->m_flags &= ~M_PKTHDR; + } + } + space = &m->m_dat[MLEN] - (m->m_data + m->m_len); + do { + count = min(min(max(len, max_protohdr), space), n->m_len); + bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, + (unsigned)count); + len -= count; + m->m_len += count; + n->m_len -= count; + space -= count; + if (n->m_len) + n->m_data += count; + else + n = m_free(n); + } while (len > 0 && n); + if (len > 0) { + (void)m_free(m); + goto bad; + } + m->m_next = n; + return (m); +bad: + m_freem(n); + MPFail++; + return (NULL); +} + +/* + * m_pullup2() works like m_pullup, save that len can be <= MCLBYTES. + * m_pullup2() only works on values of len such that MHLEN < len <= MCLBYTES, + * it calls m_pullup() for values <= MHLEN. It also only coagulates the + * reqested number of bytes. (For those of us who expect unwieldly option + * headers. + * + * KEBE SAYS: Remember that dtom() calls with data in clusters does not work! + */ +struct mbuf * +m_pullup2(n, len) + register struct mbuf *n; + int len; +{ + register struct mbuf *m; + register int count; + int space; + if (len <= MHLEN) + return m_pullup(n, len); + + if ((n->m_flags & M_EXT) != 0 && + n->m_data + len < &n->m_data[MCLBYTES] && n->m_next) { + if (n->m_len >= len) + return (n); + m = n; + n = n->m_next; + len -= m->m_len; + } else { + if (len > MCLBYTES) + goto bad; + MGET(m, M_DONTWAIT, n->m_type); + if (m == NULL) + goto bad; + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) + goto bad; + m->m_len = 0; + if (n->m_flags & M_PKTHDR) { + /* M_COPY_PKTHDR(m, n);*//* Too many adverse side effects. */ + m->m_pkthdr = n->m_pkthdr; + m->m_flags = (n->m_flags & M_COPYFLAGS) | M_EXT; + n->m_flags &= ~M_PKTHDR; + /* n->m_data is cool. */ + } + } + + do { + count = min(len, n->m_len); + bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, + (unsigned)count); + len -= count; + m->m_len += count; + n->m_len -= count; + space -= count; + if (n->m_len) + n->m_data += count; + else + n = m_free(n); + } while (len > 0 && n); + if (len > 0) { + (void)m_free(m); + goto bad; + } + m->m_next = n; + + return (m); +bad: + m_freem(n); + MPFail++; + return (NULL); +} + +/* + * Inject a new mbuf chain of length siz in mbuf chain m0 at + * position len0. Returns a pointer to the first injected mbuf, or + * NULL on failure (m0 is left undisturbed). Note that if there is + * enough space for an object of size siz in the appropriate position, + * no memory will be allocated. Also, there will be no data movement in + * the first len0 bytes (pointers to that will remain valid). + * + * XXX It is assumed that siz is less than the size of an mbuf at the moment. + */ +struct mbuf * +m_inject(m0, len0, siz, wait) + register struct mbuf *m0; + int len0, siz, wait; +{ + register struct mbuf *m, *n, *n2 = NULL, *n3; + unsigned len = len0, remain; + + if ((siz >= MHLEN) || (len0 <= 0)) + return (NULL); + for (m = m0; m && len > m->m_len; m = m->m_next) + len -= m->m_len; + if (m == NULL) + return (NULL); + remain = m->m_len - len; + if (remain == 0) { + if ((m->m_next) && (M_LEADINGSPACE(m->m_next) >= siz)) { + m->m_next->m_len += siz; + m0->m_pkthdr.len += siz; + m->m_next->m_data -= siz; + return m->m_next; + } + } else { + n2 = m_copym2(m, len, remain, wait); + if (n2 == NULL) + return (NULL); + } + + MGET(n, wait, MT_DATA); + if (n == NULL) { + if (n2) + m_freem(n2); + return (NULL); + } + + n->m_len = siz; + m0->m_pkthdr.len += siz; + m->m_len -= remain; /* Trim */ + if (n2) { + for (n3 = n; n3->m_next != NULL; n3 = n3->m_next) + ; + n3->m_next = n2; + } else + n3 = n; + for (; n3->m_next != NULL; n3 = n3->m_next) + ; + n3->m_next = m->m_next; + m->m_next = n; + return n; +} + +/* + * Partition an mbuf chain in two pieces, returning the tail -- + * all but the first len0 bytes. In case of failure, it returns NULL and + * attempts to restore the chain to its original state. + */ +struct mbuf * +m_split(m0, len0, wait) + register struct mbuf *m0; + int len0, wait; +{ + register struct mbuf *m, *n; + unsigned len = len0, remain, olen; + + for (m = m0; m && len > m->m_len; m = m->m_next) + len -= m->m_len; + if (m == NULL) + return (NULL); + remain = m->m_len - len; + if (m0->m_flags & M_PKTHDR) { + MGETHDR(n, wait, m0->m_type); + if (n == NULL) + return (NULL); + n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; + n->m_pkthdr.len = m0->m_pkthdr.len - len0; + olen = m0->m_pkthdr.len; + m0->m_pkthdr.len = len0; + if (m->m_flags & M_EXT) + goto extpacket; + if (remain > MHLEN) { + /* m can't be the lead packet */ + MH_ALIGN(n, 0); + n->m_next = m_split(m, len, wait); + if (n->m_next == NULL) { + (void) m_free(n); + m0->m_pkthdr.len = olen; + return (NULL); + } else + return (n); + } else + MH_ALIGN(n, remain); + } else if (remain == 0) { + n = m->m_next; + m->m_next = NULL; + return (n); + } else { + MGET(n, wait, m->m_type); + if (n == NULL) + return (NULL); + M_ALIGN(n, remain); + } +extpacket: + if (m->m_flags & M_EXT) { + n->m_flags |= M_EXT; + n->m_ext = m->m_ext; + if(!m->m_ext.ext_ref) + mclrefcnt[mtocl(m->m_ext.ext_buf)]++; + else + (*(m->m_ext.ext_ref))(m); + m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */ + n->m_data = m->m_data + len; + } else { + bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); + } + n->m_len = remain; + m->m_len = len; + n->m_next = m->m_next; + m->m_next = NULL; + return (n); +} +/* + * Routine to copy from device local memory into mbufs. + */ +struct mbuf * +m_devget(buf, totlen, off0, ifp, copy) + char *buf; + int totlen, off0; + struct ifnet *ifp; + void (*copy) __P((const void *, void *, size_t)); +{ + register struct mbuf *m; + struct mbuf *top = NULL, **mp = ⊤ + register int off = off0, len; + register char *cp; + char *epkt; + + cp = buf; + epkt = cp + totlen; + if (off) { + /* + * If 'off' is non-zero, packet is trailer-encapsulated, + * so we have to skip the type and length fields. + */ + cp += off + 2 * sizeof(u_int16_t); + totlen -= 2 * sizeof(u_int16_t); + } + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) + return (NULL); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + m->m_len = MHLEN; + + while (totlen > 0) { + if (top != NULL) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == NULL) { + m_freem(top); + return (NULL); + } + m->m_len = MLEN; + } + len = min(totlen, epkt - cp); + if (len >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + m->m_len = len = min(len, MCLBYTES); + else + len = m->m_len; + } else { + /* + * Place initial small packet/header at end of mbuf. + */ + if (len < m->m_len) { + if (top == NULL && + len + max_linkhdr <= m->m_len) + m->m_data += max_linkhdr; + m->m_len = len; + } else + len = m->m_len; + } + if (copy) + copy(cp, mtod(m, caddr_t), (size_t)len); + else + bcopy(cp, mtod(m, caddr_t), (size_t)len); + cp += len; + *mp = m; + mp = &m->m_next; + totlen -= len; + if (cp == epkt) + cp = buf; + } + return (top); +} + +void +m_zero(m) + struct mbuf *m; +{ + while (m) { + if (m->m_flags & M_PKTHDR) + bzero((unsigned char *)m + sizeof(struct m_hdr) + + sizeof(struct pkthdr), MHLEN); + else + bzero((unsigned char *)m + sizeof(struct m_hdr), MLEN); + if ((m->m_flags & M_EXT) && + (m->m_ext.ext_free == NULL) && + !mclrefcnt[mtocl((m)->m_ext.ext_buf)]) + bzero(m->m_ext.ext_buf, m->m_ext.ext_size); + m = m->m_next; + } +} + +/* + * Apply function f to the data in an mbuf chain starting "off" bytes from the + * beginning, continuing for "len" bytes. + */ +int +m_apply(m, off, len, f, fstate) + struct mbuf *m; + int off; + int len; + /* fstate, data, len */ + int (*f)(caddr_t, caddr_t, unsigned int); + caddr_t fstate; +{ + int rval; + unsigned int count; + + if (len < 0) + panic("m_apply: len %d < 0", len); + if (off < 0) + panic("m_apply: off %d < 0", off); + while (off > 0) { + if (m == NULL) + panic("m_apply: null mbuf in skip"); + if (off < m->m_len) + break; + off -= m->m_len; + m = m->m_next; + } + while (len > 0) { + if (m == NULL) + panic("m_apply: null mbuf"); + count = min(m->m_len - off, len); + + rval = f(fstate, mtod(m, caddr_t) + off, count); + if (rval) + return (rval); + + len -= count; + off = 0; + m = m->m_next; + } + + return (0); +} + diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/uipc_proto.c b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_proto.c new file mode 100644 index 0000000..7439f49 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_proto.c @@ -0,0 +1,105 @@ +//========================================================================== +// +// sys/kern/uipc_proto.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: uipc_proto.c,v 1.3 1998/04/26 22:40:42 millert Exp $ */ +/* $NetBSD: uipc_proto.c,v 1.8 1996/02/13 21:10:47 christos Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uipc_proto.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#include <sys/domain.h> +#include <sys/mbuf.h> +#include <sys/un.h> +#include <sys/socketvar.h> + +#include <net/if.h> +#include <net/raw_cb.h> + +/* + * Definitions of protocols supported in the UNIX domain. + */ + +extern struct domain unixdomain; /* or at least forward */ + +struct protosw unixsw[] = { +{ SOCK_STREAM, &unixdomain, PF_LOCAL, PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS, + 0, 0, 0, 0, + uipc_usrreq, + 0, 0, 0, 0, +}, +{ SOCK_DGRAM, &unixdomain, PF_LOCAL, PR_ATOMIC|PR_ADDR|PR_RIGHTS, + 0, 0, 0, 0, + uipc_usrreq, + 0, 0, 0, 0, +}, +{ 0, 0, 0, 0, + raw_input, 0, raw_ctlinput, 0, + raw_usrreq, + raw_init, 0, 0, 0, +} +}; + +struct domain unixdomain = + { AF_LOCAL, "unix", 0, unp_externalize, unp_dispose, + unixsw, &unixsw[sizeof(unixsw)/sizeof(unixsw[0])] }; diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/uipc_socket.c b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_socket.c new file mode 100644 index 0000000..c840164 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_socket.c @@ -0,0 +1,1144 @@ +//========================================================================== +// +// sys/kern/uipc_socket.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: uipc_socket.c,v 1.27 1999/10/14 08:18:49 cmetz Exp $ */ +/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 + */ + +#include <sys/param.h> +#ifdef __ECOS +#include <cyg/io/file.h> +#else +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/file.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/domain.h> +#include <sys/kernel.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#ifndef __ECOS +#include <sys/signalvar.h> +#include <sys/resourcevar.h> +#endif + +#ifndef SOMINCONN +#define SOMINCONN 80 +#endif /* SOMINCONN */ + +int somaxconn = SOMAXCONN; +int sominconn = SOMINCONN; + +/* + * Socket operation routines. + * These routines are called by the routines in + * sys_socket.c or from a system process, and + * implement the semantics of socket operations by + * switching out to the protocol specific routines. + */ +/*ARGSUSED*/ +int +socreate(dom, aso, type, proto) + int dom; + struct socket **aso; + register int type; + int proto; +{ +#ifndef __ECOS + struct proc *p = curproc; /* XXX */ +#endif + register struct protosw *prp; + register struct socket *so; + register int error; + + if (proto) + prp = pffindproto(dom, proto, type); + else + prp = pffindtype(dom, type); + if (prp == 0 || prp->pr_usrreq == 0) + return (EPROTONOSUPPORT); + if (prp->pr_type != type) + return (EPROTOTYPE); + MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT); + bzero((caddr_t)so, sizeof(*so)); + so->so_type = type; +#ifdef __ECOS + so->so_state = SS_PRIV; + so->so_ruid = 0; // FIXME + so->so_euid = 0; // FIXME +#else + if (p->p_ucred->cr_uid == 0) + so->so_state = SS_PRIV; + so->so_ruid = p->p_cred->p_ruid; + so->so_euid = p->p_ucred->cr_uid; +#endif + so->so_proto = prp; + error = + (*prp->pr_usrreq)(so, PRU_ATTACH, NULL, (struct mbuf *)(long)proto, + NULL); + if (error) { + so->so_state |= SS_NOFDREF; + sofree(so); + return (error); + } +#ifdef COMPAT_SUNOS + { + extern struct emul emul_sunos; + if (p->p_emul == &emul_sunos && type == SOCK_DGRAM) + so->so_options |= SO_BROADCAST; + } +#endif + *aso = so; + return (0); +} + +int +sobind(so, nam) + struct socket *so; + struct mbuf *nam; +{ + int s = splsoftnet(); + int error; + + error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL); + splx(s); + return (error); +} + +int +solisten(so, backlog) + register struct socket *so; + int backlog; +{ + int s = splsoftnet(), error; + + error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, NULL, NULL); + if (error) { + splx(s); + return (error); + } + if (so->so_q == 0) + so->so_options |= SO_ACCEPTCONN; + if (backlog < 0 || backlog > somaxconn) + backlog = somaxconn; + if (backlog < sominconn) + backlog = sominconn; + so->so_qlimit = backlog; + splx(s); + return (0); +} + +void +sofree(so) + register struct socket *so; +{ + + if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) + return; + if (so->so_head) { + /* + * We must not decommission a socket that's on the accept(2) + * queue. If we do, then accept(2) may hang after select(2) + * indicated that the listening socket was ready. + */ + if (!soqremque(so, 0)) + return; + } + sbrelease(&so->so_snd); + sorflush(so); + FREE(so, M_SOCKET); +} + +/* + * Close a socket on last file table reference removal. + * Initiate disconnect if connected. + * Free socket when disconnect complete. + */ +int +soclose(so) + register struct socket *so; +{ + struct socket *so2; + int s = splsoftnet(); /* conservative */ + int error = 0; + + if (so->so_options & SO_ACCEPTCONN) { + while ((so2 = so->so_q0) != NULL) { + (void) soqremque(so2, 0); + (void) soabort(so2); + } + while ((so2 = so->so_q) != NULL) { + (void) soqremque(so2, 1); + (void) soabort(so2); + } + } + if (so->so_pcb == 0) + goto discard; + if (so->so_state & SS_ISCONNECTED) { + if ((so->so_state & SS_ISDISCONNECTING) == 0) { + error = sodisconnect(so); + if (error) + goto drop; + } + if (so->so_options & SO_LINGER) { + if ((so->so_state & SS_ISDISCONNECTING) && + (so->so_state & SS_NBIO)) + goto drop; + while (so->so_state & SS_ISCONNECTED) { + error = tsleep((caddr_t)&so->so_timeo, + PSOCK | PCATCH, netcls, + so->so_linger * hz); + if (error) + break; + } + } + } +drop: + if (so->so_pcb) { + int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, NULL, + NULL, NULL); + if (error == 0) + error = error2; + } +discard: + if (so->so_state & SS_NOFDREF) + panic("soclose: NOFDREF"); + so->so_state |= SS_NOFDREF; + sofree(so); + splx(s); + return (error); +} + +/* + * Must be called at splsoftnet... + */ +int +soabort(so) + struct socket *so; +{ + + return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, NULL, NULL, NULL); +} + +int +soaccept(so, nam) + register struct socket *so; + struct mbuf *nam; +{ + int s = splsoftnet(); + int error = 0; + + if ((so->so_state & SS_NOFDREF) == 0) + panic("soaccept: !NOFDREF"); + so->so_state &= ~SS_NOFDREF; + if ((so->so_state & SS_ISDISCONNECTED) == 0) + error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, NULL, + nam, NULL); + splx(s); + return (error); +} + +int +soconnect(so, nam) + register struct socket *so; + struct mbuf *nam; +{ + int s; + int error; + + if (so->so_options & SO_ACCEPTCONN) + return (EOPNOTSUPP); + s = splsoftnet(); + /* + * If protocol is connection-based, can only connect once. + * Otherwise, if connected, try to disconnect first. + * This allows user to disconnect by connecting to, e.g., + * a null address. + */ + if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && + ((so->so_proto->pr_flags & PR_CONNREQUIRED) || + (error = sodisconnect(so)))) + error = EISCONN; + else + error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, + NULL, nam, NULL); + splx(s); + return (error); +} + +int +soconnect2(so1, so2) + register struct socket *so1; + struct socket *so2; +{ + int s = splsoftnet(); + int error; + + error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, NULL, + (struct mbuf *)so2, NULL); + splx(s); + return (error); +} + +int +sodisconnect(so) + register struct socket *so; +{ + int s = splsoftnet(); + int error; + + if ((so->so_state & SS_ISCONNECTED) == 0) { + error = ENOTCONN; + goto bad; + } + if (so->so_state & SS_ISDISCONNECTING) { + error = EALREADY; + goto bad; + } + error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, NULL, NULL, + NULL); +bad: + splx(s); + return (error); +} + +#define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK) +/* + * Send on a socket. + * If send must go all at once and message is larger than + * send buffering, then hard error. + * Lock against other senders. + * If must go all at once and not enough room now, then + * inform user that this would block and do nothing. + * Otherwise, if nonblocking, send as much as possible. + * The data to be sent is described by "uio" if nonzero, + * otherwise by the mbuf chain "top" (which must be null + * if uio is not). Data provided in mbuf chain must be small + * enough to send all at once. + * + * Returns nonzero on error, timeout or signal; callers + * must check for short counts if EINTR/ERESTART are returned. + * Data and control buffers are freed on return. + */ +int +sosend(so, addr, uio, top, control, flags) + register struct socket *so; + struct mbuf *addr; + struct uio *uio; + struct mbuf *top; + struct mbuf *control; + int flags; +{ +#ifndef __ECOS + struct proc *p = curproc; /* XXX */ +#endif + struct mbuf **mp; + register struct mbuf *m; + register long space, len; + register quad_t resid; + int clen = 0, error, s, dontroute, mlen; + int atomic = sosendallatonce(so) || top; + + if (uio) + resid = uio->uio_resid; + else + resid = top->m_pkthdr.len; + /* + * In theory resid should be unsigned (since uio->uio_resid is). + * However, space must be signed, as it might be less than 0 + * if we over-committed, and we must use a signed comparison + * of space and resid. On the other hand, a negative resid + * causes us to loop sending 0-length segments to the protocol. + * MSG_EOR on a SOCK_STREAM socket is also invalid. + */ + if (resid < 0 || + (so->so_type == SOCK_STREAM && (flags & MSG_EOR))) { + error = EINVAL; + goto out; + } + dontroute = + (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && + (so->so_proto->pr_flags & PR_ATOMIC); +#ifndef __ECOS + p->p_stats->p_ru.ru_msgsnd++; +#endif + if (control) + clen = control->m_len; +#define snderr(errno) { error = errno; splx(s); goto release; } + +restart: + if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) + goto out; + do { + s = splsoftnet(); + if (so->so_state & SS_CANTSENDMORE) + snderr(EPIPE); + if (so->so_error) + snderr(so->so_error); + if ((so->so_state & SS_ISCONNECTED) == 0) { + if (so->so_proto->pr_flags & PR_CONNREQUIRED) { + if ((so->so_state & SS_ISCONFIRMING) == 0 && + !(resid == 0 && clen != 0)) + snderr(ENOTCONN); + } else if (addr == 0) + snderr(EDESTADDRREQ); + } + space = sbspace(&so->so_snd); + if (flags & MSG_OOB) + space += 1024; + if ((atomic && resid > so->so_snd.sb_hiwat) || + clen > so->so_snd.sb_hiwat) + snderr(EMSGSIZE); + if (space < resid + clen && uio && + (atomic || space < so->so_snd.sb_lowat || space < clen)) { + if (so->so_state & SS_NBIO) + snderr(EWOULDBLOCK); + sbunlock(&so->so_snd); + error = sbwait(&so->so_snd); + splx(s); + if (error) + goto out; + goto restart; + } + splx(s); + mp = ⊤ + space -= clen; + do { + if (uio == NULL) { + /* + * Data is prepackaged in "top". + */ + resid = 0; + if (flags & MSG_EOR) + top->m_flags |= M_EOR; + } else do { + if (top == 0) { + MGETHDR(m, M_WAIT, MT_DATA); + mlen = MHLEN; + m->m_pkthdr.len = 0; + m->m_pkthdr.rcvif = (struct ifnet *)0; + } else { + MGET(m, M_WAIT, MT_DATA); + mlen = MLEN; + } + if (resid >= MINCLSIZE && space >= MCLBYTES) { + MCLGET(m, M_WAIT); + if ((m->m_flags & M_EXT) == 0) + goto nopages; + mlen = MCLBYTES; +#ifdef MAPPED_MBUFS + len = min(MCLBYTES, resid); +#else + if (atomic && top == 0) { + len = min(MCLBYTES - max_hdr, resid); + m->m_data += max_hdr; + } else + len = min(MCLBYTES, resid); +#endif + space -= len; + } else { +nopages: + len = min(min(mlen, resid), space); + space -= len; + /* + * For datagram protocols, leave room + * for protocol headers in first mbuf. + */ + if (atomic && top == 0 && len < mlen) + MH_ALIGN(m, len); + } + error = uiomove(mtod(m, caddr_t), (int)len, uio); + resid = uio->uio_resid; + m->m_len = len; + *mp = m; + top->m_pkthdr.len += len; + if (error) + goto release; + mp = &m->m_next; + if (resid <= 0) { + if (flags & MSG_EOR) + top->m_flags |= M_EOR; + break; + } + } while (space > 0 && atomic); + if (dontroute) + so->so_options |= SO_DONTROUTE; + s = splsoftnet(); /* XXX */ + error = (*so->so_proto->pr_usrreq)(so, (flags & MSG_OOB) ? + PRU_SENDOOB : PRU_SEND, + top, addr, control); + splx(s); + if (dontroute) + so->so_options &= ~SO_DONTROUTE; + clen = 0; + control = 0; + top = 0; + mp = ⊤ + if (error) + goto release; + } while (resid && space > 0); + } while (resid); + +release: + sbunlock(&so->so_snd); +out: + if (top) + m_freem(top); + if (control) + m_freem(control); + return (error); +} + +/* + * Implement receive operations on a socket. + * We depend on the way that records are added to the sockbuf + * by sbappend*. In particular, each record (mbufs linked through m_next) + * must begin with an address if the protocol so specifies, + * followed by an optional mbuf or mbufs containing ancillary data, + * and then zero or more mbufs of data. + * In order to avoid blocking network interrupts for the entire time here, + * we splx() while doing the actual copy to user space. + * Although the sockbuf is locked, new data may still be appended, + * and thus we must maintain consistency of the sockbuf during that time. + * + * The caller may receive the data as a single mbuf chain by supplying + * an mbuf **mp0 for use in returning the chain. The uio is then used + * only for the count in uio_resid. + */ +int +soreceive(so, paddr, uio, mp0, controlp, flagsp) + register struct socket *so; + struct mbuf **paddr; + struct uio *uio; + struct mbuf **mp0; + struct mbuf **controlp; + int *flagsp; +{ + register struct mbuf *m, **mp; + register int flags, len, error, s, offset; + struct protosw *pr = so->so_proto; + struct mbuf *nextrecord; + int moff, type = 0; + size_t orig_resid = uio->uio_resid; + int uio_error = 0; + int resid; + + mp = mp0; + if (paddr) + *paddr = 0; + if (controlp) + *controlp = 0; + if (flagsp) + flags = *flagsp &~ MSG_EOR; + else + flags = 0; + if (so->so_state & SS_NBIO) + flags |= MSG_DONTWAIT; + if (flags & MSG_OOB) { + m = m_get(M_WAIT, MT_DATA); + error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m, + (struct mbuf *)(long)(flags & MSG_PEEK), NULL); + if (error) + goto bad; + do { + error = uiomove(mtod(m, caddr_t), + (int) min(uio->uio_resid, m->m_len), uio); + m = m_free(m); + } while (uio->uio_resid && error == 0 && m); +bad: + if (m) + m_freem(m); + return (error); + } + if (mp) + *mp = (struct mbuf *)0; + if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) + (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL); + +restart: + if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) + return (error); + s = splsoftnet(); + + m = so->so_rcv.sb_mb; + /* + * If we have less data than requested, block awaiting more + * (subject to any timeout) if: + * 1. the current count is less than the low water mark, + * 2. MSG_WAITALL is set, and it is possible to do the entire + * receive operation at once if we block (resid <= hiwat), or + * 3. MSG_DONTWAIT is not set. + * If MSG_WAITALL is set but resid is larger than the receive buffer, + * we have to do the receive in sections, and thus risk returning + * a short count if a timeout or signal occurs after we start. + */ + if (m == 0 || (((flags & MSG_DONTWAIT) == 0 && + so->so_rcv.sb_cc < uio->uio_resid) && + (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || + ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) && + m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) { +#ifdef DIAGNOSTIC + if (m == 0 && so->so_rcv.sb_cc) + panic("receive 1"); +#endif + if (so->so_error) { + if (m) + goto dontblock; + error = so->so_error; + if ((flags & MSG_PEEK) == 0) + so->so_error = 0; + goto release; + } + if (so->so_state & SS_CANTRCVMORE) { + if (m) + goto dontblock; + else + goto release; + } + for (; m; m = m->m_next) + if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { + m = so->so_rcv.sb_mb; + goto dontblock; + } + if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && + (so->so_proto->pr_flags & PR_CONNREQUIRED)) { + error = ENOTCONN; + goto release; + } + if (uio->uio_resid == 0 && controlp == NULL) + goto release; + if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) { + error = EWOULDBLOCK; + goto release; + } + sbunlock(&so->so_rcv); + error = sbwait(&so->so_rcv); + splx(s); + if (error) + return (error); + goto restart; + } +dontblock: +#ifdef notyet /* XXXX */ + if (uio->uio_procp) + uio->uio_procp->p_stats->p_ru.ru_msgrcv++; +#endif + nextrecord = m->m_nextpkt; + if (pr->pr_flags & PR_ADDR) { +#ifdef DIAGNOSTIC + if (m->m_type != MT_SONAME) + panic("receive 1a"); +#endif + orig_resid = 0; + if (flags & MSG_PEEK) { + if (paddr) + *paddr = m_copy(m, 0, m->m_len); + m = m->m_next; + } else { + sbfree(&so->so_rcv, m); + if (paddr) { + *paddr = m; + so->so_rcv.sb_mb = m->m_next; + m->m_next = 0; + m = so->so_rcv.sb_mb; + } else { + MFREE(m, so->so_rcv.sb_mb); + m = so->so_rcv.sb_mb; + } + } + } + while (m && m->m_type == MT_CONTROL && error == 0) { + if (flags & MSG_PEEK) { + if (controlp) + *controlp = m_copy(m, 0, m->m_len); + m = m->m_next; + } else { + sbfree(&so->so_rcv, m); + if (controlp) { + if (pr->pr_domain->dom_externalize && + mtod(m, struct cmsghdr *)->cmsg_type == + SCM_RIGHTS) + error = (*pr->pr_domain->dom_externalize)(m); + *controlp = m; + so->so_rcv.sb_mb = m->m_next; + m->m_next = 0; + m = so->so_rcv.sb_mb; + } else { + MFREE(m, so->so_rcv.sb_mb); + m = so->so_rcv.sb_mb; + } + } + if (controlp) { + orig_resid = 0; + controlp = &(*controlp)->m_next; + } + } + if (m) { + if ((flags & MSG_PEEK) == 0) + m->m_nextpkt = nextrecord; + type = m->m_type; + if (type == MT_OOBDATA) + flags |= MSG_OOB; + if (m->m_flags & M_BCAST) + flags |= MSG_BCAST; + if (m->m_flags & M_MCAST) + flags |= MSG_MCAST; + } + moff = 0; + offset = 0; + while (m && uio->uio_resid > 0 && error == 0) { + if (m->m_type == MT_OOBDATA) { + if (type != MT_OOBDATA) + break; + } else if (type == MT_OOBDATA) + break; +#ifdef DIAGNOSTIC + else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) + panic("receive 3"); +#endif + so->so_state &= ~SS_RCVATMARK; + len = uio->uio_resid; + if (so->so_oobmark && len > so->so_oobmark - offset) + len = so->so_oobmark - offset; + if (len > m->m_len - moff) + len = m->m_len - moff; + /* + * If mp is set, just pass back the mbufs. + * Otherwise copy them out via the uio, then free. + * Sockbuf must be consistent here (points to current mbuf, + * it points to next record) when we drop priority; + * we must note any additions to the sockbuf when we + * block interrupts again. + */ + if (mp == 0 && uio_error == 0) { + resid = uio->uio_resid; + splx(s); + uio_error = + uiomove(mtod(m, caddr_t) + moff, (int)len, + uio); + s = splsoftnet(); + if (uio_error) + uio->uio_resid = resid - len; + } else + uio->uio_resid -= len; + if (len == m->m_len - moff) { + if (m->m_flags & M_EOR) + flags |= MSG_EOR; + if (flags & MSG_PEEK) { + m = m->m_next; + moff = 0; + } else { + nextrecord = m->m_nextpkt; + sbfree(&so->so_rcv, m); + if (mp) { + *mp = m; + mp = &m->m_next; + so->so_rcv.sb_mb = m = m->m_next; + *mp = (struct mbuf *)0; + } else { + MFREE(m, so->so_rcv.sb_mb); + m = so->so_rcv.sb_mb; + } + if (m) + m->m_nextpkt = nextrecord; + } + } else { + if (flags & MSG_PEEK) + moff += len; + else { + if (mp) + *mp = m_copym(m, 0, len, M_WAIT); + m->m_data += len; + m->m_len -= len; + so->so_rcv.sb_cc -= len; + } + } + if (so->so_oobmark) { + if ((flags & MSG_PEEK) == 0) { + so->so_oobmark -= len; + if (so->so_oobmark == 0) { + so->so_state |= SS_RCVATMARK; + break; + } + } else { + offset += len; + if (offset == so->so_oobmark) + break; + } + } + if (flags & MSG_EOR) + break; + /* + * If the MSG_WAITALL flag is set (for non-atomic socket), + * we must not quit until "uio->uio_resid == 0" or an error + * termination. If a signal/timeout occurs, return + * with a short count but without error. + * Keep sockbuf locked against other readers. + */ + while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 && + !sosendallatonce(so) && !nextrecord) { + if (so->so_error || so->so_state & SS_CANTRCVMORE) + break; + error = sbwait(&so->so_rcv); + if (error) { + sbunlock(&so->so_rcv); + splx(s); + return (0); + } + if ((m = so->so_rcv.sb_mb) != NULL) + nextrecord = m->m_nextpkt; + } + } + + if (m && pr->pr_flags & PR_ATOMIC) { + flags |= MSG_TRUNC; + if ((flags & MSG_PEEK) == 0) + (void) sbdroprecord(&so->so_rcv); + } + if ((flags & MSG_PEEK) == 0) { + if (m == 0) + so->so_rcv.sb_mb = nextrecord; + if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) + (*pr->pr_usrreq)(so, PRU_RCVD, NULL, + (struct mbuf *)(long)flags, NULL); + } + if (orig_resid == uio->uio_resid && orig_resid && + (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { + sbunlock(&so->so_rcv); + splx(s); + goto restart; + } + + if (uio_error) + error = uio_error; + + if (flagsp) + *flagsp |= flags; +release: + sbunlock(&so->so_rcv); + splx(s); + return (error); +} + +int +soshutdown(so, how) + register struct socket *so; + register int how; +{ + register struct protosw *pr = so->so_proto; + + how++; + if (how & ~(FREAD|FWRITE)) + return (EINVAL); + if (how & FREAD) + sorflush(so); + if (how & FWRITE) + return (*pr->pr_usrreq)(so, PRU_SHUTDOWN, NULL, NULL, NULL); + return (0); +} + +void +sorflush(so) + register struct socket *so; +{ + register struct sockbuf *sb = &so->so_rcv; + register struct protosw *pr = so->so_proto; + register int s; + struct sockbuf asb; + + sb->sb_flags |= SB_NOINTR; + (void) sblock(sb, M_WAITOK); + s = splimp(); + socantrcvmore(so); + sbunlock(sb); + asb = *sb; + bzero((caddr_t)sb, sizeof (*sb)); + splx(s); + if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) + (*pr->pr_domain->dom_dispose)(asb.sb_mb); + sbrelease(&asb); +} + +int +sosetopt(so, level, optname, m0) + register struct socket *so; + int level, optname; + struct mbuf *m0; +{ + int error = 0; + register struct mbuf *m = m0; + + if (level != SOL_SOCKET) { + if (so->so_proto && so->so_proto->pr_ctloutput) + return ((*so->so_proto->pr_ctloutput) + (PRCO_SETOPT, so, level, optname, &m0)); + error = ENOPROTOOPT; + } else { + switch (optname) { + + case SO_LINGER: + if (m == NULL || m->m_len != sizeof (struct linger)) { + error = EINVAL; + goto bad; + } + so->so_linger = mtod(m, struct linger *)->l_linger; + /* fall thru... */ + + case SO_DEBUG: + case SO_KEEPALIVE: + case SO_DONTROUTE: + case SO_USELOOPBACK: + case SO_BROADCAST: + case SO_REUSEADDR: + case SO_REUSEPORT: + case SO_OOBINLINE: + if (m == NULL || m->m_len < sizeof (int)) { + error = EINVAL; + goto bad; + } + if (*mtod(m, int *)) + so->so_options |= optname; + else + so->so_options &= ~optname; + break; + + case SO_SNDBUF: + case SO_RCVBUF: + case SO_SNDLOWAT: + case SO_RCVLOWAT: + { + u_long cnt; + + if (m == NULL || m->m_len < sizeof (int)) { + error = EINVAL; + goto bad; + } + cnt = *mtod(m, int *); + if ((long)cnt <= 0) + cnt = 1; + switch (optname) { + + case SO_SNDBUF: + case SO_RCVBUF: + if (sbreserve(optname == SO_SNDBUF ? + &so->so_snd : &so->so_rcv, + cnt) == 0) { + error = ENOBUFS; + goto bad; + } + break; + + case SO_SNDLOWAT: + so->so_snd.sb_lowat = (cnt > so->so_snd.sb_hiwat) ? + so->so_snd.sb_hiwat : cnt; + break; + case SO_RCVLOWAT: + so->so_rcv.sb_lowat = (cnt > so->so_rcv.sb_hiwat) ? + so->so_rcv.sb_hiwat : cnt; + break; + } + break; + } + + case SO_SNDTIMEO: + case SO_RCVTIMEO: + { + struct timeval *tv; + short val; + + if (m == NULL || m->m_len < sizeof (*tv)) { + error = EINVAL; + goto bad; + } + tv = mtod(m, struct timeval *); + if (tv->tv_sec * hz + tv->tv_usec / tick > SHRT_MAX) { + error = EDOM; + goto bad; + } + val = tv->tv_sec * hz + tv->tv_usec / tick; + + switch (optname) { + + case SO_SNDTIMEO: + so->so_snd.sb_timeo = val; + break; + case SO_RCVTIMEO: + so->so_rcv.sb_timeo = val; + break; + } + break; + } + + default: + error = ENOPROTOOPT; + break; + } + if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) { + (void) ((*so->so_proto->pr_ctloutput) + (PRCO_SETOPT, so, level, optname, &m0)); + m = NULL; /* freed by protocol */ + } + } +bad: + if (m) + (void) m_free(m); + return (error); +} + +int +sogetopt(so, level, optname, mp) + register struct socket *so; + int level, optname; + struct mbuf **mp; +{ + register struct mbuf *m; + + if (level != SOL_SOCKET) { + if (so->so_proto && so->so_proto->pr_ctloutput) { + return ((*so->so_proto->pr_ctloutput) + (PRCO_GETOPT, so, level, optname, mp)); + } else + return (ENOPROTOOPT); + } else { + m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = sizeof (int); + + switch (optname) { + + case SO_LINGER: + m->m_len = sizeof (struct linger); + mtod(m, struct linger *)->l_onoff = + so->so_options & SO_LINGER; + mtod(m, struct linger *)->l_linger = so->so_linger; + break; + + case SO_USELOOPBACK: + case SO_DONTROUTE: + case SO_DEBUG: + case SO_KEEPALIVE: + case SO_REUSEADDR: + case SO_REUSEPORT: + case SO_BROADCAST: + case SO_OOBINLINE: + *mtod(m, int *) = so->so_options & optname; + break; + + case SO_TYPE: + *mtod(m, int *) = so->so_type; + break; + + case SO_ERROR: + *mtod(m, int *) = so->so_error; + so->so_error = 0; + break; + + case SO_SNDBUF: + *mtod(m, int *) = so->so_snd.sb_hiwat; + break; + + case SO_RCVBUF: + *mtod(m, int *) = so->so_rcv.sb_hiwat; + break; + + case SO_SNDLOWAT: + *mtod(m, int *) = so->so_snd.sb_lowat; + break; + + case SO_RCVLOWAT: + *mtod(m, int *) = so->so_rcv.sb_lowat; + break; + + case SO_SNDTIMEO: + case SO_RCVTIMEO: + { + int val = (optname == SO_SNDTIMEO ? + so->so_snd.sb_timeo : so->so_rcv.sb_timeo); + + m->m_len = sizeof(struct timeval); + mtod(m, struct timeval *)->tv_sec = val / hz; + mtod(m, struct timeval *)->tv_usec = + (val % hz) * tick; + break; + } + + default: + (void)m_free(m); + return (ENOPROTOOPT); + } + *mp = m; + return (0); + } +} + +void +sohasoutofband(so) + register struct socket *so; +{ +#ifndef __ECOS + csignal(so->so_pgid, SIGURG, so->so_siguid, so->so_sigeuid); +#endif + selwakeup(&so->so_rcv.sb_sel); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/uipc_socket2.c b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_socket2.c new file mode 100644 index 0000000..04a3674 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_socket2.c @@ -0,0 +1,906 @@ +//========================================================================== +// +// sys/kern/uipc_socket2.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: uipc_socket2.c,v 1.11 1999/12/08 06:50:17 itojun Exp $ */ +/* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/file.h> +#include <sys/buf.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#ifndef __ECOS +#include <sys/signalvar.h> +#endif + +#ifdef __ECOS +#include <cyg/infra/diag.h> +#endif + +/* + * Primitive routines for operating on sockets and socket buffers + */ + +/* strings for sleep message: */ +char netio[] = "netio"; +char netcon[] = "netcon"; +char netcls[] = "netcls"; + +u_long sb_max = SB_MAX; /* patchable */ + +/* + * Procedures to manipulate state flags of socket + * and do appropriate wakeups. Normal sequence from the + * active (originating) side is that soisconnecting() is + * called during processing of connect() call, + * resulting in an eventual call to soisconnected() if/when the + * connection is established. When the connection is torn down + * soisdisconnecting() is called during processing of disconnect() call, + * and soisdisconnected() is called when the connection to the peer + * is totally severed. The semantics of these routines are such that + * connectionless protocols can call soisconnected() and soisdisconnected() + * only, bypassing the in-progress calls when setting up a ``connection'' + * takes no time. + * + * From the passive side, a socket is created with + * two queues of sockets: so_q0 for connections in progress + * and so_q for connections already made and awaiting user acceptance. + * As a protocol is preparing incoming connections, it creates a socket + * structure queued on so_q0 by calling sonewconn(). When the connection + * is established, soisconnected() is called, and transfers the + * socket structure to so_q, making it available to accept(). + * + * If a socket is closed with sockets on either + * so_q0 or so_q, these sockets are dropped. + * + * If higher level protocols are implemented in + * the kernel, the wakeups done here will sometimes + * cause software-interrupt process scheduling. + */ + +void +soisconnecting(so) + register struct socket *so; +{ + + so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); + so->so_state |= SS_ISCONNECTING; +} + +void +soisconnected(so) + register struct socket *so; +{ + register struct socket *head = so->so_head; + + so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); + so->so_state |= SS_ISCONNECTED; + if (head && soqremque(so, 0)) { + soqinsque(head, so, 1); + sorwakeup(head); + wakeup((caddr_t)&head->so_timeo); + } else { + wakeup((caddr_t)&so->so_timeo); + sorwakeup(so); + sowwakeup(so); + } +} + +void +soisdisconnecting(so) + register struct socket *so; +{ + + so->so_state &= ~SS_ISCONNECTING; + so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); + wakeup((caddr_t)&so->so_timeo); + sowwakeup(so); + sorwakeup(so); +} + +void +soisdisconnected(so) + register struct socket *so; +{ + + so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); + so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED); + wakeup((caddr_t)&so->so_timeo); + sowwakeup(so); + sorwakeup(so); +} + +/* + * When an attempt at a new connection is noted on a socket + * which accepts connections, sonewconn is called. If the + * connection is possible (subject to space constraints, etc.) + * then we allocate a new structure, propoerly linked into the + * data structure of the original socket, and return this. + * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED. + * + * Currently, sonewconn() is defined as sonewconn1() in socketvar.h + * to catch calls that are missing the (new) second parameter. + */ +struct socket * +sonewconn1(head, connstatus) + register struct socket *head; + int connstatus; +{ + register struct socket *so; + int soqueue = connstatus ? 1 : 0; + + if (head->so_qlen + head->so_q0len > head->so_qlimit * 3) + return ((struct socket *)0); + MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT); + if (so == NULL) + return ((struct socket *)0); + bzero((caddr_t)so, sizeof(*so)); + so->so_type = head->so_type; + so->so_options = head->so_options &~ SO_ACCEPTCONN; + so->so_linger = head->so_linger; + so->so_state = head->so_state | SS_NOFDREF; + so->so_proto = head->so_proto; + so->so_timeo = head->so_timeo; + so->so_pgid = head->so_pgid; + so->so_euid = head->so_euid; + so->so_ruid = head->so_ruid; + (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); + soqinsque(head, so, soqueue); + if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, + (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { + (void) soqremque(so, soqueue); + (void) free((caddr_t)so, M_SOCKET); + return ((struct socket *)0); + } + if (connstatus) { + sorwakeup(head); + wakeup((caddr_t)&head->so_timeo); + so->so_state |= connstatus; + } + return (so); +} + +void +soqinsque(head, so, q) + register struct socket *head, *so; + int q; +{ + + register struct socket **prev; + so->so_head = head; + if (q == 0) { + head->so_q0len++; + so->so_q0 = 0; + for (prev = &(head->so_q0); *prev; ) + prev = &((*prev)->so_q0); + } else { + head->so_qlen++; + so->so_q = 0; + for (prev = &(head->so_q); *prev; ) + prev = &((*prev)->so_q); + } + *prev = so; +} + +int +soqremque(so, q) + register struct socket *so; + int q; +{ + register struct socket *head, *prev, *next; + + head = so->so_head; + prev = head; + for (;;) { + next = q ? prev->so_q : prev->so_q0; + if (next == so) + break; + if (next == 0) + return (0); + prev = next; + } + if (q == 0) { + prev->so_q0 = next->so_q0; + head->so_q0len--; + } else { + prev->so_q = next->so_q; + head->so_qlen--; + } + next->so_q0 = next->so_q = 0; + next->so_head = 0; + return (1); +} + +/* + * Socantsendmore indicates that no more data will be sent on the + * socket; it would normally be applied to a socket when the user + * informs the system that no more data is to be sent, by the protocol + * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data + * will be received, and will normally be applied to the socket by a + * protocol when it detects that the peer will send no more data. + * Data queued for reading in the socket may yet be read. + */ + +void +socantsendmore(so) + struct socket *so; +{ + + so->so_state |= SS_CANTSENDMORE; + sowwakeup(so); +} + +void +socantrcvmore(so) + struct socket *so; +{ + + so->so_state |= SS_CANTRCVMORE; + sorwakeup(so); +} + +/* + * Wait for data to arrive at/drain from a socket buffer. + */ +int +sbwait(sb) + struct sockbuf *sb; +{ + + sb->sb_flags |= SB_WAIT; + return (tsleep((caddr_t)&sb->sb_cc, + (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, netio, + sb->sb_timeo)); +} + +/* + * Lock a sockbuf already known to be locked; + * return any error returned from sleep (EINTR). + */ +int +sb_lock(sb) + register struct sockbuf *sb; +{ + int error; + + while (sb->sb_flags & SB_LOCK) { + sb->sb_flags |= SB_WANT; + error = tsleep((caddr_t)&sb->sb_flags, + (sb->sb_flags & SB_NOINTR) ? + PSOCK : PSOCK|PCATCH, netio, 0); + if (error) + return (error); + } + sb->sb_flags |= SB_LOCK; + return (0); +} + +#ifdef __ECOS +/* + * Set lock on sockbuf sb; sleep if lock is already held. + * Unless SB_NOINTR is set on sockbuf, sleep is interruptible. + * Returns error without lock if sleep is interrupted. + */ +int +sblock(struct sockbuf *sb, int wf) +{ + int res; + cyg_scheduler_safe_lock(); + if (sb->sb_flags & SB_LOCK) { + // Already locked by another thread + if (wf == M_WAITOK) { + res = sb_lock(sb); + // Note: scheduler unlocked by 'sb_lock()' + } else { + res = EWOULDBLOCK; + cyg_scheduler_unlock(); + } + } else { + sb->sb_flags |= SB_LOCK; + res = 0; + cyg_scheduler_unlock(); + } + return res; +} + +/* release lock on sockbuf sb */ +void +sbunlock(struct sockbuf *sb) +{ + cyg_scheduler_lock(); + sb->sb_flags &= ~SB_LOCK; + if (sb->sb_flags & SB_WANT) { + sb->sb_flags &= ~SB_WANT; + wakeup((caddr_t)&sb->sb_flags); + } + cyg_scheduler_unlock(); +} +#endif + +/* + * Wakeup processes waiting on a socket buffer. + * Do asynchronous notification via SIGIO + * if the socket has the SS_ASYNC flag set. + */ +void +sowakeup(so, sb) + register struct socket *so; + register struct sockbuf *sb; +{ + selwakeup(&sb->sb_sel); + sb->sb_flags &= ~SB_SEL; + if (sb->sb_flags & SB_WAIT) { + sb->sb_flags &= ~SB_WAIT; + wakeup((caddr_t)&sb->sb_cc); + } +#ifndef __ECOS + if (so->so_state & SS_ASYNC) + csignal(so->so_pgid, SIGIO, so->so_siguid, so->so_sigeuid); +#endif +} + +/* + * Socket buffer (struct sockbuf) utility routines. + * + * Each socket contains two socket buffers: one for sending data and + * one for receiving data. Each buffer contains a queue of mbufs, + * information about the number of mbufs and amount of data in the + * queue, and other fields allowing select() statements and notification + * on data availability to be implemented. + * + * Data stored in a socket buffer is maintained as a list of records. + * Each record is a list of mbufs chained together with the m_next + * field. Records are chained together with the m_nextpkt field. The upper + * level routine soreceive() expects the following conventions to be + * observed when placing information in the receive buffer: + * + * 1. If the protocol requires each message be preceded by the sender's + * name, then a record containing that name must be present before + * any associated data (mbuf's must be of type MT_SONAME). + * 2. If the protocol supports the exchange of ``access rights'' (really + * just additional data associated with the message), and there are + * ``rights'' to be received, then a record containing this data + * should be present (mbuf's must be of type MT_CONTROL). + * 3. If a name or rights record exists, then it must be followed by + * a data record, perhaps of zero length. + * + * Before using a new socket structure it is first necessary to reserve + * buffer space to the socket, by calling sbreserve(). This should commit + * some of the available buffer space in the system buffer pool for the + * socket (currently, it does nothing but enforce limits). The space + * should be released by calling sbrelease() when the socket is destroyed. + */ + +int +soreserve(so, sndcc, rcvcc) + register struct socket *so; + u_long sndcc, rcvcc; +{ + + if (sbreserve(&so->so_snd, sndcc) == 0) + goto bad; + if (sbreserve(&so->so_rcv, rcvcc) == 0) + goto bad2; + if (so->so_rcv.sb_lowat == 0) + so->so_rcv.sb_lowat = 1; + if (so->so_snd.sb_lowat == 0) + so->so_snd.sb_lowat = MCLBYTES; + if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) + so->so_snd.sb_lowat = so->so_snd.sb_hiwat; + return (0); +bad2: + sbrelease(&so->so_snd); +bad: + return (ENOBUFS); +} + +/* + * Allot mbufs to a sockbuf. + * Attempt to scale mbmax so that mbcnt doesn't become limiting + * if buffering efficiency is near the normal case. + */ +int +sbreserve(sb, cc) + struct sockbuf *sb; + u_long cc; +{ + + if (cc == 0 || cc > sb_max * MCLBYTES / (MSIZE + MCLBYTES)) + return (0); + sb->sb_hiwat = cc; + sb->sb_mbmax = min(cc * 2, sb_max); + if (sb->sb_lowat > sb->sb_hiwat) + sb->sb_lowat = sb->sb_hiwat; + return (1); +} + +/* + * Free mbufs held by a socket, and reserved mbuf space. + */ +void +sbrelease(sb) + struct sockbuf *sb; +{ + + sbflush(sb); + sb->sb_hiwat = sb->sb_mbmax = 0; +} + +/* + * Routines to add and remove + * data from an mbuf queue. + * + * The routines sbappend() or sbappendrecord() are normally called to + * append new mbufs to a socket buffer, after checking that adequate + * space is available, comparing the function sbspace() with the amount + * of data to be added. sbappendrecord() differs from sbappend() in + * that data supplied is treated as the beginning of a new record. + * To place a sender's address, optional access rights, and data in a + * socket receive buffer, sbappendaddr() should be used. To place + * access rights and data in a socket receive buffer, sbappendrights() + * should be used. In either case, the new data begins a new record. + * Note that unlike sbappend() and sbappendrecord(), these routines check + * for the caller that there will be enough space to store the data. + * Each fails if there is not enough space, or if it cannot find mbufs + * to store additional information in. + * + * Reliable protocols may use the socket send buffer to hold data + * awaiting acknowledgement. Data is normally copied from a socket + * send buffer in a protocol with m_copy for output to a peer, + * and then removing the data from the socket buffer with sbdrop() + * or sbdroprecord() when the data is acknowledged by the peer. + */ + +/* + * Append mbuf chain m to the last record in the + * socket buffer sb. The additional space associated + * the mbuf chain is recorded in sb. Empty mbufs are + * discarded and mbufs are compacted where possible. + */ +void +sbappend(sb, m) + struct sockbuf *sb; + struct mbuf *m; +{ + register struct mbuf *n; + + if (m == 0) + return; + if ((n = sb->sb_mb) != NULL) { + while (n->m_nextpkt) + n = n->m_nextpkt; + do { + if (n->m_flags & M_EOR) { + sbappendrecord(sb, m); /* XXXXXX!!!! */ + return; + } + } while (n->m_next && (n = n->m_next)); + } + sbcompress(sb, m, n); +} + +#ifdef SOCKBUF_DEBUG +void +sbcheck(sb) + register struct sockbuf *sb; +{ + register struct mbuf *m; + register int len = 0, mbcnt = 0; + + for (m = sb->sb_mb; m; m = m->m_next) { + len += m->m_len; + mbcnt += MSIZE; + if (m->m_flags & M_EXT) + mbcnt += m->m_ext.ext_size; + if (m->m_nextpkt) + panic("sbcheck nextpkt"); + } + if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) { + printf("cc %d != %d || mbcnt %d != %d\n", len, sb->sb_cc, + mbcnt, sb->sb_mbcnt); + panic("sbcheck"); + } +} +#endif + +/* + * As above, except the mbuf chain + * begins a new record. + */ +void +sbappendrecord(sb, m0) + register struct sockbuf *sb; + register struct mbuf *m0; +{ + register struct mbuf *m; + + if (m0 == 0) + return; + if ((m = sb->sb_mb) != NULL) + while (m->m_nextpkt) + m = m->m_nextpkt; + /* + * Put the first mbuf on the queue. + * Note this permits zero length records. + */ + sballoc(sb, m0); + if (m) + m->m_nextpkt = m0; + else + sb->sb_mb = m0; + m = m0->m_next; + m0->m_next = 0; + if (m && (m0->m_flags & M_EOR)) { + m0->m_flags &= ~M_EOR; + m->m_flags |= M_EOR; + } + sbcompress(sb, m, m0); +} + +/* + * As above except that OOB data + * is inserted at the beginning of the sockbuf, + * but after any other OOB data. + */ +void +sbinsertoob(sb, m0) + register struct sockbuf *sb; + register struct mbuf *m0; +{ + register struct mbuf *m; + register struct mbuf **mp; + + if (m0 == 0) + return; + for (mp = &sb->sb_mb; (m = *mp) != NULL; mp = &((*mp)->m_nextpkt)) { + again: + switch (m->m_type) { + + case MT_OOBDATA: + continue; /* WANT next train */ + + case MT_CONTROL: + if ((m = m->m_next) != NULL) + goto again; /* inspect THIS train further */ + } + break; + } + /* + * Put the first mbuf on the queue. + * Note this permits zero length records. + */ + sballoc(sb, m0); + m0->m_nextpkt = *mp; + *mp = m0; + m = m0->m_next; + m0->m_next = 0; + if (m && (m0->m_flags & M_EOR)) { + m0->m_flags &= ~M_EOR; + m->m_flags |= M_EOR; + } + sbcompress(sb, m, m0); +} + +/* + * Append address and data, and optionally, control (ancillary) data + * to the receive queue of a socket. If present, + * m0 must include a packet header with total length. + * Returns 0 if no space in sockbuf or insufficient mbufs. + */ +int +sbappendaddr(sb, asa, m0, control) + register struct sockbuf *sb; + struct sockaddr *asa; + struct mbuf *m0, *control; +{ + register struct mbuf *m, *n; + int space = asa->sa_len; + +if (m0 && (m0->m_flags & M_PKTHDR) == 0) +panic("sbappendaddr"); + if (m0) + space += m0->m_pkthdr.len; + for (n = control; n; n = n->m_next) { + space += n->m_len; + if (n->m_next == 0) /* keep pointer to last control buf */ + break; + } + if (space > sbspace(sb)) + return (0); + if (asa->sa_len > MLEN) + return (0); + MGET(m, M_DONTWAIT, MT_SONAME); + if (m == 0) + return (0); + m->m_len = asa->sa_len; + bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len); + if (n) + n->m_next = m0; /* concatenate data to control */ + else + control = m0; + m->m_next = control; + for (n = m; n; n = n->m_next) + sballoc(sb, n); + if ((n = sb->sb_mb) != NULL) { + while (n->m_nextpkt) + n = n->m_nextpkt; + n->m_nextpkt = m; + } else + sb->sb_mb = m; + return (1); +} + +int +sbappendcontrol(sb, m0, control) + struct sockbuf *sb; + struct mbuf *m0, *control; +{ + register struct mbuf *m, *n; + int space = 0; + + if (control == 0) + panic("sbappendcontrol"); + for (m = control; ; m = m->m_next) { + space += m->m_len; + if (m->m_next == 0) + break; + } + n = m; /* save pointer to last control buffer */ + for (m = m0; m; m = m->m_next) + space += m->m_len; + if (space > sbspace(sb)) + return (0); + n->m_next = m0; /* concatenate data to control */ + for (m = control; m; m = m->m_next) + sballoc(sb, m); + if ((n = sb->sb_mb) != NULL) { + while (n->m_nextpkt) + n = n->m_nextpkt; + n->m_nextpkt = control; + } else + sb->sb_mb = control; + return (1); +} + +/* + * Compress mbuf chain m into the socket + * buffer sb following mbuf n. If n + * is null, the buffer is presumed empty. + */ +void +sbcompress(sb, m, n) + register struct sockbuf *sb; + register struct mbuf *m, *n; +{ + register int eor = 0; + register struct mbuf *o; + + while (m) { + eor |= m->m_flags & M_EOR; + if (m->m_len == 0 && + (eor == 0 || + (((o = m->m_next) || (o = n)) && + o->m_type == m->m_type))) { + m = m_free(m); + continue; + } + if (n && (n->m_flags & (M_EXT | M_EOR)) == 0 && + (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] && + n->m_type == m->m_type) { + bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, + (unsigned)m->m_len); + n->m_len += m->m_len; + sb->sb_cc += m->m_len; + m = m_free(m); + continue; + } + if (n) + n->m_next = m; + else + sb->sb_mb = m; + sballoc(sb, m); + n = m; + m->m_flags &= ~M_EOR; + m = m->m_next; + n->m_next = 0; + } + if (eor) { + if (n) + n->m_flags |= eor; + else +#ifdef __ECOS + diag_printf("semi-panic: sbcompress\n"); +#else + printf("semi-panic: sbcompress\n"); +#endif + } +} + +/* + * Free all mbufs in a sockbuf. + * Check that all resources are reclaimed. + */ +void +sbflush(sb) + register struct sockbuf *sb; +{ + + if (sb->sb_flags & SB_LOCK) + panic("sbflush"); + while (sb->sb_mbcnt) + sbdrop(sb, (int)sb->sb_cc); + if (sb->sb_cc || sb->sb_mb) + panic("sbflush 2"); +} + +/* + * Drop data from (the front of) a sockbuf. + */ +void +sbdrop(sb, len) + register struct sockbuf *sb; + register int len; +{ + register struct mbuf *m, *mn; + struct mbuf *next; + + next = (m = sb->sb_mb) ? m->m_nextpkt : 0; + while (len > 0) { + if (m == 0) { + if (next == 0) + panic("sbdrop"); + m = next; + next = m->m_nextpkt; + continue; + } + if (m->m_len > len) { + m->m_len -= len; + m->m_data += len; + sb->sb_cc -= len; + break; + } + len -= m->m_len; + sbfree(sb, m); + MFREE(m, mn); + m = mn; + } + while (m && m->m_len == 0) { + sbfree(sb, m); + MFREE(m, mn); + m = mn; + } + if (m) { + sb->sb_mb = m; + m->m_nextpkt = next; + } else + sb->sb_mb = next; +} + +/* + * Drop a record off the front of a sockbuf + * and move the next record to the front. + */ +void +sbdroprecord(sb) + register struct sockbuf *sb; +{ + register struct mbuf *m, *mn; + + m = sb->sb_mb; + if (m) { + sb->sb_mb = m->m_nextpkt; + do { + sbfree(sb, m); + MFREE(m, mn); + } while ((m = mn) != NULL); + } +} + +/* + * Create a "control" mbuf containing the specified data + * with the specified type for presentation on a socket buffer. + */ +struct mbuf * +sbcreatecontrol(p, size, type, level) + caddr_t p; + register int size; + int type, level; +{ + register struct cmsghdr *cp; + struct mbuf *m; + + if (size + sizeof(*cp) > MCLBYTES) { +#ifdef __ECOS + diag_printf("sbcreatecontrol: message too large %d\n", size); +#else + printf("sbcreatecontrol: message too large %d\n", size); +#endif + return NULL; + } + + if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL) + return ((struct mbuf *) NULL); + if (size + sizeof(*cp) > MLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_free(m); + return NULL; + } + } + cp = mtod(m, struct cmsghdr *); + bcopy(p, CMSG_DATA(cp), size); + size += sizeof(*cp); + m->m_len = size; + cp->cmsg_len = size; + cp->cmsg_level = level; + cp->cmsg_type = type; + return (m); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/kern/uipc_syscalls.c b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_syscalls.c new file mode 100644 index 0000000..d09b422 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/kern/uipc_syscalls.c @@ -0,0 +1,1269 @@ +//========================================================================== +// +// sys/kern/uipc_syscalls.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: uipc_syscalls.c,v 1.29 1999/12/08 06:50:17 itojun Exp $ */ +/* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 + */ + +#include <sys/param.h> +#ifdef __ECOS +#include <cyg/io/file.h> +static int ecos_getsock(int fdes, struct file **fpp); +#define getsock(fdp, fdes, fpp) ecos_getsock(fdes, fpp) +#else +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/filedesc.h> +#include <sys/file.h> +#include <sys/buf.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#ifndef __ECOS +#include <sys/signalvar.h> +#include <sys/un.h> +#endif +#ifdef KTRACE +#include <sys/ktrace.h> +#endif + +#ifndef __ECOS +#include <sys/mount.h> +#endif +#include <sys/syscallargs.h> + +/* + * System call interface to the socket abstraction. + */ +extern struct fileops socketops; + +#ifdef __ECOS +int +sys_socket(struct sys_socket_args *uap, register_t *retval) +{ +#else +int +sys_socket(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_socket_args /* { + syscallarg(int) domain; + syscallarg(int) type; + syscallarg(int) protocol; + } */ *uap = v; + struct filedesc *fdp = p->p_fd; +#endif // __ECOS + struct socket *so; + struct file *fp; + int fd, error; + +#ifdef __ECOS + if ((error = falloc(&fp, &fd)) != 0) +#else + if ((error = falloc(p, &fp, &fd)) != 0) +#endif + return (error); + fp->f_flag = FREAD|FWRITE; + fp->f_type = DTYPE_SOCKET; + fp->f_ops = &socketops; + error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), + SCARG(uap, protocol)); + if (error) { +#ifndef __ECOS + fdremove(fdp, fd); +#endif + ffree(fp); + } else { +#ifdef __ECOS + fp->f_data = (CYG_ADDRWORD)so; +#else + fp->f_data = (caddr_t)so; +#endif + *retval = fd; + } + return (error); +} + +#ifdef __ECOS +int +sys_bind(struct sys_bind_args *uap, register_t *retval) + { +#else +/* ARGSUSED */ +int +sys_bind(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_bind_args /* { + syscallarg(int) s; + syscallarg(struct sockaddr *) name; + syscallarg(socklen_t) namelen; + } */ *uap = v; +#endif // __ECOS + struct file *fp; + struct mbuf *nam; + int error; + + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + return (error); + error = sockargs(&nam, (caddr_t)SCARG(uap, name), SCARG(uap, namelen), + MT_SONAME); + if (error) + return (error); + error = sobind((struct socket *)fp->f_data, nam); + m_freem(nam); + return (error); +} + +/* ARGSUSED */ +#ifdef __ECOS +int +sys_listen(struct sys_listen_args *uap, register_t *retval) +{ +#else +int +sys_listen(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_listen_args /* { + syscallarg(int) s; + syscallarg(int) backlog; + } */ *uap = v; +#endif // __ECOS + struct file *fp; + int error; + + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + return (error); + return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog))); +} + +#ifdef __ECOS +int + sys_accept(struct sys_accept_args *uap, register_t *retval) +{ +#else +int +sys_accept(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_accept_args /* { + syscallarg(int) s; + syscallarg(struct sockaddr *) name; + syscallarg(socklen_t *) anamelen; + } */ *uap = v; +#endif + struct file *fp; + struct mbuf *nam; + socklen_t namelen; + int error, s, tmpfd; + register struct socket *so; + + if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen), + (caddr_t)&namelen, sizeof (namelen)))) + return (error); + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + return (error); + s = splsoftnet(); + so = (struct socket *)fp->f_data; + if ((so->so_options & SO_ACCEPTCONN) == 0) { + splx(s); + return (EINVAL); + } + if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { + splx(s); + return (EWOULDBLOCK); + } + while (so->so_qlen == 0 && so->so_error == 0) { + if (so->so_state & SS_CANTRCVMORE) { + so->so_error = ECONNABORTED; + break; + } + error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, + netcon, 0); + if (error) { + splx(s); + return (error); + } + } + if (so->so_error) { + error = so->so_error; + so->so_error = 0; + splx(s); + return (error); + } +#ifdef __ECOS + if ((error = falloc(&fp, &tmpfd)) != 0) { +#else + if ((error = falloc(p, &fp, &tmpfd)) != 0) { +#endif + splx(s); + return (error); + } + *retval = tmpfd; + { struct socket *aso = so->so_q; + if (soqremque(aso, 1) == 0) + panic("accept"); + so = aso; + } + fp->f_type = DTYPE_SOCKET; + fp->f_flag = FREAD|FWRITE; + fp->f_ops = &socketops; +#ifdef __ECOS + fp->f_data = (CYG_ADDRWORD)so; +#else + fp->f_data = (caddr_t)so; +#endif + nam = m_get(M_WAIT, MT_SONAME); + (void) soaccept(so, nam); + if (SCARG(uap, name)) { + if (namelen > nam->m_len) + namelen = nam->m_len; + /* SHOULD COPY OUT A CHAIN HERE */ + if ((error = copyout(mtod(nam, caddr_t), + (caddr_t)SCARG(uap, name), namelen)) == 0) + error = copyout((caddr_t)&namelen, + (caddr_t)SCARG(uap, anamelen), + sizeof (*SCARG(uap, anamelen))); + } + m_freem(nam); + splx(s); + return (error); +} + +#ifdef __ECOS +int +sys_connect(struct sys_connect_args *uap, register_t *retval) +{ +#else +/* ARGSUSED */ +int +sys_connect(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_connect_args /* { + syscallarg(int) s; + syscallarg(struct sockaddr *) name; + syscallarg(socklen_t) namelen; + } */ *uap = v; +#endif // __ECOS + struct file *fp; + register struct socket *so; + struct mbuf *nam; + int error, s; + + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + return (error); + so = (struct socket *)fp->f_data; + if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) + return (EALREADY); + error = sockargs(&nam, (caddr_t)SCARG(uap, name), SCARG(uap, namelen), + MT_SONAME); + if (error) + return (error); + error = soconnect(so, nam); + if (error) + goto bad; + if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { + m_freem(nam); + return (EINPROGRESS); + } + s = splsoftnet(); + while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { + error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, + netcon, 0); + if (error) + break; + } + if (error == 0) { + error = so->so_error; + so->so_error = 0; + } + splx(s); +bad: + so->so_state &= ~SS_ISCONNECTING; + m_freem(nam); +#ifndef __ECOS + if (error == ERESTART) + error = EINTR; +#endif + return (error); +} + +#ifndef __ECOS +int +sys_socketpair(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_socketpair_args /* { + syscallarg(int) domain; + syscallarg(int) type; + syscallarg(int) protocol; + syscallarg(int *) rsv; + } */ *uap = v; + register struct filedesc *fdp = p->p_fd; + struct file *fp1, *fp2; + struct socket *so1, *so2; + int fd, error, sv[2]; + + error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), + SCARG(uap, protocol)); + if (error) + return (error); + error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), + SCARG(uap, protocol)); + if (error) + goto free1; + if ((error = falloc(p, &fp1, &fd)) != 0) + goto free2; + sv[0] = fd; + fp1->f_flag = FREAD|FWRITE; + fp1->f_type = DTYPE_SOCKET; + fp1->f_ops = &socketops; + fp1->f_data = (caddr_t)so1; + if ((error = falloc(p, &fp2, &fd)) != 0) + goto free3; + fp2->f_flag = FREAD|FWRITE; + fp2->f_type = DTYPE_SOCKET; + fp2->f_ops = &socketops; + fp2->f_data = (caddr_t)so2; + sv[1] = fd; + if ((error = soconnect2(so1, so2)) != 0) + goto free4; + if (SCARG(uap, type) == SOCK_DGRAM) { + /* + * Datagram socket connection is asymmetric. + */ + if ((error = soconnect2(so2, so1)) != 0) + goto free4; + } + error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv), + 2 * sizeof (int)); + if (error == 0) + return (error); +free4: + ffree(fp2); + fdremove(fdp, sv[1]); +free3: + ffree(fp1); + fdremove(fdp, sv[0]); +free2: + (void)soclose(so2); +free1: + (void)soclose(so1); + return (error); +} +#endif + +#ifdef __ECOS +int +sys_sendto(struct sys_sendto_args *uap, register_t *retval) +{ +#else +int +sys_sendto(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_sendto_args /* { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(struct sockaddr *) to; + syscallarg(socklen_t) tolen; + } */ *uap = v; +#endif // __ECOS + struct msghdr msg; + struct iovec aiov; + + msg.msg_name = (caddr_t)SCARG(uap, to); + msg.msg_namelen = SCARG(uap, tolen); + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; + msg.msg_control = 0; +#ifdef COMPAT_OLDSOCK + msg.msg_flags = 0; +#endif + aiov.iov_base = (char *)SCARG(uap, buf); + aiov.iov_len = SCARG(uap, len); +#ifdef __ECOS + return (sendit(SCARG(uap, s), &msg, SCARG(uap, flags), retval)); +#else + return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); +#endif +} + +#ifndef __ECOS +int +sys_sendmsg(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_sendmsg_args /* { + syscallarg(int) s; + syscallarg(caddr_t) msg; + syscallarg(int) flags; + } */ *uap = v; + struct msghdr msg; + struct iovec aiov[UIO_SMALLIOV], *iov; + int error; + + error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof (msg)); + if (error) + return (error); + if (msg.msg_iovlen <= 0 || msg.msg_iovlen > IOV_MAX) + return (EMSGSIZE); + if (msg.msg_iovlen > UIO_SMALLIOV) + MALLOC(iov, struct iovec *, + sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK); + else + iov = aiov; + if (msg.msg_iovlen && + (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, + (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) + goto done; + msg.msg_iov = iov; +#ifdef COMPAT_OLDSOCK + msg.msg_flags = 0; +#endif + error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); +done: + if (iov != aiov) + FREE(iov, M_IOV); + return (error); +} +#endif + +#ifdef __ECOS +int +sendit(int s, struct msghdr *mp, int flags, register_t *retsize) +{ +#else +int +sendit(p, s, mp, flags, retsize) + register struct proc *p; + int s; + register struct msghdr *mp; + int flags; + register_t *retsize; +{ +#endif // __ECOS + struct file *fp; + struct uio auio; + register struct iovec *iov; + register int i; + struct mbuf *to, *control; + int len, error; +#ifdef KTRACE + struct iovec *ktriov = NULL; +#endif + + if ((error = getsock(p->p_fd, s, &fp)) != 0) + return (error); + auio.uio_iov = mp->msg_iov; + auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_WRITE; +#ifndef __ECOS + auio.uio_procp = p; +#endif + auio.uio_offset = 0; /* XXX */ + auio.uio_resid = 0; + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++, iov++) { + /* Don't allow sum > SSIZE_MAX */ + if (iov->iov_len > SSIZE_MAX || + (auio.uio_resid += iov->iov_len) > SSIZE_MAX) + return (EINVAL); + } + if (mp->msg_name) { + error = sockargs(&to, mp->msg_name, mp->msg_namelen, + MT_SONAME); + if (error) + return (error); + } else + to = 0; + if (mp->msg_control) { + if (mp->msg_controllen < sizeof(struct cmsghdr) +#ifdef COMPAT_OLDSOCK + && mp->msg_flags != MSG_COMPAT +#endif + ) { + error = EINVAL; + goto bad; + } + error = sockargs(&control, mp->msg_control, + mp->msg_controllen, MT_CONTROL); + if (error) + goto bad; +#ifdef COMPAT_OLDSOCK + if (mp->msg_flags == MSG_COMPAT) { + register struct cmsghdr *cm; + + M_PREPEND(control, sizeof(*cm), M_WAIT); + if (control == 0) { + error = ENOBUFS; + goto bad; + } else { + cm = mtod(control, struct cmsghdr *); + cm->cmsg_len = control->m_len; + cm->cmsg_level = SOL_SOCKET; + cm->cmsg_type = SCM_RIGHTS; + } + } +#endif + } else + control = 0; +#ifdef KTRACE + if (KTRPOINT(p, KTR_GENIO)) { + int iovlen = auio.uio_iovcnt * sizeof (struct iovec); + + MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); + bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); + } +#endif + len = auio.uio_resid; + error = sosend((struct socket *)fp->f_data, to, &auio, + NULL, control, flags); + if (error) { +#ifdef __ECOS + if (auio.uio_resid != len && + (error == EINTR || error == EWOULDBLOCK)) +#else + if (auio.uio_resid != len && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) +#endif + error = 0; +#ifndef __ECOS + if (error == EPIPE) + psignal(p, SIGPIPE); +#endif + } + if (error == 0) + *retsize = len - auio.uio_resid; +#ifdef KTRACE + if (ktriov != NULL) { + if (error == 0) + ktrgenio(p->p_tracep, s, UIO_WRITE, + ktriov, *retsize, error); + FREE(ktriov, M_TEMP); + } +#endif +bad: + if (to) + m_freem(to); + return (error); +} + +#ifdef __ECOS +int +sys_recvfrom(struct sys_recvfrom_args *uap, register_t *retval) +{ +#else +int +sys_recvfrom(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_recvfrom_args /* { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(struct sockaddr *) from; + syscallarg(socklen_t *) fromlenaddr; + } */ *uap = v; +#endif // __ECOS + struct msghdr msg; + struct iovec aiov; + int error; + + if (SCARG(uap, fromlenaddr)) { + error = copyin((caddr_t)SCARG(uap, fromlenaddr), + (caddr_t)&msg.msg_namelen, + sizeof (msg.msg_namelen)); + if (error) + return (error); + } else + msg.msg_namelen = 0; + msg.msg_name = (caddr_t)SCARG(uap, from); + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, len); + msg.msg_control = 0; + msg.msg_flags = SCARG(uap, flags); +#ifdef __ECOS + return (recvit(SCARG(uap, s), &msg, + (caddr_t)SCARG(uap, fromlenaddr), retval)); +#else + return (recvit(p, SCARG(uap, s), &msg, + (caddr_t)SCARG(uap, fromlenaddr), retval)); +#endif +} + +#ifndef __ECOS +int +sys_recvmsg(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_recvmsg_args /* { + syscallarg(int) s; + syscallarg(struct msghdr *) msg; + syscallarg(int) flags; + } */ *uap = v; + struct msghdr msg; + struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; + register int error; + + error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg, + sizeof (msg)); + if (error) + return (error); + if (msg.msg_iovlen <= 0 || msg.msg_iovlen > IOV_MAX) + return (EMSGSIZE); + if (msg.msg_iovlen > UIO_SMALLIOV) + MALLOC(iov, struct iovec *, + sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK); + else + iov = aiov; +#ifdef COMPAT_OLDSOCK + msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT; +#else + msg.msg_flags = SCARG(uap, flags); +#endif + uiov = msg.msg_iov; + msg.msg_iov = iov; + error = copyin((caddr_t)uiov, (caddr_t)iov, + (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); + if (error) + goto done; + if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) { + msg.msg_iov = uiov; + error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg), + sizeof(msg)); + } +done: + if (iov != aiov) + FREE(iov, M_IOV); + return (error); +} +#endif + +#ifdef __ECOS +int +recvit(int s, struct msghdr *mp, caddr_t namelenp, register_t *retsize) +{ +#else +int +recvit(p, s, mp, namelenp, retsize) + register struct proc *p; + int s; + register struct msghdr *mp; + caddr_t namelenp; + register_t *retsize; +{ +#endif // __ECOS + struct file *fp; + struct uio auio; + register struct iovec *iov; + register int i; + size_t len; + int error; + struct mbuf *from = 0, *control = 0; +#ifdef KTRACE + struct iovec *ktriov = NULL; +#endif + + if ((error = getsock(p->p_fd, s, &fp)) != 0) + return (error); + auio.uio_iov = mp->msg_iov; + auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_READ; +#ifndef __ECOS + auio.uio_procp = p; +#endif + auio.uio_offset = 0; /* XXX */ + auio.uio_resid = 0; + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++, iov++) { + /* Don't allow sum > SSIZE_MAX */ + if (iov->iov_len > SSIZE_MAX || + (auio.uio_resid += iov->iov_len) > SSIZE_MAX) + return (EINVAL); + } +#ifdef KTRACE + if (KTRPOINT(p, KTR_GENIO)) { + int iovlen = auio.uio_iovcnt * sizeof (struct iovec); + + MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); + bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); + } +#endif + len = auio.uio_resid; + error = soreceive((struct socket *)fp->f_data, &from, &auio, + NULL, mp->msg_control ? &control : NULL, + &mp->msg_flags); + if (error) { +#ifdef __ECOS + if (auio.uio_resid != len && + (error == EINTR || error == EWOULDBLOCK)) +#else + if (auio.uio_resid != len && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) +#endif + error = 0; + } +#ifdef KTRACE + if (ktriov != NULL) { + if (error == 0) + ktrgenio(p->p_tracep, s, UIO_READ, + ktriov, len - auio.uio_resid, error); + FREE(ktriov, M_TEMP); + } +#endif + if (error) + goto out; + *retsize = len - auio.uio_resid; + if (mp->msg_name) { + len = mp->msg_namelen; + if (len <= 0 || from == 0) + len = 0; + else { + /* save sa_len before it is destroyed by MSG_COMPAT */ + if (len > from->m_len) + len = from->m_len; + /* else if len < from->m_len ??? */ +#ifdef COMPAT_OLDSOCK + if (mp->msg_flags & MSG_COMPAT) + mtod(from, struct osockaddr *)->sa_family = + mtod(from, struct sockaddr *)->sa_family; +#endif + error = copyout(mtod(from, caddr_t), + (caddr_t)mp->msg_name, (unsigned)len); + if (error) + goto out; + } + mp->msg_namelen = len; + if (namelenp && + (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { +#ifdef COMPAT_OLDSOCK + if (mp->msg_flags & MSG_COMPAT) + error = 0; /* old recvfrom didn't check */ + else +#endif + goto out; + } + } + if (mp->msg_control) { +#ifdef COMPAT_OLDSOCK + /* + * We assume that old recvmsg calls won't receive access + * rights and other control info, esp. as control info + * is always optional and those options didn't exist in 4.3. + * If we receive rights, trim the cmsghdr; anything else + * is tossed. + */ + if (control && mp->msg_flags & MSG_COMPAT) { + if (mtod(control, struct cmsghdr *)->cmsg_level != + SOL_SOCKET || + mtod(control, struct cmsghdr *)->cmsg_type != + SCM_RIGHTS) { + mp->msg_controllen = 0; + goto out; + } + control->m_len -= sizeof (struct cmsghdr); + control->m_data += sizeof (struct cmsghdr); + } +#endif + len = mp->msg_controllen; + if (len <= 0 || control == 0) + len = 0; + else { + struct mbuf *m = control; + caddr_t p = (caddr_t)mp->msg_control; + + do { + i = m->m_len; + if (len < i) { + mp->msg_flags |= MSG_CTRUNC; + i = len; + } + error = copyout(mtod(m, caddr_t), p, + (unsigned)i); + if (m->m_next) + i = ALIGN(i); + p += i; + len -= i; + if (error != 0 || len <= 0) + break; + } while ((m = m->m_next) != NULL); + len = p - (caddr_t)mp->msg_control; + } + mp->msg_controllen = len; + } +out: + if (from) + m_freem(from); + if (control) + m_freem(control); + return (error); +} + +/* ARGSUSED */ +#ifdef __ECOS +int +sys_shutdown(struct sys_shutdown_args *uap, register_t *retval) +{ +#else +int +sys_shutdown(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_shutdown_args /* { + syscallarg(int) s; + syscallarg(int) how; + } */ *uap = v; +#endif // __ECOS + struct file *fp; + int error; + + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + return (error); + return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how))); +} + +#ifdef __ECOS +int +sys_setsockopt(struct sys_setsockopt_args *uap, register_t *retval) +{ +#else +/* ARGSUSED */ +int +sys_setsockopt(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_setsockopt_args /* { + syscallarg(int) s; + syscallarg(int) level; + syscallarg(int) name; + syscallarg(caddr_t) val; + syscallarg(socklen_t) valsize; + } */ *uap = v; +#endif // __ECOS + struct file *fp; + struct mbuf *m = NULL; + int error; + + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + return (error); + if (SCARG(uap, valsize) > MCLBYTES) + return (EINVAL); + if (SCARG(uap, val)) { + m = m_get(M_WAIT, MT_SOOPTS); + if (SCARG(uap, valsize) > MLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + return (ENOBUFS); + } + } + if (m == NULL) + return (ENOBUFS); + error = copyin(SCARG(uap, val), mtod(m, caddr_t), + SCARG(uap, valsize)); + if (error) { + (void) m_free(m); + return (error); + } + m->m_len = SCARG(uap, valsize); + } + return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level), + SCARG(uap, name), m)); +} + +#ifdef __ECOS +int +sys_getsockopt(struct sys_getsockopt_args *uap, register_t *retval) +{ +#else +/* ARGSUSED */ +int +sys_getsockopt(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_getsockopt_args /* { + syscallarg(int) s; + syscallarg(int) level; + syscallarg(int) name; + syscallarg(caddr_t) val; + syscallarg(socklen_t *) avalsize; + } */ *uap = v; +#endif // __ECOS + struct file *fp; + struct mbuf *m = NULL; + socklen_t valsize; + int error; + + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + return (error); + if (SCARG(uap, val)) { + error = copyin((caddr_t)SCARG(uap, avalsize), + (caddr_t)&valsize, sizeof (valsize)); + if (error) + return (error); + } else + valsize = 0; + if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level), + SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize && + m != NULL) { + if (valsize > m->m_len) + valsize = m->m_len; + error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); + if (error == 0) + error = copyout((caddr_t)&valsize, + (caddr_t)SCARG(uap, avalsize), sizeof (valsize)); + } + if (m != NULL) + (void) m_free(m); + return (error); +} + +#ifndef __ECOS +int +sys_pipe(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_pipe_args /* { + syscallarg(int *) fdp; + } */ *uap = v; + int error, fds[2]; + register_t rval[2]; + + if ((error = sys_opipe(p, v, rval)) == -1) + return (error); + + fds[0] = rval[0]; + fds[1] = rval[1]; + error = copyout((caddr_t)fds, (caddr_t)SCARG(uap, fdp), + 2 * sizeof (int)); + if (error) { + fdrelease(p, retval[0]); + fdrelease(p, retval[1]); + } + return (error); +} + +#ifdef OLD_PIPE + +/* ARGSUSED */ +int +sys_opipe(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct filedesc *fdp = p->p_fd; + struct file *rf, *wf; + struct socket *rso, *wso; + int fd, error; + + if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0) + return (error); + if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) + goto free1; + if ((error = falloc(p, &rf, &fd)) != 0) + goto free2; + retval[0] = fd; + rf->f_flag = FREAD; + rf->f_type = DTYPE_SOCKET; + rf->f_ops = &socketops; + rf->f_data = (caddr_t)rso; + if ((error = falloc(p, &wf, &fd)) != 0) + goto free3; + wf->f_flag = FWRITE; + wf->f_type = DTYPE_SOCKET; + wf->f_ops = &socketops; + wf->f_data = (caddr_t)wso; + retval[1] = fd; + if ((error = unp_connect2(wso, rso)) != 0) + goto free4; + return (0); +free4: + ffree(wf); + fdremove(fdp, retval[1]); +free3: + ffree(rf); + fdremove(fdp, retval[0]); +free2: + (void)soclose(wso); +free1: + (void)soclose(rso); + return (error); +} +#endif +#endif // __ECOS + +/* + * Get socket name. + */ +#ifdef __ECOS +int +sys_getsockname(struct sys_getsockname_args *uap, register_t *retval) +{ +#else +/* ARGSUSED */ +int +sys_getsockname(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_getsockname_args /* { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(socklen_t *) alen; + } */ *uap = v; +#endif // __ECOS + struct file *fp; + register struct socket *so; + struct mbuf *m; + socklen_t len; + int error; + + if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) + return (error); + error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len)); + if (error) + return (error); + so = (struct socket *)fp->f_data; + m = m_getclr(M_WAIT, MT_SONAME); + if (m == NULL) + return (ENOBUFS); + error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); + if (error) + goto bad; + if (len > m->m_len) + len = m->m_len; + error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len); + if (error == 0) + error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), + sizeof (len)); +bad: + m_freem(m); + return (error); +} + +/* + * Get name of peer for connected socket. + */ +/* ARGSUSED */ +#ifdef __ECOS +int +sys_getpeername(struct sys_getpeername_args *uap, register_t *retval) +{ +#else +int +sys_getpeername(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct sys_getpeername_args /* { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(socklen_t *) alen; + } */ *uap = v; +#endif // __ECOS + struct file *fp; + register struct socket *so; + struct mbuf *m; + socklen_t len; + int error; + + if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) + return (error); + so = (struct socket *)fp->f_data; + if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) + return (ENOTCONN); + error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len)); + if (error) + return (error); + m = m_getclr(M_WAIT, MT_SONAME); + if (m == NULL) + return (ENOBUFS); + error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0); + if (error) + goto bad; + if (len > m->m_len) + len = m->m_len; + error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len); + if (error == 0) + error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), + sizeof (len)); +bad: + m_freem(m); + return (error); +} + +int +sockargs(mp, buf, buflen, type) + struct mbuf **mp; + caddr_t buf; + socklen_t buflen; + int type; +{ + register struct sockaddr *sa; + register struct mbuf *m; + int error; + + if (buflen > MLEN) { +#ifdef COMPAT_OLDSOCK + if (type == MT_SONAME && buflen <= 112) + buflen = MLEN; /* unix domain compat. hack */ + else +#endif + return (EINVAL); + } + m = m_get(M_WAIT, type); + if (m == NULL) + return (ENOBUFS); + m->m_len = buflen; + error = copyin(buf, mtod(m, caddr_t), buflen); + if (error) { + (void) m_free(m); + return (error); + } + *mp = m; + if (type == MT_SONAME) { + sa = mtod(m, struct sockaddr *); + +#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN + if (sa->sa_family == 0 && sa->sa_len < AF_MAX) + sa->sa_family = sa->sa_len; +#endif + sa->sa_len = buflen; + } + return (0); +} + +#ifdef __ECOS +static int +ecos_getsock(int fdes, struct file **fpp) +{ + struct file *fp; + if (getfp(fdes, &fp)) + return (EBADF); + if (fp->f_type != DTYPE_SOCKET) + return (ENOTSOCK); + *fpp = fp; + return (0); +} +#else +int +getsock(fdp, fdes, fpp) + struct filedesc *fdp; + int fdes; + struct file **fpp; +{ + register struct file *fp; + + if ((unsigned)fdes >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fdes]) == NULL) + return (EBADF); + if (fp->f_type != DTYPE_SOCKET) + return (ENOTSOCK); + *fpp = fp; + return (0); +} +#endif diff --git a/ecos/packages/net/tcpip/current/src/sys/net/bridgestp.c b/ecos/packages/net/tcpip/current/src/sys/net/bridgestp.c new file mode 100644 index 0000000..e2c4afb --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/bridgestp.c @@ -0,0 +1,1511 @@ +//========================================================================== +// +// sys/net/bridgestp.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jason L. Wright (jason@thought.net) +// Contributors: Manu Sharma (manu.sharma@ascom.com) +// Date: 2000-07-18 +// Purpose: Implementation of the spanning tree protocol as defined in +// ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998. +// (In English: IEEE 802.1D, Draft 17, 1998) +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +// +/* $OpenBSD: bridgestp.c,v 1.15 2002/12/10 13:22:55 markus Exp $ */ + +/* + * Copyright (c) 2000 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Implementation of the spanning tree protocol as defined in + * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998. + * (In English: IEEE 802.1D, Draft 17, 1998) + */ + +#ifdef __ECOS +#include <pkgconf/net.h> +#include <stdio.h> +#else +#include "bridge.h" +#endif + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE +#if NBRIDGE + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#ifndef __ECOS +#include <sys/device.h> +#endif +#include <sys/kernel.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/if_llc.h> +#include <net/netisr.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#endif + +#include <net/if_bridge.h> + +#define STP_DEBUG +#define STP_DETAILED_DEBUG +#ifdef STP_DEBUG +#define STPLOG(x) diag_printf x +#else +#define STPLOG(x) +#endif + +#ifdef STP_DETAILED_DEBUG +#define STP_OPERATION_LOG(x) diag_printf x +#else +#define STP_OPERATION_LOG(x) +#endif + +/* BPDU message types */ +#define BSTP_MSGTYPE_CFG 0x00 /* Configuration */ +#define BSTP_MSGTYPE_TCN 0x80 /* Topology chg notification */ + +/* BPDU flags */ +#define BSTP_FLAG_TC 0x01 /* Topology change */ +#define BSTP_FLAG_TCA 0x80 /* Topology change ack */ + +#define BSTP_MESSAGE_AGE_INCR (1 * 256) /* in 256ths of a second */ +#define BSTP_TICK_VAL (1 * 256) /* in 256ths of a second */ + +/* + * Because BPDU's do not make nicely aligned structures, two different + * declarations are used: bstp_?bpdu (wire representation, packed) and + * bstp_*_unit (internal, nicely aligned version). + */ + +/* configuration bridge protocol data unit */ +struct bstp_cbpdu { + u_int8_t cbu_dsap; /* LLC: destination sap */ + u_int8_t cbu_ssap; /* LLC: source sap */ + u_int8_t cbu_ctl; /* LLC: control */ + u_int16_t cbu_protoid; /* protocol id */ + u_int8_t cbu_protover; /* protocol version */ + u_int8_t cbu_bpdutype; /* message type */ + u_int8_t cbu_flags; /* flags (below) */ + + /* root id */ + u_int16_t cbu_rootpri; /* root priority */ + u_int8_t cbu_rootaddr[6]; /* root address */ + + u_int32_t cbu_rootpathcost; /* root path cost */ + + /* bridge id */ + u_int16_t cbu_bridgepri; /* bridge priority */ + u_int8_t cbu_bridgeaddr[6]; /* bridge address */ + + u_int16_t cbu_portid; /* port id */ + u_int16_t cbu_messageage; /* current message age */ + u_int16_t cbu_maxage; /* maximum age */ + u_int16_t cbu_hellotime; /* hello time */ + u_int16_t cbu_forwarddelay; /* forwarding delay */ +} __attribute__((__packed__)); + +/* topology change notification bridge protocol data unit */ +struct bstp_tbpdu { + u_int8_t tbu_dsap; /* LLC: destination sap */ + u_int8_t tbu_ssap; /* LLC: source sap */ + u_int8_t tbu_ctl; /* LLC: control */ + u_int16_t tbu_protoid; /* protocol id */ + u_int8_t tbu_protover; /* protocol version */ + u_int8_t tbu_bpdutype; /* message type */ +} __attribute__((__packed__)); + +u_int8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; +u_int8_t bstp_init_done; + +void bstp_initialization(struct bridge_softc *); +void bstp_stop(struct bridge_softc *); +void bstp_initialize_port(struct bridge_softc *, struct bridge_iflist *); +void bstp_ifupdstatus(struct bridge_softc *, struct bridge_iflist *); +void bstp_enable_port(struct bridge_softc *, struct bridge_iflist *); +void bstp_disable_port(struct bridge_softc *, struct bridge_iflist *); +void bstp_enable_change_detection(struct bridge_iflist *); +void bstp_disable_change_detection(struct bridge_iflist *); +int bstp_root_bridge(struct bridge_softc *sc); +int bstp_supersedes_port_info(struct bridge_softc *, struct bridge_iflist *, + struct bstp_config_unit *); +int bstp_designated_port(struct bridge_softc *, struct bridge_iflist *); +int bstp_designated_for_some_port(struct bridge_softc *); +void bstp_transmit_config(struct bridge_softc *, struct bridge_iflist *); +void bstp_transmit_tcn(struct bridge_softc *); +struct mbuf *bstp_input(struct bridge_softc *, struct ifnet *, + struct ether_header *, struct mbuf *); +void bstp_received_config_bpdu(struct bridge_softc *, struct bridge_iflist *, + struct bstp_config_unit *); +void bstp_received_tcn_bpdu(struct bridge_softc *, struct bridge_iflist *, + struct bstp_tcn_unit *); +void bstp_record_config_information(struct bridge_softc *, + struct bridge_iflist *, struct bstp_config_unit *); +void bstp_record_config_timeout_values(struct bridge_softc *, + struct bstp_config_unit *); +void bstp_config_bpdu_generation(struct bridge_softc *); +void bstp_send_config_bpdu(struct bridge_iflist *, struct bstp_config_unit *); +void bstp_configuration_update(struct bridge_softc *); +void bstp_root_selection(struct bridge_softc *); +void bstp_designated_port_selection(struct bridge_softc *); +void bstp_become_designated_port(struct bridge_softc *, struct bridge_iflist *); +void bstp_port_state_selection(struct bridge_softc *); +void bstp_make_forwarding(struct bridge_softc *, struct bridge_iflist *); +void bstp_make_blocking(struct bridge_softc *, struct bridge_iflist *); +void bstp_set_port_state(struct bridge_iflist *, u_int8_t); +void bstp_set_bridge_priority(struct bridge_softc *, u_int64_t); +void bstp_set_port_priority(struct bridge_softc *, struct bridge_iflist *, + u_int16_t); +void bstp_set_path_cost(struct bridge_softc *, struct bridge_iflist *, + u_int32_t); +void bstp_topology_change_detection(struct bridge_softc *); +void bstp_topology_change_acknowledged(struct bridge_softc *); +void bstp_acknowledge_topology_change(struct bridge_softc *, + struct bridge_iflist *); + +void bstp_tick(void *); +void bstp_timer_start(struct bridge_timer *, u_int16_t); +void bstp_timer_stop(struct bridge_timer *); +int bstp_timer_expired(struct bridge_timer *, u_int16_t); + +void bstp_hold_timer_expiry(struct bridge_softc *, struct bridge_iflist *); +void bstp_message_age_timer_expiry(struct bridge_softc *, + struct bridge_iflist *); +void bstp_forward_delay_timer_expiry(struct bridge_softc *, + struct bridge_iflist *); +void bstp_topology_change_timer_expiry(struct bridge_softc *); +void bstp_tcn_timer_expiry(struct bridge_softc *); +void bstp_hello_timer_expiry(struct bridge_softc *); + +char stp_buf [32]; +char * +stp_port_state (unsigned int state) { + memset (stp_buf, 0x0, 32); + switch (state) { + case BSTP_IFSTATE_DISABLED : sprintf (stp_buf, " Disabled "); break; + case BSTP_IFSTATE_LISTENING : sprintf (stp_buf, " Listn'ng "); break; + case BSTP_IFSTATE_LEARNING : sprintf (stp_buf, " Lrn'ng "); break; + case BSTP_IFSTATE_FORWARDING : sprintf (stp_buf, " Fwd'ng "); break; + case BSTP_IFSTATE_BLOCKING : sprintf (stp_buf, " Blk'ng "); break; + default: sprintf (stp_buf, " UNKNOWN "); break; + } + return stp_buf; +} + +void +bstp_transmit_config(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + if (bif->bif_hold_timer.active) { + bif->bif_config_pending = 1; + return; + } + + bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG; + bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root; + bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost; + bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id; + bif->bif_config_bpdu.cu_port_id = bif->bif_port_id; + + if (bstp_root_bridge(sc)) + bif->bif_config_bpdu.cu_message_age = 0; + else + bif->bif_config_bpdu.cu_message_age = + sc->sc_root_port->bif_message_age_timer.value + + BSTP_MESSAGE_AGE_INCR; + + bif->bif_config_bpdu.cu_max_age = sc->sc_max_age; + bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time; + bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay; + bif->bif_config_bpdu.cu_topology_change_acknowledgment + = bif->bif_topology_change_acknowledge; + bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change; + + if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) { + bif->bif_topology_change_acknowledge = 0; + bif->bif_config_pending = 0; + bstp_send_config_bpdu(bif, &bif->bif_config_bpdu); + bstp_timer_start(&bif->bif_hold_timer, 0); + } +} + +void +bstp_send_config_bpdu(bif, cu) + struct bridge_iflist *bif; + struct bstp_config_unit *cu; +{ + struct arpcom *arp; + struct ifnet *ifp; + struct mbuf *m; + struct ether_header eh; + struct bstp_cbpdu bpdu; + int s, error; + + s = splimp(); + ifp = bif->ifp; + arp = (struct arpcom *)ifp; + + if ((ifp->if_flags & IFF_RUNNING) == 0) { + splx(s); + return; + } +#ifdef ALTQ + if (!ALTQ_IS_ENABLED(&ifp->if_snd)) +#endif + if (IF_QFULL(&ifp->if_snd)) { + splx(s); + return; + } + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) { + splx(s); + return; + } + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = sizeof(eh) + sizeof(bpdu); + m->m_len = m->m_pkthdr.len; + + bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP; + bpdu.cbu_ctl = LLC_UI; + bpdu.cbu_protoid = htons(0); + bpdu.cbu_protover = 0; + bpdu.cbu_bpdutype = cu->cu_message_type; + bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) | + (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0); + + bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48); + bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40; + bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32; + bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24; + bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16; + bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8; + bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0; + + bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost); + + bpdu.cbu_bridgepri = htons(cu->cu_rootid >> 48); + bpdu.cbu_bridgeaddr[0] = cu->cu_rootid >> 40; + bpdu.cbu_bridgeaddr[1] = cu->cu_rootid >> 32; + bpdu.cbu_bridgeaddr[2] = cu->cu_rootid >> 24; + bpdu.cbu_bridgeaddr[3] = cu->cu_rootid >> 16; + bpdu.cbu_bridgeaddr[4] = cu->cu_rootid >> 8; + bpdu.cbu_bridgeaddr[5] = cu->cu_rootid >> 0; + + bpdu.cbu_portid = htons(cu->cu_port_id); + bpdu.cbu_messageage = htons(cu->cu_message_age); + bpdu.cbu_maxage = htons(cu->cu_max_age); + bpdu.cbu_hellotime = htons(cu->cu_hello_time); + bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay); + + bcopy(arp->ac_enaddr, eh.ether_shost, ETHER_ADDR_LEN); + bcopy(bstp_etheraddr, eh.ether_dhost, ETHER_ADDR_LEN); + eh.ether_type = htons(sizeof(bpdu)); + + bcopy(&eh, m->m_data, sizeof(eh)); + bcopy(&bpdu, m->m_data + sizeof(eh), sizeof(bpdu)); + + STPLOG ((" - <%s>: Tx with Port 0x%x; Age %d; Flags %d\n", bif->ifp->if_xname, + cu->cu_port_id, cu->cu_message_age, bpdu.cbu_flags)); + + IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); + if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + splx(s); +} + +int +bstp_root_bridge(sc) + struct bridge_softc *sc; +{ + return (sc->sc_designated_root == sc->sc_bridge_id); +} + +int +bstp_supersedes_port_info(sc, bif, cu) + struct bridge_softc *sc; + struct bridge_iflist *bif; + struct bstp_config_unit *cu; +{ + if (cu->cu_rootid < bif->bif_designated_root) { + return (1); + } + if (cu->cu_rootid > bif->bif_designated_root) { + return (0); + } + + if (cu->cu_root_path_cost < bif->bif_designated_cost) { + return (1); + } + if (cu->cu_root_path_cost > bif->bif_designated_cost) { + return (0); + } + + if (cu->cu_bridge_id < bif->bif_designated_bridge) { + return (1); + } + if (cu->cu_bridge_id > bif->bif_designated_bridge) { + return (0); + } + + if (sc->sc_bridge_id != cu->cu_bridge_id) { + return (1); + } + if (cu->cu_port_id <= bif->bif_designated_port) { + return (1); + } + return (0); +} + +void +bstp_record_config_information(sc, bif, cu) + struct bridge_softc *sc; + struct bridge_iflist *bif; + struct bstp_config_unit *cu; +{ + bif->bif_designated_root = cu->cu_rootid; + bif->bif_designated_cost = cu->cu_root_path_cost; + bif->bif_designated_bridge = cu->cu_bridge_id; + bif->bif_designated_port = cu->cu_port_id; + bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age); +} + +void +bstp_record_config_timeout_values(sc, config) + struct bridge_softc *sc; + struct bstp_config_unit *config; +{ + sc->sc_max_age = config->cu_max_age; + sc->sc_hello_time = config->cu_hello_time; + sc->sc_forward_delay = config->cu_forward_delay; + sc->sc_topology_change = config->cu_topology_change; +} + +void +bstp_config_bpdu_generation(sc) + struct bridge_softc *sc; +{ + struct bridge_iflist *bif; + + STPLOG (("STP : Tx Hello BPDU ...\n")); + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + if (bstp_designated_port(sc, bif) && + (bif->bif_state != BSTP_IFSTATE_DISABLED)) { + bstp_transmit_config(sc, bif); + } else { + STPLOG ((" - <%s>: No Tx\n", bif->ifp->if_xname)); + } + } +} + +int +bstp_designated_port(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + return ((bif->bif_designated_bridge == sc->sc_bridge_id) + && (bif->bif_designated_port == bif->bif_port_id)); +} + +void +bstp_transmit_tcn(sc) + struct bridge_softc *sc; +{ + struct bstp_tbpdu bpdu; + struct bridge_iflist *bif = sc->sc_root_port; + struct ifnet *ifp = bif->ifp; + struct arpcom *arp = (struct arpcom *)ifp; + struct ether_header *eh; + struct mbuf *m; + int s, error; + + if ((ifp->if_flags & IFF_RUNNING) == 0) + return; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) + return; + + STPLOG (("STP : Tx TCN BPDU on <%s> ...\n", ifp->if_xname)); + + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu); + m->m_len = m->m_pkthdr.len; + + eh = mtod(m, struct ether_header *); + bcopy(arp->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN); + bcopy(bstp_etheraddr, eh->ether_dhost, ETHER_ADDR_LEN); + eh->ether_type = htons(sizeof(bpdu)); + + bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP; + bpdu.tbu_ctl = LLC_UI; + bpdu.tbu_protoid = 0; + bpdu.tbu_protover = 0; + bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN; + bcopy(&bpdu, m->m_data + sizeof(*eh), sizeof(bpdu)); + + s = splimp(); + IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); + if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + m = NULL; + + splx(s); + if (m != NULL) + m_freem(m); +} + +void +bstp_configuration_update(sc) + struct bridge_softc *sc; +{ + STP_OPERATION_LOG ((" %s \n", __FUNCTION__)); + bstp_root_selection(sc); + bstp_designated_port_selection(sc); +} + +void +bstp_root_selection(sc) + struct bridge_softc *sc; +{ + struct bridge_iflist *root_port = NULL, *bif; + + STP_OPERATION_LOG ((" => Root Port selection ...\n", __FUNCTION__)); + LIST_FOREACH(bif, &sc->sc_iflist, next) { + STP_OPERATION_LOG ((" - <%s>", bif->ifp->if_xname)); + if (!(bif->bif_flags & IFBIF_STP)) { + STP_OPERATION_LOG ((" STP not configured\n")); + continue; + } + if (bstp_designated_port(sc, bif)) { + STP_OPERATION_LOG ((" dsgntd port\n")); + continue; + } + if (bif->bif_state == BSTP_IFSTATE_DISABLED) { + STP_OPERATION_LOG ((" .. in state DISABLED \n")); + continue; + } + if (bif->bif_designated_root >= sc->sc_bridge_id) { + STP_OPERATION_LOG ((" root: ifp dsgntd >= sc\n")); + continue; + } + if (root_port == NULL) { + STP_OPERATION_LOG ((" Set as Root Port\n")); + goto set_port; + } + + if (bif->bif_designated_root < root_port->bif_designated_root) { + STP_OPERATION_LOG ((" ifp dsgntd < root dsgntd; Set as Root Port \n")); + goto set_port; + } + if (bif->bif_designated_root > root_port->bif_designated_root) { + STP_OPERATION_LOG ((" root: ifp dsgntd > root dsgntd \n")); + continue; + } + + if ((bif->bif_designated_cost + bif->bif_path_cost) < + (root_port->bif_designated_cost + root_port->bif_path_cost)) { + STP_OPERATION_LOG ((" (dsgntd_cost+path_cost): ifp < root; Set as Root Port \n")); + goto set_port; + } + if ((bif->bif_designated_cost + bif->bif_path_cost) > + (root_port->bif_designated_cost + root_port->bif_path_cost)) { + STP_OPERATION_LOG ((" (dsgntd_cost+path_cost): ifp > root \n")); + continue; + } + + if (bif->bif_designated_bridge < root_port->bif_designated_bridge) { + STP_OPERATION_LOG ((" bridge: ifp dsgntd < root dsgntd; Set as Root Port \n")); + goto set_port; + } + if (bif->bif_designated_bridge > root_port->bif_designated_bridge) { + STP_OPERATION_LOG ((" bridge: ifp dsgntd > root dsgntd \n")); + continue; + } + + if (bif->bif_designated_port < root_port->bif_designated_port) { + STP_OPERATION_LOG ((" port: ifp dsgntd (%d) < root dsgntd (%d); Set as Root Port\n", + bif->bif_designated_port, root_port->bif_designated_port)); + goto set_port; + } + if (bif->bif_designated_port > root_port->bif_designated_port) { + STP_OPERATION_LOG ((" port: ifp dsgntd (%d) > root dsgntd (%d)\n", + bif->bif_designated_port, root_port->bif_designated_port)); + continue; + } + + if (bif->bif_port_id >= root_port->bif_port_id) { + STP_OPERATION_LOG ((" ifp port_id (%d) >= root port_id (%d) 8 \n", + bif->bif_port_id, root_port->bif_port_id)); + continue; + } +set_port: + root_port = bif; + } + + sc->sc_root_port = root_port; + if (root_port == NULL) { + sc->sc_designated_root = sc->sc_bridge_id; + sc->sc_root_path_cost = 0; + STPLOG ((" Root Port : <SELF ROOT>, Path Cost : 0\n")); + } else { + sc->sc_designated_root = root_port->bif_designated_root; + sc->sc_root_path_cost = root_port->bif_designated_cost + + root_port->bif_path_cost; + STPLOG ((" Root Port : <%s>, Path Cost : 0\n", + root_port->ifp->if_xname, sc->sc_root_path_cost)); + } +} + +void +bstp_designated_port_selection(sc) + struct bridge_softc *sc; +{ + struct bridge_iflist *bif; + + STP_OPERATION_LOG ((" => Designated Port selection ...\n")); + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + if (bstp_designated_port(sc, bif)) { + STPLOG ((" - <%s>: already designated \n", bif->ifp->if_xname)); + goto designated; + } + if (bif->bif_designated_root != sc->sc_designated_root) { + STPLOG ((" - <%s>: becomes designated\n", bif->ifp->if_xname)); + goto designated; + } + + /* + * PLC network is special, we cannot go as per standards because of + * our network topology and behavior + * + if (sc->sc_root_path_cost < bif->bif_designated_cost) { + STPLOG ((" - <%s>: becomes designated path cost (1)\n", bif->ifp->if_xname)); + goto designated; + } + if (sc->sc_root_path_cost > bif->bif_designated_cost) { + STPLOG ((" - <%s>: Cannot be designated; Root cost (%d) > Desig cost (%d) \n", + bif->ifp->if_xname, sc->sc_root_path_cost, bif->bif_designated_cost)); + continue; + } + */ + + if (sc->sc_bridge_id < bif->bif_designated_bridge) { + STPLOG ((" - <%s>: becomes dsgntd (self-brdgid < dsgntd-brdgid); \n", bif->ifp->if_xname)); + goto designated; + } + if (sc->sc_bridge_id > bif->bif_designated_bridge) { + STPLOG ((" - <%s>: Cannot be dsgntd (self-brdgid > dsgntd-brdgid); \n", bif->ifp->if_xname)); + continue; + } + + if (bif->bif_port_id > bif->bif_designated_port) { + STPLOG ((" - <%s>: Cannot be dsgntd (self-portid > bsgntd-portid); \n", bif->ifp->if_xname)); + continue; + } + + /* + * PLC network is special, we cannot go as per standards because of + * our network topology and behavior + */ + if (sc->sc_root_path_cost < bif->bif_designated_cost) { + STPLOG ((" - <%s>: becomes dsgntd path cost (1)\n", bif->ifp->if_xname)); + goto designated; + } + if (sc->sc_root_path_cost > bif->bif_designated_cost) { + STPLOG ((" - <%s>: Cannot be dsgntd; Root cost (%d) > Desig cost (%d) \n", + bif->ifp->if_xname, sc->sc_root_path_cost, bif->bif_designated_cost)); + continue; + } +designated: + bstp_become_designated_port(sc, bif); + } +} + +void +bstp_become_designated_port(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + bif->bif_designated_root = sc->sc_designated_root; + bif->bif_designated_cost = sc->sc_root_path_cost; + bif->bif_designated_bridge = sc->sc_bridge_id; + bif->bif_designated_port = bif->bif_port_id; + + STP_OPERATION_LOG ((" => %s values (cost:%d, port:0x%x)\n", + __FUNCTION__, bif->ifp->if_xname, bif->bif_designated_cost, bif->bif_designated_port)); + //STP_OPERATION_LOG (("(cost:%d, port:0x%x)\n", bif->bif_designated_cost, bif->bif_designated_port)); +} + +void +bstp_port_state_selection(sc) + struct bridge_softc *sc; +{ + struct bridge_iflist *bif; + + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + if (bif == sc->sc_root_port) { + bif->bif_config_pending = 0; + bif->bif_topology_change_acknowledge = 0; + bstp_make_forwarding(sc, bif); + } else if (bstp_designated_port(sc, bif)) { + bstp_timer_stop(&bif->bif_message_age_timer); + bstp_make_forwarding(sc, bif); + } else { + bif->bif_config_pending = 0; + bif->bif_topology_change_acknowledge = 0; + bstp_make_blocking(sc, bif); + } + } +} + +void +bstp_make_forwarding(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + if (bif->bif_state == BSTP_IFSTATE_BLOCKING) { + bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING); + bstp_timer_start(&bif->bif_forward_delay_timer, 0); + } +} + +void +bstp_make_blocking(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + if ((bif->bif_state != BSTP_IFSTATE_DISABLED) && + (bif->bif_state != BSTP_IFSTATE_BLOCKING)) { + if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) || + (bif->bif_state == BSTP_IFSTATE_LEARNING)) { + if (bif->bif_change_detection_enabled) { + bstp_topology_change_detection(sc); + } + bridge_rtdelete(sc, bif->ifp, 1); + } + bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING); + bstp_timer_stop(&bif->bif_forward_delay_timer); + } +} + +void +bstp_set_port_state(bif, state) + struct bridge_iflist *bif; + u_int8_t state; +{ + bif->bif_state = state; +} + +void +bstp_topology_change_detection(sc) + struct bridge_softc *sc; +{ + if (bstp_root_bridge(sc)) { + STPLOG ((" -> %s : Root Bridge\n", __FUNCTION__)); + sc->sc_topology_change = 1; + bstp_timer_start(&sc->sc_topology_change_timer, 0); + } else if (!sc->sc_topology_change_detected) { + STPLOG ((" -> %s : NOT Root Bridge, Tx TCN\n", __FUNCTION__)); + bstp_transmit_tcn(sc); + bstp_timer_start(&sc->sc_tcn_timer, 0); + } + sc->sc_topology_change_detected = 1; +} + +void +bstp_topology_change_acknowledged(sc) + struct bridge_softc *sc; +{ + sc->sc_topology_change_detected = 0; + bstp_timer_stop(&sc->sc_tcn_timer); +} + +void +bstp_acknowledge_topology_change(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + bif->bif_topology_change_acknowledge = 1; + bstp_transmit_config(sc, bif); +} + +struct mbuf * +bstp_input(sc, ifp, eh, m) + struct bridge_softc *sc; + struct ifnet *ifp; + struct ether_header *eh; + struct mbuf *m; +{ + struct bridge_iflist *bif = NULL; + struct bstp_tbpdu tpdu; + struct bstp_cbpdu cpdu; + struct bstp_config_unit cu; + struct bstp_tcn_unit tu; + u_int16_t len; + + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + if (bif->ifp == ifp) + break; + } + + if (bif == NULL) + goto out; + + len = ntohs(eh->ether_type); + if (len < sizeof(tpdu)) { + goto out; + } + if (m->m_pkthdr.len > len) + m_adj(m, len - m->m_pkthdr.len); + if ((m = m_pullup(m, sizeof(tpdu))) == NULL) { + goto out; + } + bcopy(mtod(m, struct tpdu *), &tpdu, sizeof(tpdu)); + + if (tpdu.tbu_dsap != LLC_8021D_LSAP || + tpdu.tbu_ssap != LLC_8021D_LSAP || + tpdu.tbu_ctl != LLC_UI) { + goto out; + } + if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0) { + goto out; + } + + switch (tpdu.tbu_bpdutype) { + case BSTP_MSGTYPE_TCN: + + STPLOG (("STP : Rx TCN on <%s> from %02X:%02X:%02X:%02X:%02X:%02X \n", bif->ifp->if_xname, + eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2], + eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5])); + + tu.tu_message_type = tpdu.tbu_bpdutype; + bstp_received_tcn_bpdu(sc, bif, &tu); + break; + + case BSTP_MSGTYPE_CFG: + + STPLOG (("STP : Rx CFG on <%s> from %02X:%02X:%02X:%02X:%02X:%02X \n", bif->ifp->if_xname, + eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2], + eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5])); + + if ((m = m_pullup(m, sizeof(cpdu))) == NULL) + goto out; + bcopy(mtod(m, struct bstp_cpdu *), &cpdu, sizeof(cpdu)); + + cu.cu_rootid = + (((u_int64_t)ntohs(cpdu.cbu_rootpri)) << 48) | + (((u_int64_t)cpdu.cbu_rootaddr[0]) << 40) | + (((u_int64_t)cpdu.cbu_rootaddr[1]) << 32) | + (((u_int64_t)cpdu.cbu_rootaddr[2]) << 24) | + (((u_int64_t)cpdu.cbu_rootaddr[3]) << 16) | + (((u_int64_t)cpdu.cbu_rootaddr[4]) << 8) | + (((u_int64_t)cpdu.cbu_rootaddr[5]) << 0); + + cu.cu_bridge_id = + (((u_int64_t)ntohs(cpdu.cbu_bridgepri)) << 48) | + (((u_int64_t)cpdu.cbu_bridgeaddr[0]) << 40) | + (((u_int64_t)cpdu.cbu_bridgeaddr[1]) << 32) | + (((u_int64_t)cpdu.cbu_bridgeaddr[2]) << 24) | + (((u_int64_t)cpdu.cbu_bridgeaddr[3]) << 16) | + (((u_int64_t)cpdu.cbu_bridgeaddr[4]) << 8) | + (((u_int64_t)cpdu.cbu_bridgeaddr[5]) << 0); + + cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost); + cu.cu_message_age = ntohs(cpdu.cbu_messageage); + cu.cu_max_age = ntohs(cpdu.cbu_maxage); + cu.cu_hello_time = ntohs(cpdu.cbu_hellotime); + cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay); + cu.cu_port_id = ntohs(cpdu.cbu_portid); + cu.cu_message_type = cpdu.cbu_bpdutype; + cu.cu_topology_change_acknowledgment = + (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0; + cu.cu_topology_change = + (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0; + bstp_received_config_bpdu(sc, bif, &cu); + break; + default: + goto out; + } + +out: + if (m) + m_freem(m); + return (NULL); +} + +void +bstp_received_config_bpdu(sc, bif, cu) + struct bridge_softc *sc; + struct bridge_iflist *bif; + struct bstp_config_unit *cu; +{ + int root; + + root = bstp_root_bridge(sc); + + if (bif->bif_state != BSTP_IFSTATE_DISABLED) { + if (bstp_supersedes_port_info(sc, bif, cu)) { + STPLOG ((" Rx CFG on <%s> superseds port info; RE-Evaluating...\n", bif->ifp->if_xname)); + bstp_record_config_information(sc, bif, cu); + bstp_configuration_update(sc); + bstp_port_state_selection(sc); + + if ((!bstp_root_bridge(sc)) && root) { + bstp_timer_stop(&sc->sc_hello_timer); + + if (sc->sc_topology_change_detected) { + bstp_timer_stop(&sc->sc_topology_change_timer); + bstp_transmit_tcn(sc); + bstp_timer_start(&sc->sc_tcn_timer, 0); + } + } + + if (bif == sc->sc_root_port) { + bstp_record_config_timeout_values(sc, cu); + bstp_config_bpdu_generation(sc); + + if (cu->cu_topology_change_acknowledgment) { + bstp_topology_change_acknowledged(sc); + } + } + } else if (bstp_designated_port(sc, bif)) { + STPLOG ((" Port <%s> supersedes Rx CFG info\n", bif->ifp->if_xname)); + bstp_transmit_config(sc, bif); + } + } +} + +void +bstp_received_tcn_bpdu(sc, bif, tcn) + struct bridge_softc *sc; + struct bridge_iflist *bif; + struct bstp_tcn_unit *tcn; +{ + if (bif->bif_state != BSTP_IFSTATE_DISABLED && + bstp_designated_port(sc, bif)) { + bstp_topology_change_detection(sc); + bstp_acknowledge_topology_change(sc, bif); + } +} + +void +bstp_hello_timer_expiry(sc) + struct bridge_softc *sc; +{ + bstp_config_bpdu_generation(sc); + bstp_timer_start(&sc->sc_hello_timer, 0); +} + +void +bstp_message_age_timer_expiry(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + int root; + + root = bstp_root_bridge(sc); + bstp_become_designated_port(sc, bif); + bstp_configuration_update(sc); + bstp_port_state_selection(sc); + + if ((bstp_root_bridge(sc)) && (!root)) { + sc->sc_max_age = sc->sc_bridge_max_age; + sc->sc_hello_time = sc->sc_bridge_hello_time; + sc->sc_forward_delay = sc->sc_bridge_forward_delay; + bstp_topology_change_detection(sc); + bstp_timer_stop(&sc->sc_tcn_timer); + bstp_config_bpdu_generation(sc); + bstp_timer_start(&sc->sc_hello_timer, 0); + } +} + +void +bstp_forward_delay_timer_expiry(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + if (bif->bif_state == BSTP_IFSTATE_LISTENING) { + bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING); + bstp_timer_start(&bif->bif_forward_delay_timer, 0); + } else if (bif->bif_state == BSTP_IFSTATE_LEARNING) { + bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING); + if (bstp_designated_for_some_port(sc) && + bif->bif_change_detection_enabled) + bstp_topology_change_detection(sc); + } +} + +int +bstp_designated_for_some_port(sc) + struct bridge_softc *sc; +{ + + struct bridge_iflist *bif; + + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + if (bif->bif_designated_bridge == sc->sc_bridge_id) + return (1); + } + return (0); +} + +void +bstp_tcn_timer_expiry(sc) + struct bridge_softc *sc; +{ + STPLOG ((" STP: tcn timer expired \n")); + bstp_transmit_tcn(sc); + bstp_timer_start(&sc->sc_tcn_timer, 0); +} + +void +bstp_topology_change_timer_expiry(sc) + struct bridge_softc *sc; +{ + STPLOG ((" STP: topology change timer expired \n")); + sc->sc_topology_change_detected = 0; + sc->sc_topology_change = 0; +} + +void +bstp_hold_timer_expiry(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + if (bif->bif_config_pending) + bstp_transmit_config(sc, bif); +} + +void +bstp_initialization(sc) + struct bridge_softc *sc; +{ + struct bridge_iflist *bif, *mif; + struct arpcom *ac, *mac; + + mif = NULL; mac = NULL; + /* Browse through the ethernet address of each interface and pick the + * one which has lowest value + */ + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) { + continue; + } + if (bif->ifp->if_type != IFT_ETHER) { + continue; + } + bif->bif_port_id = (bif->bif_priority << 8) | + (bif->ifp->if_index & 0xff); + + if (mif == NULL) { + mif = bif; + mac = (struct arpcom *)bif->ifp; + continue; + } + ac = (struct arpcom *)bif->ifp; + if (memcmp(ac->ac_enaddr, mac->ac_enaddr, ETHER_ADDR_LEN) < 0) { + mif = bif; + mac = (struct arpcom *)bif->ifp; + continue; + } + } + + if (mif == NULL) { + bstp_stop(sc); + return; + } + + /* Configure bridge-id as specified in standards + */ + sc->sc_bridge_id = + (((u_int64_t)sc->sc_bridge_priority) << 48) | + (((u_int64_t)mac->ac_enaddr[0]) << 40) | + (((u_int64_t)mac->ac_enaddr[1]) << 32) | + (mac->ac_enaddr[2] << 24) | (mac->ac_enaddr[3] << 16) | + (mac->ac_enaddr[4] << 8) | (mac->ac_enaddr[5]); + + /* Configure self as root bridge + */ + sc->sc_designated_root = sc->sc_bridge_id; + sc->sc_root_path_cost = 0; + sc->sc_root_port = NULL; + + sc->sc_max_age = sc->sc_bridge_max_age; + sc->sc_hello_time = sc->sc_bridge_hello_time; + sc->sc_forward_delay = sc->sc_bridge_forward_delay; + sc->sc_topology_change_detected = 0; + sc->sc_topology_change = 0; + bstp_timer_stop(&sc->sc_tcn_timer); + bstp_timer_stop(&sc->sc_topology_change_timer); + + /* If there is a timeout already set on this, cancel it and restart. + * The intent is to avoid setting duplicate timeouts. If the timeout + * is already set, untimeout would cancel it. + */ +#ifdef __ECOS + if (!bstp_init_done) { + untimeout(bstp_tick, sc); + timeout(bstp_tick, sc, hz); + bstp_init_done = 1; + } +#else + if (!timeout_initialized(&sc->sc_bstptimeout)) + timeout_set(&sc->sc_bstptimeout, bstp_tick, sc); + if (!timeout_pending(&sc->sc_bstptimeout)) + timeout_add(&sc->sc_bstptimeout, hz); +#endif // __ECOS + + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (bif->bif_flags & IFBIF_STP) { + STPLOG (("%s:%s ..(en). \n", __FUNCTION__, bif->ifp->if_xname)); + bstp_enable_port(sc, bif); + } + else { + STPLOG (("%s:%s ..(dis). \n", __FUNCTION__, bif->ifp->if_xname)); + bstp_disable_port(sc, bif); + } + } + + bstp_port_state_selection(sc); + bstp_config_bpdu_generation(sc); + bstp_timer_start(&sc->sc_hello_timer, 0); +} + +void +bstp_stop(sc) + struct bridge_softc *sc; +{ + + struct bridge_iflist *bif; + + STPLOG ((" %s\n", __FUNCTION__)); + LIST_FOREACH(bif, &sc->sc_iflist, next) { + bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED); + bstp_timer_stop(&bif->bif_hold_timer); + bstp_timer_stop(&bif->bif_message_age_timer); + bstp_timer_stop(&bif->bif_forward_delay_timer); + } + +#ifdef __ECOS + if (bstp_init_done) { + STPLOG (("##### untimeout ##### loc 1\n")); + untimeout(bstp_tick, sc); + bstp_init_done = 0; + } +#else + if (timeout_initialized(&sc->sc_bstptimeout) && + timeout_pending(&sc->sc_bstptimeout)) + timeout_del(&sc->sc_bstptimeout); +#endif //__ECOS + + bstp_timer_stop(&sc->sc_topology_change_timer); + bstp_timer_stop(&sc->sc_tcn_timer); + bstp_timer_stop(&sc->sc_hello_timer); + +} + +void +bstp_initialize_port(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + bstp_become_designated_port(sc, bif); + bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING); + bif->bif_topology_change_acknowledge = 0; + bif->bif_config_pending = 0; + bstp_enable_change_detection(bif); + bstp_timer_stop(&bif->bif_message_age_timer); + bstp_timer_stop(&bif->bif_forward_delay_timer); + bstp_timer_stop(&bif->bif_hold_timer); +} + +void +bstp_enable_port(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + bstp_initialize_port(sc, bif); + bstp_port_state_selection(sc); +} + +void +bstp_disable_port(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + int root; + + root = bstp_root_bridge(sc); + bstp_become_designated_port(sc, bif); + bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED); + bif->bif_topology_change_acknowledge = 0; + bif->bif_config_pending = 0; + bstp_timer_stop(&bif->bif_message_age_timer); + bstp_timer_stop(&bif->bif_forward_delay_timer); + bstp_configuration_update(sc); + bridge_rtdelete(sc, bif->ifp, 1); + + if (bstp_root_bridge(sc) && (!root)) { + sc->sc_max_age = sc->sc_bridge_max_age; + sc->sc_hello_time = sc->sc_bridge_hello_time; + sc->sc_forward_delay = sc->sc_bridge_forward_delay; + bstp_topology_change_detection(sc); + bstp_timer_stop(&sc->sc_tcn_timer); + bstp_config_bpdu_generation(sc); + bstp_timer_start(&sc->sc_hello_timer, 0); + } +} + +void +bstp_set_bridge_priority(sc, new_bridge_id) + struct bridge_softc *sc; + u_int64_t new_bridge_id; +{ + int root; + struct bridge_iflist *bif; + + root = bstp_root_bridge(sc); + + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + if (bstp_designated_port(sc, bif)) + bif->bif_designated_bridge = new_bridge_id; + } + + sc->sc_bridge_id = new_bridge_id; + + bstp_configuration_update(sc); + bstp_port_state_selection(sc); + + if (bstp_root_bridge(sc) && (!root)) { + sc->sc_max_age = sc->sc_bridge_max_age; + sc->sc_hello_time = sc->sc_bridge_hello_time; + sc->sc_forward_delay = sc->sc_bridge_forward_delay; + bstp_topology_change_detection(sc); + bstp_timer_stop(&sc->sc_tcn_timer); + bstp_config_bpdu_generation(sc); + bstp_timer_start(&sc->sc_hello_timer, 0); + } +} + +void +bstp_set_port_priority(sc, bif, new_port_id) + struct bridge_softc *sc; + struct bridge_iflist *bif; + u_int16_t new_port_id; +{ + if (bstp_designated_port(sc, bif)) + bif->bif_designated_port = new_port_id; + + bif->bif_port_id = new_port_id; + + if ((sc->sc_bridge_id == bif->bif_designated_bridge) && + (bif->bif_port_id < bif->bif_designated_port)) { + bstp_become_designated_port(sc, bif); + bstp_port_state_selection(sc); + } +} + +void +bstp_set_path_cost(sc, bif, path_cost) + struct bridge_softc *sc; + struct bridge_iflist *bif; + u_int32_t path_cost; +{ + bif->bif_path_cost = path_cost; + bstp_configuration_update(sc); + bstp_port_state_selection(sc); +} + +void +bstp_enable_change_detection(bif) + struct bridge_iflist *bif; +{ + bif->bif_change_detection_enabled = 1; +} + +void +bstp_disable_change_detection(bif) + struct bridge_iflist *bif; +{ + bif->bif_change_detection_enabled = 0; +} + +void +bstp_ifupdstatus(sc, bif) + struct bridge_softc *sc; + struct bridge_iflist *bif; +{ + struct ifnet *ifp = bif->ifp; +#ifndef __ECOS + struct ifmediareq ifmr; +#endif + int err = EOPNOTSUPP; + + if (ifp->if_flags & IFF_UP) { +#ifndef __ECOS + ifmr.ifm_count = 0; + err = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr); +#endif + if (err) { + if (bif->bif_state == BSTP_IFSTATE_DISABLED) + bstp_enable_port(sc, bif); + STPLOG (("<%s:%s> ", bif->ifp->if_xname, stp_port_state(bif->bif_state))); + return; + } +#ifndef __ECOS + if (!(ifmr.ifm_status & IFM_AVALID)) { + if (bif->bif_state == BSTP_IFSTATE_DISABLED) + bstp_enable_port(sc, bif); + return; + } + + if (ifmr.ifm_status & IFM_ACTIVE) { + if (bif->bif_state == BSTP_IFSTATE_DISABLED) + bstp_enable_port(sc, bif); + return; + } +#endif + + if (bif->bif_state != BSTP_IFSTATE_DISABLED) { + bstp_disable_port(sc, bif); + } + + return; + } + + if (bif->bif_state != BSTP_IFSTATE_DISABLED) + bstp_disable_port(sc, bif); +} + +void +bstp_tick(vsc) + void *vsc; +{ + struct bridge_softc *sc = vsc; + struct bridge_iflist *bif; + int s; + + s = splnet(); + + STPLOG (("Port Status: ")); + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + bstp_ifupdstatus(sc, bif); + } + STPLOG (("\n")); + + if (bstp_timer_expired(&sc->sc_hello_timer, sc->sc_hello_time)) + bstp_hello_timer_expiry(sc); + + if (bstp_timer_expired(&sc->sc_tcn_timer, sc->sc_bridge_hello_time)) + bstp_tcn_timer_expiry(sc); + + if (bstp_timer_expired(&sc->sc_topology_change_timer, + sc->sc_topology_change_time)) + bstp_topology_change_timer_expiry(sc); + + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + if (bstp_timer_expired(&bif->bif_message_age_timer, + sc->sc_max_age)) + bstp_message_age_timer_expiry(sc, bif); + } + + LIST_FOREACH(bif, &sc->sc_iflist, next) { + if (!(bif->bif_flags & IFBIF_STP)) + continue; + if (bstp_timer_expired(&bif->bif_forward_delay_timer, + sc->sc_forward_delay)) + bstp_forward_delay_timer_expiry(sc, bif); + + if (bstp_timer_expired(&bif->bif_hold_timer, + sc->sc_hold_time)) + bstp_hold_timer_expiry(sc, bif); + } + +#ifdef __ECOS + if (sc->sc_if.if_flags & IFF_RUNNING) { + timeout (bstp_tick, sc, hz); + } +#else + if (sc->sc_if.if_flags & IFF_RUNNING) + timeout_add(&sc->sc_bstptimeout, hz); +#endif //__ECOS + + splx(s); +} + +void +bstp_timer_start(t, v) + struct bridge_timer *t; + u_int16_t v; +{ + t->value = v; + t->active = 1; +} + +void +bstp_timer_stop(t) + struct bridge_timer *t; +{ + t->value = 0; + t->active = 0; +} + +int +bstp_timer_expired(t, v) + struct bridge_timer *t; + u_int16_t v; +{ + if (!t->active) + return (0); + t->value += BSTP_TICK_VAL; + if (t->value >= v) { + bstp_timer_stop(t); + return (1); + } + return (0); + +} + +int +bstp_ioctl(ifp, cmd, data) + struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + struct ifbrparam *bp = (struct ifbrparam *)data; + struct bridge_softc *sc = (struct bridge_softc *)ifp; + int r = 0, err = 0; + + switch (cmd) { + case SIOCBRDGGPRI: + bp->ifbrp_prio = sc->sc_bridge_priority; + break; + case SIOCBRDGGMA: + bp->ifbrp_maxage = sc->sc_bridge_max_age >> 8; + break; + case SIOCBRDGGHT: + bp->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8; + break; + case SIOCBRDGGFD: + bp->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8; + break; + case SIOCBRDGSPRI: + sc->sc_bridge_priority = bp->ifbrp_prio; + r = 1; + break; + case SIOCBRDGSMA: + if (bp->ifbrp_maxage == 0) { + err = EINVAL; + break; + } + sc->sc_bridge_max_age = bp->ifbrp_maxage << 8; + r = 1; + break; + case SIOCBRDGSHT: + if (bp->ifbrp_hellotime == 0) { + err = EINVAL; + break; + } + sc->sc_bridge_hello_time = bp->ifbrp_hellotime << 8; + r = 1; + break; + case SIOCBRDGSFD: + if (bp->ifbrp_fwddelay == 0) { + err = EINVAL; + break; + } + sc->sc_bridge_forward_delay = bp->ifbrp_fwddelay << 8; + r = 1; + break; + case SIOCBRDGSIFCOST: + case SIOCBRDGSIFPRIO: + case SIOCBRDGSIFFLGS: + case SIOCBRDGADD: + case SIOCBRDGDEL: + r = 1; + break; + default: + break; + } + + if (r) + bstp_initialization(sc); + + return (err); +} + +#endif /* NBRIDGE */ +#endif /* CYGPKG_NET_BRIDGE_STP_CODE */ diff --git a/ecos/packages/net/tcpip/current/src/sys/net/if.c b/ecos/packages/net/tcpip/current/src/sys/net/if.c new file mode 100644 index 0000000..3a07cb7 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/if.c @@ -0,0 +1,959 @@ +//========================================================================== +// +// sys/net/if.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if.c,v 1.25 1999/12/08 06:50:17 itojun Exp $ */ +/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1980, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if.c 8.3 (Berkeley) 1/4/94 + */ + +#ifdef __ECOS +#include <pkgconf/net.h> +#else +#include "bpfilter.h" +#include "bridge.h" +#endif + +#include <sys/param.h> +#include <sys/mbuf.h> +#ifndef __ECOS +#include <sys/systm.h> +#include <sys/proc.h> +#endif +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/protosw.h> +#include <sys/kernel.h> +#include <sys/ioctl.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> +#include <net/radix.h> + +#include <net/route.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/if_ether.h> +#include <netinet/igmp.h> +#ifdef MROUTING +#include <netinet/ip_mroute.h> +#endif +#endif + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#endif + +#ifdef IPFILTER +#include <netinet/ip_fil_compat.h> +#include <netinet/ip_fil.h> +#include <netinet/ip_nat.h> +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#endif + +#if NBRIDGE > 0 +#include <net/if_bridge.h> +#endif + +void if_attachsetup __P((struct ifnet *)); +int if_detach_rtdelete __P((struct radix_node *, void *)); + +int ifqmaxlen = IFQ_MAXLEN; +void if_slowtimo __P((void *arg)); + +#ifdef INET6 +/* + * XXX: declare here to avoid to include many inet6 related files.. + * should be more generalized? + */ +extern void nd6_setmtu __P((struct ifnet *)); +#endif + +/* + * Network interface utility routines. + * + * Routines with ifa_ifwith* names take sockaddr *'s as + * parameters. + */ +void +ifinit() +{ + register struct ifnet *ifp; + + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; + if_slowtimo(NULL); +} + +int if_index = 0; +struct ifaddr **ifnet_addrs = NULL; +struct ifnet **ifindex2ifnet = NULL; + +/* + * Attach an interface to the + * list of "active" interfaces. + */ +void +if_attachsetup(ifp) + struct ifnet *ifp; +{ + unsigned int socksize, ifasize; + int namelen, masklen; + register struct sockaddr_dl *sdl; + register struct ifaddr *ifa; + static int if_indexlim = 8; + + ifp->if_index = ++if_index; + + /* + * We have some arrays that should be indexed by if_index. + * since if_index will grow dynamically, they should grow too. + * struct ifadd **ifnet_addrs + * struct ifnet **ifindex2ifnet + */ + if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) { + size_t n; + caddr_t q; + + while (if_index >= if_indexlim) + if_indexlim <<= 1; + + /* grow ifnet_addrs */ + n = if_indexlim * sizeof(ifa); + q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); + bzero(q, n); + if (ifnet_addrs) { + bcopy((caddr_t)ifnet_addrs, q, n/2); + free((caddr_t)ifnet_addrs, M_IFADDR); + } + ifnet_addrs = (struct ifaddr **)q; + + /* grow ifindex2ifnet */ + n = if_indexlim * sizeof(struct ifnet *); + q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); + bzero(q, n); + if (ifindex2ifnet) { + bcopy((caddr_t)ifindex2ifnet, q, n/2); + free((caddr_t)ifindex2ifnet, M_IFADDR); + } + ifindex2ifnet = (struct ifnet **)q; + } + + ifindex2ifnet[if_index] = ifp; + + /* + * create a Link Level name for this device + */ + namelen = strlen(ifp->if_xname); +#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) + masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; + socksize = masklen + ifp->if_addrlen; +#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) + if (socksize < sizeof(*sdl)) + socksize = sizeof(*sdl); + socksize = ROUNDUP(socksize); + ifasize = sizeof(*ifa) + 2 * socksize; + ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); + bzero((caddr_t)ifa, ifasize); + sdl = (struct sockaddr_dl *)(ifa + 1); + sdl->sdl_len = socksize; + sdl->sdl_family = AF_LINK; + bcopy(ifp->if_xname, sdl->sdl_data, namelen); + sdl->sdl_nlen = namelen; + sdl->sdl_index = ifp->if_index; + sdl->sdl_type = ifp->if_type; + ifnet_addrs[if_index] = ifa; + ifa->ifa_ifp = ifp; + ifa->ifa_rtrequest = link_rtrequest; + TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list); + ifa->ifa_addr = (struct sockaddr *)sdl; + sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); + ifa->ifa_netmask = (struct sockaddr *)sdl; + sdl->sdl_len = masklen; + while (namelen != 0) + sdl->sdl_data[--namelen] = 0xff; +} + +void +if_attachhead(ifp) + struct ifnet *ifp; +{ + if (if_index == 0) + TAILQ_INIT(&ifnet); + TAILQ_INIT(&ifp->if_addrlist); + TAILQ_INSERT_HEAD(&ifnet, ifp, if_list); + if_attachsetup(ifp); +} + +void +if_attach(ifp) + struct ifnet *ifp; +{ +// Initialize queue - moved here to support "late" attaches + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; +// + if (if_index == 0) + TAILQ_INIT(&ifnet); + TAILQ_INIT(&ifp->if_addrlist); + TAILQ_INSERT_TAIL(&ifnet, ifp, if_list); + if_attachsetup(ifp); +} + +/* + * Delete a route if it has a specific interface for output. + * This function complies to the rn_walktree callback API. + */ +int +if_detach_rtdelete(rn, vifp) + struct radix_node *rn; + void *vifp; +{ + struct ifnet *ifp = vifp; + struct rtentry *rt = (struct rtentry *)rn; + + if (rt->rt_ifp == ifp) + rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), + 0, NULL); + + /* + * XXX There should be no need to check for rt_ifa belonging to this + * interface, because then rt_ifp is set, right? + */ + + return (0); +} + +/* + * Detach an interface from everything in the kernel. Also deallocate + * private resources. + * XXX So far only the INET protocol family has been looked over + * wrt resource usage that needs to be decoupled. + */ +void +if_detach(ifp) + struct ifnet *ifp; +{ + struct ifaddr *ifa; + int i, s = splimp(); + struct radix_node_head *rnh; + +#if NBRIDGE > 0 + /* Remove the interface from any bridge it is part of. */ + if (ifp->if_bridge) + bridge_ifdetach(ifp); +#endif + +#if NBPFILTER > 0 + /* If there is a bpf device attached, detach from it. */ + if (ifp->if_bpf) + bpfdetach(ifp); +#endif + + /* + * Find and remove all routes which is using this interface. + * XXX Factor out into a route.c function? + */ + for (i = 1; i <= AF_MAX; i++) { + rnh = rt_tables[i]; + if (rnh) + (*rnh->rnh_walktree)(rnh, if_detach_rtdelete, ifp); + } + +#ifdef INET + rti_delete(ifp); + myip_ifp = NULL; +#ifdef MROUTING + vif_delete(ifp); +#endif +#endif + /* + * XXX transient ifp refs? inpcb.ip_moptions.imo_multicast_ifp? + * Other network stacks than INET? + */ + + /* Remove the interface from the list of all interfaces. */ + TAILQ_REMOVE(&ifnet, ifp, if_list); + +#ifdef IPFILTER + /* XXX More ipf & ipnat cleanup needed. */ + nat_ifdetach(ifp); +#endif + + /* Deallocate private resources. */ + for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa; + ifa = TAILQ_FIRST(&ifp->if_addrlist)) { + TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list); +#ifdef INET + if (ifa->ifa_addr->sa_family == AF_INET) + TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa, + ia_list); +#endif + free(ifa, M_IFADDR); + } + splx(s); +} + +/* + * Locate an interface based on a complete address. + */ +/*ARGSUSED*/ +struct ifaddr * +ifa_ifwithaddr(addr) + register struct sockaddr *addr; +{ + register struct ifnet *ifp; + register struct ifaddr *ifa; + +#define equal(a1, a2) \ + (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != addr->sa_family) + continue; + if (ifa->ifa_dstaddr == NULL) + continue; + if (equal(addr, ifa->ifa_addr)) + return (ifa); + if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && + /* IP6 doesn't have broadcast */ + ifa->ifa_broadaddr->sa_len != 0 && + equal(ifa->ifa_broadaddr, addr)) + return (ifa); + } + return (NULL); +} +/* + * Locate the point to point interface with a given destination address. + */ +/*ARGSUSED*/ +struct ifaddr * +ifa_ifwithdstaddr(addr) + register struct sockaddr *addr; +{ + register struct ifnet *ifp; + register struct ifaddr *ifa; + + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + if (ifp->if_flags & IFF_POINTOPOINT) + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != addr->sa_family || + ifa->ifa_dstaddr == NULL) + continue; + if (equal(addr, ifa->ifa_dstaddr)) + return (ifa); + } + return (NULL); +} + +/* + * Find an interface on a specific network. If many, choice + * is most specific found. + */ +struct ifaddr * +ifa_ifwithnet(addr) + struct sockaddr *addr; +{ + register struct ifnet *ifp; + register struct ifaddr *ifa; + struct ifaddr *ifa_maybe = 0; + u_int af = addr->sa_family; + char *addr_data = addr->sa_data, *cplim; + + if (af == AF_LINK) { + register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; + if (sdl->sdl_index && sdl->sdl_index <= if_index) + return (ifnet_addrs[sdl->sdl_index]); + } + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { + register char *cp, *cp2, *cp3; + + if (ifa->ifa_addr->sa_family != af || + ifa->ifa_netmask == 0) + next: continue; + cp = addr_data; + cp2 = ifa->ifa_addr->sa_data; + cp3 = ifa->ifa_netmask->sa_data; + cplim = (char *)ifa->ifa_netmask + + ifa->ifa_netmask->sa_len; + while (cp3 < cplim) + if ((*cp++ ^ *cp2++) & *cp3++) + /* want to continue for() loop */ + goto next; + if (ifa_maybe == 0 || + rn_refines((caddr_t)ifa->ifa_netmask, + (caddr_t)ifa_maybe->ifa_netmask)) + ifa_maybe = ifa; + } + return (ifa_maybe); +} + +/* + * Find an interface using a specific address family + */ +struct ifaddr * +ifa_ifwithaf(af) + register int af; +{ + register struct ifnet *ifp; + register struct ifaddr *ifa; + + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) + if (ifa->ifa_addr->sa_family == af) + return (ifa); + return (NULL); +} + +/* + * Find an interface address specific to an interface best matching + * a given address. + */ +struct ifaddr * +ifaof_ifpforaddr(addr, ifp) + struct sockaddr *addr; + register struct ifnet *ifp; +{ + register struct ifaddr *ifa; + register char *cp, *cp2, *cp3; + register char *cplim; + struct ifaddr *ifa_maybe = 0; + u_int af = addr->sa_family; + + if (af >= AF_MAX) + return (NULL); + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != af) + continue; + ifa_maybe = ifa; + if (ifa->ifa_netmask == 0) { + if (equal(addr, ifa->ifa_addr) || + (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) + return (ifa); + continue; + } + cp = addr->sa_data; + cp2 = ifa->ifa_addr->sa_data; + cp3 = ifa->ifa_netmask->sa_data; + cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; + for (; cp3 < cplim; cp3++) + if ((*cp++ ^ *cp2++) & *cp3) + break; + if (cp3 == cplim) + return (ifa); + } + return (ifa_maybe); +} + +/* + * Default action when installing a route with a Link Level gateway. + * Lookup an appropriate real ifa to point to. + * This should be moved to /sys/net/link.c eventually. + */ +void +link_rtrequest(cmd, rt, sa) + int cmd; + register struct rtentry *rt; + struct sockaddr *sa; +{ + register struct ifaddr *ifa; + struct sockaddr *dst; + struct ifnet *ifp; + + if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || + ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) + return; + if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) { + IFAFREE(rt->rt_ifa); + rt->rt_ifa = ifa; + ifa->ifa_refcnt++; + if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) + ifa->ifa_rtrequest(cmd, rt, sa); + } +} + +/* + * Mark an interface down and notify protocols of + * the transition. + * NOTE: must be called at splsoftnet or equivalent. + */ +void +if_down(ifp) + register struct ifnet *ifp; +{ + register struct ifaddr *ifa; + + ifp->if_flags &= ~IFF_UP; + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) + pfctlinput(PRC_IFDOWN, ifa->ifa_addr); + if_qflush(&ifp->if_snd); + rt_ifmsg(ifp); +} + +/* + * Mark an interface up and notify protocols of + * the transition. + * NOTE: must be called at splsoftnet or equivalent. + */ +void +if_up(ifp) + register struct ifnet *ifp; +{ +#ifdef notyet + register struct ifaddr *ifa; +#endif + + ifp->if_flags |= IFF_UP; +#ifdef notyet + /* this has no effect on IP, and will kill all ISO connections XXX */ + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; + ifa = ifa->ifa_list.tqe_next) + pfctlinput(PRC_IFUP, ifa->ifa_addr); +#endif + rt_ifmsg(ifp); +#ifdef INET6 + in6_if_up(ifp); +#endif +} + +/* + * Flush an interface queue. + */ +void +if_qflush(ifq) + register struct ifqueue *ifq; +{ + register struct mbuf *m, *n; + + n = ifq->ifq_head; + while ((m = n) != NULL) { + n = m->m_act; + m_freem(m); + } + ifq->ifq_head = 0; + ifq->ifq_tail = 0; + ifq->ifq_len = 0; +} + +/* + * Handle interface watchdog timer routines. Called + * from softclock, we decrement timers (if set) and + * call the appropriate interface routine on expiration. + */ +void +if_slowtimo(arg) + void *arg; +{ + register struct ifnet *ifp; + int s = splimp(); + + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) { + if (ifp->if_timer == 0 || --ifp->if_timer) + continue; + if (ifp->if_watchdog) + (*ifp->if_watchdog)(ifp); + } + splx(s); + timeout(if_slowtimo, NULL, hz / IFNET_SLOWHZ); +} + +/* + * Map interface name to + * interface structure pointer. + */ +struct ifnet * +ifunit(name) + register char *name; +{ + register struct ifnet *ifp; + + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + if (strcmp(ifp->if_xname, name) == 0) + return (ifp); + + return (NULL); +} + + +/* + * Map interface name in a sockaddr_dl to + * interface structure pointer. + */ +struct ifnet * +if_withname(sa) + struct sockaddr *sa; +{ + char ifname[IFNAMSIZ+1]; + struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; + + if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) || + (sdl->sdl_nlen > IFNAMSIZ) ) + return NULL; + + /* + * ifunit wants a null-terminated name. It may not be null-terminated + * in the sockaddr. We don't want to change the caller's sockaddr, + * and there might not be room to put the trailing null anyway, so we + * make a local copy that we know we can null terminate safely. + */ + + bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen); + ifname[sdl->sdl_nlen] = '\0'; + return ifunit(ifname); +} + + +/* + * Interface ioctls. + */ +int +ifioctl(so, cmd, data, p) + struct socket *so; + u_long cmd; + caddr_t data; + struct proc *p; +{ + register struct ifnet *ifp; + register struct ifreq *ifr; + int error = 0; + short oif_flags; + + switch (cmd) { + + case SIOCGIFCONF: + case OSIOCGIFCONF: + return (ifconf(cmd, data)); + } + ifr = (struct ifreq *)data; + ifp = ifunit(ifr->ifr_name); + if (ifp == 0) + return (ENXIO); + oif_flags = ifp->if_flags; + switch (cmd) { + + case SIOCGIFFLAGS: + ifr->ifr_flags = ifp->if_flags; + break; + + case SIOCGIFMETRIC: + ifr->ifr_metric = ifp->if_metric; + break; + + case SIOCGIFDATA: + error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data, + sizeof(ifp->if_data)); + break; + + case SIOCSIFFLAGS: +#ifndef __ECOS + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); +#endif + if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { + int s = splimp(); + if_down(ifp); + splx(s); + } + if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { + int s = splimp(); + if_up(ifp); + splx(s); + } + ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | + (ifr->ifr_flags &~ IFF_CANTCHANGE); + if (ifp->if_ioctl) + (void) (*ifp->if_ioctl)(ifp, cmd, data); + break; + + case SIOCSIFMETRIC: +#ifndef __ECOS + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); +#endif + ifp->if_metric = ifr->ifr_metric; + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + case SIOCSIFMEDIA: +#ifndef __ECOS + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); +#endif + /* FALLTHROUGH */ +#ifdef SIOCGIFSTATS + case SIOCGIFSTATS: +#ifdef SIOCGIFSTATSUD + case SIOCGIFSTATSUD: +#endif +#endif // SIOCGIFSTATS + case SIOCGIFMEDIA: + if (ifp->if_ioctl == 0) + return (EOPNOTSUPP); + error = (*ifp->if_ioctl)(ifp, cmd, data); + break; + + default: + if (so->so_proto == 0) + return (EOPNOTSUPP); +#if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4) + error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, + (struct mbuf *) cmd, (struct mbuf *) data, + (struct mbuf *) ifp)); +#else + { + u_long ocmd = cmd; + + switch (cmd) { + + case SIOCSIFADDR: + case SIOCSIFDSTADDR: + case SIOCSIFBRDADDR: + case SIOCSIFNETMASK: +#if BYTE_ORDER != BIG_ENDIAN + if (ifr->ifr_addr.sa_family == 0 && + ifr->ifr_addr.sa_len < 16) { + ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; + ifr->ifr_addr.sa_len = 16; + } +#else + if (ifr->ifr_addr.sa_len == 0) + ifr->ifr_addr.sa_len = 16; +#endif + break; + + case OSIOCGIFADDR: + cmd = SIOCGIFADDR; + break; + + case OSIOCGIFDSTADDR: + cmd = SIOCGIFDSTADDR; + break; + + case OSIOCGIFBRDADDR: + cmd = SIOCGIFBRDADDR; + break; + + case OSIOCGIFNETMASK: + cmd = SIOCGIFNETMASK; + } + error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, + (struct mbuf *) cmd, + (struct mbuf *) data, + (struct mbuf *) ifp)); + switch (ocmd) { + + case OSIOCGIFADDR: + case OSIOCGIFDSTADDR: + case OSIOCGIFBRDADDR: + case OSIOCGIFNETMASK: + *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; + } + + } +#endif + break; + } + + if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) { +#ifdef INET6 + if ((ifp->if_flags & IFF_UP) != 0) { + int s = splimp(); + in6_if_up(ifp); + splx(s); + } +#endif + } + return (error); +} + +/* + * Return interface configuration + * of system. List may be used + * in later ioctl's (above) to get + * other information. + */ +/*ARGSUSED*/ +int +ifconf(cmd, data) + u_long cmd; + caddr_t data; +{ + register struct ifconf *ifc = (struct ifconf *)data; + register struct ifnet *ifp; + register struct ifaddr *ifa; + struct ifreq ifr, *ifrp; + int space = ifc->ifc_len, error = 0; + + /* If ifc->ifc_len is 0, fill it in with the needed size and return. */ + if (space == 0) { + for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) { + register struct sockaddr *sa; + + if ((ifa = ifp->if_addrlist.tqh_first) == 0) + space += sizeof (ifr); + else + for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) { + sa = ifa->ifa_addr; +#if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) + if (cmd != OSIOCGIFCONF) +#endif + if (sa->sa_len > sizeof(*sa)) + space += sa->sa_len - + sizeof (*sa); + space += sizeof (ifr); + } + } + ifc->ifc_len = space; + return(0); + } + + ifrp = ifc->ifc_req; + for (ifp = ifnet.tqh_first; space >= sizeof (ifr) && ifp != 0; + ifp = ifp->if_list.tqe_next) { + bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ); + if ((ifa = ifp->if_addrlist.tqh_first) == 0) { + bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); + error = copyout((caddr_t)&ifr, (caddr_t)ifrp, + sizeof(ifr)); + if (error) + break; + space -= sizeof (ifr), ifrp++; + } else + for (; space >= sizeof (ifr) && ifa != 0; + ifa = ifa->ifa_list.tqe_next) { + register struct sockaddr *sa = ifa->ifa_addr; +#if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) + if (cmd == OSIOCGIFCONF) { + struct osockaddr *osa = + (struct osockaddr *)&ifr.ifr_addr; + ifr.ifr_addr = *sa; + osa->sa_family = sa->sa_family; + error = copyout((caddr_t)&ifr, (caddr_t)ifrp, + sizeof (ifr)); + ifrp++; + } else +#endif + if (sa->sa_len <= sizeof(*sa)) { + ifr.ifr_addr = *sa; + error = copyout((caddr_t)&ifr, (caddr_t)ifrp, + sizeof (ifr)); + ifrp++; + } else { + space -= sa->sa_len - sizeof(*sa); + if (space < sizeof (ifr)) + break; + error = copyout((caddr_t)&ifr, (caddr_t)ifrp, + sizeof (ifr.ifr_name)); + if (error == 0) + error = copyout((caddr_t)sa, + (caddr_t)&ifrp->ifr_addr, + sa->sa_len); + ifrp = (struct ifreq *)(sa->sa_len + + (caddr_t)&ifrp->ifr_addr); + } + if (error) + break; + space -= sizeof (ifr); + } + } + ifc->ifc_len -= space; + return (error); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/net/if_bridge.c b/ecos/packages/net/tcpip/current/src/sys/net/if_bridge.c new file mode 100644 index 0000000..04093c6 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/if_bridge.c @@ -0,0 +1,2349 @@ +//========================================================================== +// +// sys/net/if_bridge.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jason L. Wright (jason@thought.net) +// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt, manu.sharma@ascom.com +// Date: 2000-07-18 +// Purpose: Ethernet bridge +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/* $OpenBSD: if_bridge.c,v 1.33 2000/06/20 05:50:16 jason Exp $ */ + +/* + * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef __ECOS +#include <pkgconf/net.h> +#else +#include "bridge.h" +#include "bpfilter.h" +#include "enc.h" +#endif + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/proc.h> +#include <sys/systm.h> +#endif +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#ifndef __ECOS +#include <sys/device.h> +#endif +#include <sys/kernel.h> +#include <machine/cpu.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/if_llc.h> +#include <net/route.h> +#include <net/netisr.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> +#include <netinet/ip_ipsp.h> + +#ifndef __ECOS +#include <net/if_enc.h> +#endif +#ifdef IPFILTER +#include <netinet/ip_fil_compat.h> +#include <netinet/ip_fil.h> +#endif +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#endif + +#include <net/if_bridge.h> + +#ifdef __ECOS +#include <stdio.h> /* for sprintf */ +#endif + +#ifndef BRIDGE_RTABLE_SIZE +#define BRIDGE_RTABLE_SIZE 1024 +#endif +#define BRIDGE_RTABLE_MASK (BRIDGE_RTABLE_SIZE - 1) + +/* + * Maximum number of addresses to cache + */ +#ifndef BRIDGE_RTABLE_MAX +#define BRIDGE_RTABLE_MAX 100 +#endif + +/* + * Timeout (in seconds) for entries learned dynamically + */ +#ifndef BRIDGE_RTABLE_TIMEOUT +#define BRIDGE_RTABLE_TIMEOUT 300 +#endif + +/* Spanning tree defaults */ +#define BSTP_DEFAULT_MAX_AGE (20 * 256) +#define BSTP_DEFAULT_HELLO_TIME (2 * 256) +#define BSTP_DEFAULT_FORWARD_DELAY (15 * 256) +#define BSTP_DEFAULT_HOLD_TIME (1 * 256) +#define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000 +#define BSTP_DEFAULT_PORT_PRIORITY 0x80 +#define BSTP_DEFAULT_PATH_COST 55 + +extern int ifqmaxlen; + +/* SNAP LLC header */ +struct snap { + u_int8_t dsap; + u_int8_t ssap; + u_int8_t control; + u_int8_t org[3]; + u_int16_t type; +}; + +struct bridge_softc bridgectl[CYGNUM_NET_BRIDGES]; + +void bridgeattach __P((int)); +int bridge_ioctl __P((struct ifnet *, u_long, caddr_t)); +void bridge_start __P((struct ifnet *)); +void bridgeintr_frame __P((struct bridge_softc *, struct mbuf *)); +void bridge_broadcast __P((struct bridge_softc *, struct ifnet *, + struct ether_header *, struct mbuf *)) __attribute ((weak)); +void bridge_stop __P((struct bridge_softc *)); +void bridge_init __P((struct bridge_softc *)); +int bridge_bifconf __P((struct bridge_softc *, struct ifbifconf *)); + +int bridge_rtfind __P((struct bridge_softc *, struct ifbaconf *)); +void bridge_rtage __P((void *)); +void bridge_rttrim __P((struct bridge_softc *)); +int bridge_rtdaddr __P((struct bridge_softc *, struct ether_addr *)); +int bridge_rtflush __P((struct bridge_softc *, int)); +struct ifnet * bridge_rtupdate __P((struct bridge_softc *, + struct ether_addr *, struct ifnet *ifp, int, u_int8_t)); +struct ifnet * bridge_rtlookup __P((struct bridge_softc *, + struct ether_addr *)); +u_int32_t bridge_hash __P((struct ether_addr *)); +int bridge_blocknonip __P((struct ether_header *, struct mbuf *)); +int bridge_addrule __P((struct bridge_iflist *, + struct ifbrlreq *, int out)); +int bridge_flushrule __P((struct bridge_iflist *)); +int bridge_brlconf __P((struct bridge_softc *, struct ifbrlconf *)); +u_int8_t bridge_filterrule __P((struct brl_node *, struct ether_header *)); +int bridge_ifenqueue __P((struct bridge_softc *, struct ifnet *, struct mbuf *)); + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE +void bridge_span (struct bridge_softc *, struct ether_header *, struct mbuf *); +#endif + +#define ETHERADDR_IS_IP_MCAST(a) \ + /* struct etheraddr *a; */ \ + ((a)->ether_addr_octet[0] == 0x01 && \ + (a)->ether_addr_octet[1] == 0x00 && \ + (a)->ether_addr_octet[2] == 0x5e) + + +#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM)) +/* + * Filter hooks + */ +struct mbuf *bridge_filter __P((struct bridge_softc *, struct ifnet *, + struct ether_header *, struct mbuf *m)); +#endif + +void +bridgeattach(unused) + int unused; +{ + int i; + struct ifnet *ifp; + + for (i = 0; i < CYGNUM_NET_BRIDGES; i++) { + bridgectl[i].sc_brtmax = BRIDGE_RTABLE_MAX; + bridgectl[i].sc_brttimeout = (BRIDGE_RTABLE_TIMEOUT * hz) / 2; + bridgectl[i].sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE; + bridgectl[i].sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME; + bridgectl[i].sc_bridge_forward_delay= BSTP_DEFAULT_FORWARD_DELAY; + bridgectl[i].sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; + bridgectl[i].sc_hold_time = BSTP_DEFAULT_HOLD_TIME; + LIST_INIT(&bridgectl[i].sc_iflist); + LIST_INIT(&bridgectl[i].sc_spanlist); + ifp = &bridgectl[i].sc_if; + sprintf(ifp->if_xname, "bridge%d", i); + ifp->if_softc = &bridgectl[i]; + ifp->if_mtu = ETHERMTU; + ifp->if_ioctl = bridge_ioctl; + ifp->if_output = bridge_output; + ifp->if_start = bridge_start; + ifp->if_type = IFT_PROPVIRTUAL; + ifp->if_snd.ifq_maxlen = ifqmaxlen; + ifp->if_hdrlen = sizeof(struct ether_header); + if_attach(ifp); +#if NBPFILTER > 0 + bpfattach(&bridgectl[i].sc_if.if_bpf, ifp, + DLT_EN10MB, sizeof(struct ether_header)); +#endif + } +} + +int +bridge_ioctl(ifp, cmd, data) + struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ +#ifndef __ECOS + struct proc *prc = curproc; /* XXX */ +#endif + struct ifnet *ifs; + struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc; + struct ifbreq *req = (struct ifbreq *)data; + struct ifbaconf *baconf = (struct ifbaconf *)data; + struct ifbareq *bareq = (struct ifbareq *)data; + struct ifbcachereq *bcachereq = (struct ifbcachereq *)data; + struct ifbifconf *bifconf = (struct ifbifconf *)data; + struct ifbcachetoreq *bcacheto = (struct ifbcachetoreq *)data; + struct ifbrlreq *brlreq = (struct ifbrlreq *)data; + struct ifbrlconf *brlconf = (struct ifbrlconf *)data; + struct ifreq ifreq; + int error = 0, s; + struct bridge_iflist *p; + + s = splimp(); + switch (cmd) { + case SIOCBRDGADD: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + ifs = ifunit(req->ifbr_ifsname); + if (ifs == NULL) { /* no such interface */ + error = ENOENT; + break; + } + if (ifs->if_bridge == (caddr_t)sc) { + error = EEXIST; + break; + } + if (ifs->if_bridge != NULL) { + error = EBUSY; + break; + } + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + /* If it's in the span list, it can't be a member. */ + LIST_FOREACH(p, &sc->sc_spanlist, next) { + if (p->ifp == ifs) + break; + } + if (p != LIST_END(&sc->sc_spanlist)) { + error = EBUSY; + break; + } +#endif + + + if (ifs->if_type == IFT_ETHER) { + if ((ifs->if_flags & IFF_UP) == 0) { + /* + * Bring interface up long enough to set + * promiscuous flag, then shut it down again. + */ + strncpy(ifreq.ifr_name, req->ifbr_ifsname, + sizeof(ifreq.ifr_name) - 1); + ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0'; + ifs->if_flags |= IFF_UP; + ifreq.ifr_flags = ifs->if_flags; + error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS, + (caddr_t)&ifreq); + if (error != 0) + break; + + error = ifpromisc(ifs, 1); + if (error != 0) + break; + + strncpy(ifreq.ifr_name, req->ifbr_ifsname, + sizeof(ifreq.ifr_name) - 1); + ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0'; + ifs->if_flags &= ~IFF_UP; + ifreq.ifr_flags = ifs->if_flags; + error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS, + (caddr_t)&ifreq); + if (error != 0) { + ifpromisc(ifs, 0); + break; + } + } else { + error = ifpromisc(ifs, 1); + if (error != 0) + break; + } + } +#ifndef __ECOS +#if NENC > 0 + else if (ifs->if_type == IFT_ENC) { + /* Can't bind enc0 to a bridge */ + if (ifs->if_softc == &encif[0]) { + error = EINVAL; + break; + } + } +#endif /* NENC */ +#endif + else { + error = EINVAL; + break; + } + + p = (struct bridge_iflist *) malloc( + sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT); + if (p == NULL && ifs->if_type == IFT_ETHER) { + error = ENOMEM; + ifpromisc(ifs, 0); + break; + } + + p->ifp = ifs; + p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; + p->bif_priority = BSTP_DEFAULT_PORT_PRIORITY; + p->bif_path_cost = BSTP_DEFAULT_PATH_COST; + SIMPLEQ_INIT(&p->bif_brlin); + SIMPLEQ_INIT(&p->bif_brlout); + LIST_INSERT_HEAD(&sc->sc_iflist, p, next); + ifs->if_bridge = (caddr_t)sc; + break; + case SIOCBRDGDEL: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + p = LIST_FIRST(&sc->sc_iflist); + while (p != NULL) { + if (strncmp(p->ifp->if_xname, req->ifbr_ifsname, + sizeof(p->ifp->if_xname)) == 0) { + p->ifp->if_bridge = NULL; + + error = ifpromisc(p->ifp, 0); + + LIST_REMOVE(p, next); + bridge_rtdelete(sc, p->ifp, 0); + bridge_flushrule(p); + free(p, M_DEVBUF); + break; + } + p = LIST_NEXT(p, next); + } + if (p == NULL) { + error = ENOENT; + break; + } + break; + case SIOCBRDGIFS: + error = bridge_bifconf(sc, bifconf); + break; +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + case SIOCBRDGADDS: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + + ifs = ifunit(req->ifbr_ifsname); + if (ifs == NULL) { /* no such interface */ + error = ENOENT; + break; + } + if (ifs->if_bridge == (caddr_t)sc) { + error = EEXIST; + break; + } + if (ifs->if_bridge != NULL) { + error = EBUSY; + break; + } + LIST_FOREACH(p, &sc->sc_spanlist, next) { + if (p->ifp == ifs) + break; + } + if (p != LIST_END(&sc->sc_spanlist)) { + error = EBUSY; + break; + } + p = (struct bridge_iflist *)malloc( + sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT); + if (p == NULL) { + error = ENOMEM; + break; + } + bzero(p, sizeof(struct bridge_iflist)); + p->ifp = ifs; + SIMPLEQ_INIT(&p->bif_brlin); + SIMPLEQ_INIT(&p->bif_brlout); + LIST_INSERT_HEAD(&sc->sc_spanlist, p, next); + break; + case SIOCBRDGDELS: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + + LIST_FOREACH(p, &sc->sc_spanlist, next) { + if (strncmp(p->ifp->if_xname, req->ifbr_ifsname, + sizeof(p->ifp->if_xname)) == 0) { + LIST_REMOVE(p, next); + free(p, M_DEVBUF); + break; + } + } + if (p == LIST_END(&sc->sc_spanlist)) { + error = ENOENT; + break; + } + break; +#endif + + case SIOCBRDGGIFFLGS: + ifs = ifunit(req->ifbr_ifsname); + if (ifs == NULL) { + error = ENOENT; + break; + } + if ((caddr_t)sc != ifs->if_bridge) { + error = ESRCH; + break; + } + p = LIST_FIRST(&sc->sc_iflist); + while (p != NULL && p->ifp != ifs) { + p = LIST_NEXT(p, next); + } + if (p == NULL) { + error = ESRCH; + break; + } + req->ifbr_ifsflags = p->bif_flags; + req->ifbr_state = p->bif_state; + req->ifbr_priority = p->bif_priority; + req->ifbr_path_cost = p->bif_path_cost; + req->ifbr_portno = p->ifp->if_index & 0xff; + break; + case SIOCBRDGSIFFLGS: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + ifs = ifunit(req->ifbr_ifsname); + if (ifs == NULL) { + error = ENOENT; + break; + } + if ((caddr_t)sc != ifs->if_bridge) { + error = ESRCH; + break; + } + p = LIST_FIRST(&sc->sc_iflist); + while (p != NULL && p->ifp != ifs) { + p = LIST_NEXT(p, next); + } + if (p == NULL) { + error = ESRCH; + break; + } + p->bif_flags = req->ifbr_ifsflags; + break; + case SIOCBRDGSIFPRIO: + case SIOCBRDGSIFCOST: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + + ifs = ifunit(req->ifbr_ifsname); + if (ifs == NULL) { + error = ENOENT; + break; + } + if ((caddr_t)sc != ifs->if_bridge) { + error = ESRCH; + break; + } + LIST_FOREACH(p, &sc->sc_iflist, next) { + if (p->ifp == ifs) + break; + } + if (p == LIST_END(&sc->sc_iflist)) { + error = ESRCH; + break; + } + if (cmd == SIOCBRDGSIFPRIO) + p->bif_priority = req->ifbr_priority; + else { + if (req->ifbr_path_cost < 1) + error = EINVAL; + else + p->bif_path_cost = req->ifbr_path_cost; + } + break; + case SIOCBRDGRTS: + error = bridge_rtfind(sc, baconf); + break; + case SIOCBRDGFLUSH: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + error = bridge_rtflush(sc, req->ifbr_ifsflags); + break; + case SIOCBRDGSADDR: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + ifs = ifunit(bareq->ifba_ifsname); + if (ifs == NULL) { /* no such interface */ + error = ENOENT; + break; + } + + if (ifs->if_bridge == NULL || + ifs->if_bridge != (caddr_t)sc) { + error = ESRCH; + break; + } + + ifs = bridge_rtupdate(sc, &bareq->ifba_dst, ifs, 1, + bareq->ifba_flags); + if (ifs == NULL) + error = ENOMEM; + break; + case SIOCBRDGDADDR: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + error = bridge_rtdaddr(sc, &bareq->ifba_dst); + break; + case SIOCBRDGGCACHE: + bcachereq->ifbc_size = sc->sc_brtmax; + break; + case SIOCBRDGSCACHE: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + sc->sc_brtmax = bcachereq->ifbc_size; + bridge_rttrim(sc); + break; + case SIOCBRDGSTO: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + sc->sc_brttimeout = (bcacheto->ifbct_time * hz) / 2; + untimeout(bridge_rtage, sc); + if (bcacheto->ifbct_time != 0) + timeout(bridge_rtage, sc, sc->sc_brttimeout); + break; + case SIOCBRDGGTO: + bcacheto->ifbct_time = (2 * sc->sc_brttimeout) / hz; + break; + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == IFF_UP) + bridge_init(sc); + + if ((ifp->if_flags & IFF_UP) == 0) + bridge_stop(sc); + + break; + case SIOCBRDGARL: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + ifs = ifunit(brlreq->ifbr_ifsname); + if (ifs == NULL) { + error = ENOENT; + break; + } + if (ifs->if_bridge == NULL || + ifs->if_bridge != (caddr_t)sc) { + error = ESRCH; + break; + } + p = LIST_FIRST(&sc->sc_iflist); + while (p != NULL && p->ifp != ifs) { + p = LIST_NEXT(p, next); + } + if (p == NULL) { + error = ESRCH; + break; + } + if ((brlreq->ifbr_action != BRL_ACTION_BLOCK && + brlreq->ifbr_action != BRL_ACTION_PASS) || + (brlreq->ifbr_flags & (BRL_FLAG_IN|BRL_FLAG_OUT)) == 0) { + error = EINVAL; + break; + } + if (brlreq->ifbr_flags & BRL_FLAG_IN) { + error = bridge_addrule(p, brlreq, 0); + if (error) + break; + } + if (brlreq->ifbr_flags & BRL_FLAG_OUT) { + error = bridge_addrule(p, brlreq, 1); + if (error) + break; + } + break; + case SIOCBRDGFRL: +#ifndef __ECOS + if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) + break; +#endif + ifs = ifunit(brlreq->ifbr_ifsname); + if (ifs == NULL) { + error = ENOENT; + break; + } + if (ifs->if_bridge == NULL || + ifs->if_bridge != (caddr_t)sc) { + error = ESRCH; + break; + } + p = LIST_FIRST(&sc->sc_iflist); + while (p != NULL && p->ifp != ifs) { + p = LIST_NEXT(p, next); + } + if (p == NULL) { + error = ESRCH; + break; + } + error = bridge_flushrule(p); + break; + case SIOCBRDGGRL: + error = bridge_brlconf(sc, brlconf); + break; + case SIOCBRDGGPRI: + case SIOCBRDGGMA: + case SIOCBRDGGHT: + case SIOCBRDGGFD: + break; + case SIOCBRDGSPRI: + case SIOCBRDGSFD: + case SIOCBRDGSMA: + case SIOCBRDGSHT: +#ifndef __ECOS + error = suser(prc->p_ucred, &prc->p_acflag); +#endif + break; + default: + error = EINVAL; + } + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + if (!error) + error = bstp_ioctl(ifp, cmd, data); +#endif + splx(s); + return (error); +} + +/* Detach an interface from a bridge. */ +void +bridge_ifdetach(ifp) + struct ifnet *ifp; +{ + struct bridge_softc *bsc = (struct bridge_softc *)ifp->if_bridge; + struct bridge_iflist *bif; + + for (bif = LIST_FIRST(&bsc->sc_iflist); bif; + bif = LIST_NEXT(bif, next)) + if (bif->ifp == ifp) { + LIST_REMOVE(bif, next); + bridge_rtdelete(bsc, ifp, 0); + bridge_flushrule(bif); + free(bif, M_DEVBUF); + ifp->if_bridge = NULL; + break; + } +} + +int +bridge_bifconf(sc, bifc) + struct bridge_softc *sc; + struct ifbifconf *bifc; +{ + struct bridge_iflist *p; + u_int32_t total = 0, i; +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + u_int32_t j; +#endif + int error = 0; + struct ifbreq breq; + + p = LIST_FIRST(&sc->sc_iflist); + while (p != NULL) { + total++; + p = LIST_NEXT(p, next); + } + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + p = LIST_FIRST(&sc->sc_spanlist); + while (p != NULL) { + total++; + p = LIST_NEXT(p, next); + } +#endif + + if (bifc->ifbic_len == 0) { + i = total; + goto done; + } + + p = LIST_FIRST(&sc->sc_iflist); + i = 0; + while (p != NULL && bifc->ifbic_len > i * sizeof(breq)) { + strncpy(breq.ifbr_name, sc->sc_if.if_xname, + sizeof(breq.ifbr_name)-1); + breq.ifbr_name[sizeof(breq.ifbr_name) - 1] = '\0'; + strncpy(breq.ifbr_ifsname, p->ifp->if_xname, + sizeof(breq.ifbr_ifsname)-1); + breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname) - 1] = '\0'; + breq.ifbr_ifsflags = p->bif_flags; + breq.ifbr_state = p->bif_state; + breq.ifbr_priority = p->bif_priority; + breq.ifbr_path_cost = p->bif_path_cost; + breq.ifbr_portno = p->ifp->if_index & 0xff; + error = copyout((caddr_t)&breq, + (caddr_t)(bifc->ifbic_req + i), sizeof(breq)); + if (error) + goto done; + p = LIST_NEXT(p, next); + i++; + bifc->ifbic_len -= sizeof(breq); + } + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + p = LIST_FIRST(&sc->sc_spanlist); + j = 0; + while (p != NULL && bifc->ifbic_len > j * sizeof(breq)) { + strncpy(breq.ifbr_name, sc->sc_if.if_xname, + sizeof(breq.ifbr_name)-1); + breq.ifbr_name[sizeof(breq.ifbr_name) - 1] = '\0'; + strncpy(breq.ifbr_ifsname, p->ifp->if_xname, + sizeof(breq.ifbr_ifsname)-1); + breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname) - 1] = '\0'; + breq.ifbr_ifsflags = p->bif_flags | IFBIF_SPAN; + breq.ifbr_state = p->bif_state; + breq.ifbr_priority = p->bif_priority; + breq.ifbr_path_cost = p->bif_path_cost; + breq.ifbr_portno = p->ifp->if_index & 0xff; + error = copyout((caddr_t)&breq, + (caddr_t)(bifc->ifbic_req + j), sizeof(breq)); + if (error) + goto done; + p = LIST_NEXT(p, next); + j++; + bifc->ifbic_len -= sizeof(breq); + } +#endif +done: + bifc->ifbic_len = i * sizeof(breq); + return (error); +} + +int +bridge_brlconf(sc, bc) + struct bridge_softc *sc; + struct ifbrlconf *bc; +{ + struct ifnet *ifp; + struct bridge_iflist *ifl; + struct brl_node *n; + struct ifbrlreq req; + int error = 0; + u_int32_t i, total=0; + + ifp = ifunit(bc->ifbrl_ifsname); + if (ifp == NULL) + return (ENOENT); + if (ifp->if_bridge == NULL || ifp->if_bridge != (caddr_t)sc) + return (ESRCH); + ifl = LIST_FIRST(&sc->sc_iflist); + while (ifl != NULL && ifl->ifp != ifp) + ifl = LIST_NEXT(ifl, next); + if (ifl == NULL) + return (ESRCH); + + n = SIMPLEQ_FIRST(&ifl->bif_brlin); + while (n != NULL) { + total++; + n = SIMPLEQ_NEXT(n, brl_next); + } + n = SIMPLEQ_FIRST(&ifl->bif_brlout); + while (n != NULL) { + total++; + n = SIMPLEQ_NEXT(n, brl_next); + } + + if (bc->ifbrl_len == 0) { + i = total; + goto done; + } + + i = 0; + n = SIMPLEQ_FIRST(&ifl->bif_brlin); + while (n != NULL && bc->ifbrl_len > i * sizeof(req)) { + strncpy(req.ifbr_name, sc->sc_if.if_xname, + sizeof(req.ifbr_name) - 1); + req.ifbr_name[sizeof(req.ifbr_name) - 1] = '\0'; + strncpy(req.ifbr_ifsname, ifl->ifp->if_xname, + sizeof(req.ifbr_ifsname) - 1); + req.ifbr_ifsname[sizeof(req.ifbr_ifsname) - 1] = '\0'; + req.ifbr_action = n->brl_action; + req.ifbr_flags = n->brl_flags; + req.ifbr_src = n->brl_src; + req.ifbr_dst = n->brl_dst; + error = copyout((caddr_t)&req, + (caddr_t)(bc->ifbrl_buf + (i * sizeof(req))), sizeof(req)); + if (error) + goto done; + n = SIMPLEQ_NEXT(n, brl_next); + i++; + bc->ifbrl_len -= sizeof(req); + } + + n = SIMPLEQ_FIRST(&ifl->bif_brlout); + while (n != NULL && bc->ifbrl_len > i * sizeof(req)) { + strncpy(req.ifbr_name, sc->sc_if.if_xname, + sizeof(req.ifbr_name) - 1); + req.ifbr_name[sizeof(req.ifbr_name) - 1] = '\0'; + strncpy(req.ifbr_ifsname, ifl->ifp->if_xname, + sizeof(req.ifbr_ifsname) - 1); + req.ifbr_ifsname[sizeof(req.ifbr_ifsname) - 1] = '\0'; + req.ifbr_action = n->brl_action; + req.ifbr_flags = n->brl_flags; + req.ifbr_src = n->brl_src; + req.ifbr_dst = n->brl_dst; + error = copyout((caddr_t)&req, + (caddr_t)(bc->ifbrl_buf + (i * sizeof(req))), sizeof(req)); + if (error) + goto done; + n = SIMPLEQ_NEXT(n, brl_next); + i++; + bc->ifbrl_len -= sizeof(req); + } + +done: + bc->ifbrl_len = i * sizeof(req); + return (error); +} + +void +bridge_init(sc) + struct bridge_softc *sc; +{ + struct ifnet *ifp = &sc->sc_if; + int i, s; + + if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING) + return; + + s = splhigh(); + if (sc->sc_rts == NULL) { + sc->sc_rts = (struct bridge_rthead *)malloc( + BRIDGE_RTABLE_SIZE * (sizeof(struct bridge_rthead)), + M_DEVBUF, M_NOWAIT); + if (sc->sc_rts == NULL) { + splx(s); + return; + } + for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) { + LIST_INIT(&sc->sc_rts[i]); + } + } + ifp->if_flags |= IFF_RUNNING; + splx(s); + + if (sc->sc_brttimeout != 0) + timeout(bridge_rtage, sc, sc->sc_brttimeout); +} + +/* + * Stop the bridge and deallocate the routing table. + */ +void +bridge_stop(sc) + struct bridge_softc *sc; +{ + struct ifnet *ifp = &sc->sc_if; + + /* + * If we're not running, there's nothing to do. + */ + if ((ifp->if_flags & IFF_RUNNING) == 0) + return; + + untimeout(bridge_rtage, sc); + + bridge_rtflush(sc, IFBF_FLUSHDYN); + + ifp->if_flags &= ~IFF_RUNNING; +} + +/* + * Send output from the bridge. The mbuf has the ethernet header + * already attached. We must enqueue or free the mbuf before exiting. + */ +int +bridge_output(ifp, m, sa, rt) + struct ifnet *ifp; + struct mbuf *m; + struct sockaddr *sa; + struct rtentry *rt; +{ + struct ether_header *eh; + struct ifnet *dst_if; + struct ether_addr *src, *dst; + struct bridge_softc *sc; + int s; + + if (m->m_len < sizeof(*eh)) { + m = m_pullup(m, sizeof(*eh)); + if (m == NULL) + return (0); + } + eh = mtod(m, struct ether_header *); + dst = (struct ether_addr *)&eh->ether_dhost[0]; + src = (struct ether_addr *)&eh->ether_shost[0]; + sc = (struct bridge_softc *)ifp->if_bridge; + + s = splimp(); + + /* + * If bridge is down, but original output interface is up, + * go ahead and send out that interface. Otherwise the packet + * is dropped below. + */ + if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { + dst_if = ifp; + goto sendunicast; + } + + /* + * If the packet is a broadcast or we don't know a better way to + * get there, send to all interfaces. + */ + dst_if = bridge_rtlookup(sc, dst); + if (dst_if == NULL || eh->ether_dhost[0] & 1) { + struct bridge_iflist *p; + struct mbuf *mc; + int used = 0; + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + bridge_span(sc, NULL, m); +#endif + + for (p = LIST_FIRST(&sc->sc_iflist); p != NULL; + p = LIST_NEXT(p, next)) { + if ((p->ifp->if_flags & IFF_RUNNING) == 0) + continue; + if (IF_QFULL(&p->ifp->if_snd)) { + sc->sc_if.if_oerrors++; + continue; + } + + if (LIST_NEXT(p, next) == NULL) { + used = 1; + mc = m; + } else { + mc = m_copym(m, 0, M_COPYALL, M_NOWAIT); + if (mc == NULL) { + sc->sc_if.if_oerrors++; + continue; + } + } + + sc->sc_if.if_opackets++; + sc->sc_if.if_obytes += m->m_pkthdr.len; + // Also count the bytes in the outgoing interface; normally + // done in if_ethersubr.c but here we bypass that route. + p->ifp->if_obytes += m->m_pkthdr.len; + IF_ENQUEUE(&p->ifp->if_snd, mc); + if ((p->ifp->if_flags & IFF_OACTIVE) == 0) + (*p->ifp->if_start)(p->ifp); + } + if (!used) + m_freem(m); + splx(s); + return (0); + } + +sendunicast: + if ((dst_if->if_flags & IFF_RUNNING) == 0) { + m_freem(m); + splx(s); + return (0); + } + if (IF_QFULL(&dst_if->if_snd)) { + sc->sc_if.if_oerrors++; + m_freem(m); + splx(s); + return (0); + } + sc->sc_if.if_opackets++; + sc->sc_if.if_obytes += m->m_pkthdr.len; + // Also count the bytes in the outgoing interface; normally + // done in if_ethersubr.c but here we bypass that route. + dst_if->if_obytes += m->m_pkthdr.len; + IF_ENQUEUE(&dst_if->if_snd, m); + if ((dst_if->if_flags & IFF_OACTIVE) == 0) + (*dst_if->if_start)(dst_if); + splx(s); + return (0); +} + +/* + * Start output on the bridge. This function should never be called. + */ +void +bridge_start(ifp) + struct ifnet *ifp; +{ +} + +void +bridgeintr(void) +{ + struct bridge_softc *sc; + struct mbuf *m; + int i, s; + + for (i = 0; i < CYGNUM_NET_BRIDGES; i++) { + sc = &bridgectl[i]; + for (;;) { + s = splimp(); + IF_DEQUEUE(&sc->sc_if.if_snd, m); + splx(s); + if (m == NULL) + break; + bridgeintr_frame(sc, m); + } + } +} + +/* + * Loop through each bridge interface and process their input queues. + */ +void +bridgeintr_frame(sc, m) + struct bridge_softc *sc; + struct mbuf *m; +{ + int s; + struct ifnet *src_if, *dst_if; + struct bridge_iflist *ifl; + struct ether_addr *dst, *src; + struct ether_header eh; + + if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { + m_freem(m); + return; + } + + src_if = m->m_pkthdr.rcvif; + + /* + * Pick out 802.1D packets. + * */ +#ifdef CYGPKG_NET_BRIDGE_STP_CODE +#ifdef __ECOS + if (m->m_flags & (M_BCAST | M_MCAST)) { + if (bcmp (mtod(m,struct ether_header *), bstp_etheraddr, ETHER_ADDR_LEN) == 0) { + m_copydata(m, 0, sizeof(struct ether_header), (caddr_t)&eh); + m_adj (m, sizeof(struct ether_header)); + m = bstp_input(sc, src_if, &eh, m); + if (m == NULL) + return; + } + } +#endif // __ECOS +#endif + +#if NBPFILTER > 0 + if (sc->sc_if.if_bpf) + bpf_mtap(sc->sc_if.if_bpf, m); +#endif + + sc->sc_if.if_lastchange = time; + sc->sc_if.if_ipackets++; + sc->sc_if.if_ibytes += m->m_pkthdr.len; + + ifl = LIST_FIRST(&sc->sc_iflist); + while (ifl != NULL && ifl->ifp != src_if) { + ifl = LIST_NEXT(ifl, next); + } + if (ifl == NULL) { + m_freem(m); + return; + } + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + if ((ifl->bif_flags & IFBIF_STP) && + (ifl->bif_state == BSTP_IFSTATE_BLOCKING || + ifl->bif_state == BSTP_IFSTATE_LISTENING || + ifl->bif_state == BSTP_IFSTATE_DISABLED)) { + m_freem(m); + return; + } +#endif + + if (m->m_pkthdr.len < sizeof(eh)) { + m_freem(m); + return; + } + m_copydata(m, 0, sizeof(struct ether_header), (caddr_t)&eh); + dst = (struct ether_addr *)&eh.ether_dhost[0]; + src = (struct ether_addr *)&eh.ether_shost[0]; + + /* + * If interface is learning, and if source address + * is not broadcast or multicast, record it's address. + */ + if ((ifl->bif_flags & IFBIF_LEARNING) && + (eh.ether_shost[0] & 1) == 0 && + !(eh.ether_shost[0] == 0 && + eh.ether_shost[1] == 0 && + eh.ether_shost[2] == 0 && + eh.ether_shost[3] == 0 && + eh.ether_shost[4] == 0 && + eh.ether_shost[5] == 0)) + bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC); + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + if ((ifl->bif_flags & IFBIF_STP) && + (ifl->bif_state == BSTP_IFSTATE_LEARNING)) { + m_freem(m); + return; + } +#endif + /* + * At this point, the port either does not participate in stp or + * it is in forwarding state. + */ + + /* + * If packet is unicast, destined for someone on "this" + * side of the bridge, drop it. + */ + if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) { + dst_if = bridge_rtlookup(sc, dst); + if (dst_if == src_if) { + m_freem(m); + return; + } + } else + dst_if = NULL; + + /* + * Multicast packets get handled a little differently: + * If interface is: + * -link0,-link1 (default) Forward all multicast + * as broadcast. + * -link0,link1 Drop non-IP multicast, forward + * as broadcast IP multicast. + * link0,-link1 Drop IP multicast, forward as + * broadcast non-IP multicast. + * link0,link1 Drop all multicast. + */ + if (m->m_flags & M_MCAST) { + if ((sc->sc_if.if_flags & + (IFF_LINK0 | IFF_LINK1)) == + (IFF_LINK0 | IFF_LINK1)) { + m_freem(m); + return; + } + if (sc->sc_if.if_flags & IFF_LINK0 && + ETHERADDR_IS_IP_MCAST(dst)) { + m_freem(m); + return; + } + if (sc->sc_if.if_flags & IFF_LINK1 && + !ETHERADDR_IS_IP_MCAST(dst)) { + m_freem(m); + return; + } + } + + if (ifl->bif_flags & IFBIF_BLOCKNONIP && bridge_blocknonip(&eh, m)) { + m_freem(m); + return; + } + + if (SIMPLEQ_FIRST(&ifl->bif_brlin) && + bridge_filterrule(SIMPLEQ_FIRST(&ifl->bif_brlin), &eh) == + BRL_ACTION_BLOCK) { + m_freem(m); + return; + } + +#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM)) + m = bridge_filter(sc, src_if, &eh, m); + if (m == NULL) + return; +#endif + + /* + * If the packet is a multicast or broadcast OR if we don't + * know any better, forward it to all interfaces. + */ + if ((m->m_flags & (M_BCAST | M_MCAST)) || dst_if == NULL) { + sc->sc_if.if_imcasts++; + s = splimp(); + bridge_broadcast(sc, src_if, &eh, m); + splx(s); + return; + } + + /* + * At this point, we're dealing with a unicast frame going to a + * different interface + */ + if ((dst_if->if_flags & IFF_RUNNING) == 0) { + m_freem(m); + return; + } + ifl = LIST_FIRST(&sc->sc_iflist); + while (ifl != NULL && ifl->ifp != dst_if) + ifl = LIST_NEXT(ifl, next); +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + if ((ifl->bif_flags & IFBIF_STP) && + (ifl->bif_state == BSTP_IFSTATE_DISABLED || + ifl->bif_state == BSTP_IFSTATE_BLOCKING)) { + m_freem(m); + return; + } +#endif + + if (SIMPLEQ_FIRST(&ifl->bif_brlout) && + bridge_filterrule(SIMPLEQ_FIRST(&ifl->bif_brlout), &eh) == + BRL_ACTION_BLOCK) { + m_freem(m); + return; + } + s = splimp(); + if (IF_QFULL(&dst_if->if_snd)) { + sc->sc_if.if_oerrors++; + m_freem(m); + splx(s); + return; + } + sc->sc_if.if_opackets++; + sc->sc_if.if_obytes += m->m_pkthdr.len; + // Also count the bytes in the outgoing interface; normally + // done in if_ethersubr.c but here we bypass that route. + dst_if->if_obytes += m->m_pkthdr.len; + IF_ENQUEUE(&dst_if->if_snd, m); + if ((dst_if->if_flags & IFF_OACTIVE) == 0) + (*dst_if->if_start)(dst_if); + splx(s); +} + +/* + * Receive input from an interface. Queue the packet for bridging if its + * not for us, and schedule an interrupt. + */ +struct mbuf * +bridge_input(ifp, eh, m) + struct ifnet *ifp; + struct ether_header *eh; + struct mbuf *m; +{ + struct bridge_softc *sc; + int s; + struct bridge_iflist *ifl; + struct arpcom *ac; + struct mbuf *mc; + + /* + * Make sure this interface is a bridge member. + */ + if (ifp == NULL || ifp->if_bridge == NULL || m == NULL) + return (m); + + if ((m->m_flags & M_PKTHDR) == 0) + panic("bridge_input(): no HDR"); + + sc = (struct bridge_softc *)ifp->if_bridge; + if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) + return (m); + + LIST_FOREACH (ifl, &sc->sc_iflist, next) { + if (ifl->ifp == ifp) + break; + } + if (ifl == LIST_END (&sc->sc_iflist)) + return (m); + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + bridge_span(sc, eh, m); + /* + * Tap off 802.1D packets, they do not get forwarded + */ + if (m->m_flags & (M_BCAST | M_MCAST)) { + if (bcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0) { +#ifdef __ECOS + M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); + if (m == NULL) + return (NULL); + bcopy(eh, mtod(m, caddr_t), sizeof(struct ether_header)); + + s = splimp (); + if (IF_QFULL(&sc->sc_if.if_snd)) { + m_freem (m); + splx (s); + return (NULL); + } + IF_ENQUEUE(&sc->sc_if.if_snd, m); + splx (s); + schednetisr (NETISR_BRIDGE); + return (NULL); +#else + m = bstp_input(sc, ifp, eh, m); + if (m == NULL) + return (NULL); +#endif + } + } +#endif + + if (m->m_flags & (M_BCAST | M_MCAST)) { + /* + * make a copy of 'm' with 'eh' tacked on to the + * beginning. Return 'm' for local processing + * and enqueue the copy. Schedule netisr. + */ + mc = m_copym2(m, 0, M_COPYALL, M_NOWAIT); + if (mc == NULL) + return (m); + M_PREPEND(mc, sizeof(struct ether_header), M_DONTWAIT); + if (mc == NULL) + return (m); + bcopy(eh, mtod(mc, caddr_t), sizeof(struct ether_header)); + s = splimp(); + if (IF_QFULL(&sc->sc_if.if_snd)) { + m_freem(mc); + splx(s); + return (m); + } + IF_ENQUEUE(&sc->sc_if.if_snd, mc); + splx(s); + schednetisr(NETISR_BRIDGE); + return (m); + } + + /* + * No need to queue frames for ifs in blocking, disabled or listening state + */ +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + if ((ifl->bif_flags & IFBIF_STP) && + ((ifl->bif_state == BSTP_IFSTATE_BLOCKING) || + (ifl->bif_state == BSTP_IFSTATE_LISTENING) || + (ifl->bif_state == BSTP_IFSTATE_DISABLED))) + return (m); +#endif + + /* + * Unicast, make sure it's not for us. + */ + for (ifl = LIST_FIRST(&sc->sc_iflist);ifl; ifl = LIST_NEXT(ifl,next)) { + if (ifl->ifp->if_type != IFT_ETHER) + continue; + ac = (struct arpcom *)ifl->ifp; + if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0) { + if (ifl->bif_flags & IFBIF_LEARNING) + bridge_rtupdate(sc, + (struct ether_addr *)&eh->ether_shost, + ifp, 0, IFBAF_DYNAMIC); + m->m_pkthdr.rcvif = ifl->ifp; + return (m); + } + if (bcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN) == 0) { + m_freem(m); + return (NULL); + } + } + M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT); + if (m == NULL) + return (NULL); + bcopy(eh, mtod(m, caddr_t), sizeof(struct ether_header)); + s = splimp(); + if (IF_QFULL(&sc->sc_if.if_snd)) { + m_freem(m); + splx(s); + return (NULL); + } + IF_ENQUEUE(&sc->sc_if.if_snd, m); + splx(s); + schednetisr(NETISR_BRIDGE); + return (NULL); +} + +/* + * Send a frame to all interfaces that are members of the bridge + * (except the one it came in on). This code assumes that it is + * running at splnet or higher. + */ +void +bridge_broadcast(sc, ifp, eh, m) + struct bridge_softc *sc; + struct ifnet *ifp; + struct ether_header *eh; + struct mbuf *m; +{ + struct bridge_iflist *p; + struct mbuf *mc; + int used = 0; + + for (p = LIST_FIRST(&sc->sc_iflist); p; p = LIST_NEXT(p, next)) { + /* + * Don't retransmit out of the same interface where + * the packet was received from. + */ + if (p->ifp->if_index == ifp->if_index) + continue; + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + if ((p->bif_flags & IFBIF_STP) && + (p->bif_state != BSTP_IFSTATE_FORWARDING)) + continue; +#endif + + if ((p->bif_flags & IFBIF_DISCOVER) == 0 && + (m->m_flags & (M_BCAST | M_MCAST)) == 0) + continue; + + if ((p->ifp->if_flags & IFF_RUNNING) == 0) + continue; + + if (IF_QFULL(&p->ifp->if_snd)) { + sc->sc_if.if_oerrors++; + continue; + } + + if (SIMPLEQ_FIRST(&p->bif_brlout) && + bridge_filterrule(SIMPLEQ_FIRST(&p->bif_brlout), eh) == + BRL_ACTION_BLOCK) + continue; + + /* If last one, reuse the passed-in mbuf */ + if (LIST_NEXT(p, next) == NULL) { + mc = m; + used = 1; + } else { + mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT); + if (mc == NULL) { + sc->sc_if.if_oerrors++; + continue; + } + } + + if (p->bif_flags & IFBIF_BLOCKNONIP && + bridge_blocknonip(eh, mc)) { + m_freem(mc); + continue; + } + + sc->sc_if.if_opackets++; + sc->sc_if.if_obytes += mc->m_pkthdr.len; + if (ifp && ((eh->ether_shost[0] & 1) == 0) ) + ifp->if_omcasts++; + // Also count the bytes in the outgoing interface; normally + // done in if_ethersubr.c but here we bypass that route. + p->ifp->if_obytes += m->m_pkthdr.len; + IF_ENQUEUE(&p->ifp->if_snd, mc); + if ((p->ifp->if_flags & IFF_OACTIVE) == 0) + (*p->ifp->if_start)(p->ifp); + } + + if (!used) + m_freem(m); +} + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE +void +bridge_span(sc, eh, morig) + struct bridge_softc *sc; + struct ether_header *eh; + struct mbuf *morig; +{ + struct bridge_iflist *p; + struct ifnet *ifp; + struct mbuf *mc, *m; + int error; + + if (LIST_EMPTY(&sc->sc_spanlist)) + return; + + m = m_copym2(morig, 0, M_COPYALL, M_NOWAIT); + if (m == NULL) + return; + if (eh != NULL) { + M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT); + if (m == NULL) + return; + bcopy(eh, mtod(m, caddr_t), sizeof(struct ether_header)); + } + + LIST_FOREACH(p, &sc->sc_spanlist, next) { + ifp = p->ifp; + + if ((ifp->if_flags & IFF_RUNNING) == 0) + continue; + +#ifdef ALTQ + if (ALTQ_IS_ENABLED(&ifp->if_snd) == 0) +#endif + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); + sc->sc_if.if_oerrors++; + continue; + } + + mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT); + if (mc == NULL) { + sc->sc_if.if_oerrors++; + continue; + } + + error = bridge_ifenqueue(sc, ifp, m); + if (error) + continue; + } + m_freem(m); +} +#endif + +struct ifnet * +bridge_rtupdate(sc, ea, ifp, setflags, flags) + struct bridge_softc *sc; + struct ether_addr *ea; + struct ifnet *ifp; + int setflags; + u_int8_t flags; +{ + struct bridge_rtnode *p, *q; + u_int32_t h; + int s, dir; + + s = splhigh(); + if (sc->sc_rts == NULL) { + if (setflags && flags == IFBAF_STATIC) { + sc->sc_rts = (struct bridge_rthead *)malloc( + BRIDGE_RTABLE_SIZE * + (sizeof(struct bridge_rthead)),M_DEVBUF,M_NOWAIT); + + if (sc->sc_rts == NULL) + goto done; + + for (h = 0; h < BRIDGE_RTABLE_SIZE; h++) + LIST_INIT(&sc->sc_rts[h]); + } else + goto done; + } + + h = bridge_hash(ea); + p = LIST_FIRST(&sc->sc_rts[h]); + if (p == NULL) { + if (sc->sc_brtcnt >= sc->sc_brtmax) + goto done; + p = (struct bridge_rtnode *)malloc( + sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT); + if (p == NULL) + goto done; + + bcopy(ea, &p->brt_addr, sizeof(p->brt_addr)); + p->brt_if = ifp; + p->brt_age = 1; + + if (setflags) + p->brt_flags = flags; + else + p->brt_flags = IFBAF_DYNAMIC; + + LIST_INSERT_HEAD(&sc->sc_rts[h], p, brt_next); + sc->sc_brtcnt++; + goto want; + } + + do { + q = p; + p = LIST_NEXT(p, brt_next); + + dir = memcmp(ea, &q->brt_addr, sizeof(q->brt_addr)); + if (dir == 0) { + if (setflags) { + q->brt_if = ifp; + q->brt_flags = flags; + } + + if (q->brt_if == ifp) + q->brt_age = 1; + ifp = q->brt_if; + goto want; + } + + if (dir > 0) { + if (sc->sc_brtcnt >= sc->sc_brtmax) + goto done; + p = (struct bridge_rtnode *)malloc( + sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT); + if (p == NULL) + goto done; + + bcopy(ea, &p->brt_addr, sizeof(p->brt_addr)); + p->brt_if = ifp; + p->brt_age = 1; + + if (setflags) + p->brt_flags = flags; + else + p->brt_flags = IFBAF_DYNAMIC; + + LIST_INSERT_BEFORE(q, p, brt_next); + sc->sc_brtcnt++; + goto want; + } + + if (p == NULL) { + if (sc->sc_brtcnt >= sc->sc_brtmax) + goto done; + p = (struct bridge_rtnode *)malloc( + sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT); + if (p == NULL) + goto done; + + bcopy(ea, &p->brt_addr, sizeof(p->brt_addr)); + p->brt_if = ifp; + p->brt_age = 1; + + if (setflags) + p->brt_flags = flags; + else + p->brt_flags = IFBAF_DYNAMIC; + LIST_INSERT_AFTER(q, p, brt_next); + sc->sc_brtcnt++; + goto want; + } + } while (p != NULL); + +done: + ifp = NULL; +want: + splx(s); + return (ifp); +} + +struct ifnet * +bridge_rtlookup(sc, ea) + struct bridge_softc *sc; + struct ether_addr *ea; +{ + struct bridge_rtnode *p; + u_int32_t h; + int s, dir; + + /* + * Lock out everything else + */ + s = splhigh(); + + if (sc->sc_rts == NULL) + goto fail; + + h = bridge_hash(ea); + p = LIST_FIRST(&sc->sc_rts[h]); + while (p != NULL) { + dir = memcmp(ea, &p->brt_addr, sizeof(p->brt_addr)); + if (dir == 0) { + splx(s); + return (p->brt_if); + } + if (dir > 0) + goto fail; + p = LIST_NEXT(p, brt_next); + } +fail: + splx(s); + return (NULL); +} + +/* + * The following hash function is adapted from 'Hash Functions' by Bob Jenkins + * ("Algorithm Alley", Dr. Dobbs Journal, September 1997). + * "You may use this code any way you wish, private, educational, or + * commercial. It's free." + */ +#define mix(a,b,c) \ + do { \ + a -= b; a -= c; a ^= (c >> 13); \ + b -= c; b -= a; b ^= (a << 8); \ + c -= a; c -= b; c ^= (b >> 13); \ + a -= b; a -= c; a ^= (c >> 12); \ + b -= c; b -= a; b ^= (a << 16); \ + c -= a; c -= b; c ^= (b >> 5); \ + a -= b; a -= c; a ^= (c >> 3); \ + b -= c; b -= a; b ^= (a << 10); \ + c -= a; c -= b; c ^= (b >> 15); \ + } while(0) + +u_int32_t +bridge_hash(addr) + struct ether_addr *addr; +{ + u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = 0xdeadbeef; + + b += addr->ether_addr_octet[5] << 8; + b += addr->ether_addr_octet[4]; + a += addr->ether_addr_octet[3] << 24; + a += addr->ether_addr_octet[2] << 16; + a += addr->ether_addr_octet[1] << 8; + a += addr->ether_addr_octet[0]; + + mix(a, b, c); + return (c & BRIDGE_RTABLE_MASK); +} + +/* + * Trim the routing table so that we've got a number of routes + * less than or equal to the maximum. + */ +void +bridge_rttrim(sc) + struct bridge_softc *sc; +{ + struct bridge_rtnode *n, *p; + int s, i; + + s = splhigh(); + if (sc->sc_rts == NULL) + goto done; + + /* + * Make sure we have to trim the address table + */ + if (sc->sc_brtcnt <= sc->sc_brtmax) + goto done; + + /* + * Force an aging cycle, this might trim enough addresses. + */ + splx(s); + bridge_rtage(sc); + s = splhigh(); + + if (sc->sc_brtcnt <= sc->sc_brtmax) + goto done; + + for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) { + n = LIST_FIRST(&sc->sc_rts[i]); + while (n != NULL) { + p = LIST_NEXT(n, brt_next); + if ((n->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { + LIST_REMOVE(n, brt_next); + sc->sc_brtcnt--; + free(n, M_DEVBUF); + n = p; + if (sc->sc_brtcnt <= sc->sc_brtmax) + goto done; + } + } + } + +done: + if (sc->sc_rts != NULL && sc->sc_brtcnt == 0 && + (sc->sc_if.if_flags & IFF_UP) == 0) { + free(sc->sc_rts, M_DEVBUF); + sc->sc_rts = NULL; + } + + splx(s); +} + +/* + * Perform an aging cycle + */ +void +bridge_rtage(vsc) + void *vsc; +{ + struct bridge_softc *sc = (struct bridge_softc *)vsc; + struct bridge_rtnode *n, *p; + int s, i; + + s = splhigh(); + if (sc->sc_rts == NULL) { + splx(s); + return; + } + + for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) { + n = LIST_FIRST(&sc->sc_rts[i]); + while (n != NULL) { + if ((n->brt_flags & IFBAF_TYPEMASK) == IFBAF_STATIC) { + n->brt_age = !n->brt_age; + if (n->brt_age) + n->brt_age = 0; + n = LIST_NEXT(n, brt_next); + } else if (n->brt_age) { + n->brt_age = 0; + n = LIST_NEXT(n, brt_next); + } else { + p = LIST_NEXT(n, brt_next); + LIST_REMOVE(n, brt_next); + sc->sc_brtcnt--; + free(n, M_DEVBUF); + n = p; + } + } + } + splx(s); + + if (sc->sc_brttimeout != 0) + timeout(bridge_rtage, sc, sc->sc_brttimeout); +} + +/* + * Remove all dynamic addresses from the cache + */ +int +bridge_rtflush(sc, full) + struct bridge_softc *sc; + int full; +{ + int s, i; + struct bridge_rtnode *p, *n; + + s = splhigh(); + if (sc->sc_rts == NULL) + goto done; + + for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) { + n = LIST_FIRST(&sc->sc_rts[i]); + while (n != NULL) { + if (full || + (n->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { + p = LIST_NEXT(n, brt_next); + LIST_REMOVE(n, brt_next); + sc->sc_brtcnt--; + free(n, M_DEVBUF); + n = p; + } else + n = LIST_NEXT(n, brt_next); + } + } + + if (sc->sc_brtcnt == 0 && (sc->sc_if.if_flags & IFF_UP) == 0) { + free(sc->sc_rts, M_DEVBUF); + sc->sc_rts = NULL; + } + +done: + splx(s); + return (0); +} + +/* + * Remove an address from the cache + */ +int +bridge_rtdaddr(sc, ea) + struct bridge_softc *sc; + struct ether_addr *ea; +{ + int h, s; + struct bridge_rtnode *p; + + s = splhigh(); + if (sc->sc_rts == NULL) + goto done; + + h = bridge_hash(ea); + p = LIST_FIRST(&sc->sc_rts[h]); + while (p != NULL) { + if (bcmp(ea, &p->brt_addr, sizeof(p->brt_addr)) == 0) { + LIST_REMOVE(p, brt_next); + sc->sc_brtcnt--; + free(p, M_DEVBUF); + if (sc->sc_brtcnt == 0 && + (sc->sc_if.if_flags & IFF_UP) == 0) { + free(sc->sc_rts, M_DEVBUF); + sc->sc_rts = NULL; + } + splx(s); + return (0); + } + p = LIST_NEXT(p, brt_next); + } + +done: + splx(s); + return (ENOENT); +} +/* + * Delete routes to a specific interface member. + */ +void +bridge_rtdelete(sc, ifp, dynonly) + struct bridge_softc *sc; + struct ifnet *ifp; +{ + int i, s; + struct bridge_rtnode *n, *p; + + s = splhigh(); + if (sc->sc_rts == NULL) + goto done; + + /* + * Loop through all of the hash buckets and traverse each + * chain looking for routes to this interface. + */ + for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) { + n = LIST_FIRST(&sc->sc_rts[i]); + while (n != NULL) { + if (n->brt_if == ifp) { /* found one */ + p = LIST_NEXT(n, brt_next); + LIST_REMOVE(n, brt_next); + sc->sc_brtcnt--; + free(n, M_DEVBUF); + n = p; + } else + n = LIST_NEXT(n, brt_next); + } + } + if (sc->sc_brtcnt == 0 && (sc->sc_if.if_flags & IFF_UP) == 0) { + free(sc->sc_rts, M_DEVBUF); + sc->sc_rts = NULL; + } + +done: + splx(s); +} + +/* + * Gather all of the routes for this interface. + */ +int +bridge_rtfind(sc, baconf) + struct bridge_softc *sc; + struct ifbaconf *baconf; +{ + int i, s, error = 0; + u_int32_t cnt = 0; + struct bridge_rtnode *n; + struct ifbareq bareq; + + s = splhigh(); + + if (sc->sc_rts == NULL || baconf->ifbac_len == 0) + goto done; + + for (i = 0, cnt = 0; i < BRIDGE_RTABLE_SIZE; i++) { + n = LIST_FIRST(&sc->sc_rts[i]); + while (n != NULL) { + if (baconf->ifbac_len < + (cnt + 1) * sizeof(struct ifbareq)) + goto done; + bcopy(sc->sc_if.if_xname, bareq.ifba_name, + sizeof(bareq.ifba_name)); + bcopy(n->brt_if->if_xname, bareq.ifba_ifsname, + sizeof(bareq.ifba_ifsname)); + bcopy(&n->brt_addr, &bareq.ifba_dst, + sizeof(bareq.ifba_dst)); + bareq.ifba_age = n->brt_age; + bareq.ifba_flags = n->brt_flags; + error = copyout((caddr_t)&bareq, + (caddr_t)(baconf->ifbac_req + cnt), sizeof(bareq)); + if (error) + goto done; + n = LIST_NEXT(n, brt_next); + cnt++; + } + } +done: + baconf->ifbac_len = cnt * sizeof(struct ifbareq); + splx(s); + return (error); +} + +/* + * Block non-ip frames: + * Returns 0 if frame is ip, and 1 if it should be dropped. + */ +int +bridge_blocknonip(eh, m) + struct ether_header *eh; + struct mbuf *m; +{ + struct snap snap; + u_int16_t etype; + + if (m->m_pkthdr.len < sizeof(struct ether_header)) + return (1); + + etype = ntohs(eh->ether_type); + switch (etype) { + case ETHERTYPE_ARP: + case ETHERTYPE_REVARP: + case ETHERTYPE_IP: + case ETHERTYPE_IPV6: + return (0); + } + + if (etype > ETHERMTU) + return (1); + + if (m->m_pkthdr.len < + (sizeof(struct ether_header) + sizeof(struct snap))) + return (1); + + m_copydata(m, sizeof(struct ether_header), sizeof(struct snap), + (caddr_t)&snap); + + etype = ntohs(snap.type); + if (snap.dsap == LLC_SNAP_LSAP && snap.ssap == LLC_SNAP_LSAP && + snap.control == LLC_UI && + snap.org[0] == 0 && snap.org[1] == 0 && snap.org[2] == 0 && + (etype == ETHERTYPE_ARP || + etype == ETHERTYPE_REVARP || + etype == ETHERTYPE_IP || + etype == ETHERTYPE_IPV6)) { + return (0); + } + + return (1); +} + +u_int8_t +bridge_filterrule(n, eh) + struct brl_node *n; + struct ether_header *eh; +{ + u_int8_t flags; + + for (; n != NULL; n = SIMPLEQ_NEXT(n, brl_next)) { + flags = n->brl_flags & (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID); + if (flags == 0) + return (n->brl_action); + if (flags == (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID)) { + if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN)) + continue; + if (bcmp(eh->ether_dhost, &n->brl_src, ETHER_ADDR_LEN)) + continue; + return (n->brl_action); + } + if (flags == BRL_FLAG_SRCVALID) { + if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN)) + continue; + return (n->brl_action); + } + if (flags == BRL_FLAG_DSTVALID) { + if (bcmp(eh->ether_dhost, &n->brl_dst, ETHER_ADDR_LEN)) + continue; + return (n->brl_action); + } + } + return (BRL_ACTION_PASS); +} + +int +bridge_addrule(bif, req, out) + struct bridge_iflist *bif; + struct ifbrlreq *req; + int out; +{ + struct brl_node *n; + + n = (struct brl_node *)malloc(sizeof(struct brl_node), M_DEVBUF, M_NOWAIT); + if (n == NULL) + return (ENOMEM); + bcopy(&req->ifbr_src, &n->brl_src, sizeof(struct ether_addr)); + bcopy(&req->ifbr_dst, &n->brl_dst, sizeof(struct ether_addr)); + n->brl_action = req->ifbr_action; + n->brl_flags = req->ifbr_flags; + if (out) { + n->brl_flags &= ~BRL_FLAG_IN; + n->brl_flags |= BRL_FLAG_OUT; + SIMPLEQ_INSERT_TAIL(&bif->bif_brlout, n, brl_next); + } else { + n->brl_flags &= ~BRL_FLAG_OUT; + n->brl_flags |= BRL_FLAG_IN; + SIMPLEQ_INSERT_TAIL(&bif->bif_brlin, n, brl_next); + } + return (0); +} + +int +bridge_flushrule(bif) + struct bridge_iflist *bif; +{ + struct brl_node *p, *q; + + p = SIMPLEQ_FIRST(&bif->bif_brlin); + while (p != NULL) { + q = SIMPLEQ_NEXT(p, brl_next); + SIMPLEQ_REMOVE_HEAD(&bif->bif_brlin, p, brl_next); + free(p, M_DEVBUF); + p = q; + } + p = SIMPLEQ_FIRST(&bif->bif_brlout); + while (p != NULL) { + q = SIMPLEQ_NEXT(p, brl_next); + SIMPLEQ_REMOVE_HEAD(&bif->bif_brlout, p, brl_next); + free(p, M_DEVBUF); + p = q; + } + return (0); +} + +#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM)) + +/* + * Maximum sized IP header + */ +union maxip { + struct ip ip; + u_int32_t _padding[16]; +}; + +/* + * Filter IP packets by peeking into the ethernet frame. This violates + * the ISO model, but allows us to act as a IP filter at the data link + * layer. As a result, most of this code will look familiar to those + * who've read net/if_ethersubr.c and netinet/ip_input.c + */ +struct mbuf * +bridge_filter(sc, ifp, eh, m) + struct bridge_softc *sc; + struct ifnet *ifp; + struct ether_header *eh; + struct mbuf *m; +{ + struct snap snap; + int hassnap = 0; + struct ip *ip; + int hlen; + + if (fr_checkp == NULL) + return (m); + + if (eh->ether_type != htons(ETHERTYPE_IP)) { + if (eh->ether_type > ETHERMTU || + m->m_pkthdr.len < (sizeof(struct snap) + + sizeof(struct ether_header))) + return (m); + + m_copydata(m, sizeof(struct ether_header), + sizeof(struct snap), (caddr_t)&snap); + + if (snap.dsap != LLC_SNAP_LSAP || snap.ssap != LLC_SNAP_LSAP || + snap.control != LLC_UI || + snap.org[0] != 0 || snap.org[1] != 0 || snap.org[2] || + snap.type != htons(ETHERTYPE_IP)) + return (m); + hassnap = 1; + } + + m_adj(m, sizeof(struct ether_header)); + if (hassnap) + m_adj(m, sizeof(struct snap)); + + if (m->m_pkthdr.len < sizeof(struct ip)) + goto dropit; + + /* Copy minimal header, and drop invalids */ + if (m->m_len < sizeof(struct ip) && + (m = m_pullup(m, sizeof(struct ip))) == NULL) + return (NULL); + ip = mtod(m, struct ip *); + + if (ip->ip_v != IPVERSION) + goto dropit; + + hlen = ip->ip_hl << 2; /* get whole header length */ + if (hlen < sizeof(struct ip)) + goto dropit; + if (hlen > m->m_len) { + if ((m = m_pullup(m, sizeof(struct ip))) == NULL) + return (NULL); + ip = mtod(m, struct ip *); + } + + if ((ip->ip_sum = in_cksum(m, hlen)) != 0) + goto dropit; + + NTOHS(ip->ip_len); + if (ip->ip_len < hlen) + goto dropit; + NTOHS(ip->ip_id); + NTOHS(ip->ip_off); + + if (m->m_pkthdr.len < ip->ip_len) + goto dropit; + if (m->m_pkthdr.len > ip->ip_len) { + if (m->m_len == m->m_pkthdr.len) { + m->m_len = ip->ip_len; + m->m_pkthdr.len = ip->ip_len; + } else + m_adj(m, ip->ip_len - m->m_pkthdr.len); + } + + /* Finally, we get to filter the packet! */ + if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m)) + return (NULL); + + /* Rebuild the IP header */ + if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) + return (NULL); + if (m->m_len < sizeof(struct ip)) + goto dropit; + ip = mtod(m, struct ip *); + HTONS(ip->ip_len); + HTONS(ip->ip_id); + HTONS(ip->ip_off); + ip->ip_sum = in_cksum(m, hlen); + + /* Reattach SNAP header */ + if (hassnap) { + M_PREPEND(m, sizeof(snap), M_DONTWAIT); + if (m == NULL) + goto dropit; + bcopy(&snap, mtod(m, caddr_t), sizeof(snap)); + } + + /* Reattach ethernet header */ + M_PREPEND(m, sizeof(*eh), M_DONTWAIT); + if (m == NULL) + goto dropit; + bcopy(eh, mtod(m, caddr_t), sizeof(*eh)); + + return (m); + +dropit: + if (m != NULL) + m_freem(m); + return (NULL); +} +#endif + +int +ifpromisc(ifp, pswitch) + struct ifnet *ifp; + int pswitch; +{ + struct ifreq ifr; + + if (pswitch) { + /* + * If the device is not configured up, we cannot put it in + * promiscuous mode. + */ + if ((ifp->if_flags & IFF_UP) == 0) + return (ENETDOWN); + if (ifp->if_pcount++ != 0) + return (0); + ifp->if_flags |= IFF_PROMISC; + } else { + if (--ifp->if_pcount > 0) + return (0); + ifp->if_flags &= ~IFF_PROMISC; + /* + * If the device is not configured up, we should not need to + * turn off promiscuous mode (device should have turned it + * off when interface went down; and will look at IFF_PROMISC + * again next time interface comes up). + */ + if ((ifp->if_flags & IFF_UP) == 0) + return (0); + } + ifr.ifr_flags = ifp->if_flags; + return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); +} + +int +bridge_ifenqueue(sc, ifp, m) + struct bridge_softc *sc; + struct ifnet *ifp; + struct mbuf *m; +{ + int error, len; + short mflags; + + len = m->m_pkthdr.len; + mflags = m->m_flags; + IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); + if (error) { + sc->sc_if.if_oerrors++; + return (error); + } + sc->sc_if.if_opackets++; + sc->sc_if.if_obytes += len; + ifp->if_obytes += len; + if (mflags & M_MCAST) + ifp->if_omcasts++; + if ((ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + return (0); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/net/if_ethersubr.c b/ecos/packages/net/tcpip/current/src/sys/net/if_ethersubr.c new file mode 100644 index 0000000..d1be3bd --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/if_ethersubr.c @@ -0,0 +1,1179 @@ +//========================================================================== +// +// sys/net/if_ethersubr.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_ethersubr.c,v 1.32 1999/12/08 06:50:17 itojun Exp $ */ +/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#ifndef __ECOS +#include <sys/syslog.h> +#endif + +#include <machine/cpu.h> + +#include <net/if.h> +#include <net/netisr.h> +#include <net/route.h> +#include <net/if_llc.h> +#include <net/if_dl.h> +#include <net/if_types.h> + +#include <netinet/in.h> +#ifdef INET +#include <netinet/in_var.h> +#endif +#include <netinet/if_ether.h> + +#ifndef __ECOS +#include "bridge.h" +#endif +#if NBRIDGE > 0 +#include <net/if_bridge.h> +#endif + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#include <netinet6/in6_var.h> +#include <netinet6/nd6.h> +#endif + +#ifdef NS +#include <netns/ns.h> +#include <netns/ns_if.h> +#endif + +#ifdef IPX +#include <netipx/ipx.h> +#include <netipx/ipx_if.h> +#endif + +#ifdef ISO +#include <netiso/argo_debug.h> +#include <netiso/iso.h> +#include <netiso/iso_var.h> +#include <netiso/iso_snpac.h> +#endif + +#ifdef CCITT +#include <netccitt/x25.h> +#include <netccitt/pk.h> +#include <netccitt/pk_extern.h> +#include <netccitt/dll.h> +#include <netccitt/llc_var.h> +#endif + +#ifdef NETATALK +#include <netatalk/at.h> +#include <netatalk/at_var.h> +#include <netatalk/at_extern.h> + +#define llc_snap_org_code llc_un.type_snap.org_code +#define llc_snap_ether_type llc_un.type_snap.ether_type + +extern u_char at_org_code[ 3 ]; +extern u_char aarp_org_code[ 3 ]; +#endif /* NETATALK */ + +#if defined(CCITT) +#include <sys/socketvar.h> +#endif + +#if 0 /*NRL INET6*/ +#include <netinet6/in6.h> +#include <netinet6/in6_var.h> +#endif /* INET6 */ + +u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#define senderr(e) { error = (e); goto bad;} + + +int +ether_ioctl(ifp, arp, cmd, data) + register struct ifnet *ifp; + struct arpcom *arp; + u_long cmd; + caddr_t data; +{ + struct ifaddr *ifa = (struct ifaddr *)data; + int error = 0; + + switch (cmd) { + +#if defined(CCITT) + case SIOCSIFCONF_X25: + ifp->if_flags |= IFF_UP; + ifa->ifa_rtrequest = cons_rtrequest; + error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); + break; +#endif /* CCITT */ + case SIOCSIFADDR: + switch (ifa->ifa_addr->sa_family) { +#ifdef IPX + case AF_IPX: + { + struct ipx_addr *ina = &IA_SIPX(ifa)->sipx_addr; + + if (ipx_nullhost(*ina)) + ina->ipx_host = + *(union ipx_host *)(arp->ac_enaddr); + else + bcopy(ina->ipx_host.c_host, + arp->ac_enaddr, sizeof(arp->ac_enaddr)); + break; + } +#endif /* IPX */ +#ifdef NETATALK + case AF_APPLETALK: + /* Nothing to do. */ + break; +#endif /* NETATALK */ +#ifdef NS + /* XXX - This code is probably wrong. */ + case AF_NS: + { + struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; + + if (ns_nullhost(*ina)) + ina->x_host = + *(union ns_host *)(arp->ac_enaddr); + else + bcopy(ina->x_host.c_host, + arp->ac_enaddr, sizeof(arp->ac_enaddr)); + break; + } +#endif /* NS */ + } + break; + default: + break; + } + + return error; +} + +/* + * Ethernet output routine. + * Encapsulate a packet of type family for the local net. + * Assumes that ifp is actually pointer to arpcom structure. + */ +int +ether_output(ifp, m0, dst, rt0) + register struct ifnet *ifp; + struct mbuf *m0; + struct sockaddr *dst; + struct rtentry *rt0; +{ + u_int16_t etype; + int s, error = 0; + u_char edst[6]; + register struct mbuf *m = m0; + register struct rtentry *rt; + struct mbuf *mcopy = (struct mbuf *)0; + register struct ether_header *eh; + struct arpcom *ac = (struct arpcom *)ifp; + + if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) + senderr(ENETDOWN); + ifp->if_lastchange = time; + if ((rt = rt0) != NULL) { + if ((rt->rt_flags & RTF_UP) == 0) { + if ((rt0 = rt = rtalloc1(dst, 1)) != NULL) + rt->rt_refcnt--; + else + senderr(EHOSTUNREACH); + } + if (rt->rt_flags & RTF_GATEWAY) { + if (rt->rt_gwroute == 0) + goto lookup; + if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { + rtfree(rt); rt = rt0; + lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1); + if ((rt = rt->rt_gwroute) == 0) + senderr(EHOSTUNREACH); + } + } + if (rt->rt_flags & RTF_REJECT) + if (rt->rt_rmx.rmx_expire == 0 || + time.tv_sec < rt->rt_rmx.rmx_expire) + senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); + } + switch (dst->sa_family) { + +#ifdef INET + case AF_INET: + if (!arpresolve(ac, rt, m, dst, edst)) + return (0); /* if not yet resolved */ + /* If broadcasting on a simplex interface, loopback a copy */ + if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) + mcopy = m_copy(m, 0, (int)M_COPYALL); + etype = htons(ETHERTYPE_IP); + break; +#endif +#ifdef INET6 + case AF_INET6: +#ifndef OLDIP6OUTPUT + if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)) + return(0); /* it must be impossible, but... */ +#else + if (!nd6_resolve(ifp, rt, m, dst, (u_char *)edst)) + return(0); /* if not yet resolves */ +#endif + etype = htons(ETHERTYPE_IPV6); + break; +#endif +#ifdef NS + case AF_NS: + etype = htons(ETHERTYPE_NS); + bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), + (caddr_t)edst, sizeof (edst)); + if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))) + return (looutput(ifp, m, dst, rt)); + /* If broadcasting on a simplex interface, loopback a copy */ + if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) + mcopy = m_copy(m, 0, (int)M_COPYALL); + break; +#endif +#ifdef IPX + case AF_IPX: + etype = htons(ETHERTYPE_IPX); + bcopy((caddr_t)&satosipx(dst)->sipx_addr.ipx_host, + (caddr_t)edst, sizeof (edst)); + if (!bcmp((caddr_t)edst, (caddr_t)&ipx_thishost, sizeof(edst))) + return (looutput(ifp, m, dst, rt)); + /* If broadcasting on a simplex interface, loopback a copy */ + if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) + mcopy = m_copy(m, 0, (int)M_COPYALL); + break; +#endif +#if 0 /*NRL INET6*/ + case AF_INET6: + /* + * The bottom line here is to either queue the outgoing packet + * in the discovery engine, or fill in edst with something + * that'll work. + */ + if (m->m_flags & M_MCAST) { + /* + * If multicast dest., then use IPv6 -> Ethernet + * mcast mapping. Really simple. + */ + ETHER_MAP_IPV6_MULTICAST(&((struct sockaddr_in6 *)dst)->sin6_addr, + edst); + } else { + /* Do unicast neighbor discovery stuff. */ + if (!ipv6_discov_resolve(ifp, rt, m, dst, edst)) + return 0; + } + etype = htons(ETHERTYPE_IPV6); + break; +#endif /* INET6 */ +#ifdef NETATALK + case AF_APPLETALK: { + struct at_ifaddr *aa; + + if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) { +#ifdef NETATALKDEBUG + extern char *prsockaddr(struct sockaddr *); + printf("aarpresolv: failed for %s\n", prsockaddr(dst)); +#endif /* NETATALKDEBUG */ + return (0); + } + + /* + * ifaddr is the first thing in at_ifaddr + */ + aa = (struct at_ifaddr *)at_ifawithnet( + (struct sockaddr_at *)dst, + ifp->if_addrlist.tqh_first); + if (aa == 0) + goto bad; + + /* + * In the phase 2 case, we need to prepend an mbuf for the llc + * header. Since we must preserve the value of m, which is + * passed to us by value, we m_copy() the first mbuf, + * and use it for our llc header. + */ + if ( aa->aa_flags & AFA_PHASE2 ) { + struct llc llc; + + /* XXX Really this should use netisr too */ + M_PREPEND(m, AT_LLC_SIZE, M_WAIT); + /* + * FreeBSD doesn't count the LLC len in + * ifp->obytes, so they increment a length + * field here. We don't do this. + */ + llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; + llc.llc_control = LLC_UI; + bcopy(at_org_code, llc.llc_snap_org_code, + sizeof(at_org_code)); + llc.llc_snap_ether_type = htons( ETHERTYPE_AT ); + bcopy(&llc, mtod(m, caddr_t), AT_LLC_SIZE); + etype = htons(m->m_pkthdr.len); + } else { + etype = htons(ETHERTYPE_AT); + } + } break; +#endif /* NETATALK */ +#ifdef ISO + case AF_ISO: { + int snpalen; + struct llc *l; + register struct sockaddr_dl *sdl; + + if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && + sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { + bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); + } else { + error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst, + (char *)edst, &snpalen); + if (error) + goto bad; /* Not Resolved */ + } + /* If broadcasting on a simplex interface, loopback a copy */ + if (*edst & 1) + m->m_flags |= (M_BCAST|M_MCAST); + if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) && + (mcopy = m_copy(m, 0, (int)M_COPYALL))) { + M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); + if (mcopy) { + eh = mtod(mcopy, struct ether_header *); + bcopy(edst, eh->ether_dhost, sizeof (edst)); + bcopy(ac->ac_enaddr, eh->ether_shost, + sizeof (edst)); + } + } + M_PREPEND(m, 3, M_DONTWAIT); + if (m == NULL) + return (0); + etype = htons(m->m_pkthdr.len); + l = mtod(m, struct llc *); + l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; + l->llc_control = LLC_UI; +#ifdef ARGO_DEBUG + if (argo_debug[D_ETHER]) { + int i; + printf("unoutput: sending pkt to: "); + for (i=0; i<6; i++) + printf("%x ", edst[i] & 0xff); + printf("\n"); + } +#endif + } break; +#endif /* ISO */ +/* case AF_NSAP: */ + case AF_CCITT: { + register struct sockaddr_dl *sdl = + (struct sockaddr_dl *) rt -> rt_gateway; + + if (sdl && sdl->sdl_family == AF_LINK + && sdl->sdl_alen > 0) { + bcopy(LLADDR(sdl), (char *)edst, + sizeof(edst)); + } else goto bad; /* Not a link interface ? Funny ... */ + if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) && + (mcopy = m_copy(m, 0, (int)M_COPYALL))) { + M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT); + if (mcopy) { + eh = mtod(mcopy, struct ether_header *); + bcopy(edst, eh->ether_dhost, sizeof (edst)); + bcopy(ac->ac_enaddr, eh->ether_shost, + sizeof (edst)); + } + } + etype = htons(m->m_pkthdr.len); +#ifdef LLC_DEBUG + { + int i; + register struct llc *l = mtod(m, struct llc *); + + printf("ether_output: sending LLC2 pkt to: "); + for (i=0; i<6; i++) + printf("%x ", edst[i] & 0xff); + printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", + m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff, + l->llc_control & 0xff); + + } +#endif /* LLC_DEBUG */ + } break; + + case AF_UNSPEC: + eh = (struct ether_header *)dst->sa_data; + bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); + /* AF_UNSPEC doesn't swap the byte order of the ether_type. */ + etype = eh->ether_type; + break; + + default: +#ifdef __ECOS +// diag_printf("%s: can't handle af%d\n", ifp->if_xname, +// dst->sa_family); +#else + printf("%s: can't handle af%d\n", ifp->if_xname, + dst->sa_family); +#endif + senderr(EAFNOSUPPORT); + } + + if (mcopy) + (void) looutput(ifp, mcopy, dst, rt); + + /* + * Add local net header. If no space in first mbuf, + * allocate another. + */ + M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); + if (m == 0) + senderr(ENOBUFS); + eh = mtod(m, struct ether_header *); + bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type, + sizeof(eh->ether_type)); + bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); + bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, + sizeof(eh->ether_shost)); + +#if NBRIDGE > 0 + /* + * Interfaces that are bridge members need special handling + * for output. + */ + if (ifp->if_bridge) { + bridge_output(ifp, m, NULL, NULL); + return (error); + } +#endif + + s = splimp(); + /* + * Queue message on interface, and start output if interface + * not yet active. + */ + if (IF_QFULL(&ifp->if_snd)) { + // Let the interface try a dequeue anyway, in case the + // interface has "got better" from whatever made the queue + // fill up - being unplugged for example. + if ((ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + IF_DROP(&ifp->if_snd); + splx(s); + senderr(ENOBUFS); + } + ifp->if_obytes += m->m_pkthdr.len; + IF_ENQUEUE(&ifp->if_snd, m); + if (m->m_flags & M_MCAST) + ifp->if_omcasts++; + if ((ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + splx(s); + return (error); + +bad: + if (m) + m_freem(m); + return (error); +} + +/* + * Process a received Ethernet packet; + * the packet is in the mbuf chain m without + * the ether header, which is provided separately. + */ +void +ether_input(ifp, eh, m) + struct ifnet *ifp; + register struct ether_header *eh; + struct mbuf *m; +{ + register struct ifqueue *inq; + u_int16_t etype; + int s, llcfound = 0; + register struct llc *l; + struct arpcom *ac = (struct arpcom *)ifp; +#ifdef __ECOS + unsigned int sched_what; +#endif + + if ((ifp->if_flags & IFF_UP) == 0) { + m_freem(m); + return; + } + ifp->if_lastchange = time; + ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); + if (eh->ether_dhost[0] & 1) { + if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, + sizeof(etherbroadcastaddr)) == 0) + m->m_flags |= M_BCAST; + else + m->m_flags |= M_MCAST; + } + if (m->m_flags & (M_BCAST|M_MCAST)) + ifp->if_imcasts++; + +#if NBRIDGE > 0 + /* + * Tap the packet off here for a bridge, if configured and + * active for this interface. bridge_input returns + * NULL if it has consumed the packet, otherwise, it + * gets processed as normal. + */ + if (ifp->if_bridge) { + m = bridge_input(ifp, eh, m); + if (m == NULL) + return; + /* The bridge has determined it's for us. */ + goto decapsulate; + } +#endif + /* + * If packet is unicast and we're in promiscuous mode, make sure it + * is for us. Drop otherwise. + */ + if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 && + (ifp->if_flags & IFF_PROMISC)) { + if (bcmp(ac->ac_enaddr, (caddr_t)eh->ether_dhost, + ETHER_ADDR_LEN)) { + m_freem(m); + return; + } + } + +decapsulate: + etype = ntohs(eh->ether_type); + switch (etype) { +#ifdef INET + case ETHERTYPE_IP: +#ifdef __ECOS + sched_what = NETISR_IP; +#else + schednetisr(NETISR_IP); +#endif + inq = &ipintrq; + break; + + case ETHERTYPE_ARP: + if (ifp->if_flags & IFF_NOARP) + goto dropanyway; +#ifdef __ECOS + sched_what = NETISR_ARP; +#else + schednetisr(NETISR_ARP); +#endif + inq = &arpintrq; + break; + + case ETHERTYPE_REVARP: + if (ifp->if_flags & IFF_NOARP) + goto dropanyway; + revarpinput(m); /* XXX queue? */ + return; + +#endif +#ifdef INET6 + /* + * Schedule IPv6 software interrupt for incoming IPv6 packet. + */ + case ETHERTYPE_IPV6: +#ifdef __ECOS + sched_what = NETISR_IPV6; +#else + schednetisr(NETISR_IPV6); +#endif + inq = &ip6intrq; + break; +#endif /* INET6 */ +#ifdef IPX + case ETHERTYPE_IPX: +#ifdef __ECOS + sched_what = NETISR_IPX; +#else + schednetisr(NETISR_IPX); +#endif + inq = &ipxintrq; + break; +#endif +#ifdef NS + case ETHERTYPE_NS: +#ifdef __ECOS + sched_what = NETISR_NS; +#else + schednetisr(NETISR_NS); +#endif + inq = &nsintrq; + break; +#endif +#ifdef NETATALK + case ETHERTYPE_AT: +#ifdef __ECOS + sched_what = NETISR_ATALK; +#else + schednetisr(NETISR_ATALK); +#endif + inq = &atintrq1; + break; + case ETHERTYPE_AARP: + /* probably this should be done with a NETISR as well */ + /* XXX queue this */ + aarpinput((struct arpcom *)ifp, m); + return; +#endif + default: + if (llcfound || etype > ETHERMTU) + goto dropanyway; + llcfound = 1; + l = mtod(m, struct llc *); + switch (l->llc_dsap) { + case LLC_SNAP_LSAP: +#ifdef NETATALK + /* + * Some protocols (like Appletalk) need special + * handling depending on if they are type II + * or SNAP encapsulated. Everything else + * gets handled by stripping off the SNAP header + * and going back up to decapsulate. + */ + if (l->llc_control == LLC_UI && + l->llc_ssap == LLC_SNAP_LSAP && + Bcmp(&(l->llc_snap_org_code)[0], + at_org_code, sizeof(at_org_code)) == 0 && + ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { + inq = &atintrq2; + m_adj(m, AT_LLC_SIZE); +#ifdef __ECOS + sched_what = NETISR_ATALK; +#else + schednetisr(NETISR_ATALK); +#endif + break; + } + + if (l->llc_control == LLC_UI && + l->llc_ssap == LLC_SNAP_LSAP && + Bcmp(&(l->llc_snap_org_code)[0], + aarp_org_code, sizeof(aarp_org_code)) == 0 && + ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { + m_adj(m, AT_LLC_SIZE); + /* XXX Really this should use netisr too */ + aarpinput((struct arpcom *)ifp, m); + return; + } +#endif /* NETATALK */ + if (l->llc_control == LLC_UI && + l->llc_dsap == LLC_SNAP_LSAP && + l->llc_ssap == LLC_SNAP_LSAP) { + /* SNAP */ + if (m->m_pkthdr.len > etype) + m_adj(m, etype - m->m_pkthdr.len); + m->m_data += 6; /* XXX */ + m->m_len -= 6; /* XXX */ + m->m_pkthdr.len -= 6; /* XXX */ + M_PREPEND(m, sizeof *eh, M_DONTWAIT); + if (m == 0) + return; + *mtod(m, struct ether_header *) = *eh; + goto decapsulate; + } + goto dropanyway; +#ifdef ISO + case LLC_ISO_LSAP: + switch (l->llc_control) { + case LLC_UI: + /* LLC_UI_P forbidden in class 1 service */ + if ((l->llc_dsap == LLC_ISO_LSAP) && + (l->llc_ssap == LLC_ISO_LSAP)) { + /* LSAP for ISO */ + if (m->m_pkthdr.len > etype) + m_adj(m, etype - m->m_pkthdr.len); + m->m_data += 3; /* XXX */ + m->m_len -= 3; /* XXX */ + m->m_pkthdr.len -= 3; /* XXX */ + M_PREPEND(m, sizeof *eh, M_DONTWAIT); + if (m == 0) + return; + *mtod(m, struct ether_header *) = *eh; +#ifdef ARGO_DEBUG + if (argo_debug[D_ETHER]) + printf("clnp packet"); +#endif +#ifdef __ECOS + sched_what = NETISR_ISO; +#else + schednetisr(NETISR_ISO); +#endif + inq = &clnlintrq; + break; + } + goto dropanyway; + + case LLC_XID: + case LLC_XID_P: + if(m->m_len < 6) + goto dropanyway; + l->llc_window = 0; + l->llc_fid = 9; + l->llc_class = 1; + l->llc_dsap = l->llc_ssap = 0; + /* Fall through to */ + case LLC_TEST: + case LLC_TEST_P: + { + struct sockaddr sa; + register struct ether_header *eh2; + int i; + u_char c = l->llc_dsap; + + l->llc_dsap = l->llc_ssap; + l->llc_ssap = c; + if (m->m_flags & (M_BCAST | M_MCAST)) + bcopy(ac->ac_enaddr, + eh->ether_dhost, 6); + sa.sa_family = AF_UNSPEC; + sa.sa_len = sizeof(sa); + eh2 = (struct ether_header *)sa.sa_data; + for (i = 0; i < 6; i++) { + eh2->ether_shost[i] = c = eh->ether_dhost[i]; + eh2->ether_dhost[i] = + eh->ether_dhost[i] = eh->ether_shost[i]; + eh->ether_shost[i] = c; + } + ifp->if_output(ifp, m, &sa, NULL); + return; + } + break; + } +#endif /* ISO */ +#ifdef CCITT + case LLC_X25_LSAP: + if (m->m_pkthdr.len > etype) + m_adj(m, etype - m->m_pkthdr.len); + M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); + if (m == 0) + return; + if (!sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP, + eh->ether_dhost, LLC_X25_LSAP, 6, + mtod(m, struct sdl_hdr *))) + panic("ETHER cons addr failure"); + mtod(m, struct sdl_hdr *)->sdlhdr_len = etype; +#ifdef LLC_DEBUG + printf("llc packet\n"); +#endif /* LLC_DEBUG */ +#ifdef __ECOS + sched_what = NETISR_CCITT; +#else + schednetisr(NETISR_CCITT); +#endif + inq = &llcintrq; + break; +#endif /* CCITT */ + dropanyway: + default: + m_freem(m); + return; + } + } + + s = splimp(); + if (IF_QFULL(inq)) { + IF_DROP(inq); + m_freem(m); + } else + IF_ENQUEUE(inq, m); + splx(s); +#ifdef __ECOS + schednetisr(sched_what); +#endif +} + +/* + * Convert Ethernet address to printable (loggable) representation. + */ +static char digits[] = "0123456789abcdef"; +char * +ether_sprintf(ap) + register u_char *ap; +{ + register int i; + static char etherbuf[18]; + register char *cp = etherbuf; + + for (i = 0; i < 6; i++) { + *cp++ = digits[*ap >> 4]; + *cp++ = digits[*ap++ & 0xf]; + *cp++ = ':'; + } + *--cp = 0; + return (etherbuf); +} + +/* + * Perform common duties while attaching to interface list + */ +void +ether_ifattach(ifp) + register struct ifnet *ifp; +{ + register struct ifaddr *ifa; + register struct sockaddr_dl *sdl; + + ifp->if_type = IFT_ETHER; + ifp->if_addrlen = 6; + ifp->if_hdrlen = 14; + ifp->if_mtu = ETHERMTU; + ifp->if_output = ether_output; + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; + ifa = ifa->ifa_list.tqe_next) + if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && + sdl->sdl_family == AF_LINK) { + sdl->sdl_type = IFT_ETHER; + sdl->sdl_alen = ifp->if_addrlen; + bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, + LLADDR(sdl), ifp->if_addrlen); + break; + } + LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs); +} + +void +ether_ifdetach(ifp) + struct ifnet *ifp; +{ + struct arpcom *ac = (struct arpcom *)ifp; + struct ether_multi *enm; + + for (enm = LIST_FIRST(&ac->ac_multiaddrs); enm; + enm = LIST_FIRST(&ac->ac_multiaddrs)) { + LIST_REMOVE(enm, enm_list); + free(enm, M_IFMADDR); + } +} + +u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; +u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; + +#ifdef INET6 +u_char ether_ip6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; +u_char ether_ip6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff }; +#endif + +/* + * Add an Ethernet multicast address or range of addresses to the list for a + * given interface. + */ +int +ether_addmulti(ifr, ac) + struct ifreq *ifr; + register struct arpcom *ac; +{ + register struct ether_multi *enm; + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif /* INET6 */ + u_char addrlo[6]; + u_char addrhi[6]; + int s = splimp(); + + switch (ifr->ifr_addr.sa_family) { + + case AF_UNSPEC: + bcopy(ifr->ifr_addr.sa_data, addrlo, 6); + bcopy(addrlo, addrhi, 6); + break; + +#ifdef INET + case AF_INET: + sin = (struct sockaddr_in *)&(ifr->ifr_addr); + if (sin->sin_addr.s_addr == INADDR_ANY) { + /* + * An IP address of INADDR_ANY means listen to all + * of the Ethernet multicast addresses used for IP. + * (This is for the sake of IP multicast routers.) + */ + bcopy(ether_ipmulticast_min, addrlo, 6); + bcopy(ether_ipmulticast_max, addrhi, 6); + } + else { + ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); + bcopy(addrlo, addrhi, 6); + } + break; +#endif +#ifdef INET6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *) + &(((struct in6_ifreq *)ifr)->ifr_addr); + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* + * An unspecified IPv6 address means listen to all + * of the IPv6 multicast addresses on this Ethernet. + * (Multicast routers like this.) + */ + bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN); + bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN); + } else { + ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); + bcopy(addrlo, addrhi, ETHER_ADDR_LEN); + } + break; +#endif /* INET6 */ + + default: + splx(s); + return (EAFNOSUPPORT); + } + + /* + * Verify that we have valid Ethernet multicast addresses. + */ + if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { + splx(s); + return (EINVAL); + } + /* + * See if the address range is already in the list. + */ + ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); + if (enm != NULL) { + /* + * Found it; just increment the reference count. + */ + ++enm->enm_refcount; + splx(s); + return (0); + } + /* + * New address or range; malloc a new multicast record + * and link it into the interface's multicast list. + */ + enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); + if (enm == NULL) { + splx(s); + return (ENOBUFS); + } + bcopy(addrlo, enm->enm_addrlo, 6); + bcopy(addrhi, enm->enm_addrhi, 6); + enm->enm_ac = ac; + enm->enm_refcount = 1; + LIST_INSERT_HEAD(&ac->ac_multiaddrs, enm, enm_list); + ac->ac_multicnt++; + splx(s); + /* + * Return ENETRESET to inform the driver that the list has changed + * and its reception filter should be adjusted accordingly. + */ + return (ENETRESET); +} + +/* + * Delete a multicast address record. + */ +int +ether_delmulti(ifr, ac) + struct ifreq *ifr; + register struct arpcom *ac; +{ + register struct ether_multi *enm; + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif /* INET6 */ + u_char addrlo[6]; + u_char addrhi[6]; + int s = splimp(); + + switch (ifr->ifr_addr.sa_family) { + + case AF_UNSPEC: + bcopy(ifr->ifr_addr.sa_data, addrlo, 6); + bcopy(addrlo, addrhi, 6); + break; + +#ifdef INET + case AF_INET: + sin = (struct sockaddr_in *)&(ifr->ifr_addr); + if (sin->sin_addr.s_addr == INADDR_ANY) { + /* + * An IP address of INADDR_ANY means stop listening + * to the range of Ethernet multicast addresses used + * for IP. + */ + bcopy(ether_ipmulticast_min, addrlo, 6); + bcopy(ether_ipmulticast_max, addrhi, 6); + } + else { + ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); + bcopy(addrlo, addrhi, 6); + } + break; +#endif +#ifdef INET6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&(ifr->ifr_addr); + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* + * An unspecified IPv6 address means stop listening to + * all IPv6 multicast addresses on this Ethernet.' + * + * (This might not be healthy, given IPv6's reliance on + * multicast for things like neighbor discovery. + * Perhaps initializing all-nodes, solicited nodes, and + * possibly all-routers for this interface afterwards + * is not a bad idea.) + */ + bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN); + bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN); + } else { + ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo); + bcopy(addrlo, addrhi, ETHER_ADDR_LEN); + } + break; +#endif /* INET6 */ + + default: + splx(s); + return (EAFNOSUPPORT); + } + + /* + * Look up the address in our list. + */ + ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); + if (enm == NULL) { + splx(s); + return (ENXIO); + } + if (--enm->enm_refcount != 0) { + /* + * Still some claims to this record. + */ + splx(s); + return (0); + } + /* + * No remaining claims to this record; unlink and free it. + */ + LIST_REMOVE(enm, enm_list); + free(enm, M_IFMADDR); + ac->ac_multicnt--; + splx(s); + /* + * Return ENETRESET to inform the driver that the list has changed + * and its reception filter should be adjusted accordingly. + */ + return (ENETRESET); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/net/if_loop.c b/ecos/packages/net/tcpip/current/src/sys/net/if_loop.c new file mode 100644 index 0000000..7929f42 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/if_loop.c @@ -0,0 +1,446 @@ +//========================================================================== +// +// sys/net/if_loop.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_loop.c,v 1.12 1999/12/08 06:50:18 itojun Exp $ */ +/* $NetBSD: if_loop.c,v 1.15 1996/05/07 02:40:33 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_loop.c 8.1 (Berkeley) 6/10/93 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +/* + * Loopback interface driver for protocol testing and timing. + */ + +#ifndef __ECOS +#include "bpfilter.h" +#include "loop.h" +#endif + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/time.h> + +#include <machine/cpu.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/netisr.h> +#include <net/route.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#endif + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#include <netinet6/in6_var.h> +#include <netinet6/ip6.h> +#endif + +#ifdef NS +#include <netns/ns.h> +#include <netns/ns_if.h> +#endif + +#ifdef IPX +#include <netipx/ipx.h> +#include <netipx/ipx_if.h> +#endif + +#ifdef ISO +#include <netiso/iso.h> +#include <netiso/iso_var.h> +#endif + +#ifdef NETATALK +#include <netinet/if_ether.h> +#include <netatalk/at.h> +#include <netatalk/at_var.h> +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#endif + +#if defined(LARGE_LOMTU) +#define LOMTU (131072 + MHLEN + MLEN) +#else +#define LOMTU (32768 + MHLEN + MLEN) +#endif + +#ifndef __ECOS +#include <stdio.h> // for 'sprintf()' +#endif + +struct ifnet loif[NLOOP]; + +void +loopattach(n) + int n; +{ + register int i; + register struct ifnet *ifp; + + for (i = NLOOP; i--; ) { + ifp = &loif[i]; +#if !defined(__ECOS) || (CYGPKG_NET_NLOOP > 1) + sprintf(ifp->if_xname, "lo%d", i); +#else + strcpy(ifp->if_xname, "lo0"); +#endif + ifp->if_softc = NULL; + ifp->if_mtu = LOMTU; + ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; + ifp->if_ioctl = loioctl; + ifp->if_output = looutput; + ifp->if_type = IFT_LOOP; + ifp->if_hdrlen = sizeof(u_int32_t); + ifp->if_addrlen = 0; + if_attachhead(ifp); +#if NBPFILTER > 0 + bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); +#endif + } +} + +int +looutput(ifp, m, dst, rt) + struct ifnet *ifp; + register struct mbuf *m; + struct sockaddr *dst; + register struct rtentry *rt; +{ + int s, isr; + register struct ifqueue *ifq = 0; + + if ((m->m_flags & M_PKTHDR) == 0) + panic("looutput: no header mbuf"); + ifp->if_lastchange = time; +#if NBPFILTER > 0 + /* + * only send packets to bpf if they are real loopback packets; + * looutput() is also called for SIMPLEX interfaces to duplicate + * packets for local use. But don't dup them to bpf. + */ + if (ifp->if_bpf && (ifp->if_flags&IFF_LOOPBACK)) { + /* + * We need to prepend the address family as + * a four byte field. Cons up a dummy header + * to pacify bpf. This is safe because bpf + * will only read from the mbuf (i.e., it won't + * try to free it or keep a pointer to it). + */ + struct mbuf m0; + u_int32_t af = htonl(dst->sa_family); + + m0.m_next = m; + m0.m_len = sizeof(af); + m0.m_data = (char *)⁡ + + bpf_mtap(ifp->if_bpf, &m0); + } +#endif + m->m_pkthdr.rcvif = ifp; + + if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { + m_freem(m); + return (rt->rt_flags & RTF_BLACKHOLE ? 0 : + rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); + } + +#ifndef PULLDOWN_TEST + /* + * KAME requires that the packet to be contiguous on the + * mbuf. We need to make that sure. + * this kind of code should be avoided. + * XXX other conditions to avoid running this part? + */ + if (m && m->m_next != NULL) { + struct mbuf *n; + + MGETHDR(n, M_DONTWAIT, MT_HEADER); + if (n) { + MCLGET(n, M_DONTWAIT); + if ((n->m_flags & M_EXT) == 0) { + m_free(n); + n = NULL; + } + } + if (!n) { +#ifdef __ECOS + diag_printf("looutput: mbuf allocation failed\n"); +#else + printf("looutput: mbuf allocation failed\n"); +#endif + m_freem(m); + return ENOBUFS; + } + + n->m_pkthdr.rcvif = m->m_pkthdr.rcvif; + n->m_pkthdr.len = m->m_pkthdr.len; + if (m->m_pkthdr.len <= MCLBYTES) { + m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); + n->m_len = m->m_pkthdr.len; + m_freem(m); + } else { + m_copydata(m, 0, MCLBYTES, mtod(n, caddr_t)); + m_adj(m, MCLBYTES); + n->m_len = MCLBYTES; + n->m_next = m; + m->m_flags &= ~M_PKTHDR; + } + m = n; + } +#if 0 + if (m && m->m_next != NULL) { + printf("loop: not contiguous...\n"); + m_freem(m); + return ENOBUFS; + } +#endif +#endif + + ifp->if_opackets++; + ifp->if_obytes += m->m_pkthdr.len; + switch (dst->sa_family) { + +#ifdef INET + case AF_INET: + ifq = &ipintrq; + isr = NETISR_IP; + break; +#endif +#ifdef INET6 + case AF_INET6: + ifq = &ip6intrq; + isr = NETISR_IPV6; + break; +#endif /* INET6 */ +#ifdef NS + case AF_NS: + ifq = &nsintrq; + isr = NETISR_NS; + break; +#endif +#ifdef IPX + case AF_IPX: + ifq = &ipxintrq; + isr = NETISR_IPX; + break; +#endif +#ifdef ISO + case AF_ISO: + ifq = &clnlintrq; + isr = NETISR_ISO; + break; +#endif +#ifdef NETATALK + case AF_APPLETALK: + ifq = &atintrq2; + isr = NETISR_ATALK; + break; +#endif + default: +#ifdef __ECOS + diag_printf("%s: can't handle af%d\n", ifp->if_xname, + dst->sa_family); +#else + printf("%s: can't handle af%d\n", ifp->if_xname, + dst->sa_family); +#endif + m_freem(m); + return (EAFNOSUPPORT); + } + s = splimp(); + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + m_freem(m); + splx(s); + return (ENOBUFS); + } + IF_ENQUEUE(ifq, m); + schednetisr(isr); + ifp->if_ipackets++; + ifp->if_ibytes += m->m_pkthdr.len; + splx(s); + return (0); +} + +/* ARGSUSED */ +void +lortrequest(cmd, rt, sa) + int cmd; + struct rtentry *rt; + struct sockaddr *sa; +{ + + if (rt) + rt->rt_rmx.rmx_mtu = LOMTU; +} + +/* + * Process an ioctl request. + */ +/* ARGSUSED */ +int +loioctl(ifp, cmd, data) + register struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + register struct ifaddr *ifa; + register struct ifreq *ifr; + register int error = 0; + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + ifa = (struct ifaddr *)data; + if (ifa != 0 /*&& ifa->ifa_addr->sa_family == AF_ISO*/) + ifa->ifa_rtrequest = lortrequest; + /* + * Everything else is done at a higher level. + */ + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + ifr = (struct ifreq *)data; + if (ifr == 0) { + error = EAFNOSUPPORT; /* XXX */ + break; + } + switch (ifr->ifr_addr.sa_family) { + +#ifdef INET + case AF_INET: + break; +#endif +#ifdef INET6 + case AF_INET6: + break; +#endif /* INET6 */ + + default: + error = EAFNOSUPPORT; + break; + } + break; + + default: + error = EINVAL; + } + return (error); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/net/radix.c b/ecos/packages/net/tcpip/current/src/sys/net/radix.c new file mode 100644 index 0000000..04f20d5 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/radix.c @@ -0,0 +1,965 @@ +//========================================================================== +// +// sys/net/radix.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: radix.c,v 1.4 1996/09/05 08:42:32 mickey Exp $ */ +/* $NetBSD: radix.c,v 1.11 1996/03/16 23:55:36 christos Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)radix.c 8.4 (Berkeley) 11/2/94 + */ + +/* + * Routines to build and maintain radix trees for routing lookups. + */ +#include <sys/param.h> +#ifdef _KERNEL +#ifndef __ECOS +#include <sys/systm.h> +#include <sys/syslog.h> +#endif +#include <sys/malloc.h> +#define M_DONTWAIT M_NOWAIT +#include <sys/domain.h> +#else +#include <stdlib.h> +#endif +#include <net/radix.h> + +int max_keylen; +struct radix_mask *rn_mkfreelist; +struct radix_node_head *mask_rnhead; +static char *addmask_key; +static char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, -1}; +static char *rn_zeros, *rn_ones; + +#define rn_masktop (mask_rnhead->rnh_treetop) +#undef Bcmp +#define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l)) + + +static int rn_satsifies_leaf __P((char *, struct radix_node *, int)); +static int rn_lexobetter __P((void *, void *)); +static struct radix_mask *rn_new_radix_mask __P((struct radix_node *, + struct radix_mask *)); +/* + * The data structure for the keys is a radix tree with one way + * branching removed. The index rn_b at an internal node n represents a bit + * position to be tested. The tree is arranged so that all descendants + * of a node n have keys whose bits all agree up to position rn_b - 1. + * (We say the index of n is rn_b.) + * + * There is at least one descendant which has a one bit at position rn_b, + * and at least one with a zero there. + * + * A route is determined by a pair of key and mask. We require that the + * bit-wise logical and of the key and mask to be the key. + * We define the index of a route to associated with the mask to be + * the first bit number in the mask where 0 occurs (with bit number 0 + * representing the highest order bit). + * + * We say a mask is normal if every bit is 0, past the index of the mask. + * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b, + * and m is a normal mask, then the route applies to every descendant of n. + * If the index(m) < rn_b, this implies the trailing last few bits of k + * before bit b are all 0, (and hence consequently true of every descendant + * of n), so the route applies to all descendants of the node as well. + * + * Similar logic shows that a non-normal mask m such that + * index(m) <= index(n) could potentially apply to many children of n. + * Thus, for each non-host route, we attach its mask to a list at an internal + * node as high in the tree as we can go. + * + * The present version of the code makes use of normal routes in short- + * circuiting an explict mask and compare operation when testing whether + * a key satisfies a normal route, and also in remembering the unique leaf + * that governs a subtree. + */ + +struct radix_node * +rn_search(v_arg, head) + void *v_arg; + struct radix_node *head; +{ + register struct radix_node *x; + register caddr_t v; + + for (x = head, v = v_arg; x->rn_b >= 0;) { + if (x->rn_bmask & v[x->rn_off]) + x = x->rn_r; + else + x = x->rn_l; + } + return (x); +} + +struct radix_node * +rn_search_m(v_arg, head, m_arg) + struct radix_node *head; + void *v_arg, *m_arg; +{ + register struct radix_node *x; + register caddr_t v = v_arg, m = m_arg; + + for (x = head; x->rn_b >= 0;) { + if ((x->rn_bmask & m[x->rn_off]) && + (x->rn_bmask & v[x->rn_off])) + x = x->rn_r; + else + x = x->rn_l; + } + return x; +} + +int +rn_refines(m_arg, n_arg) + void *m_arg, *n_arg; +{ + register caddr_t m = m_arg, n = n_arg; + register caddr_t lim, lim2 = lim = n + *(u_char *)n; + int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); + int masks_are_equal = 1; + + if (longer > 0) + lim -= longer; + while (n < lim) { + if (*n & ~(*m)) + return 0; + if (*n++ != *m++) + masks_are_equal = 0; + } + while (n < lim2) + if (*n++) + return 0; + if (masks_are_equal && (longer < 0)) + for (lim2 = m - longer; m < lim2; ) + if (*m++) + return 1; + return (!masks_are_equal); +} + +struct radix_node * +rn_lookup(v_arg, m_arg, head) + void *v_arg, *m_arg; + struct radix_node_head *head; +{ + register struct radix_node *x; + caddr_t netmask = 0; + + if (m_arg) { + if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0) + return (0); + netmask = x->rn_key; + } + x = rn_match(v_arg, head); + if (x && netmask) { + while (x && x->rn_mask != netmask) + x = x->rn_dupedkey; + } + return x; +} + +static int +rn_satsifies_leaf(trial, leaf, skip) + char *trial; + register struct radix_node *leaf; + int skip; +{ + register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask; + char *cplim; + int length = min(*(u_char *)cp, *(u_char *)cp2); + + if (cp3 == 0) + cp3 = rn_ones; + else + length = min(length, *(u_char *)cp3); + cplim = cp + length; cp3 += skip; cp2 += skip; + for (cp += skip; cp < cplim; cp++, cp2++, cp3++) + if ((*cp ^ *cp2) & *cp3) + return 0; + return 1; +} + +struct radix_node * +rn_match(v_arg, head) + void *v_arg; + struct radix_node_head *head; +{ + caddr_t v = v_arg; + register struct radix_node *t = head->rnh_treetop, *x; + register caddr_t cp = v, cp2; + caddr_t cplim; + struct radix_node *saved_t, *top = t; + int off = t->rn_off, vlen = *(u_char *)cp, matched_off; + register int test, b, rn_b; + + /* + * Open code rn_search(v, top) to avoid overhead of extra + * subroutine call. + */ + for (; t->rn_b >= 0; ) { + if (t->rn_bmask & cp[t->rn_off]) + t = t->rn_r; + else + t = t->rn_l; + } + /* + * See if we match exactly as a host destination + * or at least learn how many bits match, for normal mask finesse. + * + * It doesn't hurt us to limit how many bytes to check + * to the length of the mask, since if it matches we had a genuine + * match and the leaf we have is the most specific one anyway; + * if it didn't match with a shorter length it would fail + * with a long one. This wins big for class B&C netmasks which + * are probably the most common case... + */ + if (t->rn_mask) + vlen = *(u_char *)t->rn_mask; + cp += off; cp2 = t->rn_key + off; cplim = v + vlen; + for (; cp < cplim; cp++, cp2++) + if (*cp != *cp2) + goto on1; + /* + * This extra grot is in case we are explicitly asked + * to look up the default. Ugh! + */ + if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey) + t = t->rn_dupedkey; + return t; +on1: + test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */ + for (b = 7; (test >>= 1) > 0;) + b--; + matched_off = cp - v; + b += matched_off << 3; + rn_b = -1 - b; + /* + * If there is a host route in a duped-key chain, it will be first. + */ + if ((saved_t = t)->rn_mask == 0) + t = t->rn_dupedkey; + for (; t; t = t->rn_dupedkey) + /* + * Even if we don't match exactly as a host, + * we may match if the leaf we wound up at is + * a route to a net. + */ + if (t->rn_flags & RNF_NORMAL) { + if (rn_b <= t->rn_b) + return t; + } else if (rn_satsifies_leaf(v, t, matched_off)) + return t; + t = saved_t; + /* start searching up the tree */ + do { + register struct radix_mask *m; + t = t->rn_p; + if ((m = t->rn_mklist) != NULL) { + /* + * If non-contiguous masks ever become important + * we can restore the masking and open coding of + * the search and satisfaction test and put the + * calculation of "off" back before the "do". + */ + do { + if (m->rm_flags & RNF_NORMAL) { + if (rn_b <= m->rm_b) + return (m->rm_leaf); + } else { + off = min(t->rn_off, matched_off); + x = rn_search_m(v, t, m->rm_mask); + while (x && x->rn_mask != m->rm_mask) + x = x->rn_dupedkey; + if (x && rn_satsifies_leaf(v, x, off)) + return x; + } + } while ((m = m->rm_mklist) != NULL); + } + } while (t != top); + return 0; +} + +#ifdef RN_DEBUG +int rn_nodenum; +struct radix_node *rn_clist; +int rn_saveinfo; +int rn_debug = 1; +#endif + +struct radix_node * +rn_newpair(v, b, nodes) + void *v; + int b; + struct radix_node nodes[2]; +{ + register struct radix_node *tt = nodes, *t = tt + 1; + t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7); + t->rn_l = tt; t->rn_off = b >> 3; + tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t; + tt->rn_flags = t->rn_flags = RNF_ACTIVE; +#ifdef RN_DEBUG + tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; + tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; +#endif + return t; +} + +struct radix_node * +rn_insert(v_arg, head, dupentry, nodes) + void *v_arg; + struct radix_node_head *head; + int *dupentry; + struct radix_node nodes[2]; +{ + caddr_t v = v_arg; + struct radix_node *top = head->rnh_treetop; + int head_off = top->rn_off, vlen = (int)*((u_char *)v); + register struct radix_node *t = rn_search(v_arg, top); + register caddr_t cp = v + head_off; + register int b; + struct radix_node *tt; + /* + * Find first bit at which v and t->rn_key differ + */ + { + register caddr_t cp2 = t->rn_key + head_off; + register int cmp_res; + caddr_t cplim = v + vlen; + + while (cp < cplim) + if (*cp2++ != *cp++) + goto on1; + *dupentry = 1; + return t; +on1: + *dupentry = 0; + cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; + for (b = (cp - v) << 3; cmp_res; b--) + cmp_res >>= 1; + } + { + register struct radix_node *p, *x = top; + cp = v; + do { + p = x; + if (cp[x->rn_off] & x->rn_bmask) + x = x->rn_r; + else x = x->rn_l; + } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */ +#ifdef __ECOS +#else +#ifdef RN_DEBUG + if (rn_debug) + log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p); +#endif +#endif + t = rn_newpair(v_arg, b, nodes); tt = t->rn_l; + if ((cp[p->rn_off] & p->rn_bmask) == 0) + p->rn_l = t; + else + p->rn_r = t; + x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */ + if ((cp[t->rn_off] & t->rn_bmask) == 0) { + t->rn_r = x; + } else { + t->rn_r = tt; t->rn_l = x; + } +#ifdef __ECOS +#else +#ifdef RN_DEBUG + if (rn_debug) + log(LOG_DEBUG, "rn_insert: Coming Out:\n"), traverse(p); +#endif +#endif + } + return (tt); +} + +struct radix_node * +rn_addmask(n_arg, search, skip) + int search, skip; + void *n_arg; +{ + caddr_t netmask = (caddr_t)n_arg; + register struct radix_node *x; + register caddr_t cp, cplim; + register int b = 0, mlen, j; + int maskduplicated, m0, isnormal; + struct radix_node *saved_x; + static int last_zeroed = 0; + + if ((mlen = *(u_char *)netmask) > max_keylen) + mlen = max_keylen; + if (skip == 0) + skip = 1; + if (mlen <= skip) + return (mask_rnhead->rnh_nodes); + if (skip > 1) + Bcopy(rn_ones + 1, addmask_key + 1, skip - 1); + if ((m0 = mlen) > skip) + Bcopy(netmask + skip, addmask_key + skip, mlen - skip); + /* + * Trim trailing zeroes. + */ + for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;) + cp--; + mlen = cp - addmask_key; + if (mlen <= skip) { + if (m0 >= last_zeroed) + last_zeroed = mlen; + return (mask_rnhead->rnh_nodes); + } + if (m0 < last_zeroed) + Bzero(addmask_key + m0, last_zeroed - m0); + *addmask_key = last_zeroed = mlen; + x = rn_search(addmask_key, rn_masktop); + if (Bcmp(addmask_key, x->rn_key, mlen) != 0) + x = 0; + if (x || search) + return (x); + R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x)); + if ((saved_x = x) == 0) + return (0); + Bzero(x, max_keylen + 2 * sizeof (*x)); + netmask = cp = (caddr_t)(x + 2); + Bcopy(addmask_key, cp, mlen); + x = rn_insert(cp, mask_rnhead, &maskduplicated, x); + if (maskduplicated) { +#ifdef __ECOS +#else + log(LOG_ERR, "rn_addmask: mask impossibly already in tree"); +#endif + Free(saved_x); + return (x); + } + /* + * Calculate index of mask, and check for normalcy. + */ + cplim = netmask + mlen; isnormal = 1; + for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;) + cp++; + if (cp != cplim) { + for (j = 0x80; (j & *cp) != 0; j >>= 1) + b++; + if (*cp != normal_chars[b] || cp != (cplim - 1)) + isnormal = 0; + } + b += (cp - netmask) << 3; + x->rn_b = -1 - b; + if (isnormal) + x->rn_flags |= RNF_NORMAL; + return (x); +} + +static int /* XXX: arbitrary ordering for non-contiguous masks */ +rn_lexobetter(m_arg, n_arg) + void *m_arg, *n_arg; +{ + register u_char *mp = m_arg, *np = n_arg, *lim; + + if (*mp > *np) + return 1; /* not really, but need to check longer one first */ + if (*mp == *np) + for (lim = mp + *mp; mp < lim;) + if (*mp++ > *np++) + return 1; + return 0; +} + +static struct radix_mask * +rn_new_radix_mask(tt, next) + register struct radix_node *tt; + register struct radix_mask *next; +{ + register struct radix_mask *m; + + MKGet(m); + if (m == 0) { +#ifdef __ECOS +#else + log(LOG_ERR, "Mask for route not entered\n"); +#endif + return (0); + } + Bzero(m, sizeof *m); + m->rm_b = tt->rn_b; + m->rm_flags = tt->rn_flags; + if (tt->rn_flags & RNF_NORMAL) + m->rm_leaf = tt; + else + m->rm_mask = tt->rn_mask; + m->rm_mklist = next; + tt->rn_mklist = m; + return m; +} + +struct radix_node * +rn_addroute(v_arg, n_arg, head, treenodes) + void *v_arg, *n_arg; + struct radix_node_head *head; + struct radix_node treenodes[2]; +{ + caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; + register struct radix_node *t, *x = NULL, *tt; + struct radix_node *saved_tt, *top = head->rnh_treetop; + short b = 0, b_leaf = 0; + int keyduplicated; + caddr_t mmask; + struct radix_mask *m, **mp; + + /* + * In dealing with non-contiguous masks, there may be + * many different routes which have the same mask. + * We will find it useful to have a unique pointer to + * the mask to speed avoiding duplicate references at + * nodes and possibly save time in calculating indices. + */ + if (netmask) { + if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0) + return (0); + b_leaf = x->rn_b; + b = -1 - x->rn_b; + netmask = x->rn_key; + } + /* + * Deal with duplicated keys: attach node to previous instance + */ + saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes); + if (keyduplicated) { + for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) { + if (tt->rn_mask == netmask) + return (0); + if (netmask == 0 || + (tt->rn_mask && + ((b_leaf < tt->rn_b) || /* index(netmask) > node */ + rn_refines(netmask, tt->rn_mask) || + rn_lexobetter(netmask, tt->rn_mask)))) + break; + } + /* + * If the mask is not duplicated, we wouldn't + * find it among possible duplicate key entries + * anyway, so the above test doesn't hurt. + * + * We sort the masks for a duplicated key the same way as + * in a masklist -- most specific to least specific. + * This may require the unfortunate nuisance of relocating + * the head of the list. + */ + if (tt == saved_tt) { + struct radix_node *xx = x; + /* link in at head of list */ + (tt = treenodes)->rn_dupedkey = t; + tt->rn_flags = t->rn_flags; + tt->rn_p = x = t->rn_p; + if (x->rn_l == t) x->rn_l = tt; else x->rn_r = tt; + saved_tt = tt; x = xx; + } else { + (tt = treenodes)->rn_dupedkey = t->rn_dupedkey; + t->rn_dupedkey = tt; + } +#ifdef RN_DEBUG + t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; + tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; +#endif + tt->rn_key = (caddr_t) v; + tt->rn_b = -1; + tt->rn_flags = RNF_ACTIVE; + } + /* + * Put mask in tree. + */ + if (netmask) { + tt->rn_mask = netmask; + tt->rn_b = x->rn_b; + tt->rn_flags |= x->rn_flags & RNF_NORMAL; + } + t = saved_tt->rn_p; + if (keyduplicated) + goto on2; + b_leaf = -1 - t->rn_b; + if (t->rn_r == saved_tt) x = t->rn_l; else x = t->rn_r; + /* Promote general routes from below */ + if (x->rn_b < 0) { + for (mp = &t->rn_mklist; x; x = x->rn_dupedkey) + if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) { + *mp = m = rn_new_radix_mask(x, 0); + if (m) + mp = &m->rm_mklist; + } + } else if (x->rn_mklist) { + /* + * Skip over masks whose index is > that of new node + */ + for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) + if (m->rm_b >= b_leaf) + break; + t->rn_mklist = m; *mp = 0; + } +on2: + /* Add new route to highest possible ancestor's list */ + if ((netmask == 0) || (b > t->rn_b )) + return tt; /* can't lift at all */ + b_leaf = tt->rn_b; + do { + x = t; + t = t->rn_p; + } while (b <= t->rn_b && x != top); + /* + * Search through routes associated with node to + * insert new route according to index. + * Need same criteria as when sorting dupedkeys to avoid + * double loop on deletion. + */ + for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) { + if (m->rm_b < b_leaf) + continue; + if (m->rm_b > b_leaf) + break; + if (m->rm_flags & RNF_NORMAL) { + mmask = m->rm_leaf->rn_mask; + if (tt->rn_flags & RNF_NORMAL) { +#ifdef __ECOS +#else + log(LOG_ERR, + "Non-unique normal route, mask not entered"); +#endif + return tt; + } + } else + mmask = m->rm_mask; + if (mmask == netmask) { + m->rm_refs++; + tt->rn_mklist = m; + return tt; + } + if (rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask)) + break; + } + *mp = rn_new_radix_mask(tt, *mp); + return tt; +} + +struct radix_node * +rn_delete(v_arg, netmask_arg, head) + void *v_arg, *netmask_arg; + struct radix_node_head *head; +{ + register struct radix_node *t, *p, *x, *tt; + struct radix_mask *m, *saved_m, **mp; + struct radix_node *dupedkey, *saved_tt, *top; + caddr_t v, netmask; + int b, head_off, vlen; + + v = v_arg; + netmask = netmask_arg; + x = head->rnh_treetop; + tt = rn_search(v, x); + head_off = x->rn_off; + vlen = *(u_char *)v; + saved_tt = tt; + top = x; + if (tt == 0 || + Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off)) + return (0); + /* + * Delete our route from mask lists. + */ + if (netmask) { + if ((x = rn_addmask(netmask, 1, head_off)) == 0) + return (0); + netmask = x->rn_key; + while (tt->rn_mask != netmask) + if ((tt = tt->rn_dupedkey) == 0) + return (0); + } + if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0) + goto on1; + if (tt->rn_flags & RNF_NORMAL) { + if (m->rm_leaf != tt || m->rm_refs > 0) { +#ifdef __ECOS +#else + log(LOG_ERR, "rn_delete: inconsistent annotation\n"); +#endif + return 0; /* dangling ref could cause disaster */ + } + } else { + if (m->rm_mask != tt->rn_mask) { +#ifdef __ECOS +#else + log(LOG_ERR, "rn_delete: inconsistent annotation\n"); +#endif + goto on1; + } + if (--m->rm_refs >= 0) + goto on1; + } + b = -1 - tt->rn_b; + t = saved_tt->rn_p; + if (b > t->rn_b) + goto on1; /* Wasn't lifted at all */ + do { + x = t; + t = t->rn_p; + } while (b <= t->rn_b && x != top); + for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) + if (m == saved_m) { + *mp = m->rm_mklist; + MKFree(m); + break; + } + if (m == 0) { +#ifdef __ECOS +#else + log(LOG_ERR, "rn_delete: couldn't find our annotation\n"); +#endif + if (tt->rn_flags & RNF_NORMAL) + return (0); /* Dangling ref to us */ + } +on1: + /* + * Eliminate us from tree + */ + if (tt->rn_flags & RNF_ROOT) + return (0); +#ifdef RN_DEBUG + /* Get us out of the creation list */ + for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {} + if (t) t->rn_ybro = tt->rn_ybro; +#endif + t = tt->rn_p; + if ((dupedkey = saved_tt->rn_dupedkey) != 0) { + if (tt == saved_tt) { + x = dupedkey; x->rn_p = t; + if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x; + } else { + for (x = p = saved_tt; p && p->rn_dupedkey != tt;) + p = p->rn_dupedkey; + if (p) p->rn_dupedkey = tt->rn_dupedkey; +#ifdef __ECOS +#else + else log(LOG_ERR, "rn_delete: couldn't find us\n"); +#endif + } + t = tt + 1; + if (t->rn_flags & RNF_ACTIVE) { +#ifndef RN_DEBUG + *++x = *t; p = t->rn_p; +#else + b = t->rn_info; *++x = *t; t->rn_info = b; p = t->rn_p; +#endif + if (p->rn_l == t) p->rn_l = x; else p->rn_r = x; + x->rn_l->rn_p = x; x->rn_r->rn_p = x; + } + goto out; + } + if (t->rn_l == tt) x = t->rn_r; else x = t->rn_l; + p = t->rn_p; + if (p->rn_r == t) p->rn_r = x; else p->rn_l = x; + x->rn_p = p; + /* + * Demote routes attached to us. + */ + if (t->rn_mklist) { + if (x->rn_b >= 0) { + for (mp = &x->rn_mklist; (m = *mp) != NULL;) + mp = &m->rm_mklist; + *mp = t->rn_mklist; + } else { + /* If there are any key,mask pairs in a sibling + duped-key chain, some subset will appear sorted + in the same order attached to our mklist */ + for (m = t->rn_mklist; m && x; x = x->rn_dupedkey) + if (m == x->rn_mklist) { + struct radix_mask *mm = m->rm_mklist; + x->rn_mklist = 0; + if (--(m->rm_refs) < 0) + MKFree(m); + m = mm; + } +#ifdef __ECOS +#else + if (m) + log(LOG_ERR, "%s %p at %p\n", + "rn_delete: Orphaned Mask", m, x); +#endif + } + } + /* + * We may be holding an active internal node in the tree. + */ + x = tt + 1; + if (t != x) { +#ifndef RN_DEBUG + *t = *x; +#else + b = t->rn_info; *t = *x; t->rn_info = b; +#endif + t->rn_l->rn_p = t; t->rn_r->rn_p = t; + p = x->rn_p; + if (p->rn_l == x) p->rn_l = t; else p->rn_r = t; + } +out: + tt->rn_flags &= ~RNF_ACTIVE; + tt[1].rn_flags &= ~RNF_ACTIVE; + return (tt); +} + +int +rn_walktree(h, f, w) + struct radix_node_head *h; + register int (*f) __P((struct radix_node *, void *)); + void *w; +{ + int error; + struct radix_node *base, *next; + register struct radix_node *rn = h->rnh_treetop; + /* + * This gets complicated because we may delete the node + * while applying the function f to it, so we need to calculate + * the successor node in advance. + */ + /* First time through node, go left */ + while (rn->rn_b >= 0) + rn = rn->rn_l; + for (;;) { + base = rn; + /* If at right child go back up, otherwise, go right */ + while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0) + rn = rn->rn_p; + /* Find the next *leaf* since next node might vanish, too */ + for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;) + rn = rn->rn_l; + next = rn; + /* Process leaves */ + while ((rn = base) != NULL) { + base = rn->rn_dupedkey; + if (!(rn->rn_flags & RNF_ROOT) && (error = (*f)(rn, w))) + return (error); + } + rn = next; + if (rn->rn_flags & RNF_ROOT) + return (0); + } + /* NOTREACHED */ +} + +int +rn_inithead(head, off) + void **head; + int off; +{ + register struct radix_node_head *rnh; + register struct radix_node *t, *tt, *ttt; + if (*head) + return (1); + R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh)); + if (rnh == 0) + return (0); + Bzero(rnh, sizeof (*rnh)); + *head = rnh; + t = rn_newpair(rn_zeros, off, rnh->rnh_nodes); + ttt = rnh->rnh_nodes + 2; + t->rn_r = ttt; + t->rn_p = t; + tt = t->rn_l; + tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE; + tt->rn_b = -1 - off; + *ttt = *tt; + ttt->rn_key = rn_ones; + rnh->rnh_addaddr = rn_addroute; + rnh->rnh_deladdr = rn_delete; + rnh->rnh_matchaddr = rn_match; + rnh->rnh_lookup = rn_lookup; + rnh->rnh_walktree = rn_walktree; + rnh->rnh_treetop = t; + return (1); +} + +void +rn_init() +{ + char *cp, *cplim; +#ifdef _KERNEL + struct domain *dom; + + for (dom = domains; dom; dom = dom->dom_next) + if (dom->dom_maxrtkey > max_keylen) + max_keylen = dom->dom_maxrtkey; +#endif + if (max_keylen == 0) { +#ifdef __ECOS +#else + log(LOG_ERR, + "rn_init: radix functions require max_keylen be set\n"); +#endif + return; + } + R_Malloc(rn_zeros, char *, 3 * max_keylen); + if (rn_zeros == NULL) + panic("rn_init"); + Bzero(rn_zeros, 3 * max_keylen); + rn_ones = cp = rn_zeros + max_keylen; + addmask_key = cplim = rn_ones + max_keylen; + while (cp < cplim) + *cp++ = -1; + if (rn_inithead((void **)&mask_rnhead, 0) == 0) + panic("rn_init 2"); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/net/raw_cb.c b/ecos/packages/net/tcpip/current/src/sys/net/raw_cb.c new file mode 100644 index 0000000..7dacc34 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/raw_cb.c @@ -0,0 +1,178 @@ +//========================================================================== +// +// sys/net/raw_cb.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: raw_cb.c,v 1.2 1996/03/03 21:07:16 niklas Exp $ */ +/* $NetBSD: raw_cb.c,v 1.9 1996/02/13 22:00:39 christos Exp $ */ + +/* + * Copyright (c) 1980, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)raw_cb.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/domain.h> +#include <sys/protosw.h> +#include <sys/errno.h> + +#include <net/if.h> +#include <net/route.h> +#include <net/raw_cb.h> +#include <netinet/in.h> + +/* + * Routines to manage the raw protocol control blocks. + * + * TODO: + * hash lookups by protocol family/protocol + address family + * take care of unique address problems per AF? + * redo address binding to allow wildcards + */ + +u_long raw_sendspace = RAWSNDQ; +u_long raw_recvspace = RAWRCVQ; + +/* + * Allocate a control block and a nominal amount + * of buffer space for the socket. + */ +int +raw_attach(so, proto) + register struct socket *so; + int proto; +{ + register struct rawcb *rp = sotorawcb(so); + int error; + + /* + * It is assumed that raw_attach is called + * after space has been allocated for the + * rawcb. + */ + if (rp == 0) + return (ENOBUFS); + if ((error = soreserve(so, raw_sendspace, raw_recvspace)) != 0) + return (error); + rp->rcb_socket = so; + rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; + rp->rcb_proto.sp_protocol = proto; + LIST_INSERT_HEAD(&rawcb, rp, rcb_list); + return (0); +} + +/* + * Detach the raw connection block and discard + * socket resources. + */ +void +raw_detach(rp) + register struct rawcb *rp; +{ + struct socket *so = rp->rcb_socket; + + so->so_pcb = 0; + sofree(so); + LIST_REMOVE(rp, rcb_list); +#ifdef notdef + if (rp->rcb_laddr) + m_freem(dtom(rp->rcb_laddr)); + rp->rcb_laddr = 0; +#endif + free((caddr_t)(rp), M_PCB); +} + +/* + * Disconnect and possibly release resources. + */ +void +raw_disconnect(rp) + struct rawcb *rp; +{ + +#ifdef notdef + if (rp->rcb_faddr) + m_freem(dtom(rp->rcb_faddr)); + rp->rcb_faddr = 0; +#endif + if (rp->rcb_socket->so_state & SS_NOFDREF) + raw_detach(rp); +} + +#ifdef notdef +int +raw_bind(so, nam) + register struct socket *so; + struct mbuf *nam; +{ + struct sockaddr *addr = mtod(nam, struct sockaddr *); + register struct rawcb *rp; + + if (ifnet == 0) + return (EADDRNOTAVAIL); + rp = sotorawcb(so); + nam = m_copym(nam, 0, M_COPYALL, M_WAITOK); + rp->rcb_laddr = mtod(nam, struct sockaddr *); + return (0); +} +#endif diff --git a/ecos/packages/net/tcpip/current/src/sys/net/raw_usrreq.c b/ecos/packages/net/tcpip/current/src/sys/net/raw_usrreq.c new file mode 100644 index 0000000..f0fde95 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/raw_usrreq.c @@ -0,0 +1,360 @@ +//========================================================================== +// +// sys/net/raw_usrreq.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: raw_usrreq.c,v 1.3 1998/09/17 12:29:55 deraadt Exp $ */ +/* $NetBSD: raw_usrreq.c,v 1.11 1996/02/13 22:00:43 christos Exp $ */ + +/* + * Copyright (c) 1980, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/domain.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/errno.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif + +#include <net/if.h> +#include <net/route.h> +#include <net/netisr.h> +#include <net/raw_cb.h> + +#include <machine/stdarg.h> +/* + * Initialize raw connection block q. + */ +void +raw_init() +{ + + LIST_INIT(&rawcb); +} + + +/* + * Raw protocol input routine. Find the socket + * associated with the packet(s) and move them over. If + * nothing exists for this packet, drop it. + */ +/* + * Raw protocol interface. + */ +void +#if __STDC__ +raw_input(struct mbuf *m0, ...) +#else +raw_input(m0, va_alist) + struct mbuf *m0; + va_dcl +#endif +{ + register struct rawcb *rp; + register struct mbuf *m = m0; + register int sockets = 0; + struct socket *last; + va_list ap; + register struct sockproto *proto; + struct sockaddr *src, *dst; + + va_start(ap, m0); + proto = va_arg(ap, struct sockproto *); + src = va_arg(ap, struct sockaddr *); + dst = va_arg(ap, struct sockaddr *); + va_end(ap); + + last = 0; + for (rp = rawcb.lh_first; rp != 0; rp = rp->rcb_list.le_next) { + if (rp->rcb_proto.sp_family != proto->sp_family) + continue; + if (rp->rcb_proto.sp_protocol && + rp->rcb_proto.sp_protocol != proto->sp_protocol) + continue; + /* + * We assume the lower level routines have + * placed the address in a canonical format + * suitable for a structure comparison. + * + * Note that if the lengths are not the same + * the comparison will fail at the first byte. + */ +#define equal(a1, a2) \ + (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) + if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) + continue; + if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) + continue; + if (last) { + struct mbuf *n; + if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { + if (sbappendaddr(&last->so_rcv, src, + n, (struct mbuf *)0) == 0) + /* should notify about lost packet */ + m_freem(n); + else { + sorwakeup(last); + sockets++; + } + } + } + last = rp->rcb_socket; + } + if (last) { + if (sbappendaddr(&last->so_rcv, src, + m, (struct mbuf *)0) == 0) + m_freem(m); + else { + sorwakeup(last); + sockets++; + } + } else + m_freem(m); +} + +/*ARGSUSED*/ +void * +raw_ctlinput(cmd, arg, d) + int cmd; + struct sockaddr *arg; + void *d; +{ + + if (cmd < 0 || cmd > PRC_NCMDS) + return NULL; + return NULL; + /* INCOMPLETE */ +} + +/*ARGSUSED*/ +int +raw_usrreq(so, req, m, nam, control) + struct socket *so; + int req; + struct mbuf *m, *nam, *control; +{ + register struct rawcb *rp = sotorawcb(so); + register int error = 0; + int len; + + if (req == PRU_CONTROL) + return (EOPNOTSUPP); + if (control && control->m_len) { + error = EOPNOTSUPP; + goto release; + } + if (rp == 0) { + error = EINVAL; + goto release; + } + switch (req) { + + /* + * Allocate a raw control block and fill in the + * necessary info to allow packets to be routed to + * the appropriate raw interface routine. + */ + case PRU_ATTACH: +#ifndef __ECOS + if ((so->so_state & SS_PRIV) == 0) { + error = EACCES; + break; + } +#endif + error = raw_attach(so, (int)(long)nam); + break; + + /* + * Destroy state just before socket deallocation. + * Flush data or not depending on the options. + */ + case PRU_DETACH: + if (rp == 0) { + error = ENOTCONN; + break; + } + raw_detach(rp); + break; + +#ifdef notdef + /* + * If a socket isn't bound to a single address, + * the raw input routine will hand it anything + * within that protocol family (assuming there's + * nothing else around it should go to). + */ + case PRU_CONNECT: + if (rp->rcb_faddr) { + error = EISCONN; + break; + } + nam = m_copym(nam, 0, M_COPYALL, M_WAIT); + rp->rcb_faddr = mtod(nam, struct sockaddr *); + soisconnected(so); + break; + + case PRU_BIND: + if (rp->rcb_laddr) { + error = EINVAL; /* XXX */ + break; + } + error = raw_bind(so, nam); + break; +#else + case PRU_CONNECT: + case PRU_BIND: +#endif + case PRU_CONNECT2: + error = EOPNOTSUPP; + goto release; + + case PRU_DISCONNECT: + if (rp->rcb_faddr == 0) { + error = ENOTCONN; + break; + } + raw_disconnect(rp); + soisdisconnected(so); + break; + + /* + * Mark the connection as being incapable of further input. + */ + case PRU_SHUTDOWN: + socantsendmore(so); + break; + + /* + * Ship a packet out. The appropriate raw output + * routine handles any massaging necessary. + */ + case PRU_SEND: + if (nam) { + if (rp->rcb_faddr) { + error = EISCONN; + break; + } + rp->rcb_faddr = mtod(nam, struct sockaddr *); + } else if (rp->rcb_faddr == 0) { + error = ENOTCONN; + break; + } + error = (*so->so_proto->pr_output)(m, so); + m = NULL; + if (nam) + rp->rcb_faddr = 0; + break; + + case PRU_ABORT: + raw_disconnect(rp); + sofree(so); + soisdisconnected(so); + break; + + case PRU_SENSE: + /* + * stat: don't bother with a blocksize. + */ + return (0); + + /* + * Not supported. + */ + case PRU_RCVOOB: + case PRU_RCVD: + return(EOPNOTSUPP); + + case PRU_LISTEN: + case PRU_ACCEPT: + case PRU_SENDOOB: + error = EOPNOTSUPP; + break; + + case PRU_SOCKADDR: + if (rp->rcb_laddr == 0) { + error = EINVAL; + break; + } + len = rp->rcb_laddr->sa_len; + bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); + nam->m_len = len; + break; + + case PRU_PEERADDR: + if (rp->rcb_faddr == 0) { + error = ENOTCONN; + break; + } + len = rp->rcb_faddr->sa_len; + bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); + nam->m_len = len; + break; + + default: + panic("raw_usrreq"); + } +release: + if (m != NULL) + m_freem(m); + return (error); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/net/route.c b/ecos/packages/net/tcpip/current/src/sys/net/route.c new file mode 100644 index 0000000..67673d9 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/route.c @@ -0,0 +1,1074 @@ +//========================================================================== +// +// sys/net/route.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: route.c,v 1.16 1999/12/08 06:50:18 itojun Exp $ */ +/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1980, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)route.c 8.2 (Berkeley) 11/15/93 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#ifdef __ECOS +struct proc { + int __unused; +}; +#else +#include <sys/systm.h> +#include <sys/proc.h> +#endif +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/domain.h> +#include <sys/protosw.h> +#include <sys/ioctl.h> +#include <sys/kernel.h> + +#include <net/if.h> +#include <net/route.h> +#include <net/raw_cb.h> + +#include <netinet/in.h> +#include <netinet/in_var.h> + +#ifdef NS +#include <netns/ns.h> +#endif + +#ifdef IPSEC +#include <netinet/ip_ipsp.h> + +extern struct ifnet encif; +#endif + +#define SA(p) ((struct sockaddr *)(p)) + +int rttrash; /* routes not in table but not freed */ +struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ + +static int okaytoclone __P((u_int, int)); + +#ifdef IPSEC + +static struct ifaddr * +encap_findgwifa(struct sockaddr *gw) +{ + return encif.if_addrlist.tqh_first; +} + +#endif + +void +rtable_init(table) + void **table; +{ + struct domain *dom; + for (dom = domains; dom; dom = dom->dom_next) + if (dom->dom_rtattach) + dom->dom_rtattach(&table[dom->dom_family], + dom->dom_rtoffset); +} + +void +route_init() +{ + rn_init(); /* initialize all zeroes, all ones, mask table */ + rtable_init((void **)rt_tables); +} + +// FIXME: This function is only here because BOOTP fails on a second interface. +// This failure is due to the fact that a route to 0.0.0.0 seems to be +// incredibly sticky, i.e. can't be deleted. BOOTP uses this to +// achieve a generic broadcast. Sadly it seems that BOOTP servers will +// only work this way, thus the hack. +// +// This version enumerates all routes and deletes them - this leaks less +// store than the previous version. + +static int +rt_reinit_rtdelete( struct radix_node *rn, void *vifp ) +{ + struct rtentry *rt = (struct rtentry *)rn; + rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), + 0, NULL); + return (0); +} + +void +cyg_route_reinit(void) +{ + int i; + for (i = 0; i < AF_MAX+1; i++) { + struct radix_node_head *rnh; + rnh = rt_tables[i]; + if (rnh) { + (*rnh->rnh_walktree)(rnh, rt_reinit_rtdelete, NULL); + } + } +} + +void +rtalloc_noclone(ro, howstrict) + register struct route *ro; + int howstrict; +{ + if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) + return; /* XXX */ + ro->ro_rt = rtalloc2(&ro->ro_dst, 1, howstrict); +} + +static int +okaytoclone(flags, howstrict) + u_int flags; + int howstrict; +{ + if (howstrict == ALL_CLONING) + return 1; + if (howstrict == ONNET_CLONING && !(flags & (RTF_GATEWAY|RTF_TUNNEL))) + return 1; + return 0; +} + +struct rtentry * +rtalloc2(dst, report,howstrict) + register struct sockaddr *dst; + int report,howstrict; +{ + register struct radix_node_head *rnh = rt_tables[dst->sa_family]; + register struct rtentry *rt; + register struct radix_node *rn; + struct rtentry *newrt = 0; + struct rt_addrinfo info; + int s = splnet(), err = 0, msgtype = RTM_MISS; + + if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && + ((rn->rn_flags & RNF_ROOT) == 0)) { + newrt = rt = (struct rtentry *)rn; + if (report && (rt->rt_flags & RTF_CLONING) && + okaytoclone(rt->rt_flags, howstrict)) { + err = rtrequest(RTM_RESOLVE, dst, SA(0), SA(0), 0, + &newrt); + if (err) { + newrt = rt; + rt->rt_refcnt++; + goto miss; + } + if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { + msgtype = RTM_RESOLVE; + goto miss; + } + } else + rt->rt_refcnt++; + } else { + rtstat.rts_unreach++; +miss: if (report) { + bzero((caddr_t)&info, sizeof(info)); + info.rti_info[RTAX_DST] = dst; + rt_missmsg(msgtype, &info, 0, err); + } + } + splx(s); + return (newrt); +} + +/* + * Packet routing routines. + */ +void +rtalloc(ro) + register struct route *ro; +{ + if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) + return; /* XXX */ + ro->ro_rt = rtalloc1(&ro->ro_dst, 1); +} + +struct rtentry * +rtalloc1(dst, report) + register struct sockaddr *dst; + int report; +{ + register struct radix_node_head *rnh = rt_tables[dst->sa_family]; + register struct rtentry *rt; + register struct radix_node *rn; + struct rtentry *newrt = 0; + struct rt_addrinfo info; + int s = splsoftnet(), err = 0, msgtype = RTM_MISS; + + if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && + ((rn->rn_flags & RNF_ROOT) == 0)) { + newrt = rt = (struct rtentry *)rn; + if (report && (rt->rt_flags & RTF_CLONING)) { + err = rtrequest(RTM_RESOLVE, dst, SA(NULL), + SA(NULL), 0, &newrt); + if (err) { + newrt = rt; + rt->rt_refcnt++; + goto miss; + } + if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { + msgtype = RTM_RESOLVE; + goto miss; + } + } else + rt->rt_refcnt++; + } else { + if (dst->sa_family != PF_KEY) + rtstat.rts_unreach++; + /* + * IP encapsulation does lots of lookups where we don't need nor want + * the RTM_MISSes that would be generated. It causes RTM_MISS storms + * sent upward breaking user-level routing queries. + */ + miss: if (report && dst->sa_family != PF_KEY) { + bzero((caddr_t)&info, sizeof(info)); + info.rti_info[RTAX_DST] = dst; + rt_missmsg(msgtype, &info, 0, err); + } + } + splx(s); + return (newrt); +} + +void +rtfree(rt) + register struct rtentry *rt; +{ + register struct ifaddr *ifa; + + if (rt == NULL) + panic("rtfree"); + rt->rt_refcnt--; + if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { + if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) + panic ("rtfree 2"); + rttrash--; + if (rt->rt_refcnt < 0) { +#ifdef __ECOS + diag_printf("rtfree: %x not freed (neg refs)\n", rt); +#else + printf("rtfree: %x not freed (neg refs)\n", rt); +#endif + return; + } + rt_timer_remove_all(rt); + ifa = rt->rt_ifa; + if (ifa) + IFAFREE(ifa); + Free(rt_key(rt)); + Free(rt); + } +} + +void +ifafree(ifa) + register struct ifaddr *ifa; +{ + if (ifa == NULL) + panic("ifafree"); + if (ifa->ifa_refcnt == 0) + free(ifa, M_IFADDR); + else + ifa->ifa_refcnt--; +} + +/* + * Force a routing table entry to the specified + * destination to go through the given gateway. + * Normally called as a result of a routing redirect + * message from the network layer. + * + * N.B.: must be called at splsoftnet + */ +void +rtredirect(dst, gateway, netmask, flags, src, rtp) + struct sockaddr *dst, *gateway, *netmask, *src; + int flags; + struct rtentry **rtp; +{ + register struct rtentry *rt; + int error = 0; + u_int32_t *stat = NULL; + struct rt_addrinfo info; + struct ifaddr *ifa; + + /* verify the gateway is directly reachable */ + if ((ifa = ifa_ifwithnet(gateway)) == NULL) { + error = ENETUNREACH; + goto out; + } + rt = rtalloc1(dst, 0); + /* + * If the redirect isn't from our current router for this dst, + * it's either old or wrong. If it redirects us to ourselves, + * we have a routing loop, perhaps as a result of an interface + * going down recently. + */ +#define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) + if (!(flags & RTF_DONE) && rt && + (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) + error = EINVAL; + else if (ifa_ifwithaddr(gateway) != NULL) + error = EHOSTUNREACH; + if (error) + goto done; + /* + * Create a new entry if we just got back a wildcard entry + * or the the lookup failed. This is necessary for hosts + * which use routing redirects generated by smart gateways + * to dynamically build the routing tables. + */ + if ((rt == NULL) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) + goto create; + /* + * Don't listen to the redirect if it's + * for a route to an interface. + */ + if (rt->rt_flags & RTF_GATEWAY) { + if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { + /* + * Changing from route to net => route to host. + * Create new route, rather than smashing route to net. + */ + create: + flags |= RTF_GATEWAY | RTF_DYNAMIC; + error = rtrequest((int)RTM_ADD, dst, gateway, + netmask, flags, + (struct rtentry **)0); + stat = &rtstat.rts_dynamic; + } else { + /* + * Smash the current notion of the gateway to + * this destination. Should check about netmask!!! + */ + rt->rt_flags |= RTF_MODIFIED; + flags |= RTF_MODIFIED; + stat = &rtstat.rts_newgateway; + rt_setgate(rt, rt_key(rt), gateway); + } + } else + error = EHOSTUNREACH; +done: + if (rt) { + if (rtp && !error) + *rtp = rt; + else + rtfree(rt); + } +out: + if (error) + rtstat.rts_badredirect++; + else if (stat != NULL) + (*stat)++; + bzero((caddr_t)&info, sizeof(info)); + info.rti_info[RTAX_DST] = dst; + info.rti_info[RTAX_GATEWAY] = gateway; + info.rti_info[RTAX_NETMASK] = netmask; + info.rti_info[RTAX_AUTHOR] = src; + rt_missmsg(RTM_REDIRECT, &info, flags, error); +} + +/* +* Routing table ioctl interface. +*/ +int +rtioctl(req, data, p) + u_long req; + caddr_t data; + struct proc *p; +{ +#ifdef __ECOS + struct ecos_rtentry *rt; + int res; + + switch (req) { + case SIOCADDRT: + rt = (struct ecos_rtentry *)data; + res = rtrequest(RTM_ADD, + &rt->rt_dst, + &rt->rt_gateway, + &rt->rt_genmask, + rt->rt_flags, + NULL); + return (res); + case SIOCDELRT: + rt = (struct ecos_rtentry *)data; + res = rtrequest(RTM_DELETE, + &rt->rt_dst, + &rt->rt_gateway, + &rt->rt_genmask, + rt->rt_flags, + NULL); + return (res); + default: + return (EOPNOTSUPP); + } +#else + return (EOPNOTSUPP); +#endif +} + +struct ifaddr * +ifa_ifwithroute(flags, dst, gateway) + int flags; + struct sockaddr *dst, *gateway; +{ + register struct ifaddr *ifa; + +#ifdef IPSEC + /* + * If the destination is a PF_KEY address, we'll look + * for the existence of a encap interface number or address + * in the options list of the gateway. By default, we'll return + * enc0. + */ + if (dst && (dst->sa_family == PF_KEY)) + return encap_findgwifa(gateway); +#endif + + if ((flags & RTF_GATEWAY) == 0) { + /* + * If we are adding a route to an interface, + * and the interface is a pt to pt link + * we should search for the destination + * as our clue to the interface. Otherwise + * we can use the local address. + */ + ifa = NULL; + if (flags & RTF_HOST) + ifa = ifa_ifwithdstaddr(dst); + if (ifa == NULL) + ifa = ifa_ifwithaddr(gateway); + } else { + /* + * If we are adding a route to a remote net + * or host, the gateway may still be on the + * other end of a pt to pt link. + */ + ifa = ifa_ifwithdstaddr(gateway); + } + if (ifa == NULL) + ifa = ifa_ifwithnet(gateway); + if (ifa == NULL) { + struct rtentry *rt = rtalloc1(gateway, 0); + if (rt == NULL) + return (NULL); + rt->rt_refcnt--; + /* The gateway must be local if the same address family. */ + if (!(flags & RTF_TUNNEL) && (rt->rt_flags & RTF_GATEWAY) && + rt_key(rt)->sa_family == dst->sa_family) + return (0); + if ((ifa = rt->rt_ifa) == NULL) + return (NULL); + } + if (ifa->ifa_addr->sa_family != dst->sa_family) { + struct ifaddr *oifa = ifa; + ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); + if (ifa == NULL) + ifa = oifa; + } + return (ifa); +} + +#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) + +const char * +_rt_cmd(int req) +{ + switch (req) + { + case RTM_DELETE: + return "DELETE"; + case RTM_RESOLVE: + return "RESOLVE"; + case RTM_ADD: + return "ADD"; + default: + return "???"; + } +} + +int +rtrequest(req, dst, gateway, netmask, flags, ret_nrt) + int req, flags; + struct sockaddr *dst, *gateway, *netmask; + struct rtentry **ret_nrt; +{ + int s = splsoftnet(); int error = 0; + register struct rtentry *rt; + register struct radix_node *rn; + register struct radix_node_head *rnh; + struct ifaddr *ifa; + struct sockaddr *ndst; +#define senderr(x) { error = x ; goto bad; } + + if ((rnh = rt_tables[dst->sa_family]) == 0) + senderr(EAFNOSUPPORT); + if (flags & RTF_HOST) + netmask = 0; + switch (req) { + case RTM_DELETE: + if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == NULL) + senderr(ESRCH); + if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) + panic ("rtrequest delete"); + rt = (struct rtentry *)rn; + rt->rt_flags &= ~RTF_UP; + if (rt->rt_gwroute) { + if (rt != rt->rt_gwroute) + RTFREE( rt->rt_gwroute ); // Free it up as normal + else + rt->rt_refcnt--; // Just dec the refcount - freeing + // it here would be premature + rt->rt_gwroute = NULL; + } + if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) + ifa->ifa_rtrequest(RTM_DELETE, rt, SA(NULL)); + rttrash++; + if (ret_nrt) + *ret_nrt = rt; + else if (rt->rt_refcnt <= 0) { + rt->rt_refcnt++; + rtfree(rt); + } + break; + + case RTM_RESOLVE: + if (ret_nrt == NULL || (rt = *ret_nrt) == NULL) + senderr(EINVAL); + ifa = rt->rt_ifa; + flags = rt->rt_flags & ~RTF_CLONING; + gateway = rt->rt_gateway; + if ((netmask = rt->rt_genmask) == NULL) + flags |= RTF_HOST; + goto makeroute; + + case RTM_ADD: + if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == NULL) + senderr(ENETUNREACH); + + /* The interface found in the previous statement may + * be overridden later by rt_setif. See the code + * for case RTM_ADD in rtsock.c:route_output. + */ + makeroute: + R_Malloc(rt, struct rtentry *, sizeof(*rt)); + if (rt == NULL) + senderr(ENOBUFS); + Bzero(rt, sizeof(*rt)); + rt->rt_flags = RTF_UP | flags; + LIST_INIT(&rt->rt_timer); + if (rt_setgate(rt, dst, gateway)) { + Free(rt); + senderr(ENOBUFS); + } + ndst = rt_key(rt); + if (netmask) { + rt_maskedcopy(dst, ndst, netmask); + } else + Bcopy(dst, ndst, dst->sa_len); +if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { /* XXX */ + rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu; +} + rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, + rnh, rt->rt_nodes); + if (rn == NULL) { + if (rt->rt_gwroute) + rtfree(rt->rt_gwroute); + Free(rt_key(rt)); + Free(rt); + senderr(EEXIST); + } + ifa->ifa_refcnt++; + rt->rt_ifa = ifa; + rt->rt_ifp = ifa->ifa_ifp; + if (req == RTM_RESOLVE) { + /* + * Copy both metrics and a back pointer to the cloned + * route's parent. + */ + rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ + rt->rt_parent = *ret_nrt; /* Back ptr. to parent. */ + } + if (ifa->ifa_rtrequest) + ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : NULL)); + if (ret_nrt) { + *ret_nrt = rt; + rt->rt_refcnt++; + } +#ifdef INET6 + /* If we have a v4_in_v4 or a v4_in_v6 tunnel route + * then do some tunnel state (e.g. security state) + * initialization. + * + * Since IPV6 packets flow down this path, we don't + * want it using ipv4_tunnelsetup(rt) (since they + * have their own ipv6_tunnel_parent/child() + * routines which are called ipv6_rtrequest().) + * + * Thus, we check to see if the packet is to a v4 + * destination. + */ + if (dst->sa_family == AF_INET && (rt->rt_flags & RTF_TUNNEL)) + ipv4_tunnelsetup(rt); +#endif /* INET6 */ + break; + } +bad: + splx(s); + return (error); +} + +/* + * Set up any tunnel states (e.g. security) information + * for v4_in_v4 or v4_in_v6 tunnel routes. + */ +void +ipv4_tunnelsetup(rt) + register struct rtentry *rt; +{ + /* XXX */ +} + +int +rt_setgate(rt0, dst, gate) + struct rtentry *rt0; + struct sockaddr *dst, *gate; +{ + caddr_t new, old; + int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); + register struct rtentry *rt = rt0; + + if (rt->rt_gateway == NULL || glen > ROUNDUP(rt->rt_gateway->sa_len)) { + old = (caddr_t)rt_key(rt); + R_Malloc(new, caddr_t, dlen + glen); + if (new == NULL) + return 1; + rt->rt_nodes->rn_key = new; + } else { + new = rt->rt_nodes->rn_key; + old = NULL; + } + Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); + if (old) { + Bcopy(dst, new, dlen); + Free(old); + } + if (rt->rt_gwroute != NULL) { + rt = rt->rt_gwroute; + RTFREE(rt); + rt = rt0; + rt->rt_gwroute = NULL; + } + if (rt->rt_flags & RTF_GATEWAY) { + rt->rt_gwroute = rtalloc1(gate, 1); + } + return 0; +} + +void +rt_maskedcopy(src, dst, netmask) + struct sockaddr *src, *dst, *netmask; +{ + register u_char *cp1 = (u_char *)src; + register u_char *cp2 = (u_char *)dst; + register u_char *cp3 = (u_char *)netmask; + u_char *cplim = cp2 + *cp3; + u_char *cplim2 = cp2 + *cp1; + + *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ + cp3 += 2; + if (cplim > cplim2) + cplim = cplim2; + while (cp2 < cplim) + *cp2++ = *cp1++ & *cp3++; + if (cp2 < cplim2) + bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); +} + +/* + * Set up a routing table entry, normally + * for an interface. + */ +int +rtinit(ifa, cmd, flags) + register struct ifaddr *ifa; + int cmd, flags; +{ + register struct rtentry *rt; + register struct sockaddr *dst; + register struct sockaddr *deldst; + struct mbuf *m = NULL; + struct rtentry *nrt = NULL; + int error; + + dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; + if (cmd == RTM_DELETE) { + if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { + m = m_get(M_DONTWAIT, MT_SONAME); + if (m == NULL) + return(ENOBUFS); + deldst = mtod(m, struct sockaddr *); + rt_maskedcopy(dst, deldst, ifa->ifa_netmask); + dst = deldst; + } + if ((rt = rtalloc1(dst, 0)) != NULL) { + rt->rt_refcnt--; + if (rt->rt_ifa != ifa) { + if (m != NULL) + (void) m_free(m); + return (flags & RTF_HOST ? EHOSTUNREACH + : ENETUNREACH); + } + } + } + error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask, + flags | ifa->ifa_flags, &nrt); + if (m != NULL) + (void) m_free(m); + if (cmd == RTM_DELETE && error == 0 && (rt = nrt) != NULL) { + rt_newaddrmsg(cmd, ifa, error, nrt); + if (rt->rt_refcnt <= 0) { + rt->rt_refcnt++; + rtfree(rt); + } + } + if (cmd == RTM_ADD && error == 0 && (rt = nrt) != NULL) { + rt->rt_refcnt--; +#ifdef INET6 + /* Initialize Path MTU for IPv6 interface route */ + if (ifa->ifa_addr->sa_family == AF_INET6 && + !rt->rt_rmx.rmx_mtu) + rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu; +#endif /* INET6 */ + if (rt->rt_ifa != ifa) { +#ifdef __ECOS + diag_printf("rtinit: wrong ifa (%x) was (%x)\n", + ifa, rt->rt_ifa); +#else + printf("rtinit: wrong ifa (%x) was (%x)\n", + ifa, rt->rt_ifa); +#endif + if (rt->rt_ifa->ifa_rtrequest) + rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, + SA(NULL)); + IFAFREE(rt->rt_ifa); + rt->rt_ifa = ifa; + rt->rt_ifp = ifa->ifa_ifp; + rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu; /*XXX*/ + ifa->ifa_refcnt++; + if (ifa->ifa_rtrequest) + ifa->ifa_rtrequest(RTM_ADD, rt, SA(NULL)); + } + rt_newaddrmsg(cmd, ifa, error, nrt); + } + return (error); +} + +/* + * Route timer routines. These routes allow functions to be called + * for various routes at any time. This is useful in supporting + * path MTU discovery and redirect route deletion. + * + * This is similar to some BSDI internal functions, but it provides + * for multiple queues for efficiency's sake... + */ + +LIST_HEAD(, rttimer_queue) rttimer_queue_head; +static int rt_init_done = 0; + +#define RTTIMER_CALLOUT(r) { \ + if (r->rtt_func != NULL) { \ + (*r->rtt_func)(r->rtt_rt, r); \ + } else { \ + rtrequest((int) RTM_DELETE, \ + (struct sockaddr *)rt_key(r->rtt_rt), \ + 0, 0, 0, 0); \ + } \ +} + +/* + * Some subtle order problems with domain initialization mean that + * we cannot count on this being run from rt_init before various + * protocol initializations are done. Therefore, we make sure + * that this is run when the first queue is added... + */ + +void +rt_timer_init() +{ +#ifndef __ECOS + assert(rt_init_done == 0); +#endif + +#if 0 + pool_init(&rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl", + 0, NULL, NULL, M_RTABLE); +#endif + + LIST_INIT(&rttimer_queue_head); + timeout(rt_timer_timer, NULL, hz); /* every second */ + rt_init_done = 1; +} + +struct rttimer_queue * +rt_timer_queue_create(timeout) + u_int timeout; +{ + struct rttimer_queue *rtq; + + if (rt_init_done == 0) + rt_timer_init(); + + R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq); + if (rtq == NULL) + return (NULL); + + rtq->rtq_timeout = timeout; + TAILQ_INIT(&rtq->rtq_head); + LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link); + + return (rtq); +} + +void +rt_timer_queue_change(rtq, timeout) + struct rttimer_queue *rtq; + long timeout; +{ + + rtq->rtq_timeout = timeout; +} + + +void +rt_timer_queue_destroy(rtq, destroy) + struct rttimer_queue *rtq; + int destroy; +{ + struct rttimer *r; + + while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) { + LIST_REMOVE(r, rtt_link); + TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); + if (destroy) + RTTIMER_CALLOUT(r); +#if 0 + pool_put(&rttimer_pool, r); +#else + free(r, M_RTABLE); +#endif + } + + LIST_REMOVE(rtq, rtq_link); + + /* + * Caller is responsible for freeing the rttimer_queue structure. + */ +} + +void +rt_timer_remove_all(rt) + struct rtentry *rt; +{ + struct rttimer *r; + + while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { + LIST_REMOVE(r, rtt_link); + TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); +#if 0 + pool_put(&rttimer_pool, r); +#else + free(r, M_RTABLE); +#endif + } +} + +int +rt_timer_add(rt, func, queue) + struct rtentry *rt; + void(*func) __P((struct rtentry *, struct rttimer *)); + struct rttimer_queue *queue; +{ + struct rttimer *r; + long current_time; + int s; + + s = splclock(); +#ifdef __ECOS + get_mono_time(); +#endif + current_time = mono_time.tv_sec; + splx(s); + + /* + * If there's already a timer with this action, destroy it before + * we add a new one. + */ + for (r = LIST_FIRST(&rt->rt_timer); r != NULL; + r = LIST_NEXT(r, rtt_link)) { + if (r->rtt_func == func) { + LIST_REMOVE(r, rtt_link); + TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); +#if 0 + pool_put(&rttimer_pool, r); +#else + free(r, M_RTABLE); +#endif + break; /* only one per list, so we can quit... */ + } + } + +#if 0 + r = pool_get(&rttimer_pool, PR_NOWAIT); +#else + r = (struct rttimer *)malloc(sizeof(*r), M_RTABLE, M_NOWAIT); +#endif + if (r == NULL) + return (ENOBUFS); + + r->rtt_rt = rt; + r->rtt_time = current_time; + r->rtt_func = func; + r->rtt_queue = queue; + LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link); + TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next); + + return (0); +} + +/* ARGSUSED */ +void +rt_timer_timer(arg) + void *arg; +{ + struct rttimer_queue *rtq; + struct rttimer *r; + long current_time; + int s; + + s = splclock(); +#ifdef __ECOS + get_mono_time(); +#endif + current_time = mono_time.tv_sec; + splx(s); + + s = splsoftnet(); + for (rtq = LIST_FIRST(&rttimer_queue_head); rtq != NULL; + rtq = LIST_NEXT(rtq, rtq_link)) { + while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL && + (r->rtt_time + rtq->rtq_timeout) < current_time) { + LIST_REMOVE(r, rtt_link); + TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); + RTTIMER_CALLOUT(r); +#if 0 + pool_put(&rttimer_pool, r); +#else + free(r, M_RTABLE); +#endif + } + } + splx(s); + + timeout(rt_timer_timer, NULL, hz); /* every second */ +} diff --git a/ecos/packages/net/tcpip/current/src/sys/net/rtsock.c b/ecos/packages/net/tcpip/current/src/sys/net/rtsock.c new file mode 100644 index 0000000..5e8317b --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/net/rtsock.c @@ -0,0 +1,1053 @@ +//========================================================================== +// +// sys/net/rtsock.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: rtsock.c,v 1.8 1999/12/08 06:50:18 itojun Exp $ */ +/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rtsock.c 8.6 (Berkeley) 2/11/95 + */ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#include <sys/proc.h> +#endif +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/domain.h> +#include <sys/protosw.h> + +#ifndef __ECOS +#include <vm/vm.h> +#include <sys/sysctl.h> +#endif + +#include <net/if.h> +#include <net/route.h> +#include <net/raw_cb.h> + +#include <machine/stdarg.h> + +struct sockaddr route_dst = { 2, PF_ROUTE, }; +struct sockaddr route_src = { 2, PF_ROUTE, }; +struct sockproto route_proto = { PF_ROUTE, }; + +struct walkarg { + int w_op, w_arg, w_given, w_needed, w_tmemsize; + caddr_t w_where, w_tmem; +}; + +static struct mbuf * + rt_msg1 __P((int, struct rt_addrinfo *)); +static int rt_msg2 __P((int, + struct rt_addrinfo *, caddr_t, struct walkarg *)); +static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); +static void rt_setif __P((struct rtentry *, struct sockaddr *, + struct sockaddr *, struct sockaddr *)); + +/* Sleazy use of local variables throughout file, warning!!!! */ +#define dst info.rti_info[RTAX_DST] +#define gate info.rti_info[RTAX_GATEWAY] +#define netmask info.rti_info[RTAX_NETMASK] +#define genmask info.rti_info[RTAX_GENMASK] +#define ifpaddr info.rti_info[RTAX_IFP] +#define ifaaddr info.rti_info[RTAX_IFA] +#define brdaddr info.rti_info[RTAX_BRD] + +/*ARGSUSED*/ +int +route_usrreq(so, req, m, nam, control) + register struct socket *so; + int req; + struct mbuf *m, *nam, *control; +{ + register int error = 0; + register struct rawcb *rp = sotorawcb(so); + int s; + + if (req == PRU_ATTACH) { + MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); + if ((so->so_pcb = rp) != NULL) + bzero(so->so_pcb, sizeof(*rp)); + + } + if (req == PRU_DETACH && rp) { + int af = rp->rcb_proto.sp_protocol; + if (af == AF_INET) + route_cb.ip_count--; + else if (af == AF_INET6) + route_cb.ip6_count--; + else if (af == AF_NS) + route_cb.ns_count--; + else if (af == AF_ISO) + route_cb.iso_count--; + route_cb.any_count--; + } + s = splsoftnet(); + /* + * Don't call raw_usrreq() in the attach case, because + * we want to allow non-privileged processes to listen on + * and send "safe" commands to the routing socket. + */ + if (req == PRU_ATTACH) { +#ifndef __ECOS + if (curproc == 0) + error = EACCES; + else +#endif // FIXME? + error = raw_attach(so, (int)(long)nam); + } else + error = raw_usrreq(so, req, m, nam, control); + + rp = sotorawcb(so); + if (req == PRU_ATTACH && rp) { + int af = rp->rcb_proto.sp_protocol; + if (error) { + free((caddr_t)rp, M_PCB); + splx(s); + return (error); + } + if (af == AF_INET) + route_cb.ip_count++; + else if (af == AF_INET6) + route_cb.ip6_count++; + else if (af == AF_NS) + route_cb.ns_count++; + else if (af == AF_ISO) + route_cb.iso_count++; + rp->rcb_faddr = &route_src; + route_cb.any_count++; + soisconnected(so); + so->so_options |= SO_USELOOPBACK; + } + splx(s); + return (error); +} + +/*ARGSUSED*/ +int +#if __STDC__ +route_output(struct mbuf *m, ...) +#else +route_output(m, va_alist) + struct mbuf *m; + va_dcl +#endif +{ + register struct rt_msghdr *rtm = 0; + register struct rtentry *rt = 0; + struct rtentry *saved_nrt = 0; + struct radix_node_head *rnh; + struct rt_addrinfo info; + int len, error = 0; + struct ifnet *ifp = 0; + struct socket *so; + va_list ap; + + va_start(ap, m); + so = va_arg(ap, struct socket *); + va_end(ap); + + bzero(&info, sizeof(info)); +#define senderr(e) { error = e; goto flush;} + if (m == 0 || ((m->m_len < sizeof(int32_t)) && + (m = m_pullup(m, sizeof(int32_t))) == 0)) + return (ENOBUFS); + if ((m->m_flags & M_PKTHDR) == 0) + panic("route_output"); + len = m->m_pkthdr.len; + if (len < sizeof(*rtm) || + len != mtod(m, struct rt_msghdr *)->rtm_msglen) { + dst = 0; + senderr(EINVAL); + } + R_Malloc(rtm, struct rt_msghdr *, len); + if (rtm == 0) { + dst = 0; + senderr(ENOBUFS); + } + m_copydata(m, 0, len, (caddr_t)rtm); + if (rtm->rtm_version != RTM_VERSION) { + dst = 0; + senderr(EPROTONOSUPPORT); + } +#ifdef __ECOS + rtm->rtm_pid = 0; // FIXME +#else + rtm->rtm_pid = curproc->p_pid; +#endif + info.rti_addrs = rtm->rtm_addrs; + rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info); + if (dst == 0) + senderr(EINVAL); + if (genmask) { + struct radix_node *t; + t = rn_addmask((caddr_t)genmask, 0, 1); + if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0) + genmask = (struct sockaddr *)(t->rn_key); + else + senderr(ENOBUFS); + } + + /* + * Verify that the caller has the appropriate privilege; RTM_GET + * is the only operation the non-superuser is allowed. + */ +#ifndef __ECOS + if (rtm->rtm_type != RTM_GET && + suser(curproc->p_ucred, &curproc->p_acflag) != 0) + senderr(EACCES); +#endif + switch (rtm->rtm_type) { + + case RTM_ADD: + if (gate == 0) + senderr(EINVAL); + error = rtrequest(RTM_ADD, dst, gate, netmask, + rtm->rtm_flags, &saved_nrt); + if (error == 0 && saved_nrt) { + /* + * If the route request specified an interface with + * IFA and/or IFP, we set the requested interface on + * the route with rt_setif. It would be much better + * to do this inside rtrequest, but that would + * require passing the desired interface, in some + * form, to rtrequest. Since rtrequest is called in + * so many places (roughly 40 in our source), adding + * a parameter is to much for us to swallow; this is + * something for the FreeBSD developers to tackle. + * Instead, we let rtrequest compute whatever + * interface it wants, then come in behind it and + * stick in the interface that we really want. This + * works reasonably well except when rtrequest can't + * figure out what interface to use (with + * ifa_withroute) and returns ENETUNREACH. Ideally + * it shouldn't matter if rtrequest can't figure out + * the interface if we're going to explicitly set it + * ourselves anyway. But practically we can't + * recover here because rtrequest will not do any of + * the work necessary to add the route if it can't + * find an interface. As long as there is a default + * route that leads to some interface, rtrequest will + * find an interface, so this problem should be + * rarely encountered. + * dwiggins@bbn.com + */ + + rt_setif(saved_nrt, ifpaddr, ifaaddr, gate); + rt_setmetrics(rtm->rtm_inits, + &rtm->rtm_rmx, &saved_nrt->rt_rmx); + saved_nrt->rt_refcnt--; + saved_nrt->rt_genmask = genmask; + } + break; + + case RTM_DELETE: + error = rtrequest(RTM_DELETE, dst, gate, netmask, + rtm->rtm_flags, &saved_nrt); + if (error == 0) { + (rt = saved_nrt)->rt_refcnt++; + goto report; + } + break; + + case RTM_GET: + case RTM_CHANGE: + case RTM_LOCK: + if ((rnh = rt_tables[dst->sa_family]) == 0) { + senderr(EAFNOSUPPORT); + } else if ((rt = (struct rtentry *) + rnh->rnh_lookup(dst, netmask, rnh)) != NULL) + rt->rt_refcnt++; + else + senderr(ESRCH); + switch(rtm->rtm_type) { + + case RTM_GET: + report: + dst = rt_key(rt); + gate = rt->rt_gateway; + netmask = rt_mask(rt); + genmask = rt->rt_genmask; + if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { + if ((ifp = rt->rt_ifp) != NULL) { + ifpaddr = ifp->if_addrlist.tqh_first->ifa_addr; + ifaaddr = rt->rt_ifa->ifa_addr; + if (ifp->if_flags & IFF_POINTOPOINT) + brdaddr = rt->rt_ifa->ifa_dstaddr; + else + brdaddr = 0; + rtm->rtm_index = ifp->if_index; + } else { + ifpaddr = 0; + ifaaddr = 0; + } + } + len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0, + (struct walkarg *)0); + if (len > rtm->rtm_msglen) { + struct rt_msghdr *new_rtm; + R_Malloc(new_rtm, struct rt_msghdr *, len); + if (new_rtm == 0) + senderr(ENOBUFS); + Bcopy(rtm, new_rtm, rtm->rtm_msglen); + Free(rtm); rtm = new_rtm; + } + (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, + (struct walkarg *)0); + rtm->rtm_flags = rt->rt_flags; + rtm->rtm_rmx = rt->rt_rmx; + rtm->rtm_addrs = info.rti_addrs; + break; + + case RTM_CHANGE: + if (gate && rt_setgate(rt, rt_key(rt), gate)) +#ifdef __ECOS + senderr(EMFILE); +#else + senderr(EDQUOT); +#endif + +#if 1 + rt_setif(rt, ifpaddr, ifaaddr, gate); +#else + /* new gateway could require new ifaddr, ifp; + flags may also be different; ifp may be specified + by ll sockaddr when protocol address is ambiguous */ + if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) && + (ifp = ifa->ifa_ifp) && (ifaaddr || gate)) + ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate, + ifp); + else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) || + (gate && (ifa = ifa_ifwithroute(rt->rt_flags, + rt_key(rt), gate)))) + ifp = ifa->ifa_ifp; + if (ifa) { + register struct ifaddr *oifa = rt->rt_ifa; + if (oifa != ifa) { + if (oifa && oifa->ifa_rtrequest) + oifa->ifa_rtrequest(RTM_DELETE, + rt, gate); + IFAFREE(rt->rt_ifa); + rt->rt_ifa = ifa; + ifa->ifa_refcnt++; + rt->rt_ifp = ifp; + } + } +#endif + rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, + &rt->rt_rmx); +#if 0 + if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) + rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate); +#endif + if (genmask) + rt->rt_genmask = genmask; + /* + * Fall into + */ + case RTM_LOCK: + rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); + rt->rt_rmx.rmx_locks |= + (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); + break; + } + break; + + default: + senderr(EOPNOTSUPP); + } + +flush: + if (rtm) { + if (error) + rtm->rtm_errno = error; + else + rtm->rtm_flags |= RTF_DONE; + } + if (rt) + rtfree(rt); + { + register struct rawcb *rp = 0; + /* + * Check to see if we don't want our own messages. + */ + if ((so->so_options & SO_USELOOPBACK) == 0) { + if (route_cb.any_count <= 1) { + if (rtm) + Free(rtm); + m_freem(m); + return (error); + } + /* There is another listener, so construct message */ + rp = sotorawcb(so); + } + if (rtm) { + m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); + Free(rtm); + } + if (rp) + rp->rcb_proto.sp_family = 0; /* Avoid us */ + if (dst) + route_proto.sp_protocol = dst->sa_family; + raw_input(m, &route_proto, &route_src, &route_dst); + if (rp) + rp->rcb_proto.sp_family = PF_ROUTE; + } + return (error); +} + +void +rt_setmetrics(which, in, out) + u_long which; + register struct rt_metrics *in, *out; +{ +#define metric(f, e) if (which & (f)) out->e = in->e; + metric(RTV_RPIPE, rmx_recvpipe); + metric(RTV_SPIPE, rmx_sendpipe); + metric(RTV_SSTHRESH, rmx_ssthresh); + metric(RTV_RTT, rmx_rtt); + metric(RTV_RTTVAR, rmx_rttvar); + metric(RTV_HOPCOUNT, rmx_hopcount); + metric(RTV_MTU, rmx_mtu); + metric(RTV_EXPIRE, rmx_expire); +#undef metric +} + +/* + * Set route's interface given ifpaddr, ifaaddr, and gateway. + */ +static void +rt_setif(rt, Ifpaddr, Ifaaddr, Gate) + struct rtentry *rt; + struct sockaddr *Ifpaddr, *Ifaaddr, *Gate; +{ + struct ifaddr *ifa = 0; + struct ifnet *ifp = 0; + + /* new gateway could require new ifaddr, ifp; + flags may also be different; ifp may be specified + by ll sockaddr when protocol address is ambiguous */ + if (Ifpaddr && (ifa = ifa_ifwithnet(Ifpaddr)) && + (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate)) + ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate, + ifp); + else if (Ifpaddr && (ifp = if_withname(Ifpaddr)) ) { + ifa = Gate ? ifaof_ifpforaddr(Gate, ifp) : + TAILQ_FIRST(&ifp->if_addrlist); + } + else if ((Ifaaddr && (ifa = ifa_ifwithaddr(Ifaaddr))) || + (Gate && (ifa = ifa_ifwithroute(rt->rt_flags, + rt_key(rt), Gate)))) + ifp = ifa->ifa_ifp; + if (ifa) { + register struct ifaddr *oifa = rt->rt_ifa; + if (oifa != ifa) { + if (oifa && oifa->ifa_rtrequest) + oifa->ifa_rtrequest(RTM_DELETE, + rt, Gate); + IFAFREE(rt->rt_ifa); + rt->rt_ifa = ifa; + ifa->ifa_refcnt++; + rt->rt_ifp = ifp; + rt->rt_rmx.rmx_mtu = ifp->if_mtu; + if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) + rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate); + } else + goto call_ifareq; + return; + } + call_ifareq: + /* XXX: to reset gateway to correct value, at RTM_CHANGE */ + if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) + rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate); +} + + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +static void +rt_xaddrs(cp, cplim, rtinfo) + register caddr_t cp, cplim; + register struct rt_addrinfo *rtinfo; +{ + register struct sockaddr *sa; + register int i; + + bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info)); + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { + if ((rtinfo->rti_addrs & (1 << i)) == 0) + continue; + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; + ADVANCE(cp, sa); + } +} + +/* + * Copy data from a buffer back into the indicated mbuf chain, + * starting "off" bytes from the beginning, extending the mbuf + * chain if necessary. The mbuf needs to be properly initalized + * including the setting of m_len. + */ +void +m_copyback(m0, off, len, cp) + struct mbuf *m0; + register int off; + register int len; + caddr_t cp; +{ + register int mlen; + register struct mbuf *m = m0, *n; + int totlen = 0; + + if (m0 == 0) + return; + while (off > (mlen = m->m_len)) { + off -= mlen; + totlen += mlen; + if (m->m_next == 0) { + n = m_getclr(M_DONTWAIT, m->m_type); + if (n == 0) + goto out; + n->m_len = min(MLEN, len + off); + m->m_next = n; + } + m = m->m_next; + } + while (len > 0) { + mlen = min (m->m_len - off, len); + bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); + cp += mlen; + len -= mlen; + mlen += off; + off = 0; + totlen += mlen; + if (len == 0) + break; + if (m->m_next == 0) { + n = m_get(M_DONTWAIT, m->m_type); + if (n == 0) + break; + n->m_len = min(MLEN, len); + m->m_next = n; + } + m = m->m_next; + } +out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) + m->m_pkthdr.len = totlen; +} + +static struct mbuf * +rt_msg1(type, rtinfo) + int type; + register struct rt_addrinfo *rtinfo; +{ + register struct rt_msghdr *rtm; + register struct mbuf *m; + register int i; + register struct sockaddr *sa; + int len, dlen; + + m = m_gethdr(M_DONTWAIT, MT_DATA); + if (m == 0) + return (m); + switch (type) { + + case RTM_DELADDR: + case RTM_NEWADDR: + len = sizeof(struct ifa_msghdr); + break; + + case RTM_IFINFO: + len = sizeof(struct if_msghdr); + break; + + default: + len = sizeof(struct rt_msghdr); + } + if (len > MHLEN) + panic("rt_msg1"); + m->m_pkthdr.len = m->m_len = len; + m->m_pkthdr.rcvif = 0; + rtm = mtod(m, struct rt_msghdr *); + bzero((caddr_t)rtm, len); + for (i = 0; i < RTAX_MAX; i++) { + if ((sa = rtinfo->rti_info[i]) == NULL) + continue; + rtinfo->rti_addrs |= (1 << i); + dlen = ROUNDUP(sa->sa_len); + m_copyback(m, len, dlen, (caddr_t)sa); + len += dlen; + } + if (m->m_pkthdr.len != len) { + m_freem(m); + return (NULL); + } + rtm->rtm_msglen = len; + rtm->rtm_version = RTM_VERSION; + rtm->rtm_type = type; + return (m); +} + +static int +rt_msg2(type, rtinfo, cp, w) + int type; + register struct rt_addrinfo *rtinfo; + caddr_t cp; + struct walkarg *w; +{ + register int i; + int len, dlen, second_time = 0; + caddr_t cp0; + + rtinfo->rti_addrs = 0; +again: + switch (type) { + + case RTM_DELADDR: + case RTM_NEWADDR: + len = sizeof(struct ifa_msghdr); + break; + + case RTM_IFINFO: + len = sizeof(struct if_msghdr); + break; + + default: + len = sizeof(struct rt_msghdr); + } + if ((cp0 = cp) != NULL) + cp += len; + for (i = 0; i < RTAX_MAX; i++) { + register struct sockaddr *sa; + + if ((sa = rtinfo->rti_info[i]) == 0) + continue; + rtinfo->rti_addrs |= (1 << i); + dlen = ROUNDUP(sa->sa_len); + if (cp) { + bcopy((caddr_t)sa, cp, (unsigned)dlen); + cp += dlen; + } + len += dlen; + } + if (cp == 0 && w != NULL && !second_time) { + register struct walkarg *rw = w; + + rw->w_needed += len; + if (rw->w_needed <= 0 && rw->w_where) { + if (rw->w_tmemsize < len) { + if (rw->w_tmem) + free(rw->w_tmem, M_RTABLE); + rw->w_tmem = (caddr_t) malloc(len, M_RTABLE, + M_NOWAIT); + if (rw->w_tmem) + rw->w_tmemsize = len; + } + if (rw->w_tmem) { + cp = rw->w_tmem; + second_time = 1; + goto again; + } else + rw->w_where = 0; + } + } + if (cp) { + register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; + + rtm->rtm_version = RTM_VERSION; + rtm->rtm_type = type; + rtm->rtm_msglen = len; + } + return (len); +} + +/* + * This routine is called to generate a message from the routing + * socket indicating that a redirect has occured, a routing lookup + * has failed, or that a protocol has detected timeouts to a particular + * destination. + */ +void +rt_missmsg(type, rtinfo, flags, error) + int type, flags, error; + register struct rt_addrinfo *rtinfo; +{ + register struct rt_msghdr *rtm; + register struct mbuf *m; + struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; + + if (route_cb.any_count == 0) + return; + m = rt_msg1(type, rtinfo); + if (m == 0) + return; + rtm = mtod(m, struct rt_msghdr *); + rtm->rtm_flags = RTF_DONE | flags; + rtm->rtm_errno = error; + rtm->rtm_addrs = rtinfo->rti_addrs; + route_proto.sp_protocol = sa ? sa->sa_family : 0; + raw_input(m, &route_proto, &route_src, &route_dst); +} + +/* + * This routine is called to generate a message from the routing + * socket indicating that the status of a network interface has changed. + */ +void +rt_ifmsg(ifp) + register struct ifnet *ifp; +{ + register struct if_msghdr *ifm; + struct mbuf *m; + struct rt_addrinfo info; + + if (route_cb.any_count == 0) + return; + bzero((caddr_t)&info, sizeof(info)); + m = rt_msg1(RTM_IFINFO, &info); + if (m == 0) + return; + ifm = mtod(m, struct if_msghdr *); + ifm->ifm_index = ifp->if_index; + ifm->ifm_flags = ifp->if_flags; + ifm->ifm_data = ifp->if_data; + ifm->ifm_addrs = 0; + route_proto.sp_protocol = 0; + raw_input(m, &route_proto, &route_src, &route_dst); +} + +/* + * This is called to generate messages from the routing socket + * indicating a network interface has had addresses associated with it. + * if we ever reverse the logic and replace messages TO the routing + * socket indicate a request to configure interfaces, then it will + * be unnecessary as the routing socket will automatically generate + * copies of it. + */ +void +rt_newaddrmsg(cmd, ifa, error, rt) + int cmd, error; + register struct ifaddr *ifa; + register struct rtentry *rt; +{ + struct rt_addrinfo info; + struct sockaddr *sa = NULL; + int pass; + struct mbuf *m = NULL; + struct ifnet *ifp = ifa->ifa_ifp; + + if (route_cb.any_count == 0) + return; + for (pass = 1; pass < 3; pass++) { + bzero((caddr_t)&info, sizeof(info)); + if ((cmd == RTM_ADD && pass == 1) || + (cmd == RTM_DELETE && pass == 2)) { + register struct ifa_msghdr *ifam; + int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; + + ifaaddr = sa = ifa->ifa_addr; + ifpaddr = ifp->if_addrlist.tqh_first->ifa_addr; + netmask = ifa->ifa_netmask; + brdaddr = ifa->ifa_dstaddr; + if ((m = rt_msg1(ncmd, &info)) == NULL) + continue; + ifam = mtod(m, struct ifa_msghdr *); + ifam->ifam_index = ifp->if_index; + ifam->ifam_metric = ifa->ifa_metric; + ifam->ifam_flags = ifa->ifa_flags; + ifam->ifam_addrs = info.rti_addrs; + } + if ((cmd == RTM_ADD && pass == 2) || + (cmd == RTM_DELETE && pass == 1)) { + register struct rt_msghdr *rtm; + + if (rt == 0) + continue; + netmask = rt_mask(rt); + dst = sa = rt_key(rt); + gate = rt->rt_gateway; + if ((m = rt_msg1(cmd, &info)) == NULL) + continue; + rtm = mtod(m, struct rt_msghdr *); + rtm->rtm_index = ifp->if_index; + rtm->rtm_flags |= rt->rt_flags; + rtm->rtm_errno = error; + rtm->rtm_addrs = info.rti_addrs; + } + route_proto.sp_protocol = sa ? sa->sa_family : 0; + raw_input(m, &route_proto, &route_src, &route_dst); + } +} + +#ifndef __ECOS +/* + * This is used in dumping the kernel table via sysctl(). + */ +int +sysctl_dumpentry(rn, v) + struct radix_node *rn; + register void *v; +{ + register struct walkarg *w = v; + register struct rtentry *rt = (struct rtentry *)rn; + int error = 0, size; + struct rt_addrinfo info; + + if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) + return 0; + bzero((caddr_t)&info, sizeof(info)); + dst = rt_key(rt); + gate = rt->rt_gateway; + netmask = rt_mask(rt); + genmask = rt->rt_genmask; + if (rt->rt_ifp) { + ifpaddr = rt->rt_ifp->if_addrlist.tqh_first->ifa_addr; + ifaaddr = rt->rt_ifa->ifa_addr; + if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) + brdaddr = rt->rt_ifa->ifa_dstaddr; + } + size = rt_msg2(RTM_GET, &info, 0, w); + if (w->w_where && w->w_tmem) { + register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; + + rtm->rtm_flags = rt->rt_flags; + rtm->rtm_use = rt->rt_use; + rtm->rtm_rmx = rt->rt_rmx; + rtm->rtm_index = rt->rt_ifp->if_index; + rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; + rtm->rtm_addrs = info.rti_addrs; + if ((error = copyout((caddr_t)rtm, w->w_where, size)) != 0) + w->w_where = NULL; + else + w->w_where += size; + } + return (error); +} + +int +sysctl_iflist(af, w) + int af; + register struct walkarg *w; +{ + register struct ifnet *ifp; + register struct ifaddr *ifa; + struct rt_addrinfo info; + int len, error = 0; + + bzero((caddr_t)&info, sizeof(info)); + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) { + if (w->w_arg && w->w_arg != ifp->if_index) + continue; + ifa = ifp->if_addrlist.tqh_first; + ifpaddr = ifa->ifa_addr; + len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w); + ifpaddr = 0; + if (w->w_where && w->w_tmem) { + register struct if_msghdr *ifm; + + ifm = (struct if_msghdr *)w->w_tmem; + ifm->ifm_index = ifp->if_index; + ifm->ifm_flags = ifp->if_flags; + ifm->ifm_data = ifp->if_data; + ifm->ifm_addrs = info.rti_addrs; + error = copyout((caddr_t)ifm, w->w_where, len); + if (error) + return (error); + w->w_where += len; + } + while ((ifa = ifa->ifa_list.tqe_next) != NULL) { + if (af && af != ifa->ifa_addr->sa_family) + continue; + ifaaddr = ifa->ifa_addr; + netmask = ifa->ifa_netmask; + brdaddr = ifa->ifa_dstaddr; + len = rt_msg2(RTM_NEWADDR, &info, 0, w); + if (w->w_where && w->w_tmem) { + register struct ifa_msghdr *ifam; + + ifam = (struct ifa_msghdr *)w->w_tmem; + ifam->ifam_index = ifa->ifa_ifp->if_index; + ifam->ifam_flags = ifa->ifa_flags; + ifam->ifam_metric = ifa->ifa_metric; + ifam->ifam_addrs = info.rti_addrs; + error = copyout(w->w_tmem, w->w_where, len); + if (error) + return (error); + w->w_where += len; + } + } + ifaaddr = netmask = brdaddr = 0; + } + return (0); +} + +int +sysctl_rtable(name, namelen, where, given, new, newlen) + int *name; + u_int namelen; + void *where; + size_t *given; + void *new; + size_t newlen; +{ + register struct radix_node_head *rnh; + int i, s, error = EINVAL; + u_char af; + struct walkarg w; + + if (new) + return (EPERM); + if (namelen != 3) + return (EINVAL); + af = name[0]; + Bzero(&w, sizeof(w)); + w.w_where = where; + w.w_given = *given; + w.w_needed = 0 - w.w_given; + w.w_op = name[1]; + w.w_arg = name[2]; + + s = splsoftnet(); + switch (w.w_op) { + + case NET_RT_DUMP: + case NET_RT_FLAGS: + for (i = 1; i <= AF_MAX; i++) + if ((rnh = rt_tables[i]) && (af == 0 || af == i) && + (error = (*rnh->rnh_walktree)(rnh, + sysctl_dumpentry, + &w))) + break; + break; + + case NET_RT_IFLIST: + error = sysctl_iflist(af, &w); + } + splx(s); + if (w.w_tmem) + free(w.w_tmem, M_RTABLE); + w.w_needed += w.w_given; + if (where) { + *given = w.w_where - (caddr_t) where; + if (*given < w.w_needed) + return (ENOMEM); + } else { + *given = (11 * w.w_needed) / 10; + } + return (error); +} +#endif + +/* + * Definitions of protocols supported in the ROUTE domain. + */ + +extern struct domain routedomain; /* or at least forward */ + +struct protosw routesw[] = { +{ SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, + raw_input, route_output, raw_ctlinput, 0, + route_usrreq, + raw_init, 0, 0, 0, +#ifdef __ECOS + 0, +#else + sysctl_rtable, +#endif +} +}; + +struct domain routedomain = + { PF_ROUTE, "route", route_init, 0, 0, + routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] }; diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/if_ether.c b/ecos/packages/net/tcpip/current/src/sys/netinet/if_ether.c new file mode 100644 index 0000000..93b1fdf --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/if_ether.c @@ -0,0 +1,996 @@ +//========================================================================== +// +// sys/netinet/if_ether.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: if_ether.c,v 1.19 1999/11/10 18:48:47 chris Exp $ */ +/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_ether.c 8.1 (Berkeley) 6/10/93 + */ + +/* + * Ethernet address resolution protocol. + * TODO: + * add "inuse/lock" bit (or ref. count) along with valid bit + */ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/kernel.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#ifndef __ECOS +#include <sys/syslog.h> +#include <sys/proc.h> +#endif + +#ifdef INET + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> + +#define SIN(s) ((struct sockaddr_in *)s) +#define SDL(s) ((struct sockaddr_dl *)s) +#define SRP(s) ((struct sockaddr_inarp *)s) + +/* + * ARP trailer negotiation. Trailer protocol is not IP specific, + * but ARP request/response use IP addresses. + */ +#define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL + +/* timer values */ +int arpt_prune = (5*60*1); /* walk list every 5 minutes */ +int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ +int arpt_down = 20; /* once declared down, don't send for 20 secs */ +#define rt_expire rt_rmx.rmx_expire + +static void arprequest + __P((struct arpcom *, u_int32_t *, u_int32_t *, u_int8_t *)); +static void arptfree __P((struct llinfo_arp *)); +static void arptimer __P((void *)); +static struct llinfo_arp *arplookup __P((u_int32_t, int, int)); +static void in_arpinput __P((struct mbuf *)); + +extern struct ifnet loif; +LIST_HEAD(, llinfo_arp) llinfo_arp; +struct ifqueue arpintrq = {0, 0, 0, 50}; +int arp_inuse, arp_allocated, arp_intimer; +int arp_maxtries = 5; +int useloopback = 1; /* use loopback interface for local traffic */ +int arpinit_done = 0; + +/* revarp state */ +static struct in_addr myip, srv_ip; +static int myip_initialized = 0; +static int revarp_in_progress = 0; +struct ifnet *myip_ifp = NULL; + +static void arptimer __P((void *)); +static void arprequest __P((struct arpcom *, u_int32_t *, u_int32_t *, + u_int8_t *)); +static void in_arpinput __P((struct mbuf *)); +static void arptfree __P((struct llinfo_arp *)); +static struct llinfo_arp *arplookup __P((u_int32_t, int, int )); +#ifdef DDB +#include <vm/vm.h> + +static void db_print_sa __P((struct sockaddr *)); +static void db_print_ifa __P((struct ifaddr *)); +static void db_print_llinfo __P((caddr_t)); +static int db_show_radix_node __P((struct radix_node *, void *)); +#endif + +/* + * Timeout routine. Age arp_tab entries periodically. + */ +/* ARGSUSED */ +static void +arptimer(arg) + void *arg; +{ + int s; + register struct llinfo_arp *la, *nla; + + s = splsoftnet(); + timeout(arptimer, NULL, arpt_prune * hz); + for (la = llinfo_arp.lh_first; la != 0; la = nla) { + register struct rtentry *rt = la->la_rt; + + nla = la->la_list.le_next; + if (rt->rt_expire && rt->rt_expire <= time.tv_sec) + arptfree(la); /* timer has expired; clear */ + } + splx(s); +} + +/* + * Parallel to llc_rtrequest. + */ +void +arp_rtrequest(req, rt, sa) + int req; + register struct rtentry *rt; + struct sockaddr *sa; +{ + register struct sockaddr *gate = rt->rt_gateway; + register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; + static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; + + if (!arpinit_done) { + arpinit_done = 1; + /* + * We generate expiration times from time.tv_sec + * so avoid accidently creating permanent routes. + */ + if (time.tv_sec == 0) { + time.tv_sec++; + } + timeout(arptimer, (caddr_t)0, hz); + } + if (rt->rt_flags & RTF_GATEWAY) + return; + switch (req) { + + case RTM_ADD: + /* + * XXX: If this is a manually added route to interface + * such as older version of routed or gated might provide, + * restore cloning bit. + */ + if ((rt->rt_flags & RTF_HOST) == 0 && + SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) + rt->rt_flags |= RTF_CLONING; + if (rt->rt_flags & RTF_CLONING) { + /* + * Case 1: This route should come from a route to iface. + */ + rt_setgate(rt, rt_key(rt), + (struct sockaddr *)&null_sdl); + gate = rt->rt_gateway; + SDL(gate)->sdl_type = rt->rt_ifp->if_type; + SDL(gate)->sdl_index = rt->rt_ifp->if_index; + /* + * Give this route an expiration time, even though + * it's a "permanent" route, so that routes cloned + * from it do not need their expiration time set. + */ + rt->rt_expire = time.tv_sec; + break; + } + /* Announce a new entry if requested. */ + if (rt->rt_flags & RTF_ANNOUNCE) + arprequest((struct arpcom *)rt->rt_ifp, + &SIN(rt_key(rt))->sin_addr.s_addr, + &SIN(rt_key(rt))->sin_addr.s_addr, + (u_char *)LLADDR(SDL(gate))); + /*FALLTHROUGH*/ + case RTM_RESOLVE: + if (gate->sa_family != AF_LINK || + gate->sa_len < sizeof(null_sdl)) { +#ifdef __ECOS +#else + log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n"); +#endif + break; + } + SDL(gate)->sdl_type = rt->rt_ifp->if_type; + SDL(gate)->sdl_index = rt->rt_ifp->if_index; + if (la != 0) + break; /* This happens on a route change */ + /* + * Case 2: This route may come from cloning, or a manual route + * add with a LL address. + */ + R_Malloc(la, struct llinfo_arp *, sizeof(*la)); + rt->rt_llinfo = (caddr_t)la; + if (la == 0) { +#ifdef __ECOS +#else + log(LOG_DEBUG, "arp_rtrequest: malloc failed\n"); +#endif + break; + } + arp_inuse++, arp_allocated++; + Bzero(la, sizeof(*la)); + la->la_rt = rt; + rt->rt_flags |= RTF_LLINFO; + LIST_INSERT_HEAD(&llinfo_arp, la, la_list); + if (SIN(rt_key(rt))->sin_addr.s_addr == + (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) { + /* + * This test used to be + * if (loif.if_flags & IFF_UP) + * It allowed local traffic to be forced through + * the hardware by configuring the loopback down. + * However, it causes problems during network + * configuration for boards that can't receive + * packets they send. It is now necessary to clear + * "useloopback" and remove the route to force + * traffic out to the hardware. + */ + rt->rt_expire = 0; + Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr, + LLADDR(SDL(gate)), + SDL(gate)->sdl_alen = ETHER_ADDR_LEN); + if (useloopback) + rt->rt_ifp = &loif; + } + break; + + case RTM_DELETE: + if (la == 0) + break; + arp_inuse--; + LIST_REMOVE(la, la_list); + rt->rt_llinfo = 0; + rt->rt_flags &= ~RTF_LLINFO; + if (la->la_hold) + m_freem(la->la_hold); + Free((caddr_t)la); + } +} + +/* + * Broadcast an ARP request. Caller specifies: + * - arp header source ip address + * - arp header target ip address + * - arp header source ethernet address + */ +static void +arprequest(ac, sip, tip, enaddr) + register struct arpcom *ac; + register u_int32_t *sip, *tip; + register u_int8_t *enaddr; +{ + register struct mbuf *m; + register struct ether_header *eh; + register struct ether_arp *ea; + struct sockaddr sa; + + if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) + return; + m->m_len = sizeof(*ea); + m->m_pkthdr.len = sizeof(*ea); + MH_ALIGN(m, sizeof(*ea)); + ea = mtod(m, struct ether_arp *); + eh = (struct ether_header *)sa.sa_data; + bzero((caddr_t)ea, sizeof (*ea)); + bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, + sizeof(eh->ether_dhost)); + eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */ + ea->arp_hrd = htons(ARPHRD_ETHER); + ea->arp_pro = htons(ETHERTYPE_IP); + ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ + ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ + ea->arp_op = htons(ARPOP_REQUEST); + bcopy((caddr_t)enaddr, (caddr_t)eh->ether_shost, + sizeof(eh->ether_shost)); + bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); + bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); + bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa)); + sa.sa_family = AF_UNSPEC; + sa.sa_len = sizeof(sa); + (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0); +} + +/* + * Resolve an IP address into an ethernet address. If success, + * desten is filled in. If there is no entry in arptab, + * set one up and broadcast a request for the IP address. + * Hold onto this mbuf and resend it once the address + * is finally resolved. A return value of 1 indicates + * that desten has been filled in and the packet should be sent + * normally; a 0 return indicates that the packet has been + * taken over here, either now or for later transmission. + */ +int +arpresolve(ac, rt, m, dst, desten) + register struct arpcom *ac; + register struct rtentry *rt; + struct mbuf *m; + register struct sockaddr *dst; + register u_char *desten; +{ + register struct llinfo_arp *la; + struct sockaddr_dl *sdl; + + if (m->m_flags & M_BCAST) { /* broadcast */ + bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten, + sizeof(etherbroadcastaddr)); + return (1); + } + if (m->m_flags & M_MCAST) { /* multicast */ + ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); + return (1); + } + if (rt) + la = (struct llinfo_arp *)rt->rt_llinfo; + else { + if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)) != NULL) + rt = la->la_rt; + } + if (la == 0 || rt == 0) { +#ifdef __ECOS +#else + log(LOG_DEBUG, "arpresolve: can't allocate llinfo\n"); +#endif + m_freem(m); + return (0); + } + sdl = SDL(rt->rt_gateway); + /* + * Check the address family and length is valid, the address + * is resolved; otherwise, try to resolve. + */ + if ((rt->rt_expire == 0 || rt->rt_expire > time.tv_sec) && + sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { + bcopy(LLADDR(sdl), desten, sdl->sdl_alen); + return 1; + } + if (((struct ifnet *)ac)->if_flags & IFF_NOARP) + return 0; + + /* + * There is an arptab entry, but no ethernet address + * response yet. Replace the held mbuf with this + * latest one. + */ + if (la->la_hold) + m_freem(la->la_hold); + la->la_hold = m; + /* + * Re-send the ARP request when appropriate. + */ +#ifdef DIAGNOSTIC + if (rt->rt_expire == 0) { + /* This should never happen. (Should it? -gwr) */ + printf("arpresolve: unresolved and rt_expire == 0\n"); + /* Set expiration time to now (expired). */ + rt->rt_expire = time.tv_sec; + } +#endif + if (rt->rt_expire) { + rt->rt_flags &= ~RTF_REJECT; + if (la->la_asked == 0 || rt->rt_expire != time.tv_sec) { + rt->rt_expire = time.tv_sec; + if (la->la_asked++ < arp_maxtries) + arprequest(ac, + &(SIN(rt->rt_ifa->ifa_addr)->sin_addr.s_addr), + &(SIN(dst)->sin_addr.s_addr), + ac->ac_enaddr); + else { + rt->rt_flags |= RTF_REJECT; + rt->rt_expire += arpt_down; + la->la_asked = 0; + } + } + } + return (0); +} + +/* + * Common length and type checks are done here, + * then the protocol-specific routine is called. + */ +void +arpintr() +{ + register struct mbuf *m; + register struct arphdr *ar; + int s; + + while (arpintrq.ifq_head) { + s = splimp(); + IF_DEQUEUE(&arpintrq, m); + splx(s); + if (m == 0 || (m->m_flags & M_PKTHDR) == 0) + panic("arpintr"); + if (m->m_len >= sizeof(struct arphdr) && + (ar = mtod(m, struct arphdr *)) && + ntohs(ar->ar_hrd) == ARPHRD_ETHER && + m->m_len >= + sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) + switch (ntohs(ar->ar_pro)) { + + case ETHERTYPE_IP: + case ETHERTYPE_IPTRAILERS: + in_arpinput(m); + continue; + } + m_freem(m); + } +} + +/* + * ARP for Internet protocols on Ethernet. + * Algorithm is that given in RFC 826. + * In addition, a sanity check is performed on the sender + * protocol address, to catch impersonators. + * We no longer handle negotiations for use of trailer protocol: + * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent + * along with IP replies if we wanted trailers sent to us, + * and also sent them in response to IP replies. + * This allowed either end to announce the desire to receive + * trailer packets. + * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, + * but formerly didn't normally send requests. + */ +static void +in_arpinput(m) + struct mbuf *m; +{ + register struct ether_arp *ea; + register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif; + struct ether_header *eh; + register struct llinfo_arp *la = 0; + register struct rtentry *rt; + struct in_ifaddr *ia, *maybe_ia = 0; + struct sockaddr_dl *sdl; + struct sockaddr sa; + struct in_addr isaddr, itaddr, myaddr; + int op; + + ea = mtod(m, struct ether_arp *); + op = ntohs(ea->arp_op); + bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr)); + bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr)); + for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) + if (ia->ia_ifp == &ac->ac_if || + (ia->ia_ifp->if_bridge && + ia->ia_ifp->if_bridge == ac->ac_if.if_bridge)) { + maybe_ia = ia; + if (itaddr.s_addr == ia->ia_addr.sin_addr.s_addr || + isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) + break; + } + if (maybe_ia == 0) + goto out; + myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr; + if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr, + sizeof (ea->arp_sha))) + goto out; /* it's from me, ignore it. */ + if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr, + sizeof (ea->arp_sha))) { +#ifdef __ECOS +#else + log(LOG_ERR, + "arp: ether address is broadcast for IP address %s!\n", + inet_ntoa(isaddr)); +#endif + goto out; + } + if (isaddr.s_addr == myaddr.s_addr) { +#ifdef __ECOS +#else + log(LOG_ERR, + "duplicate IP address %s sent from ethernet address %s\n", + inet_ntoa(isaddr), ether_sprintf(ea->arp_sha)); +#endif + itaddr = myaddr; + goto reply; + } + la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0); + if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) { + if (sdl->sdl_alen && + bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) { + if (rt->rt_flags & RTF_PERMANENT_ARP) { +#ifdef __ECOS +#else + log(LOG_WARNING, + "arp: attempt to overwrite permanent " + "entry for %s by %s on %s\n", + inet_ntoa(isaddr), + ether_sprintf(ea->arp_sha), + (&ac->ac_if)->if_xname); +#endif + goto out; + } else if (rt->rt_ifp != &ac->ac_if) { +#ifdef __ECOS +#else + log(LOG_WARNING, + "arp: attempt to overwrite entry for %s " + "on %s by %s on %s\n", + inet_ntoa(isaddr), rt->rt_ifp->if_xname, + ether_sprintf(ea->arp_sha), + (&ac->ac_if)->if_xname); +#endif + goto out; + } else { +#ifdef __ECOS +#else + log(LOG_INFO, + "arp info overwritten for %s by %s on %s\n", + inet_ntoa(isaddr), + ether_sprintf(ea->arp_sha), + (&ac->ac_if)->if_xname); +#endif + rt->rt_expire = 1; /* no longer static */ + } + } + bcopy((caddr_t)ea->arp_sha, LLADDR(sdl), + sdl->sdl_alen = sizeof(ea->arp_sha)); + if (rt->rt_expire) + rt->rt_expire = time.tv_sec + arpt_keep; + rt->rt_flags &= ~RTF_REJECT; + la->la_asked = 0; + if (la->la_hold) { + (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold, + rt_key(rt), rt); + la->la_hold = 0; + } + } +reply: + if (op != ARPOP_REQUEST) { + out: + m_freem(m); + return; + } + if (itaddr.s_addr == myaddr.s_addr) { + /* I am the target */ + bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, + sizeof(ea->arp_sha)); + bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, + sizeof(ea->arp_sha)); + } else { + la = arplookup(itaddr.s_addr, 0, SIN_PROXY); + if (la == 0) + goto out; + rt = la->la_rt; + bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, + sizeof(ea->arp_sha)); + sdl = SDL(rt->rt_gateway); + bcopy(LLADDR(sdl), (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); + } + + bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof(ea->arp_spa)); + bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); + ea->arp_op = htons(ARPOP_REPLY); + ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ + eh = (struct ether_header *)sa.sa_data; + bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost, + sizeof(eh->ether_dhost)); + bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, + sizeof(eh->ether_shost)); + eh->ether_type = htons(ETHERTYPE_ARP); + sa.sa_family = AF_UNSPEC; + sa.sa_len = sizeof(sa); + (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0); + return; +} + +/* + * Free an arp entry. + */ +static void +arptfree(la) + register struct llinfo_arp *la; +{ + register struct rtentry *rt = la->la_rt; + register struct sockaddr_dl *sdl; + + if (rt == 0) + panic("arptfree"); + if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) && + sdl->sdl_family == AF_LINK) { + sdl->sdl_alen = 0; + la->la_asked = 0; + rt->rt_flags &= ~RTF_REJECT; + return; + } + rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt), + 0, (struct rtentry **)0); +} + +/* + * Lookup or enter a new address in arptab. + */ +static struct llinfo_arp * +arplookup(addr, create, proxy) + u_int32_t addr; + int create, proxy; +{ + register struct rtentry *rt; + static struct sockaddr_inarp sin; + + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = addr; + sin.sin_other = proxy ? SIN_PROXY : 0; + rt = rtalloc1(sintosa(&sin), create); + if (rt == 0) + return (0); + rt->rt_refcnt--; + if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 || + rt->rt_gateway->sa_family != AF_LINK) { + if (create) +#ifdef __ECOS +#else + log(LOG_DEBUG, + "arplookup: unable to enter address for %s\n", + inet_ntoa(sin.sin_addr)); +#endif + return (0); + } + return ((struct llinfo_arp *)rt->rt_llinfo); +} + +int +arpioctl(cmd, data) + u_long cmd; + caddr_t data; +{ + + return (EOPNOTSUPP); +} + +void +arp_ifinit(ac, ifa) + struct arpcom *ac; + struct ifaddr *ifa; +{ + + /* Warn the user if another station has this IP address. */ + arprequest(ac, + &(IA_SIN(ifa)->sin_addr.s_addr), + &(IA_SIN(ifa)->sin_addr.s_addr), + ac->ac_enaddr); + ifa->ifa_rtrequest = arp_rtrequest; + ifa->ifa_flags |= RTF_CLONING; +} + +/* + * Called from Ethernet interrupt handlers + * when ether packet type ETHERTYPE_REVARP + * is received. Common length and type checks are done here, + * then the protocol-specific routine is called. + */ +void +revarpinput(m) + struct mbuf *m; +{ + struct arphdr *ar; + + if (m->m_len < sizeof(struct arphdr)) + goto out; + ar = mtod(m, struct arphdr *); + if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) + goto out; + if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) + goto out; + switch (ntohs(ar->ar_pro)) { + + case ETHERTYPE_IP: + case ETHERTYPE_IPTRAILERS: + in_revarpinput(m); + return; + + default: + break; + } +out: + m_freem(m); +} + +/* + * RARP for Internet protocols on Ethernet. + * Algorithm is that given in RFC 903. + * We are only using for bootstrap purposes to get an ip address for one of + * our interfaces. Thus we support no user-interface. + * + * Since the contents of the RARP reply are specific to the interface that + * sent the request, this code must ensure that they are properly associated. + * + * Note: also supports ARP via RARP packets, per the RFC. + */ +void +in_revarpinput(m) + struct mbuf *m; +{ + struct ifnet *ifp; + struct ether_arp *ar; + int op; + + ar = mtod(m, struct ether_arp *); + op = ntohs(ar->arp_op); + switch (op) { + case ARPOP_REQUEST: + case ARPOP_REPLY: /* per RFC */ + in_arpinput(m); + return; + case ARPOP_REVREPLY: + break; + case ARPOP_REVREQUEST: /* handled by rarpd(8) */ + default: + goto out; + } + if (!revarp_in_progress) + goto out; + ifp = m->m_pkthdr.rcvif; + if (ifp != myip_ifp) /* !same interface */ + goto out; + if (myip_initialized) + goto wake; + if (bcmp(ar->arp_tha, ((struct arpcom *)ifp)->ac_enaddr, + sizeof(ar->arp_tha))) + goto out; + bcopy((caddr_t)ar->arp_spa, (caddr_t)&srv_ip, sizeof(srv_ip)); + bcopy((caddr_t)ar->arp_tpa, (caddr_t)&myip, sizeof(myip)); + myip_initialized = 1; +wake: /* Do wakeup every time in case it was missed. */ + wakeup((caddr_t)&myip); + +out: + m_freem(m); +} + +/* + * Send a RARP request for the ip address of the specified interface. + * The request should be RFC 903-compliant. + */ +void +revarprequest(ifp) + struct ifnet *ifp; +{ + struct sockaddr sa; + struct mbuf *m; + struct ether_header *eh; + struct ether_arp *ea; + struct arpcom *ac = (struct arpcom *)ifp; + + if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) + return; + m->m_len = sizeof(*ea); + m->m_pkthdr.len = sizeof(*ea); + MH_ALIGN(m, sizeof(*ea)); + ea = mtod(m, struct ether_arp *); + eh = (struct ether_header *)sa.sa_data; + bzero((caddr_t)ea, sizeof(*ea)); + bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, + sizeof(eh->ether_dhost)); + eh->ether_type = htons(ETHERTYPE_REVARP); + ea->arp_hrd = htons(ARPHRD_ETHER); + ea->arp_pro = htons(ETHERTYPE_IP); + ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ + ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ + ea->arp_op = htons(ARPOP_REVREQUEST); + bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost, + sizeof(ea->arp_tha)); + bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, + sizeof(ea->arp_sha)); + bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_tha, + sizeof(ea->arp_tha)); + sa.sa_family = AF_UNSPEC; + sa.sa_len = sizeof(sa); + ifp->if_output(ifp, m, &sa, (struct rtentry *)0); +} + +/* + * RARP for the ip address of the specified interface, but also + * save the ip address of the server that sent the answer. + * Timeout if no response is received. + */ +int +revarpwhoarewe(ifp, serv_in, clnt_in) + struct ifnet *ifp; + struct in_addr *serv_in; + struct in_addr *clnt_in; +{ + int result, count = 20; + + if (myip_initialized) + return EIO; + + myip_ifp = ifp; + revarp_in_progress = 1; + while (count--) { + revarprequest(ifp); + result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2); + if (result != EWOULDBLOCK) + break; + } + revarp_in_progress = 0; + if (!myip_initialized) + return ENETUNREACH; + + bcopy((caddr_t)&srv_ip, serv_in, sizeof(*serv_in)); + bcopy((caddr_t)&myip, clnt_in, sizeof(*clnt_in)); + return 0; +} + +/* For compatibility: only saves interface address. */ +int +revarpwhoami(in, ifp) + struct in_addr *in; + struct ifnet *ifp; +{ + struct in_addr server; + return (revarpwhoarewe(ifp, &server, in)); +} + + +#ifdef DDB + +#include <machine/db_machdep.h> +#include <ddb/db_interface.h> +#include <ddb/db_output.h> + +static void +db_print_sa(sa) + struct sockaddr *sa; +{ + int len; + u_char *p; + + if (sa == 0) { + db_printf("[NULL]"); + return; + } + + p = (u_char*)sa; + len = sa->sa_len; + db_printf("["); + while (len > 0) { + db_printf("%d", *p); + p++; + len--; + if (len) + db_printf(","); + } + db_printf("]\n"); +} + +static void +db_print_ifa(ifa) + struct ifaddr *ifa; +{ + if (ifa == 0) + return; + db_printf(" ifa_addr="); + db_print_sa(ifa->ifa_addr); + db_printf(" ifa_dsta="); + db_print_sa(ifa->ifa_dstaddr); + db_printf(" ifa_mask="); + db_print_sa(ifa->ifa_netmask); + db_printf(" flags=0x%x, refcnt=%d, metric=%d\n", + ifa->ifa_flags, ifa->ifa_refcnt, ifa->ifa_metric); +} + +static void +db_print_llinfo(li) + caddr_t li; +{ + struct llinfo_arp *la; + + if (li == 0) + return; + la = (struct llinfo_arp *)li; + db_printf(" la_rt=%p la_hold=%p, la_asked=0x%lx\n", + la->la_rt, la->la_hold, la->la_asked); +} + +/* + * Function to pass to rn_walktree(). + * Return non-zero error to abort walk. + */ +static int +db_show_radix_node(rn, w) + struct radix_node *rn; + void *w; +{ + struct rtentry *rt = (struct rtentry *)rn; + + db_printf("rtentry=%p", rt); + + db_printf(" flags=0x%x refcnt=%d use=%ld expire=%ld\n", + rt->rt_flags, rt->rt_refcnt, rt->rt_use, rt->rt_expire); + + db_printf(" key="); db_print_sa(rt_key(rt)); + db_printf(" mask="); db_print_sa(rt_mask(rt)); + db_printf(" gw="); db_print_sa(rt->rt_gateway); + + db_printf(" ifp=%p ", rt->rt_ifp); + if (rt->rt_ifp) + db_printf("(%s)", rt->rt_ifp->if_xname); + else + db_printf("(NULL)"); + + db_printf(" ifa=%p\n", rt->rt_ifa); + db_print_ifa(rt->rt_ifa); + + db_printf(" genmask="); db_print_sa(rt->rt_genmask); + + db_printf(" gwroute=%p llinfo=%p\n", rt->rt_gwroute, rt->rt_llinfo); + db_print_llinfo(rt->rt_llinfo); + return (0); +} + +/* + * Function to print all the route trees. + * Use this from ddb: "call db_show_arptab" + */ +int +db_show_arptab() +{ + struct radix_node_head *rnh; + rnh = rt_tables[AF_INET]; + db_printf("Route tree for AF_INET\n"); + if (rnh == NULL) { + db_printf(" (not initialized)\n"); + return (0); + } + rn_walktree(rnh, db_show_radix_node, NULL); + return (0); +} +#endif +#endif /* INET */ diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/igmp.c b/ecos/packages/net/tcpip/current/src/sys/netinet/igmp.c new file mode 100644 index 0000000..f84c84f --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/igmp.c @@ -0,0 +1,614 @@ +//========================================================================== +// +// sys/netinet/igmp.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: igmp.c,v 1.6 1999/12/08 06:50:19 itojun Exp $ */ +/* $NetBSD: igmp.c,v 1.15 1996/02/13 23:41:25 christos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Internet Group Management Protocol (IGMP) routines. + * + * Written by Steve Deering, Stanford, May 1988. + * Modified by Rosen Sharma, Stanford, Aug 1994. + * Modified by Bill Fenner, Xerox PARC, Feb 1995. + * + * MULTICAST Revision: 1.3 + */ + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/igmp.h> +#include <netinet/igmp_var.h> +#ifndef __ECOS +#include <dev/rndvar.h> +#endif + +#include <machine/stdarg.h> + +#define IP_MULTICASTOPTS 0 + +int igmp_timers_are_running; +static struct router_info *rti_head; + +void igmp_sendpkt __P((struct in_multi *, int)); +static int rti_fill __P((struct in_multi *)); +static struct router_info * rti_find __P((struct ifnet *)); + +void +igmp_init() +{ + + /* + * To avoid byte-swapping the same value over and over again. + */ + igmp_timers_are_running = 0; + rti_head = 0; +} + +static int +rti_fill(inm) + struct in_multi *inm; +{ + register struct router_info *rti; + + for (rti = rti_head; rti != 0; rti = rti->rti_next) { + if (rti->rti_ifp == inm->inm_ifp) { + inm->inm_rti = rti; + if (rti->rti_type == IGMP_v1_ROUTER) + return (IGMP_v1_HOST_MEMBERSHIP_REPORT); + else + return (IGMP_v2_HOST_MEMBERSHIP_REPORT); + } + } + + rti = (struct router_info *)malloc(sizeof(struct router_info), + M_MRTABLE, M_NOWAIT); + rti->rti_ifp = inm->inm_ifp; + rti->rti_type = IGMP_v2_ROUTER; + rti->rti_next = rti_head; + rti_head = rti; + inm->inm_rti = rti; + return (IGMP_v2_HOST_MEMBERSHIP_REPORT); +} + +static struct router_info * +rti_find(ifp) + struct ifnet *ifp; +{ + register struct router_info *rti; + + for (rti = rti_head; rti != 0; rti = rti->rti_next) { + if (rti->rti_ifp == ifp) + return (rti); + } + + rti = (struct router_info *)malloc(sizeof(struct router_info), + M_MRTABLE, M_NOWAIT); + rti->rti_ifp = ifp; + rti->rti_type = IGMP_v2_ROUTER; + rti->rti_next = rti_head; + rti_head = rti; + return (rti); +} + +void +rti_delete(ifp) + struct ifnet *ifp; +{ + struct router_info *rti, **prti = &rti_head; + + for (rti = rti_head; rti != 0; rti = rti->rti_next) { + if (rti->rti_ifp == ifp) { + *prti = rti->rti_next; + free(rti, M_MRTABLE); + break; + } + prti = &rti->rti_next; + } +} + +void +#if __STDC__ +igmp_input(struct mbuf *m, ...) +#else +igmp_input(m, va_alist) + struct mbuf *m; + va_dcl +#endif +{ + int proto; + register int iphlen; + register struct ifnet *ifp = m->m_pkthdr.rcvif; + register struct ip *ip = mtod(m, struct ip *); + register struct igmp *igmp; + register int igmplen; + register int minlen; + struct in_multi *inm; + struct in_multistep step; + struct router_info *rti; + register struct in_ifaddr *ia; + int timer; + va_list ap; + + va_start(ap, m); + iphlen = va_arg(ap, int); + proto = va_arg(ap, int); + va_end(ap); + + ++igmpstat.igps_rcv_total; + + igmplen = ip->ip_len; + + /* + * Validate lengths + */ + if (igmplen < IGMP_MINLEN) { + ++igmpstat.igps_rcv_tooshort; + m_freem(m); + return; + } + minlen = iphlen + IGMP_MINLEN; + if ((m->m_flags & M_EXT || m->m_len < minlen) && + (m = m_pullup(m, minlen)) == 0) { + ++igmpstat.igps_rcv_tooshort; + return; + } + + /* + * Validate checksum + */ + m->m_data += iphlen; + m->m_len -= iphlen; + igmp = mtod(m, struct igmp *); + if (in_cksum(m, igmplen)) { + ++igmpstat.igps_rcv_badsum; + m_freem(m); + return; + } + m->m_data -= iphlen; + m->m_len += iphlen; + ip = mtod(m, struct ip *); + + switch (igmp->igmp_type) { + + case IGMP_HOST_MEMBERSHIP_QUERY: + ++igmpstat.igps_rcv_queries; + + if (ifp->if_flags & IFF_LOOPBACK) + break; + + if (igmp->igmp_code == 0) { + rti = rti_find(ifp); + rti->rti_type = IGMP_v1_ROUTER; + rti->rti_age = 0; + + if (ip->ip_dst.s_addr != INADDR_ALLHOSTS_GROUP) { + ++igmpstat.igps_rcv_badqueries; + m_freem(m); + return; + } + + /* + * Start the timers in all of our membership records + * for the interface on which the query arrived, + * except those that are already running and those + * that belong to a "local" group (224.0.0.X). + */ + IN_FIRST_MULTI(step, inm); + while (inm != NULL) { + if (inm->inm_ifp == ifp && + inm->inm_timer == 0 && + !IN_LOCAL_GROUP(inm->inm_addr.s_addr)) { + inm->inm_state = IGMP_DELAYING_MEMBER; + inm->inm_timer = IGMP_RANDOM_DELAY( + IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ); + igmp_timers_are_running = 1; + } + IN_NEXT_MULTI(step, inm); + } + } else { + if (!IN_MULTICAST(ip->ip_dst.s_addr)) { + ++igmpstat.igps_rcv_badqueries; + m_freem(m); + return; + } + + timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE; + + /* + * Start the timers in all of our membership records + * for the interface on which the query arrived, + * except those that are already running and those + * that belong to a "local" group (224.0.0.X). For + * timers already running, check if they need to be + * reset. + */ + IN_FIRST_MULTI(step, inm); + while (inm != NULL) { + if (inm->inm_ifp == ifp && + !IN_LOCAL_GROUP(inm->inm_addr.s_addr) && + (ip->ip_dst.s_addr == INADDR_ALLHOSTS_GROUP || + ip->ip_dst.s_addr == inm->inm_addr.s_addr)) { + switch (inm->inm_state) { + case IGMP_DELAYING_MEMBER: + if (inm->inm_timer <= timer) + break; + /* FALLTHROUGH */ + case IGMP_IDLE_MEMBER: + case IGMP_LAZY_MEMBER: + case IGMP_AWAKENING_MEMBER: + inm->inm_state = + IGMP_DELAYING_MEMBER; + inm->inm_timer = + IGMP_RANDOM_DELAY(timer); + igmp_timers_are_running = 1; + break; + case IGMP_SLEEPING_MEMBER: + inm->inm_state = + IGMP_AWAKENING_MEMBER; + break; + } + } + IN_NEXT_MULTI(step, inm); + } + } + + break; + + case IGMP_v1_HOST_MEMBERSHIP_REPORT: + ++igmpstat.igps_rcv_reports; + + if (ifp->if_flags & IFF_LOOPBACK) + break; + + if (!IN_MULTICAST(igmp->igmp_group.s_addr) || + igmp->igmp_group.s_addr != ip->ip_dst.s_addr) { + ++igmpstat.igps_rcv_badreports; + m_freem(m); + return; + } + + /* + * KLUDGE: if the IP source address of the report has an + * unspecified (i.e., zero) subnet number, as is allowed for + * a booting host, replace it with the correct subnet number + * so that a process-level multicast routing daemon can + * determine which subnet it arrived from. This is necessary + * to compensate for the lack of any way for a process to + * determine the arrival interface of an incoming packet. + */ + if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) { + IFP_TO_IA(ifp, ia); + if (ia) + ip->ip_src.s_addr = ia->ia_subnet; + } + + /* + * If we belong to the group being reported, stop + * our timer for that group. + */ + IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm); + if (inm != NULL) { + inm->inm_timer = 0; + ++igmpstat.igps_rcv_ourreports; + + switch (inm->inm_state) { + case IGMP_IDLE_MEMBER: + case IGMP_LAZY_MEMBER: + case IGMP_AWAKENING_MEMBER: + case IGMP_SLEEPING_MEMBER: + inm->inm_state = IGMP_SLEEPING_MEMBER; + break; + case IGMP_DELAYING_MEMBER: + if (inm->inm_rti->rti_type == IGMP_v1_ROUTER) + inm->inm_state = IGMP_LAZY_MEMBER; + else + inm->inm_state = IGMP_SLEEPING_MEMBER; + break; + } + } + + break; + + case IGMP_v2_HOST_MEMBERSHIP_REPORT: +#ifdef MROUTING + /* + * Make sure we don't hear our own membership report. Fast + * leave requires knowing that we are the only member of a + * group. + */ + IFP_TO_IA(ifp, ia); + if (ia && ip->ip_src.s_addr == ia->ia_addr.sin_addr.s_addr) + break; +#endif + + ++igmpstat.igps_rcv_reports; + + if (ifp->if_flags & IFF_LOOPBACK) + break; + + if (!IN_MULTICAST(igmp->igmp_group.s_addr) || + igmp->igmp_group.s_addr != ip->ip_dst.s_addr) { + ++igmpstat.igps_rcv_badreports; + m_freem(m); + return; + } + + /* + * KLUDGE: if the IP source address of the report has an + * unspecified (i.e., zero) subnet number, as is allowed for + * a booting host, replace it with the correct subnet number + * so that a process-level multicast routing daemon can + * determine which subnet it arrived from. This is necessary + * to compensate for the lack of any way for a process to + * determine the arrival interface of an incoming packet. + */ + if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) { +#ifndef MROUTING + IFP_TO_IA(ifp, ia); +#endif + if (ia) + ip->ip_src.s_addr = ia->ia_subnet; + } + + /* + * If we belong to the group being reported, stop + * our timer for that group. + */ + IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm); + if (inm != NULL) { + inm->inm_timer = 0; + ++igmpstat.igps_rcv_ourreports; + + switch (inm->inm_state) { + case IGMP_DELAYING_MEMBER: + case IGMP_IDLE_MEMBER: + case IGMP_AWAKENING_MEMBER: + inm->inm_state = IGMP_LAZY_MEMBER; + break; + case IGMP_LAZY_MEMBER: + case IGMP_SLEEPING_MEMBER: + break; + } + } + + break; + + } + + /* + * Pass all valid IGMP packets up to any process(es) listening + * on a raw IGMP socket. + */ + rip_input(m, iphlen, proto); + return; +} + +void +igmp_joingroup(inm) + struct in_multi *inm; +{ + int s = splsoftnet(); + + inm->inm_state = IGMP_IDLE_MEMBER; + + if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) && + (inm->inm_ifp->if_flags & IFF_LOOPBACK) == 0) { + igmp_sendpkt(inm, rti_fill(inm)); + inm->inm_state = IGMP_DELAYING_MEMBER; + inm->inm_timer = IGMP_RANDOM_DELAY( + IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ); + igmp_timers_are_running = 1; + } else + inm->inm_timer = 0; + splx(s); +} + +void +igmp_leavegroup(inm) + struct in_multi *inm; +{ + + switch (inm->inm_state) { + case IGMP_DELAYING_MEMBER: + case IGMP_IDLE_MEMBER: + if (!IN_LOCAL_GROUP(inm->inm_addr.s_addr) && + (inm->inm_ifp->if_flags & IFF_LOOPBACK) == 0) + if (inm->inm_rti->rti_type != IGMP_v1_ROUTER) + igmp_sendpkt(inm, IGMP_HOST_LEAVE_MESSAGE); + break; + case IGMP_LAZY_MEMBER: + case IGMP_AWAKENING_MEMBER: + case IGMP_SLEEPING_MEMBER: + break; + } +} + +void +igmp_fasttimo() +{ + register struct in_multi *inm; + struct in_multistep step; + int s; + + /* + * Quick check to see if any work needs to be done, in order + * to minimize the overhead of fasttimo processing. + */ + if (!igmp_timers_are_running) + return; + + s = splsoftnet(); + igmp_timers_are_running = 0; + IN_FIRST_MULTI(step, inm); + while (inm != NULL) { + if (inm->inm_timer == 0) { + /* do nothing */ + } else if (--inm->inm_timer == 0) { + if (inm->inm_state == IGMP_DELAYING_MEMBER) { + if (inm->inm_rti->rti_type == IGMP_v1_ROUTER) + igmp_sendpkt(inm, + IGMP_v1_HOST_MEMBERSHIP_REPORT); + else + igmp_sendpkt(inm, + IGMP_v2_HOST_MEMBERSHIP_REPORT); + inm->inm_state = IGMP_IDLE_MEMBER; + } + } else { + igmp_timers_are_running = 1; + } + IN_NEXT_MULTI(step, inm); + } + splx(s); +} + +void +igmp_slowtimo() +{ + register struct router_info *rti; + int s; + + s = splsoftnet(); + for (rti = rti_head; rti != 0; rti = rti->rti_next) { + if (rti->rti_type == IGMP_v1_ROUTER && + ++rti->rti_age >= IGMP_AGE_THRESHOLD) { + rti->rti_type = IGMP_v2_ROUTER; + } + } + splx(s); +} + +void +igmp_sendpkt(inm, type) + struct in_multi *inm; + int type; +{ + struct mbuf *m; + struct igmp *igmp; + struct ip *ip; + struct ip_moptions imo; +#ifdef MROUTING + extern struct socket *ip_mrouter; +#endif /* MROUTING */ + + MGETHDR(m, M_DONTWAIT, MT_HEADER); + if (m == NULL) + return; + /* + * Assume max_linkhdr + sizeof(struct ip) + IGMP_MINLEN + * is smaller than mbuf size returned by MGETHDR. + */ + m->m_data += max_linkhdr; + m->m_len = sizeof(struct ip) + IGMP_MINLEN; + m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN; + + ip = mtod(m, struct ip *); + ip->ip_tos = 0; + ip->ip_len = sizeof(struct ip) + IGMP_MINLEN; + ip->ip_off = 0; + ip->ip_p = IPPROTO_IGMP; + ip->ip_src.s_addr = INADDR_ANY; + ip->ip_dst = inm->inm_addr; + + m->m_data += sizeof(struct ip); + m->m_len -= sizeof(struct ip); + igmp = mtod(m, struct igmp *); + igmp->igmp_type = type; + igmp->igmp_code = 0; + igmp->igmp_group = inm->inm_addr; + igmp->igmp_cksum = 0; + igmp->igmp_cksum = in_cksum(m, IGMP_MINLEN); + m->m_data -= sizeof(struct ip); + m->m_len += sizeof(struct ip); + + imo.imo_multicast_ifp = inm->inm_ifp; + imo.imo_multicast_ttl = 1; +#ifdef RSVP_ISI + imo.imo_multicast_vif = -1; +#endif + /* + * Request loopback of the report if we are acting as a multicast + * router, so that the process-level routing demon can hear it. + */ +#ifdef MROUTING + imo.imo_multicast_loop = (ip_mrouter != NULL); +#else + imo.imo_multicast_loop = 0; +#endif /* MROUTING */ + +#if 0 /*KAME IPSEC*/ + m->m_pkthdr.rcvif = NULL; +#endif /*IPSEC*/ + ip_output(m, (struct mbuf *)0, (struct route *)0, IP_MULTICASTOPTS, + &imo, NULL); + + ++igmpstat.igps_snd_reports; +} diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/in.c b/ecos/packages/net/tcpip/current/src/sys/netinet/in.c new file mode 100644 index 0000000..1fb2f09 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/in.c @@ -0,0 +1,902 @@ +//========================================================================== +// +// sys/netinet/in.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in.c,v 1.14 1999/12/08 06:50:19 itojun Exp $ */ +/* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in.c 8.2 (Berkeley) 11/15/93 + */ + +#ifdef __ECOS +#include <pkgconf/net.h> +#else +#include "ether.h" +#include "gif.h" +#endif + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#include <sys/malloc.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif + +#include <net/if.h> +#include <net/if_types.h> +#include <net/route.h> +#if NGIF > 0 +#include <net/if_gif.h> +#endif + +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <netinet/if_ether.h> +#include <netinet/igmp_var.h> + +#ifdef MROUTING +#include <netinet/ip_mroute.h> +#endif + +#ifdef INET + +static int in_mask2len __P((struct in_addr *)); +static void in_len2mask __P((struct in_addr *, int)); +static int in_lifaddr_ioctl __P((struct socket *, u_long, caddr_t, + struct ifnet *)); + +#ifndef SUBNETSARELOCAL +#define SUBNETSARELOCAL 0 +#endif +int subnetsarelocal = SUBNETSARELOCAL; +/* + * Return 1 if an internet address is for a ``local'' host + * (one to which we have a connection). If subnetsarelocal + * is true, this includes other subnets of the local net. + * Otherwise, it includes only the directly-connected (sub)nets. + */ +int +in_localaddr(in) + struct in_addr in; +{ + register struct in_ifaddr *ia; + + if (subnetsarelocal) { + for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) + if ((in.s_addr & ia->ia_netmask) == ia->ia_net) + return (1); + } else { + for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) + if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet) + return (1); + } + return (0); +} + +/* + * Determine whether an IP address is in a reserved set of addresses + * that may not be forwarded, or whether datagrams to that destination + * may be forwarded. + */ +int +in_canforward(in) + struct in_addr in; +{ + register u_int32_t net; + + if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr)) + return (0); + if (IN_CLASSA(in.s_addr)) { + net = in.s_addr & IN_CLASSA_NET; + if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) + return (0); + } + return (1); +} + +/* + * Trim a mask in a sockaddr + */ +void +in_socktrim(ap) + struct sockaddr_in *ap; +{ + register char *cplim = (char *) &ap->sin_addr; + register char *cp = (char *) (&ap->sin_addr + 1); + + ap->sin_len = 0; + while (--cp >= cplim) + if (*cp) { + (ap)->sin_len = cp - (char *) (ap) + 1; + break; + } +} + +static int +in_mask2len(mask) + struct in_addr *mask; +{ + int x, y; + u_char *p; + + p = (u_char *)mask; + for (x = 0; x < sizeof(*mask); x++) { + if (p[x] != 0xff) + break; + } + y = 0; + if (x < sizeof(*mask)) { + for (y = 0; y < 8; y++) { + if ((p[x] & (0x80 >> y)) == 0) + break; + } + } + return x * 8 + y; +} + +static void +in_len2mask(mask, len) + struct in_addr *mask; + int len; +{ + int i; + u_char *p; + + p = (u_char *)mask; + bzero(mask, sizeof(*mask)); + for (i = 0; i < len / 8; i++) + p[i] = 0xff; + if (len % 8) + p[i] = (0xff00 >> (len % 8)) & 0xff; +} + +int in_interfaces; /* number of external internet interfaces */ + +/* + * Generic internet control operations (ioctl's). + * Ifp is 0 if not an interface-specific ioctl. + */ +/* ARGSUSED */ +int +in_control(so, cmd, data, ifp) + struct socket *so; + u_long cmd; + caddr_t data; + register struct ifnet *ifp; +{ + register struct ifreq *ifr = (struct ifreq *)data; + register struct in_ifaddr *ia = 0; + struct in_aliasreq *ifra = (struct in_aliasreq *)data; + struct sockaddr_in oldaddr; + int error, hostIsNew, maskIsNew; + +#if NGIF > 0 + if (ifp && ifp->if_type == IFT_GIF) { + switch (cmd) { + case SIOCSIFPHYADDR: + if ((so->so_state & SS_PRIV) == 0) + return(EPERM); + case SIOCGIFPSRCADDR: + case SIOCGIFPDSTADDR: + return gif_ioctl(ifp, cmd, data); + } + } +#endif + + switch (cmd) { + case SIOCALIFADDR: + case SIOCDLIFADDR: + if ((so->so_state & SS_PRIV) == 0) + return(EPERM); + /*fall through*/ + case SIOCGLIFADDR: + if (!ifp) + return EINVAL; + return in_lifaddr_ioctl(so, cmd, data, ifp); + } + + /* + * Find address for this interface, if it exists. + */ + if (ifp) + for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) + if (ia->ia_ifp == ifp) + break; + + switch (cmd) { + + case SIOCAIFADDR: + case SIOCDIFADDR: + + case SIOCSIFADDR: // Moved from after this search, otherwise repeated + // identical SIOCSIFADDRs leaked the previously allocated record. + + if (ifra->ifra_addr.sin_family == AF_INET) + for (; ia != 0; ia = ia->ia_list.tqe_next) { + if (ia->ia_ifp == ifp && + ia->ia_addr.sin_addr.s_addr == + ifra->ifra_addr.sin_addr.s_addr) + break; + } + if (cmd == SIOCDIFADDR && ia == 0) + return (EADDRNOTAVAIL); + /* FALLTHROUGH */ + case SIOCSIFNETMASK: + case SIOCSIFDSTADDR: + if ((so->so_state & SS_PRIV) == 0) + return (EPERM); + + if (ifp == 0) + panic("in_control"); + if (ia == (struct in_ifaddr *)0) { + ia = (struct in_ifaddr *) + malloc(sizeof *ia, M_IFADDR, M_WAITOK); // This alloc was leaked + if (ia == (struct in_ifaddr *)0) + return (ENOBUFS); + bzero((caddr_t)ia, sizeof *ia); + TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list); + TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, + ifa_list); + ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); + ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); + ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); + ia->ia_sockmask.sin_len = 8; + if (ifp->if_flags & IFF_BROADCAST) { + ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); + ia->ia_broadaddr.sin_family = AF_INET; + } + ia->ia_ifp = ifp; + LIST_INIT(&ia->ia_multiaddrs); + if ((ifp->if_flags & IFF_LOOPBACK) == 0) + in_interfaces++; + } + break; + + case SIOCSIFBRDADDR: + if ((so->so_state & SS_PRIV) == 0) + return (EPERM); + /* FALLTHROUGH */ + + case SIOCGIFADDR: + case SIOCGIFNETMASK: + case SIOCGIFDSTADDR: + case SIOCGIFBRDADDR: + if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) { + struct in_ifaddr *ia2; + + for (ia2 = ia; ia2; ia2 = ia2->ia_list.tqe_next) { + if (ia2->ia_ifp == ifp && + ia2->ia_addr.sin_addr.s_addr == + satosin(&ifr->ifr_addr)->sin_addr.s_addr) + break; + } + if (ia2 && ia2->ia_ifp == ifp) + ia = ia2; + } + if (ia == (struct in_ifaddr *)0) + return (EADDRNOTAVAIL); + break; + } + switch (cmd) { + + case SIOCGIFADDR: + *satosin(&ifr->ifr_addr) = ia->ia_addr; + break; + + case SIOCGIFBRDADDR: + if ((ifp->if_flags & IFF_BROADCAST) == 0) + return (EINVAL); + *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr; + break; + + case SIOCGIFDSTADDR: + if ((ifp->if_flags & IFF_POINTOPOINT) == 0) + return (EINVAL); + *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr; + break; + + case SIOCGIFNETMASK: + *satosin(&ifr->ifr_addr) = ia->ia_sockmask; + break; + + case SIOCSIFDSTADDR: + if ((ifp->if_flags & IFF_POINTOPOINT) == 0) + return (EINVAL); + oldaddr = ia->ia_dstaddr; + ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr); + if (ifp->if_ioctl && (error = (*ifp->if_ioctl) + (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { + ia->ia_dstaddr = oldaddr; + return (error); + } + if (ia->ia_flags & IFA_ROUTE) { + ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr); + rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); + ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); + rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); + } + break; + + case SIOCSIFBRDADDR: + if ((ifp->if_flags & IFF_BROADCAST) == 0) + return (EINVAL); + ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr); + break; + + case SIOCSIFADDR: + return (in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1)); + + case SIOCSIFNETMASK: + ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr = + ifra->ifra_addr.sin_addr.s_addr; + break; + + case SIOCAIFADDR: + maskIsNew = 0; + hostIsNew = 1; + error = 0; + if (ia->ia_addr.sin_family == AF_INET) { + if (ifra->ifra_addr.sin_len == 0) { + ifra->ifra_addr = ia->ia_addr; + hostIsNew = 0; + } else if (ifra->ifra_addr.sin_addr.s_addr == + ia->ia_addr.sin_addr.s_addr) + hostIsNew = 0; + } + if (ifra->ifra_mask.sin_len) { + in_ifscrub(ifp, ia); + ia->ia_sockmask = ifra->ifra_mask; + ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr; + maskIsNew = 1; + } + if ((ifp->if_flags & IFF_POINTOPOINT) && + (ifra->ifra_dstaddr.sin_family == AF_INET)) { + in_ifscrub(ifp, ia); + ia->ia_dstaddr = ifra->ifra_dstaddr; + maskIsNew = 1; /* We lie; but the effect's the same */ + } + if (ifra->ifra_addr.sin_family == AF_INET && + (hostIsNew || maskIsNew)) + error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); + if ((ifp->if_flags & IFF_BROADCAST) && + (ifra->ifra_broadaddr.sin_family == AF_INET)) + ia->ia_broadaddr = ifra->ifra_broadaddr; + return (error); + + case SIOCDIFADDR: + in_ifscrub(ifp, ia); + TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); + TAILQ_REMOVE(&in_ifaddr, ia, ia_list); + IFAFREE((&ia->ia_ifa)); + break; + +#ifdef MROUTING + case SIOCGETVIFCNT: + case SIOCGETSGCNT: + return (mrt_ioctl(cmd, data)); +#endif /* MROUTING */ + + default: + if (ifp == 0 || ifp->if_ioctl == 0) + return (EOPNOTSUPP); + return ((*ifp->if_ioctl)(ifp, cmd, data)); + } + return (0); +} + +/* + * SIOC[GAD]LIFADDR. + * SIOCGLIFADDR: get first address. ( ??? ) + * SIOCGLIFADDR with IFLR_PREFIX: + * get first address that matches the specified prefix. + * SIOCALIFADDR: add the specified address. + * SIOCALIFADDR with IFLR_PREFIX: + * EINVAL since we can't deduce hostid part of the address. + * SIOCDLIFADDR: delete the specified address. + * SIOCDLIFADDR with IFLR_PREFIX: + * delete the first address that matches the specified prefix. + * return values: + * EINVAL on invalid parameters + * EADDRNOTAVAIL on prefix match failed/specified address not found + * other values may be returned from in_ioctl() + */ +static int +in_lifaddr_ioctl(so, cmd, data, ifp) + struct socket *so; + u_long cmd; + caddr_t data; + struct ifnet *ifp; +{ + struct if_laddrreq *iflr = (struct if_laddrreq *)data; + struct ifaddr *ifa; + struct sockaddr *sa; + + /* sanity checks */ + if (!data || !ifp) { + panic("invalid argument to in_lifaddr_ioctl"); + /*NOTRECHED*/ + } + + switch (cmd) { + case SIOCGLIFADDR: + /* address must be specified on GET with IFLR_PREFIX */ + if ((iflr->flags & IFLR_PREFIX) == 0) + break; + /*FALLTHROUGH*/ + case SIOCALIFADDR: + case SIOCDLIFADDR: + /* address must be specified on ADD and DELETE */ + sa = (struct sockaddr *)&iflr->addr; + if (sa->sa_family != AF_INET) + return EINVAL; + if (sa->sa_len != sizeof(struct sockaddr_in)) + return EINVAL; + /* XXX need improvement */ + sa = (struct sockaddr *)&iflr->dstaddr; + if (sa->sa_family + && sa->sa_family != AF_INET) + return EINVAL; + if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in)) + return EINVAL; + break; + default: /*shouldn't happen*/ +#if 0 + panic("invalid cmd to in_lifaddr_ioctl"); + /*NOTREACHED*/ +#else + return EOPNOTSUPP; +#endif + } + if (sizeof(struct in_addr) * 8 < iflr->prefixlen) + return EINVAL; + + switch (cmd) { + case SIOCALIFADDR: + { + struct in_aliasreq ifra; + + if (iflr->flags & IFLR_PREFIX) + return EINVAL; + + /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */ + bzero(&ifra, sizeof(ifra)); + bcopy(iflr->iflr_name, ifra.ifra_name, + sizeof(ifra.ifra_name)); + + bcopy(&iflr->addr, &ifra.ifra_addr, + ((struct sockaddr *)&iflr->addr)->sa_len); + + if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /*XXX*/ + bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr, + ((struct sockaddr *)&iflr->dstaddr)->sa_len); + } + + ifra.ifra_mask.sin_family = AF_INET; + ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in); + in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen); + + return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp); + } + case SIOCGLIFADDR: + case SIOCDLIFADDR: + { + struct in_ifaddr *ia; + struct in_addr mask, candidate, match; + struct sockaddr_in *sin; + int cmp; + + bzero(&mask, sizeof(mask)); + if (iflr->flags & IFLR_PREFIX) { + /* lookup a prefix rather than address. */ + in_len2mask(&mask, iflr->prefixlen); + + sin = (struct sockaddr_in *)&iflr->addr; + match.s_addr = sin->sin_addr.s_addr; + match.s_addr &= mask.s_addr; + + /* if you set extra bits, that's wrong */ + if (match.s_addr != sin->sin_addr.s_addr) + return EINVAL; + + cmp = 1; + } else { + if (cmd == SIOCGLIFADDR) { + /* on getting an address, take the 1st match */ + cmp = 0; /*XXX*/ + } else { + /* on deleting an address, do exact match */ + in_len2mask(&mask, 32); + sin = (struct sockaddr_in *)&iflr->addr; + match.s_addr = sin->sin_addr.s_addr; + + cmp = 1; + } + } + + for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + if (!cmp) + break; + candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr; + candidate.s_addr &= mask.s_addr; + if (candidate.s_addr == match.s_addr) + break; + } + if (!ifa) + return EADDRNOTAVAIL; + ia = (struct in_ifaddr *)ifa; + + if (cmd == SIOCGLIFADDR) { + /* fill in the if_laddrreq structure */ + bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len); + + if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { + bcopy(&ia->ia_dstaddr, &iflr->dstaddr, + ia->ia_dstaddr.sin_len); + } else + bzero(&iflr->dstaddr, sizeof(iflr->dstaddr)); + + iflr->prefixlen = + in_mask2len(&ia->ia_sockmask.sin_addr); + + iflr->flags = 0; /*XXX*/ + + return 0; + } else { + struct in_aliasreq ifra; + + /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */ + bzero(&ifra, sizeof(ifra)); + bcopy(iflr->iflr_name, ifra.ifra_name, + sizeof(ifra.ifra_name)); + + bcopy(&ia->ia_addr, &ifra.ifra_addr, + ia->ia_addr.sin_len); + if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { + bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr, + ia->ia_dstaddr.sin_len); + } + bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr, + ia->ia_sockmask.sin_len); + + return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, ifp); + } + } + } + + return EOPNOTSUPP; /*just for safety*/ +} + +/* + * Delete any existing route for an interface. + */ +void +in_ifscrub(ifp, ia) + register struct ifnet *ifp; + register struct in_ifaddr *ia; +{ + + if ((ia->ia_flags & IFA_ROUTE) == 0) + return; + if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) + rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); + else + rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); + ia->ia_flags &= ~IFA_ROUTE; +} + +/* + * Initialize an interface's internet address + * and routing table entry. + */ +int +in_ifinit(ifp, ia, sin, scrub) + register struct ifnet *ifp; + register struct in_ifaddr *ia; + struct sockaddr_in *sin; + int scrub; +{ + register u_int32_t i = sin->sin_addr.s_addr; + struct sockaddr_in oldaddr; + int s = splimp(), flags = RTF_UP, error; + + oldaddr = ia->ia_addr; + ia->ia_addr = *sin; + /* + * Give the interface a chance to initialize + * if this is its first address, + * and to validate the address if necessary. + */ + if (ifp->if_ioctl && + (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { + splx(s); + ia->ia_addr = oldaddr; + return (error); + } + splx(s); + if (scrub) { + ia->ia_ifa.ifa_addr = sintosa(&oldaddr); + in_ifscrub(ifp, ia); + ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); + } + if (IN_CLASSA(i)) + ia->ia_netmask = IN_CLASSA_NET; + else if (IN_CLASSB(i)) + ia->ia_netmask = IN_CLASSB_NET; + else + ia->ia_netmask = IN_CLASSC_NET; + /* + * The subnet mask usually includes at least the standard network part, + * but may may be smaller in the case of supernetting. + * If it is set, we believe it. + */ + if (ia->ia_subnetmask == 0) { + ia->ia_subnetmask = ia->ia_netmask; + ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask; + } else + ia->ia_netmask &= ia->ia_subnetmask; + ia->ia_net = i & ia->ia_netmask; + ia->ia_subnet = i & ia->ia_subnetmask; + in_socktrim(&ia->ia_sockmask); + /* + * Add route for the network. + */ + ia->ia_ifa.ifa_metric = ifp->if_metric; + if (ifp->if_flags & IFF_BROADCAST) { + ia->ia_broadaddr.sin_addr.s_addr = + ia->ia_subnet | ~ia->ia_subnetmask; + ia->ia_netbroadcast.s_addr = + ia->ia_net | ~ia->ia_netmask; + } else if (ifp->if_flags & IFF_LOOPBACK) { + ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; + flags |= RTF_HOST; + } else if (ifp->if_flags & IFF_POINTOPOINT) { + if (ia->ia_dstaddr.sin_family != AF_INET) + return (0); + flags |= RTF_HOST; + } + if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) + ia->ia_flags |= IFA_ROUTE; + /* + * If the interface supports multicast, join the "all hosts" + * multicast group on that interface. + */ + if (ifp->if_flags & IFF_MULTICAST) { + struct in_addr addr; + + addr.s_addr = INADDR_ALLHOSTS_GROUP; + in_addmulti(&addr, ifp); + } + return (error); +} + + +/* + * Return 1 if the address might be a local broadcast address. + */ +int +in_broadcast(in, ifp) + struct in_addr in; + struct ifnet *ifp; +{ + struct ifnet *ifn, *if_first, *if_target; + register struct ifaddr *ifa; + + if (in.s_addr == INADDR_BROADCAST || + in.s_addr == INADDR_ANY) + return 1; + if (ifp && ((ifp->if_flags & IFF_BROADCAST) == 0)) + return 0; + + if (ifp == NULL) + { + if_first = ifnet.tqh_first; + if_target = 0; + } + else + { + if_first = ifp; + if_target = ifp->if_list.tqe_next; + } + +#define ia (ifatoia(ifa)) + /* + * Look through the list of addresses for a match + * with a broadcast address. + * If ifp is NULL, check against all the interfaces. + */ + for (ifn = if_first; ifn != if_target; ifn = ifn->if_list.tqe_next) + for (ifa = ifn->if_addrlist.tqh_first; ifa; + ifa = ifa->ifa_list.tqe_next) + if (!ifp) + { + if (ifa->ifa_addr->sa_family == AF_INET && + ((ia->ia_subnetmask != 0xffffffff && + (((ifn->if_flags & IFF_BROADCAST) && + in.s_addr == ia->ia_broadaddr.sin_addr.s_addr) || + in.s_addr == ia->ia_subnet)) || + /* + * Check for old-style (host 0) broadcast. + */ + (in.s_addr == ia->ia_netbroadcast.s_addr || + in.s_addr == ia->ia_net))) + return 1; + } + else + if (ifa->ifa_addr->sa_family == AF_INET && + (((ifn->if_flags & IFF_BROADCAST) && + in.s_addr == ia->ia_broadaddr.sin_addr.s_addr) || + in.s_addr == ia->ia_netbroadcast.s_addr || + /* + * Check for old-style (host 0) broadcast. + */ + in.s_addr == ia->ia_subnet || + in.s_addr == ia->ia_net)) + return 1; + return (0); +#undef ia +} + +/* + * Add an address to the list of IP multicast addresses for a given interface. + */ +struct in_multi * +in_addmulti(ap, ifp) + register struct in_addr *ap; + register struct ifnet *ifp; +{ + register struct in_multi *inm; + struct ifreq ifr; + struct in_ifaddr *ia; + int s = splsoftnet(); + + /* + * See if address already in list. + */ + IN_LOOKUP_MULTI(*ap, ifp, inm); + if (inm != NULL) { + /* + * Found it; just increment the reference count. + */ + ++inm->inm_refcount; + } else { + /* + * New address; allocate a new multicast record + * and link it into the interface's multicast list. + */ + inm = (struct in_multi *)malloc(sizeof(*inm), + M_IPMADDR, M_NOWAIT); + if (inm == NULL) { + splx(s); + return (NULL); + } + inm->inm_addr = *ap; + inm->inm_ifp = ifp; + inm->inm_refcount = 1; + IFP_TO_IA(ifp, ia); + if (ia == NULL) { + free(inm, M_IPMADDR); + splx(s); + return (NULL); + } + inm->inm_ia = ia; + LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list); + /* + * Ask the network driver to update its multicast reception + * filter appropriately for the new address. + */ + satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in); + satosin(&ifr.ifr_addr)->sin_family = AF_INET; + satosin(&ifr.ifr_addr)->sin_addr = *ap; + if ((ifp->if_ioctl == NULL) || + (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { + LIST_REMOVE(inm, inm_list); + free(inm, M_IPMADDR); + splx(s); + return (NULL); + } + /* + * Let IGMP know that we have joined a new IP multicast group. + */ + igmp_joingroup(inm); + } + splx(s); + return (inm); +} + +/* + * Delete a multicast address record. + */ +void +in_delmulti(inm) + register struct in_multi *inm; +{ + struct ifreq ifr; + int s = splsoftnet(); + + if (--inm->inm_refcount == 0) { + /* + * No remaining claims to this record; let IGMP know that + * we are leaving the multicast group. + */ + igmp_leavegroup(inm); + /* + * Unlink from list. + */ + LIST_REMOVE(inm, inm_list); + /* + * Notify the network driver to update its multicast reception + * filter. + */ + satosin(&ifr.ifr_addr)->sin_family = AF_INET; + satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr; + (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, + (caddr_t)&ifr); + free(inm, M_IPMADDR); + } + splx(s); +} + +#endif diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/in_cksum.c b/ecos/packages/net/tcpip/current/src/sys/netinet/in_cksum.c new file mode 100644 index 0000000..3a74df8 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/in_cksum.c @@ -0,0 +1,196 @@ +//========================================================================== +// +// sys/netinet/in_cksum.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in_cksum.c,v 1.3 1997/02/24 14:06:35 niklas Exp $ */ +/* $NetBSD: in_cksum.c,v 1.11 1996/04/08 19:55:37 jonathan Exp $ */ + +/* + * Copyright (c) 1988, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/param.h> +#include <sys/mbuf.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <netinet/in.h> + +struct net_stats stats_in_cksum; + +/* + * Checksum routine for Internet Protocol family headers (Portable Version). + * + * This routine is very heavily used in the network + * code and should be modified for each CPU to be as fast as possible. + */ + +#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) +#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} + +int +in_cksum(m, len) + register struct mbuf *m; + register int len; +{ + register u_int16_t *w; + register int sum = 0; + register int mlen = 0; + int byte_swapped = 0; + + union { + u_int8_t c[2]; + u_int16_t s; + } s_util; + union { + u_int16_t s[2]; + u_int32_t l; + } l_util; + + START_STATS(); + + for (;m && len; m = m->m_next) { + if (m->m_len == 0) + continue; + w = mtod(m, u_int16_t *); + if (mlen == -1) { + /* + * The first byte of this mbuf is the continuation + * of a word spanning between this mbuf and the + * last mbuf. + * + * s_util.c[0] is already saved when scanning previous + * mbuf. + */ + s_util.c[1] = *(u_int8_t *)w; + sum += s_util.s; + w = (u_int16_t *)((u_int8_t *)w + 1); + mlen = m->m_len - 1; + len--; + } else + mlen = m->m_len; + if (len < mlen) + mlen = len; + len -= mlen; + /* + * Force to even boundary. + */ + if ((1 & (long) w) && (mlen > 0)) { + REDUCE; + sum <<= 8; + s_util.c[0] = *(u_int8_t *)w; + w = (u_int16_t *)((int8_t *)w + 1); + mlen--; + byte_swapped = 1; + } + /* + * Unroll the loop to make overhead from + * branches &c small. + */ + while ((mlen -= 32) >= 0) { + sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; + sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; + sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; + sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; + w += 16; + } + mlen += 32; + while ((mlen -= 8) >= 0) { + sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; + w += 4; + } + mlen += 8; + if (mlen == 0 && byte_swapped == 0) + continue; + REDUCE; + while ((mlen -= 2) >= 0) { + sum += *w++; + } + if (byte_swapped) { + REDUCE; + sum <<= 8; + byte_swapped = 0; + if (mlen == -1) { + s_util.c[1] = *(u_int8_t *)w; + sum += s_util.s; + mlen = 0; + } else + mlen = -1; + } else if (mlen == -1) + s_util.c[0] = *(u_int8_t *)w; + } + if (len) +#ifdef __ECOS + diag_printf("cksum: out of data\n"); +#else + printf("cksum: out of data\n"); +#endif + if (mlen == -1) { + /* The last mbuf has odd # of bytes. Follow the + standard (the odd byte may be shifted left by 8 bits + or not as determined by endian-ness of the machine) */ + s_util.c[1] = 0; + sum += s_util.s; + } + REDUCE; + + FINISH_STATS(stats_in_cksum); + + return (~sum & 0xffff); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/in_pcb.c b/ecos/packages/net/tcpip/current/src/sys/netinet/in_pcb.c new file mode 100644 index 0000000..4b295f4 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/in_pcb.c @@ -0,0 +1,1089 @@ +//========================================================================== +// +// sys/netinet/in_pcb.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in_pcb.c,v 1.36 1999/12/08 11:36:40 angelos Exp $ */ +/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#ifdef __ECOS +#undef errno +#endif +#include <sys/time.h> +#ifndef __ECOS +#include <sys/proc.h> +#endif +#include <sys/domain.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/in_var.h> +#include <netinet/ip_var.h> +#ifndef __ECOS +#include <dev/rndvar.h> +#endif + +#ifdef INET6 +#include <netinet6/ip6_var.h> +#endif /* INET6 */ + +#ifdef IPSEC +#include <netinet/ip_ipsp.h> + +extern int check_ipsec_policy __P((struct inpcb *, u_int32_t)); +#endif + +#if 0 /*KAME IPSEC*/ +#include <netinet6/ipsec.h> +#include <netkey/key.h> +#include <netkey/key_debug.h> +#endif /* IPSEC */ + +struct in_addr zeroin_addr; + +extern int ipsec_auth_default_level; +extern int ipsec_esp_trans_default_level; +extern int ipsec_esp_network_default_level; + +/* + * These configure the range of local port addresses assigned to + * "unspecified" outgoing connections/packets/whatever. + */ +int ipport_firstauto = IPPORT_RESERVED; /* 1024 */ +int ipport_lastauto = IPPORT_USERRESERVED; /* 5000 */ +int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 40000 */ +int ipport_hilastauto = IPPORT_HILASTAUTO; /* 44999 */ + +#define INPCBHASH(table, faddr, fport, laddr, lport) \ + &(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + \ + ntohs((fport)) + ntohs((lport))) & (table->inpt_hash)] + +#define IN6PCBHASH(table, faddr, fport, laddr, lport) \ + &(table)->inpt_hashtbl[(ntohl((faddr)->s6_addr32[0] ^ \ + (faddr)->s6_addr32[3]) + ntohs((fport)) + ntohs((lport))) & \ + (table->inpt_hash)] + +void +in_pcbinit(table, hashsize) + struct inpcbtable *table; + int hashsize; +{ + + CIRCLEQ_INIT(&table->inpt_queue); + table->inpt_hashtbl = hashinit(hashsize, M_PCB, M_WAITOK, &table->inpt_hash); + table->inpt_lastport = 0; +} + +struct baddynamicports baddynamicports; + +/* + * Check if the specified port is invalid for dynamic allocation. + */ +int +in_baddynamic(port, proto) + u_int16_t port; + u_int16_t proto; +{ + + if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) + return(0); + + switch (proto) { + case IPPROTO_TCP: + return (DP_ISSET(baddynamicports.tcp, port)); + case IPPROTO_UDP: + return (DP_ISSET(baddynamicports.udp, port)); + default: + return (0); + } +} + +int +in_pcballoc(so, v) + struct socket *so; + void *v; +{ + struct inpcbtable *table = v; + register struct inpcb *inp; + int s; + + MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_NOWAIT); + if (inp == NULL) + return (ENOBUFS); + bzero((caddr_t)inp, sizeof(*inp)); + inp->inp_table = table; + inp->inp_socket = so; + inp->inp_seclevel[SL_AUTH] = ipsec_auth_default_level; + inp->inp_seclevel[SL_ESP_TRANS] = ipsec_esp_trans_default_level; + inp->inp_seclevel[SL_ESP_NETWORK] = ipsec_esp_network_default_level; + s = splnet(); + CIRCLEQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue); + LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr, inp->inp_fport, + &inp->inp_laddr, inp->inp_lport), inp, inp_hash); + splx(s); + so->so_pcb = inp; + inp->inp_hops = -1; + +#ifdef INET6 + /* + * Small change in this function to set the INP_IPV6 flag so routines + * outside pcb-specific routines don't need to use sotopf(), and all + * of it's pointer chasing, later. + */ + if (sotopf(so) == PF_INET6) + inp->inp_flags = INP_IPV6; + inp->inp_csumoffset = -1; +#endif /* INET6 */ + return (0); +} + +int +in_pcbbind(v, nam) + register void *v; + struct mbuf *nam; +{ + register struct inpcb *inp = v; + register struct socket *so = inp->inp_socket; + register struct inpcbtable *table = inp->inp_table; + u_int16_t *lastport = &inp->inp_table->inpt_lastport; + register struct sockaddr_in *sin; +#ifndef __ECOS + struct proc *p = curproc; /* XXX */ + int error; +#endif + u_int16_t lport = 0; + int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); + +#ifdef INET6 + if (sotopf(so) == PF_INET6) + return in6_pcbbind(inp, nam); +#endif /* INET6 */ + + if (in_ifaddr.tqh_first == 0) + return (EADDRNOTAVAIL); + if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY) + return (EINVAL); + if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && + ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || + (so->so_options & SO_ACCEPTCONN) == 0)) + wild = INPLOOKUP_WILDCARD; + if (nam) { + sin = mtod(nam, struct sockaddr_in *); + if (nam->m_len != sizeof (*sin)) + return (EINVAL); +#ifdef notdef + /* + * We should check the family, but old programs + * incorrectly fail to initialize it. + */ + if (sin->sin_family != AF_INET) + return (EAFNOSUPPORT); +#endif + lport = sin->sin_port; + if (IN_MULTICAST(sin->sin_addr.s_addr)) { + /* + * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; + * allow complete duplication of binding if + * SO_REUSEPORT is set, or if SO_REUSEADDR is set + * and a multicast address is bound on both + * new and duplicated sockets. + */ + if (so->so_options & SO_REUSEADDR) + reuseport = SO_REUSEADDR|SO_REUSEPORT; + } else if (sin->sin_addr.s_addr != INADDR_ANY) { + sin->sin_port = 0; /* yech... */ + if (in_iawithaddr(sin->sin_addr, NULL) == 0) + return (EADDRNOTAVAIL); + } + if (lport) { + struct inpcb *t; + + /* GROSS */ +#ifndef __ECOS + if (ntohs(lport) < IPPORT_RESERVED && + (error = suser(p->p_ucred, &p->p_acflag))) + return (EACCES); +#endif + if (so->so_euid) { + t = in_pcblookup(table, &zeroin_addr, 0, + &sin->sin_addr, lport, INPLOOKUP_WILDCARD); + if (t && (so->so_euid != t->inp_socket->so_euid)) + return (EADDRINUSE); + } + t = in_pcblookup(table, &zeroin_addr, 0, + &sin->sin_addr, lport, wild); + if (t && (reuseport & t->inp_socket->so_options) == 0) + return (EADDRINUSE); + } + inp->inp_laddr = sin->sin_addr; + } + if (lport == 0) { + u_int16_t first, last, old = 0; + int count; + int loopcount = 0; + + if (inp->inp_flags & INP_HIGHPORT) { + first = ipport_hifirstauto; /* sysctl */ + last = ipport_hilastauto; + } else if (inp->inp_flags & INP_LOWPORT) { +#ifndef __ECOS + if ((error = suser(p->p_ucred, &p->p_acflag))) + return (EACCES); +#endif + first = IPPORT_RESERVED-1; /* 1023 */ + last = 600; /* not IPPORT_RESERVED/2 */ + } else { + first = ipport_firstauto; /* sysctl */ + last = ipport_lastauto; + } + + /* + * Simple check to ensure all ports are not used up causing + * a deadlock here. + * + * We split the two cases (up and down) so that the direction + * is not being tested on each round of the loop. + */ + +portloop: + if (first > last) { + /* + * counting down + */ + if (loopcount == 0) { /* only do this once. */ + old = first; + first -= (arc4random() % (first - last)); + } + count = first - last; + *lastport = first; /* restart each time */ + + do { + if (count-- <= 0) { /* completely used? */ + if (loopcount == 0) { + last = old; + loopcount++; + goto portloop; + } + return (EADDRNOTAVAIL); + } + --*lastport; + if (*lastport > first || *lastport < last) + *lastport = first; + lport = htons(*lastport); + } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) || + in_pcblookup(table, &zeroin_addr, 0, + &inp->inp_laddr, lport, wild)); + } else { + /* + * counting up + */ + if (loopcount == 0) { /* only do this once. */ + old = first; + first += (arc4random() % (last - first)); + } + count = last - first; + *lastport = first; /* restart each time */ + + do { + if (count-- <= 0) { /* completely used? */ + if (loopcount == 0) { + first = old; + loopcount++; + goto portloop; + } + return (EADDRNOTAVAIL); + } + ++*lastport; + if (*lastport < first || *lastport > last) + *lastport = first; + lport = htons(*lastport); + } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) || + in_pcblookup(table, &zeroin_addr, 0, + &inp->inp_laddr, lport, wild)); + } + } + inp->inp_lport = lport; + in_pcbrehash(inp); + return (0); +} + +/* + * Connect from a socket to a specified address. + * Both address and port must be specified in argument sin. + * If don't have a local address for this socket yet, + * then pick one. + */ +int +in_pcbconnect(v, nam) + register void *v; + struct mbuf *nam; +{ + register struct inpcb *inp = v; + struct sockaddr_in *ifaddr = NULL; + register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); + +#ifdef INET6 + if (sotopf(inp->inp_socket) == PF_INET6) + return (in6_pcbconnect(inp, nam)); +#endif /* INET6 */ + + if (nam->m_len != sizeof (*sin)) + return (EINVAL); + if (sin->sin_family != AF_INET) + return (EAFNOSUPPORT); + if (sin->sin_port == 0) + return (EADDRNOTAVAIL); + if (in_ifaddr.tqh_first != 0) { + /* + * If the destination address is INADDR_ANY, + * use the primary local address. + * If the supplied address is INADDR_BROADCAST, + * and the primary interface supports broadcast, + * choose the broadcast address for that interface. + */ + if (sin->sin_addr.s_addr == INADDR_ANY) + sin->sin_addr = in_ifaddr.tqh_first->ia_addr.sin_addr; + else if (sin->sin_addr.s_addr == INADDR_BROADCAST && + (in_ifaddr.tqh_first->ia_ifp->if_flags & IFF_BROADCAST)) + sin->sin_addr = in_ifaddr.tqh_first->ia_broadaddr.sin_addr; + } + if (inp->inp_laddr.s_addr == INADDR_ANY) { +#if 0 + register struct route *ro; + struct sockaddr_in *sin2; + struct in_ifaddr *ia; + + ia = (struct in_ifaddr *)0; + /* + * If route is known or can be allocated now, + * our src addr is taken from the i/f, else punt. + */ + ro = &inp->inp_route; + if (ro->ro_rt && + (satosin(&ro->ro_dst)->sin_addr.s_addr != + sin->sin_addr.s_addr || + inp->inp_socket->so_options & SO_DONTROUTE)) { + RTFREE(ro->ro_rt); + ro->ro_rt = (struct rtentry *)0; + } + if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ + (ro->ro_rt == (struct rtentry *)0 || + ro->ro_rt->rt_ifp == (struct ifnet *)0)) { + /* No route yet, so try to acquire one */ + ro->ro_dst.sa_family = AF_INET; + ro->ro_dst.sa_len = sizeof(struct sockaddr_in); + satosin(&ro->ro_dst)->sin_addr = sin->sin_addr; + rtalloc(ro); + + /* + * It is important to bzero out the rest of the + * struct sockaddr_in when mixing v6 & v4! + */ + sin2 = (struct sockaddr_in *)&ro->ro_dst; + bzero(sin2->sin_zero, sizeof(sin2->sin_zero)); + } + /* + * If we found a route, use the address + * corresponding to the outgoing interface + * unless it is the loopback (in case a route + * to our address on another net goes to loopback). + */ + if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) + ia = ifatoia(ro->ro_rt->rt_ifa); + if (ia == 0) { + u_int16_t fport = sin->sin_port; + + sin->sin_port = 0; + ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); + if (ia == 0) + ia = ifatoia(ifa_ifwithnet(sintosa(sin))); + sin->sin_port = fport; + if (ia == 0) + ia = in_ifaddr.tqh_first; + if (ia == 0) + return (EADDRNOTAVAIL); + } + /* + * If the destination address is multicast and an outgoing + * interface has been set as a multicast option, use the + * address of that interface as our source address. + */ + if (IN_MULTICAST(sin->sin_addr.s_addr) && +#ifdef INET6 + inp->inp_moptions != NULL && + !(inp->inp_flags & INP_IPV6_MCAST)) +#else + inp->inp_moptions != NULL) +#endif + { + struct ip_moptions *imo; + struct ifnet *ifp; + + imo = inp->inp_moptions; + if (imo->imo_multicast_ifp != NULL) { + ifp = imo->imo_multicast_ifp; + for (ia = in_ifaddr.tqh_first; ia != 0; + ia = ia->ia_list.tqe_next) + if (ia->ia_ifp == ifp) + break; + if (ia == 0) + return (EADDRNOTAVAIL); + } + } + ifaddr = satosin(&ia->ia_addr); +#else + int error; + ifaddr = in_selectsrc(sin, &inp->inp_route, + inp->inp_socket->so_options, inp->inp_moptions, &error); + if (ifaddr == NULL) { + if (error == 0) + error = EADDRNOTAVAIL; + return error; + } +#endif + } + if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port, + inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr, + inp->inp_lport) != 0) + return (EADDRINUSE); + if (inp->inp_laddr.s_addr == INADDR_ANY) { + if (inp->inp_lport == 0 && + in_pcbbind(inp, (struct mbuf *)0) == EADDRNOTAVAIL) + return (EADDRNOTAVAIL); + inp->inp_laddr = ifaddr->sin_addr; + } + inp->inp_faddr = sin->sin_addr; + inp->inp_fport = sin->sin_port; + in_pcbrehash(inp); +#ifdef IPSEC + return (check_ipsec_policy(inp, 0)); +#else + return (0); +#endif +} + +void +in_pcbdisconnect(v) + void *v; +{ + struct inpcb *inp = v; + +#ifdef INET6 + if (sotopf(inp->inp_socket) == PF_INET6) { + inp->inp_faddr6 = in6addr_any; + /* Disconnected AF_INET6 sockets cannot be "v4-mapped" */ + inp->inp_flags &= ~INP_IPV6_MAPPED; + } else +#endif + inp->inp_faddr.s_addr = INADDR_ANY; + + inp->inp_fport = 0; + in_pcbrehash(inp); + if (inp->inp_socket->so_state & SS_NOFDREF) + in_pcbdetach(inp); +} + +void +in_pcbdetach(v) + void *v; +{ + struct inpcb *inp = v; + struct socket *so = inp->inp_socket; + int s; + +#if 0 /*KAME IPSEC*/ + if (so->so_pcb) { + KEYDEBUG(KEYDEBUG_KEY_STAMP, + printf("DP call free SO=%p from in_pcbdetach\n", so)); + key_freeso(so); + } + ipsec4_delete_pcbpolicy(inp); +#endif /*IPSEC*/ + so->so_pcb = 0; + sofree(so); + if (inp->inp_options) + (void)m_freem(inp->inp_options); + if (inp->inp_route.ro_rt) + rtfree(inp->inp_route.ro_rt); +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + ip6_freemoptions(inp->inp_moptions6); + else +#endif + ip_freemoptions(inp->inp_moptions); +#ifdef IPSEC + /* XXX IPsec cleanup here */ + s = spltdb(); + if (inp->inp_tdb) + TAILQ_REMOVE(&inp->inp_tdb->tdb_inp, inp, inp_tdb_next); + splx(s); +#endif + s = splnet(); + LIST_REMOVE(inp, inp_hash); + CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue); + splx(s); + FREE(inp, M_PCB); +} + +void +in_setsockaddr(inp, nam) + register struct inpcb *inp; + struct mbuf *nam; +{ + register struct sockaddr_in *sin; + + nam->m_len = sizeof (*sin); + sin = mtod(nam, struct sockaddr_in *); + bzero((caddr_t)sin, sizeof (*sin)); + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_port = inp->inp_lport; + sin->sin_addr = inp->inp_laddr; +} + +void +in_setpeeraddr(inp, nam) + struct inpcb *inp; + struct mbuf *nam; +{ + register struct sockaddr_in *sin; + +#ifdef INET6 + if (sotopf(inp->inp_socket) == PF_INET6) + in6_setpeeraddr(inp, nam); +#endif /* INET6 */ + + nam->m_len = sizeof (*sin); + sin = mtod(nam, struct sockaddr_in *); + bzero((caddr_t)sin, sizeof (*sin)); + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_port = inp->inp_fport; + sin->sin_addr = inp->inp_faddr; +} + +/* + * Pass some notification to all connections of a protocol + * associated with address dst. The local address and/or port numbers + * may be specified to limit the search. The "usual action" will be + * taken, depending on the ctlinput cmd. The caller must filter any + * cmds that are uninteresting (e.g., no error in the map). + * Call the protocol specific routine (if any) to report + * any errors for each matching socket. + * + * Must be called at splsoftnet. + */ +void +in_pcbnotify(table, dst, fport_arg, laddr, lport_arg, errno, notify) + struct inpcbtable *table; + struct sockaddr *dst; + u_int fport_arg, lport_arg; + struct in_addr laddr; + int errno; + void (*notify) __P((struct inpcb *, int)); +{ + register struct inpcb *inp, *oinp; + struct in_addr faddr; + u_int16_t fport = fport_arg, lport = lport_arg; + +#ifdef INET6 + /* + * See in6_pcbnotify() for IPv6 codepath. By the time this + * gets called, the addresses passed are either definitely IPv4 or + * IPv6; *_pcbnotify() never gets called with v4-mapped v6 addresses. + */ +#endif /* INET6 */ + + if (dst->sa_family != AF_INET) + return; + faddr = satosin(dst)->sin_addr; + if (faddr.s_addr == INADDR_ANY) + return; + + for (inp = table->inpt_queue.cqh_first; + inp != (struct inpcb *)&table->inpt_queue;) { + if (inp->inp_faddr.s_addr != faddr.s_addr || + inp->inp_socket == 0 || + inp->inp_fport != fport || + inp->inp_lport != lport || + inp->inp_laddr.s_addr != laddr.s_addr) { + inp = inp->inp_queue.cqe_next; + continue; + } + oinp = inp; + inp = inp->inp_queue.cqe_next; + if (notify) + (*notify)(oinp, errno); + } +} + +void +in_pcbnotifyall(table, dst, errno, notify) + struct inpcbtable *table; + struct sockaddr *dst; + int errno; + void (*notify) __P((struct inpcb *, int)); +{ + register struct inpcb *inp, *oinp; + struct in_addr faddr; + +#ifdef INET6 + /* + * See in6_pcbnotify() for IPv6 codepath. By the time this + * gets called, the addresses passed are either definitely IPv4 or + * IPv6; *_pcbnotify() never gets called with v4-mapped v6 addresses. + */ +#endif /* INET6 */ + + if (dst->sa_family != AF_INET) + return; + faddr = satosin(dst)->sin_addr; + if (faddr.s_addr == INADDR_ANY) + return; + + for (inp = table->inpt_queue.cqh_first; + inp != (struct inpcb *)&table->inpt_queue;) { + if (inp->inp_faddr.s_addr != faddr.s_addr || + inp->inp_socket == 0) { + inp = inp->inp_queue.cqe_next; + continue; + } + oinp = inp; + inp = inp->inp_queue.cqe_next; + if (notify) + (*notify)(oinp, errno); + } +} + +/* + * Check for alternatives when higher level complains + * about service problems. For now, invalidate cached + * routing information. If the route was created dynamically + * (by a redirect), time to try a default gateway again. + */ +void +in_losing(inp) + struct inpcb *inp; +{ + register struct rtentry *rt; + struct rt_addrinfo info; + + if ((rt = inp->inp_route.ro_rt)) { + inp->inp_route.ro_rt = 0; + bzero((caddr_t)&info, sizeof(info)); + info.rti_info[RTAX_DST] = &inp->inp_route.ro_dst; + info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; + info.rti_info[RTAX_NETMASK] = rt_mask(rt); + rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); + if (rt->rt_flags & RTF_DYNAMIC) + (void) rtrequest(RTM_DELETE, rt_key(rt), + rt->rt_gateway, rt_mask(rt), rt->rt_flags, + (struct rtentry **)0); + else + /* + * A new route can be allocated + * the next time output is attempted. + */ + rtfree(rt); + } +} + +/* + * After a routing change, flush old routing + * and allocate a (hopefully) better one. + */ +void +in_rtchange(inp, errno) + register struct inpcb *inp; + int errno; +{ + if (inp->inp_route.ro_rt) { + rtfree(inp->inp_route.ro_rt); + inp->inp_route.ro_rt = 0; + /* + * A new route can be allocated the next time + * output is attempted. + */ + } +} + +struct inpcb * +in_pcblookup(table, faddrp, fport_arg, laddrp, lport_arg, flags) + struct inpcbtable *table; + void *faddrp, *laddrp; + u_int fport_arg, lport_arg; + int flags; +{ + register struct inpcb *inp, *match = 0; + int matchwild = 3, wildcard; + u_int16_t fport = fport_arg, lport = lport_arg; + struct in_addr faddr = *(struct in_addr *)faddrp; + struct in_addr laddr = *(struct in_addr *)laddrp; + + for (inp = table->inpt_queue.cqh_first; + inp != (struct inpcb *)&table->inpt_queue; + inp = inp->inp_queue.cqe_next) { + if (inp->inp_lport != lport) + continue; + wildcard = 0; +#ifdef INET6 + if (flags & INPLOOKUP_IPV6) { + struct in6_addr *laddr6 = (struct in6_addr *)laddrp; + struct in6_addr *faddr6 = (struct in6_addr *)faddrp; + + /* + * Always skip AF_INET sockets when looking + * for AF_INET6 addresses. The only problem + * with this comes if the PF_INET6 addresses + * are v4-mapped addresses. From what I've + * been able to see, none of the callers cause + * such a situation to occur. If such a + * situation DID occur, then it is possible to + * miss a matching PCB. + */ + if (!(inp->inp_flags & INP_IPV6)) + continue; + + if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) { + if (IN6_IS_ADDR_UNSPECIFIED(laddr6)) + wildcard++; + else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr6)) + continue; + } else { + if (!IN6_IS_ADDR_UNSPECIFIED(laddr6)) + wildcard++; + } + + if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { + if (IN6_IS_ADDR_UNSPECIFIED(faddr6)) + wildcard++; + else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, + faddr6) || inp->inp_fport != fport) + continue; + } else { + if (!IN6_IS_ADDR_UNSPECIFIED(faddr6)) + wildcard++; + } + } else +#endif /* INET6 */ + { + if (inp->inp_faddr.s_addr != INADDR_ANY) { + if (faddr.s_addr == INADDR_ANY) + wildcard++; + else if (inp->inp_faddr.s_addr != faddr.s_addr || + inp->inp_fport != fport) + continue; + } else { + if (faddr.s_addr != INADDR_ANY) + wildcard++; + } + if (inp->inp_laddr.s_addr != INADDR_ANY) { + if (laddr.s_addr == INADDR_ANY) + wildcard++; + else if (inp->inp_laddr.s_addr != laddr.s_addr) + continue; + } else { + if (laddr.s_addr != INADDR_ANY) + wildcard++; + } + } + if ((!wildcard || (flags & INPLOOKUP_WILDCARD)) && + wildcard < matchwild) { + match = inp; + if ((matchwild = wildcard) == 0) + break; + } + } + return (match); +} + +struct sockaddr_in * +in_selectsrc(sin, ro, soopts, mopts, errorp) + struct sockaddr_in *sin; + struct route *ro; + int soopts; + struct ip_moptions *mopts; + int *errorp; +{ + struct sockaddr_in *sin2; + struct in_ifaddr *ia; + + ia = (struct in_ifaddr *)0; + /* + * If route is known or can be allocated now, + * our src addr is taken from the i/f, else punt. + */ + if (ro->ro_rt && + (satosin(&ro->ro_dst)->sin_addr.s_addr != + sin->sin_addr.s_addr || + soopts & SO_DONTROUTE)) { + RTFREE(ro->ro_rt); + ro->ro_rt = (struct rtentry *)0; + } + if ((soopts & SO_DONTROUTE) == 0 && /*XXX*/ + (ro->ro_rt == (struct rtentry *)0 || + ro->ro_rt->rt_ifp == (struct ifnet *)0)) { + /* No route yet, so try to acquire one */ + ro->ro_dst.sa_family = AF_INET; + ro->ro_dst.sa_len = sizeof(struct sockaddr_in); + satosin(&ro->ro_dst)->sin_addr = sin->sin_addr; + rtalloc(ro); + + /* + * It is important to bzero out the rest of the + * struct sockaddr_in when mixing v6 & v4! + */ + sin2 = (struct sockaddr_in *)&ro->ro_dst; + bzero(sin2->sin_zero, sizeof(sin2->sin_zero)); + } + /* + * If we found a route, use the address + * corresponding to the outgoing interface + * unless it is the loopback (in case a route + * to our address on another net goes to loopback). + */ + if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) + ia = ifatoia(ro->ro_rt->rt_ifa); + if (ia == 0) { + u_int16_t fport = sin->sin_port; + + sin->sin_port = 0; + ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); + if (ia == 0) + ia = ifatoia(ifa_ifwithnet(sintosa(sin))); + sin->sin_port = fport; + if (ia == 0) + ia = in_ifaddr.tqh_first; + if (ia == 0) { + *errorp = EADDRNOTAVAIL; + return NULL; + } + } + /* + * If the destination address is multicast and an outgoing + * interface has been set as a multicast option, use the + * address of that interface as our source address. + */ + if (IN_MULTICAST(sin->sin_addr.s_addr) && +#if 0 /*def INET6*/ + mopts != NULL && + !(inp->inp_flags & INP_IPV6_MCAST)) +#else + mopts != NULL) +#endif + { + struct ip_moptions *imo; + struct ifnet *ifp; + + imo = mopts; + if (imo->imo_multicast_ifp != NULL) { + ifp = imo->imo_multicast_ifp; + for (ia = in_ifaddr.tqh_first; ia != 0; + ia = ia->ia_list.tqe_next) + if (ia->ia_ifp == ifp) + break; + if (ia == 0) { + *errorp = EADDRNOTAVAIL; + return NULL; + } + } + } + return satosin(&ia->ia_addr); +} + +void +in_pcbrehash(inp) + struct inpcb *inp; +{ + struct inpcbtable *table = inp->inp_table; + int s; + + s = splnet(); + LIST_REMOVE(inp, inp_hash); +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) { + LIST_INSERT_HEAD(IN6PCBHASH(table, &inp->inp_faddr6, + inp->inp_fport, &inp->inp_laddr6, inp->inp_lport), + inp, inp_hash); + } else { +#endif /* INET6 */ + LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr, + inp->inp_fport, &inp->inp_laddr, inp->inp_lport), + inp, inp_hash); +#ifdef INET6 + } +#endif /* INET6 */ + splx(s); +} + +#ifdef DIAGNOSTIC +int in_pcbnotifymiss = 0; +#endif + +struct inpcb * +in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) + struct inpcbtable *table; + struct in_addr faddr, laddr; + u_int fport_arg, lport_arg; +{ + struct inpcbhead *head; + register struct inpcb *inp; + u_int16_t fport = fport_arg, lport = lport_arg; + + head = INPCBHASH(table, &faddr, fport, &laddr, lport); + for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { + if (inp->inp_faddr.s_addr == faddr.s_addr && + inp->inp_fport == fport && + inp->inp_lport == lport && + inp->inp_laddr.s_addr == laddr.s_addr) { + /* + * Move this PCB to the head of hash chain so that + * repeated accesses are quicker. This is analogous to + * the historic single-entry PCB cache. + */ + if (inp != head->lh_first) { + LIST_REMOVE(inp, inp_hash); + LIST_INSERT_HEAD(head, inp, inp_hash); + } + break; + } + } +#ifdef DIAGNOSTIC + if (inp == NULL && in_pcbnotifymiss) { + printf("in_pcbhashlookup: faddr=%08x fport=%d laddr=%08x lport=%d\n", + ntohl(faddr.s_addr), ntohs(fport), + ntohl(laddr.s_addr), ntohs(lport)); + } +#endif + return (inp); +} + +#ifdef INET6 +struct inpcb * +in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg) + struct inpcbtable *table; + struct in6_addr *faddr, *laddr; + u_int fport_arg, lport_arg; +{ + struct inpcbhead *head; + register struct inpcb *inp; + u_int16_t fport = fport_arg, lport = lport_arg; + + head = IN6PCBHASH(table, faddr, fport, laddr, lport); + for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) { + if (!(inp->inp_flags & INP_IPV6)) + continue; + if (IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, faddr) && + inp->inp_fport == fport && inp->inp_lport == lport && + IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr)) { + /* + * Move this PCB to the head of hash chain so that + * repeated accesses are quicker. This is analogous to + * the historic single-entry PCB cache. + */ + if (inp != head->lh_first) { + LIST_REMOVE(inp, inp_hash); + LIST_INSERT_HEAD(head, inp, inp_hash); + } + break; + } + } +#ifdef DIAGNOSTIC + if (inp == NULL && in_pcbnotifymiss) { + printf("in6_pcblookup_connect: faddr="); + printf(" fport=%d laddr=", ntohs(fport)); + printf(" lport=%d\n", ntohs(lport)); + } +#endif + return (inp); +} +#endif /* INET6 */ + + diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/in_proto.c b/ecos/packages/net/tcpip/current/src/sys/netinet/in_proto.c new file mode 100644 index 0000000..36e64b2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/in_proto.c @@ -0,0 +1,384 @@ +//========================================================================== +// +// sys/netinet/in_proto.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: in_proto.c,v 1.17 1999/12/09 03:46:59 angelos Exp $ */ +/* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_proto.c 8.1 (Berkeley) 6/10/93 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#include <sys/domain.h> +#include <sys/mbuf.h> + +#include <net/if.h> +#include <net/radix.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/ip_icmp.h> +#include <netinet/in_pcb.h> + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#include <netinet/ip6.h> +#endif + +#include <netinet/igmp_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_fsm.h> +#include <netinet/tcp_seq.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/tcpip.h> +#include <netinet/tcp_debug.h> +#include <netinet/udp.h> +#include <netinet/udp_var.h> +/* + * TCP/IP protocol family: IP, ICMP, UDP, TCP. + */ + +#if 0 /*KAME IPSEC*/ +#include <netinet6/ah.h> +#ifdef IPSEC_ESP +#include <netinet6/esp.h> +#endif +#include <netinet6/ipcomp.h> +#endif /* IPSEC */ + +#ifndef __ECOS +#include "gif.h" +#endif +#if NGIF > 0 +#include <netinet/in_gif.h> +#endif + +#ifdef NSIP +#include <netns/ns_var.h> +#include <netns/idp_var.h> +#endif /* NSIP */ + +#ifdef IPXIP +#include <netipx/ipx.h> +#include <netipx/ipx_ip.h> +#endif /* NSIP */ + +#ifdef TPIP +#include <netiso/tp_param.h> +#include <netiso/tp_var.h> +#endif /* TPIP */ + +#ifdef EON +#include <netiso/eonvar.h> +#endif /* EON */ + +#ifdef MROUTING +#include <netinet/ip_mroute.h> +#endif /* MROUTING */ + +#ifdef IPFILTER +void iplinit __P((void)); +#define ip_init iplinit +#endif + +#ifdef INET6 +#include <netinet6/ip6_var.h> +#endif /* INET6 */ + +#ifdef IPSEC +#include <netinet/ip_ipsp.h> +#include <netinet/ip_ah.h> +#include <netinet/ip_esp.h> +#include <netinet/ip_ip4.h> +#include <netinet/ip_ether.h> +#endif + +#ifndef CYGPKG_NET_SYSCTL +#define ip_sysctl 0 +#define udp_sysctl 0 +#define tcp_sysctl 0 +#define icmp_sysctl 0 +#endif + +extern struct domain inetdomain; + +struct protosw inetsw[] = { +{ 0, &inetdomain, 0, 0, + 0, ip_output, 0, 0, + 0, + ip_init, 0, ip_slowtimo, ip_drain, ip_sysctl +}, +{ SOCK_DGRAM, &inetdomain, IPPROTO_UDP, PR_ATOMIC|PR_ADDR, + udp_input, 0, udp_ctlinput, ip_ctloutput, + udp_usrreq, + udp_init, 0, 0, 0, udp_sysctl +}, +{ SOCK_STREAM, &inetdomain, IPPROTO_TCP, PR_CONNREQUIRED|PR_WANTRCVD, + tcp_input, 0, tcp_ctlinput, tcp_ctloutput, + tcp_usrreq, + tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain, tcp_sysctl +}, +{ SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR, + rip_input, rip_output, 0, rip_ctloutput, + rip_usrreq, + 0, 0, 0, 0, +}, +{ SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR, + icmp_input, rip_output, 0, rip_ctloutput, + rip_usrreq, + 0, 0, 0, 0, icmp_sysctl +}, +#if NGIF > 0 && !defined(IPSEC) +{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR, + in_gif_input, 0, 0, 0, + 0, + 0, 0, 0, 0, +}, +#ifdef INET6 +{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR, + in_gif_input, 0, 0, 0, + 0, + 0, 0, 0, 0, +}, +#endif /* INET6 */ +#else /* NGIF */ +#if defined(IPSEC) || defined(MROUTING) +{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR, + ip4_input, rip_output, 0, rip_ctloutput, + rip_usrreq, /* XXX */ + 0, 0, 0, 0, ip4_sysctl +}, +#if NGIF > 0 && defined(INET6) +{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR, + in_gif_input, 0, 0, 0, + 0, + 0, 0, 0, 0, +}, +#endif /* NGIF && INET6 */ +#endif /* MROUTING || IPSEC */ +#endif /*NGIF*/ +{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR, + igmp_input, rip_output, 0, rip_ctloutput, + rip_usrreq, + igmp_init, igmp_fasttimo, igmp_slowtimo, 0, +}, +#ifdef TPIP +{ SOCK_SEQPACKET,&inetdomain, IPPROTO_TP, PR_CONNREQUIRED|PR_WANTRCVD, + tpip_input, 0, tpip_ctlinput, tp_ctloutput, + tp_usrreq, + tp_init, 0, tp_slowtimo, tp_drain, +}, +#endif /* TPIP */ +/* EON (ISO CLNL over IP) */ +#ifdef EON +{ SOCK_RAW, &inetdomain, IPPROTO_EON, 0, + eoninput, 0, eonctlinput, 0, + 0, + eonprotoinit, 0, 0, 0, +}, +#endif /* EON */ +#ifdef IPXIP +{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR, + ipxip_input, rip_output, ipxip_ctlinput, 0, + rip_usrreq, + ipxipprotoinit,0, 0, 0, +}, +#endif /* NSIP */ +#ifdef NSIP +{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR, + idpip_input, rip_output, nsip_ctlinput, 0, + rip_usrreq, + 0, 0, 0, 0, +}, +#endif /* NSIP */ +#ifdef IPSEC +{ SOCK_RAW, &inetdomain, IPPROTO_AH, PR_ATOMIC|PR_ADDR, + ah_input, rip_output, 0, rip_ctloutput, + rip_usrreq, + 0, 0, 0, 0, ah_sysctl +}, +{ SOCK_RAW, &inetdomain, IPPROTO_ESP, PR_ATOMIC|PR_ADDR, + esp_input, rip_output, 0, rip_ctloutput, + rip_usrreq, + 0, 0, 0, 0, esp_sysctl +}, +{ SOCK_RAW, &inetdomain, IPPROTO_ETHERIP, PR_ATOMIC|PR_ADDR, + etherip_input, rip_output, 0, rip_ctloutput, + rip_usrreq, + 0, 0, 0, 0, etherip_sysctl +}, +#endif +#if 0 /*NRL IPv6*/ +/* IPv6 in IPv4 tunneled packets... */ +{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR, + ip6_input, rip_output, ipv6_trans_ctlinput, rip_ctloutput, + rip_usrreq, + 0, 0, 0, 0 +}, +#if 0 +/* IPv4 in IPv4 tunneled packets... */ +{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR, + ipv4_input, 0, 0, 0, + 0, + 0, 0, 0, 0 +}, +#endif /* 0 */ +#endif /* defined(INET6) */ +/* raw wildcard */ +{ SOCK_RAW, &inetdomain, 0, PR_ATOMIC|PR_ADDR, + rip_input, rip_output, 0, rip_ctloutput, + rip_usrreq, + rip_init, 0, 0, 0, +}, +}; + +struct domain inetdomain = + { AF_INET, "internet", 0, 0, 0, + inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])], 0, + rn_inithead, 32, sizeof(struct sockaddr_in) }; + +#ifdef notyet /* XXXX */ +#include "imp.h" +#if NIMP > 0 +extern struct domain impdomain; +int rimp_output(), hostslowtimo(); + +struct protosw impsw[] = { +{ SOCK_RAW, &impdomain, 0, PR_ATOMIC|PR_ADDR, + 0, rimp_output, 0, 0, + rip_usrreq, + 0, 0, hostslowtimo, 0, +}, +}; + +struct domain impdomain = + { AF_IMPLINK, "imp", 0, 0, 0, + impsw, &impsw[sizeof (impsw)/sizeof(impsw[0])] }; +#endif + +#include "hy.h" +#if NHY > 0 +/* + * HYPERchannel protocol family: raw interface. + */ +int rhy_output(); +extern struct domain hydomain; + +struct protosw hysw[] = { +{ SOCK_RAW, &hydomain, 0, PR_ATOMIC|PR_ADDR, + 0, rhy_output, 0, 0, + rip_usrreq, + 0, 0, 0, 0, +}, +}; + +struct domain hydomain = + { AF_HYLINK, "hy", 0, 0, 0, hysw, &hysw[sizeof (hysw)/sizeof(hysw[0])] }; +#endif +#endif diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/ip_icmp.c b/ecos/packages/net/tcpip/current/src/sys/netinet/ip_icmp.c new file mode 100644 index 0000000..ff123c2 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/ip_icmp.c @@ -0,0 +1,767 @@ +//========================================================================== +// +// sys/netinet/ip_icmp.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_icmp.c,v 1.19 1999/12/08 06:50:19 itojun Exp $ */ +/* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/kernel.h> +#ifndef __ECOS +#include <sys/proc.h> + +#include <vm/vm.h> +#include <sys/sysctl.h> +#endif + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#include <netinet/ip_var.h> +#include <netinet/icmp_var.h> + +#if 0 /*KAME IPSEC*/ +#include <netinet6/ipsec.h> +#include <netkey/key.h> +#include <netkey/key_debug.h> +#endif + +#include <machine/stdarg.h> + +/* + * ICMP routines: error generation, receive packet processing, and + * routines to turnaround packets back to the originator, and + * host table maintenance routines. + */ + +int icmpmaskrepl = 0; +int icmpbmcastecho = 0; +#ifdef ICMPPRINTFS +int icmpprintfs = 0; +#endif + +#if 0 +static int ip_next_mtu __P((int, int)); +#else +/*static*/ int ip_next_mtu __P((int, int)); +#endif + +extern struct protosw inetsw[]; + +/* + * Generate an error packet of type error + * in response to bad packet ip. + * + * The ip packet inside has ip_off and ip_len in host byte order. + */ +void +icmp_error(n, type, code, dest, destifp) + struct mbuf *n; + int type, code; + n_long dest; + struct ifnet *destifp; +{ + register struct ip *oip = mtod(n, struct ip *), *nip; + register unsigned oiplen = oip->ip_hl << 2; + register struct icmp *icp; + struct mbuf *m, m0; + unsigned icmplen; + +#ifdef ICMPPRINTFS + if (icmpprintfs) + printf("icmp_error(%x, %d, %d)\n", oip, type, code); +#endif + if (type != ICMP_REDIRECT) + icmpstat.icps_error++; + /* + * Don't send error if not the first fragment of message. + * Don't error if the old packet protocol was ICMP + * error message, only known informational types. + */ + if (oip->ip_off &~ (IP_MF|IP_DF)) + goto freeit; + if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && + n->m_len >= oiplen + ICMP_MINLEN && + !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) { + icmpstat.icps_oldicmp++; + goto freeit; + } + /* Don't send error in response to a multicast or broadcast packet */ + if (n->m_flags & (M_BCAST|M_MCAST)) + goto freeit; + /* + * First, formulate icmp message + */ + m = m_gethdr(M_DONTWAIT, MT_HEADER); + if (m == NULL) + goto freeit; + icmplen = oiplen + min(8, oip->ip_len); + m->m_len = icmplen + ICMP_MINLEN; + MH_ALIGN(m, m->m_len); + icp = mtod(m, struct icmp *); + if ((u_int)type > ICMP_MAXTYPE) + panic("icmp_error"); + icmpstat.icps_outhist[type]++; + icp->icmp_type = type; + if (type == ICMP_REDIRECT) + icp->icmp_gwaddr.s_addr = dest; + else { + icp->icmp_void = 0; + /* + * The following assignments assume an overlay with the + * zeroed icmp_void field. + */ + if (type == ICMP_PARAMPROB) { + icp->icmp_pptr = code; + code = 0; + } else if (type == ICMP_UNREACH && + code == ICMP_UNREACH_NEEDFRAG && destifp) + icp->icmp_nextmtu = htons(destifp->if_mtu); + } + + icp->icmp_code = code; + bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen); + nip = &icp->icmp_ip; + nip->ip_off = htons(nip->ip_off); + nip->ip_len = htons(nip->ip_len); + + m0.m_next = NULL; /* correct nip->ip_sum */ + m0.m_data = (char *)nip; + m0.m_len = nip->ip_hl << 2; + nip->ip_sum = 0; + nip->ip_sum = in_cksum(&m0, nip->ip_hl << 2); + + /* + * Now, copy old ip header (without options) + * in front of icmp message. + */ + if (m->m_data - sizeof(struct ip) < m->m_pktdat) + panic("icmp len"); + m->m_data -= sizeof(struct ip); + m->m_len += sizeof(struct ip); + m->m_pkthdr.len = m->m_len; + m->m_pkthdr.rcvif = n->m_pkthdr.rcvif; + nip = mtod(m, struct ip *); + bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip)); + nip->ip_off = htons(nip->ip_off); + nip->ip_len = m->m_len; + nip->ip_hl = sizeof(struct ip) >> 2; + nip->ip_p = IPPROTO_ICMP; + nip->ip_tos = 0; + icmp_reflect(m); + +freeit: + m_freem(n); +} + +static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET }; +static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET }; +static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET }; +struct sockaddr_in icmpmask = { 8, 0 }; + +/* + * Process a received ICMP message. + */ +void +#if __STDC__ +icmp_input(struct mbuf *m, ...) +#else +icmp_input(m, va_alist) + struct mbuf *m; + va_dcl +#endif +{ + int proto; + register struct icmp *icp; + register struct ip *ip = mtod(m, struct ip *); + int icmplen = ip->ip_len; + register int i; + struct in_ifaddr *ia; + void *(*ctlfunc) __P((int, struct sockaddr *, void *)); + int code; + extern u_char ip_protox[]; + int hlen; + va_list ap; + + va_start(ap, m); + hlen = va_arg(ap, int); + proto = va_arg(ap, int); + va_end(ap); + + /* + * Locate icmp structure in mbuf, and check + * that not corrupted and of at least minimum length. + */ +#ifdef ICMPPRINTFS + if (icmpprintfs) { + char buf[4*sizeof "123"]; + + strcpy(buf, inet_ntoa(ip->ip_dst)); + printf("icmp_input from %s to %s, len %d\n", + inet_ntoa(ip->ip_src), buf, icmplen); + } +#endif + if (icmplen < ICMP_MINLEN) { + icmpstat.icps_tooshort++; + goto freeit; + } + i = hlen + min(icmplen, ICMP_ADVLENMIN); + if (m->m_len < i && (m = m_pullup(m, i)) == 0) { + icmpstat.icps_tooshort++; + return; + } + ip = mtod(m, struct ip *); + m->m_len -= hlen; + m->m_data += hlen; + icp = mtod(m, struct icmp *); + if (in_cksum(m, icmplen)) { + icmpstat.icps_checksum++; + goto freeit; + } + m->m_len += hlen; + m->m_data -= hlen; + +#ifdef ICMPPRINTFS + /* + * Message type specific processing. + */ + if (icmpprintfs) + printf("icmp_input, type %d code %d\n", icp->icmp_type, + icp->icmp_code); +#endif +#if 0 /*KAME IPSEC*/ + /* drop it if it does not match the policy */ + if (ipsec4_in_reject(m, NULL)) { + ipsecstat.in_polvio++; + goto freeit; + } +#endif + if (icp->icmp_type > ICMP_MAXTYPE) + goto raw; + icmpstat.icps_inhist[icp->icmp_type]++; + code = icp->icmp_code; + switch (icp->icmp_type) { + + case ICMP_UNREACH: + switch (code) { + case ICMP_UNREACH_NET: + case ICMP_UNREACH_HOST: + case ICMP_UNREACH_PROTOCOL: + case ICMP_UNREACH_PORT: + case ICMP_UNREACH_SRCFAIL: + code += PRC_UNREACH_NET; + break; + + case ICMP_UNREACH_NEEDFRAG: +#if 0 /*NRL INET6*/ + if (icp->icmp_nextmtu) { + extern int ipv6_trans_mtu + __P((struct mbuf **, int, int)); + struct mbuf *m0 = m; + + /* + * Do cool v4-related path MTU, for now, + * only v6-in-v4 can handle it. + */ + if (icmplen >= ICMP_V6ADVLENMIN && + icmplen >= ICMP_V6ADVLEN(icp) && + icp->icmp_ip.ip_p == IPPROTO_IPV6) { + /* + * ipv6_trans_mtu returns 1 if + * the mbuf is still intact. + */ + if (ipv6_trans_mtu(&m0,icp->icmp_nextmtu, + hlen + ICMP_V6ADVLEN(icp))) { + m = m0; + goto raw; + } else + return; + } + } +#endif /* INET6 */ + code = PRC_MSGSIZE; + break; + + case ICMP_UNREACH_NET_UNKNOWN: + case ICMP_UNREACH_NET_PROHIB: + case ICMP_UNREACH_TOSNET: + code = PRC_UNREACH_NET; + break; + + case ICMP_UNREACH_HOST_UNKNOWN: + case ICMP_UNREACH_ISOLATED: + case ICMP_UNREACH_HOST_PROHIB: + case ICMP_UNREACH_TOSHOST: + case ICMP_UNREACH_FILTER_PROHIB: + case ICMP_UNREACH_HOST_PRECEDENCE: + case ICMP_UNREACH_PRECEDENCE_CUTOFF: + code = PRC_UNREACH_HOST; + break; + + default: + goto badcode; + } + goto deliver; + + case ICMP_TIMXCEED: + if (code > 1) + goto badcode; + code += PRC_TIMXCEED_INTRANS; + goto deliver; + + case ICMP_PARAMPROB: + if (code > 1) + goto badcode; + code = PRC_PARAMPROB; + goto deliver; + + case ICMP_SOURCEQUENCH: + if (code) + goto badcode; + code = PRC_QUENCH; + deliver: + /* + * Problem with datagram; advise higher level routines. + */ + if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || + icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { + icmpstat.icps_badlen++; + goto freeit; + } + if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr)) + goto badcode; + NTOHS(icp->icmp_ip.ip_len); +#ifdef INET6 + /* Get more contiguous data for a v6 in v4 ICMP message. */ + if (icp->icmp_ip.ip_p == IPPROTO_IPV6) { + if (icmplen < ICMP_V6ADVLENMIN || + icmplen < ICMP_V6ADVLEN(icp)) { + icmpstat.icps_badlen++; + goto freeit; + } else { + if (!(m = m_pullup(m, (ip->ip_hl << 2) + + ICMP_V6ADVLEN(icp)))) { + icmpstat.icps_tooshort++; + return; + } + ip = mtod(m, struct ip *); + icp = (struct icmp *)(m->m_data + (ip->ip_hl << 2)); + } + } +#endif /* INET6 */ +#ifdef ICMPPRINTFS + if (icmpprintfs) + printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); +#endif + icmpsrc.sin_addr = icp->icmp_ip.ip_dst; + /* + * XXX if the packet contains [IPv4 AH TCP], we can't make a + * notification to TCP layer. + */ + ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; + if (ctlfunc) + (*ctlfunc)(code, sintosa(&icmpsrc), &icp->icmp_ip); + break; + + badcode: + icmpstat.icps_badcode++; + break; + + case ICMP_ECHO: + if (!icmpbmcastecho && + (m->m_flags & (M_MCAST | M_BCAST)) != 0) { + icmpstat.icps_bmcastecho++; + break; + } + icp->icmp_type = ICMP_ECHOREPLY; + goto reflect; + + case ICMP_TSTAMP: + if (!icmpbmcastecho && + (m->m_flags & (M_MCAST | M_BCAST)) != 0) { + icmpstat.icps_bmcastecho++; + break; + } + if (icmplen < ICMP_TSLEN) { + icmpstat.icps_badlen++; + break; + } + icp->icmp_type = ICMP_TSTAMPREPLY; + icp->icmp_rtime = iptime(); + icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ + goto reflect; + + case ICMP_MASKREQ: + if (icmpmaskrepl == 0) + break; + /* + * We are not able to respond with all ones broadcast + * unless we receive it over a point-to-point interface. + */ + if (icmplen < ICMP_MASKLEN) { + icmpstat.icps_badlen++; + break; + } + if (ip->ip_dst.s_addr == INADDR_BROADCAST || + ip->ip_dst.s_addr == INADDR_ANY) + icmpdst.sin_addr = ip->ip_src; + else + icmpdst.sin_addr = ip->ip_dst; + ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst), + m->m_pkthdr.rcvif)); + if (ia == 0) + break; + icp->icmp_type = ICMP_MASKREPLY; + icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr; + if (ip->ip_src.s_addr == 0) { + if (ia->ia_ifp->if_flags & IFF_BROADCAST) + ip->ip_src = ia->ia_broadaddr.sin_addr; + else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) + ip->ip_src = ia->ia_dstaddr.sin_addr; + } +reflect: + ip->ip_len += hlen; /* since ip_input deducts this */ + icmpstat.icps_reflect++; + icmpstat.icps_outhist[icp->icmp_type]++; + icmp_reflect(m); + return; + + case ICMP_REDIRECT: + if (code > 3) + goto badcode; + if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || + icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { + icmpstat.icps_badlen++; + break; + } + /* + * Short circuit routing redirects to force + * immediate change in the kernel's routing + * tables. The message is also handed to anyone + * listening on a raw socket (e.g. the routing + * daemon for use in updating its tables). + */ + icmpgw.sin_addr = ip->ip_src; + icmpdst.sin_addr = icp->icmp_gwaddr; +#ifdef ICMPPRINTFS + if (icmpprintfs) { + char buf[4 * sizeof "123"]; + strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst)); + + printf("redirect dst %s to %s\n", + buf, inet_ntoa(icp->icmp_gwaddr)); + } +#endif + icmpsrc.sin_addr = icp->icmp_ip.ip_dst; + rtredirect(sintosa(&icmpsrc), sintosa(&icmpdst), + (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, + sintosa(&icmpgw), (struct rtentry **)0); + pfctlinput(PRC_REDIRECT_HOST, sintosa(&icmpsrc)); +#if 0 /*KAME IPSEC*/ + key_sa_routechange((struct sockaddr *)&icmpsrc); +#endif + break; + + /* + * No kernel processing for the following; + * just fall through to send to raw listener. + */ + case ICMP_ECHOREPLY: + case ICMP_ROUTERADVERT: + case ICMP_ROUTERSOLICIT: + case ICMP_TSTAMPREPLY: + case ICMP_IREQREPLY: + case ICMP_MASKREPLY: + default: + break; + } + +raw: + rip_input(m, hlen, proto); + return; + +freeit: + m_freem(m); +} + +/* + * Reflect the ip packet back to the source + */ +void +icmp_reflect(m) + struct mbuf *m; +{ + register struct ip *ip = mtod(m, struct ip *); + register struct in_ifaddr *ia; + struct in_addr t; + struct mbuf *opts = 0; + int optlen = (ip->ip_hl << 2) - sizeof(struct ip); + + if (!in_canforward(ip->ip_src) && + ((ip->ip_src.s_addr & IN_CLASSA_NET) != + htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) { + m_freem(m); /* Bad return address */ + goto done; /* ip_output() will check for broadcast */ + } + t = ip->ip_dst; + ip->ip_dst = ip->ip_src; + /* + * If the incoming packet was addressed directly to us, + * use dst as the src for the reply. Otherwise (broadcast + * or anonymous), use the address which corresponds + * to the incoming interface. + */ + for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) { + if (t.s_addr == ia->ia_addr.sin_addr.s_addr) + break; + if ((ia->ia_ifp->if_flags & IFF_BROADCAST) && + t.s_addr == ia->ia_broadaddr.sin_addr.s_addr) + break; + } + icmpdst.sin_addr = t; + if (ia == (struct in_ifaddr *)0) + ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst), + m->m_pkthdr.rcvif)); + /* + * The following happens if the packet was not addressed to us, + * and was received on an interface with no IP address. + */ + if (ia == (struct in_ifaddr *)0) + ia = in_ifaddr.tqh_first; + t = ia->ia_addr.sin_addr; + ip->ip_src = t; + ip->ip_ttl = MAXTTL; + + if (optlen > 0) { + register u_char *cp; + int opt, cnt; + u_int len; + + /* + * Retrieve any source routing from the incoming packet; + * add on any record-route or timestamp options. + */ + cp = (u_char *) (ip + 1); + if ((opts = ip_srcroute()) == 0 && + (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { + opts->m_len = sizeof(struct in_addr); + mtod(opts, struct in_addr *)->s_addr = 0; + } + if (opts) { +#ifdef ICMPPRINTFS + if (icmpprintfs) + printf("icmp_reflect optlen %d rt %d => ", + optlen, opts->m_len); +#endif + for (cnt = optlen; cnt > 0; cnt -= len, cp += len) { + opt = cp[IPOPT_OPTVAL]; + if (opt == IPOPT_EOL) + break; + if (opt == IPOPT_NOP) + len = 1; + else { + len = cp[IPOPT_OLEN]; + if (len <= 0 || len > cnt) + break; + } + /* + * Should check for overflow, but it "can't happen" + */ + if (opt == IPOPT_RR || opt == IPOPT_TS || + opt == IPOPT_SECURITY) { + bcopy((caddr_t)cp, + mtod(opts, caddr_t) + opts->m_len, len); + opts->m_len += len; + } + } + /* Terminate & pad, if necessary */ + if ((cnt = opts->m_len % 4) != 0) { + for (; cnt < 4; cnt++) { + *(mtod(opts, caddr_t) + opts->m_len) = + IPOPT_EOL; + opts->m_len++; + } + } +#ifdef ICMPPRINTFS + if (icmpprintfs) + printf("%d\n", opts->m_len); +#endif + } + /* + * Now strip out original options by copying rest of first + * mbuf's data back, and adjust the IP length. + */ + ip->ip_len -= optlen; + ip->ip_hl = sizeof(struct ip) >> 2; + m->m_len -= optlen; + if (m->m_flags & M_PKTHDR) + m->m_pkthdr.len -= optlen; + optlen += sizeof(struct ip); + bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1), + (unsigned)(m->m_len - sizeof(struct ip))); + } + m->m_flags &= ~(M_BCAST|M_MCAST); + icmp_send(m, opts); +done: + if (opts) + (void)m_free(opts); +} + +/* + * Send an icmp packet back to the ip level, + * after supplying a checksum. + */ +void +icmp_send(m, opts) + register struct mbuf *m; + struct mbuf *opts; +{ + register struct ip *ip = mtod(m, struct ip *); + register int hlen; + register struct icmp *icp; + + hlen = ip->ip_hl << 2; + m->m_data += hlen; + m->m_len -= hlen; + icp = mtod(m, struct icmp *); + icp->icmp_cksum = 0; + icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); + m->m_data -= hlen; + m->m_len += hlen; +#ifdef ICMPPRINTFS + if (icmpprintfs) { + char buf[4 * sizeof "123"]; + + strcpy(buf, inet_ntoa(ip->ip_dst)); + printf("icmp_send dst %s src %s\n", + buf, inet_ntoa(ip->ip_src)); + } +#endif +#if 0 /*KAME IPSEC*/ + m->m_pkthdr.rcvif = NULL; +#endif /*IPSEC*/ + (void) ip_output(m, opts, NULL, 0, NULL, NULL); +} + +n_time +iptime() +{ + struct timeval atv; + u_long t; + + microtime(&atv); + t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000; + return (htonl(t)); +} + +#ifdef CYGPKG_NET_SYSCTL +int +icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; +{ + + /* All sysctl names at this level are terminal. */ + if (namelen != 1) + return (ENOTDIR); + + switch (name[0]) { + case ICMPCTL_MASKREPL: + return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpmaskrepl)); + case ICMPCTL_BMCASTECHO: + return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpbmcastecho)); + default: + return (ENOPROTOOPT); + } + /* NOTREACHED */ +} +#endif // CYGPKG_NET_SYSCTL diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/ip_id.c b/ecos/packages/net/tcpip/current/src/sys/netinet/ip_id.c new file mode 100644 index 0000000..177bb58 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/ip_id.c @@ -0,0 +1,232 @@ +//========================================================================== +// +// sys/netinet/ip_id.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_id.c,v 1.2 1999/08/26 13:37:01 provos Exp $ */ + +/* + * Copyright 1998 Niels Provos <provos@citi.umich.edu> + * All rights reserved. + * + * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using + * such a mathematical system to generate more random (yet non-repeating) + * ids to solve the resolver/named problem. But Niels designed the + * actual system based on the constraints. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * seed = random 15bit + * n = prime, g0 = generator to n, + * j = random so that gcd(j,n-1) == 1 + * g = g0^j mod n will be a generator again. + * + * X[0] = random seed. + * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator + * with a = 7^(even random) mod m, + * b = random with gcd(b,m) == 1 + * m = 31104 and a maximal period of m-1. + * + * The transaction id is determined by: + * id[n] = seed xor (g^X[n] mod n) + * + * Effectivly the id is restricted to the lower 15 bits, thus + * yielding two different cycles by toggling the msb on and off. + * This avoids reuse issues caused by reseeding. + */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/kernel.h> + +#ifndef __ECOS +#include <dev/rndvar.h> +#endif + +#define RU_OUT 180 /* Time after wich will be reseeded */ +#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */ +#define RU_GEN 2 /* Starting generator */ +#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */ +#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */ +#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */ + +#define PFAC_N 3 +const static u_int16_t pfacts[PFAC_N] = { + 2, + 3, + 2729 +}; + +static u_int16_t ru_x; +static u_int16_t ru_seed, ru_seed2; +static u_int16_t ru_a, ru_b; +static u_int16_t ru_g; +static u_int16_t ru_counter = 0; +static u_int16_t ru_msb = 0; +static long ru_reseed; +static u_int32_t tmp; /* Storage for unused random */ + +static u_int16_t pmod __P((u_int16_t, u_int16_t, u_int16_t)); +static void ip_initid __P((void)); +u_int16_t ip_randomid __P((void)); + +/* + * Do a fast modular exponation, returned value will be in the range + * of 0 - (mod-1) + */ + +#ifdef __STDC__ +static u_int16_t +pmod(u_int16_t gen, u_int16_t exp, u_int16_t mod) +#else +static u_int16_t +pmod(gen, exp, mod) + u_int16_t gen, exp, mod; +#endif +{ + u_int16_t s, t, u; + + s = 1; + t = gen; + u = exp; + + while (u) { + if (u & 1) + s = (s*t) % mod; + u >>= 1; + t = (t*t) % mod; + } + return (s); +} + +/* + * Initalizes the seed and chooses a suitable generator. Also toggles + * the msb flag. The msb flag is used to generate two distinct + * cycles of random numbers and thus avoiding reuse of ids. + * + * This function is called from id_randomid() when needed, an + * application does not have to worry about it. + */ +static void +ip_initid(void) +{ + u_int16_t j, i; + int noprime = 1; + + get_random_bytes((void *) &tmp, sizeof(tmp)); + ru_x = (tmp & 0xFFFF) % RU_M; + + /* 15 bits of random seed */ + ru_seed = (tmp >> 16) & 0x7FFF; + get_random_bytes((void *) &tmp, sizeof(tmp)); + ru_seed2 = tmp & 0x7FFF; + + get_random_bytes((void *) &tmp, sizeof(tmp)); + + /* Determine the LCG we use */ + ru_b = (tmp & 0xfffe) | 1; + ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M); + while (ru_b % 3 == 0) + ru_b += 2; + + get_random_bytes((void *) &tmp, sizeof(tmp)); + j = tmp % RU_N; + tmp = tmp >> 16; + + /* + * Do a fast gcd(j,RU_N-1), so we can find a j with + * gcd(j, RU_N-1) == 1, giving a new generator for + * RU_GEN^j mod RU_N + */ + + while (noprime) { + for (i=0; i<PFAC_N; i++) + if (j%pfacts[i] == 0) + break; + + if (i>=PFAC_N) + noprime = 0; + else + j = (j+1) % RU_N; + } + + ru_g = pmod(RU_GEN,j,RU_N); + ru_counter = 0; + + ru_reseed = time.tv_sec + RU_OUT; + ru_msb = ru_msb == 0x8000 ? 0 : 0x8000; +} + +u_int16_t +ip_randomid(void) +{ + int i, n; + + if (ru_counter >= RU_MAX || time.tv_sec > ru_reseed) + ip_initid(); + + if (!tmp) + get_random_bytes((void *) &tmp, sizeof(tmp)); + + /* Skip a random number of ids */ + n = tmp & 0x3; tmp = tmp >> 2; + if (ru_counter + n >= RU_MAX) + ip_initid(); + + for (i = 0; i <= n; i++) + /* Linear Congruential Generator */ + ru_x = (ru_a*ru_x + ru_b) % RU_M; + + ru_counter += i; + + return (ru_seed ^ pmod(ru_g,ru_seed2 ^ ru_x,RU_N)) | ru_msb; +} diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/ip_input.c b/ecos/packages/net/tcpip/current/src/sys/netinet/ip_input.c new file mode 100644 index 0000000..b3850a9 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/ip_input.c @@ -0,0 +1,1562 @@ +//========================================================================== +// +// sys/netinet/ip_input.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_input.c,v 1.44 1999/12/08 06:50:20 itojun Exp $ */ +/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 + */ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/domain.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/errno.h> +#include <sys/time.h> +#include <sys/kernel.h> +#ifndef __ECOS +#include <sys/syslog.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <sys/sysctl.h> +#endif + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/if_ether.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/in_var.h> +#include <netinet/ip_var.h> +#include <netinet/ip_icmp.h> +#include <netinet/ip_ipsp.h> + +#ifdef __ECOS +#include <stdio.h> // for 'sprintf()' +#endif + +#ifndef IPFORWARDING +#ifdef GATEWAY +#define IPFORWARDING 1 /* forward IP packets not for us */ +#else /* GATEWAY */ +#define IPFORWARDING 0 /* don't forward IP packets not for us */ +#endif /* GATEWAY */ +#endif /* IPFORWARDING */ +#ifndef IPSENDREDIRECTS +#define IPSENDREDIRECTS 1 +#endif + +int encdebug = 0; + +/* + * Note: DIRECTED_BROADCAST is handled this way so that previous + * configuration using this option will Just Work. + */ +#ifndef IPDIRECTEDBCAST +#ifdef DIRECTED_BROADCAST +#define IPDIRECTEDBCAST 1 +#else +#define IPDIRECTEDBCAST 0 +#endif /* DIRECTED_BROADCAST */ +#endif /* IPDIRECTEDBCAST */ +int ipforwarding = IPFORWARDING; +int ipsendredirects = IPSENDREDIRECTS; +int ip_dosourceroute = 0; /* no src-routing unless sysctl'd to enable */ +int ip_defttl = IPDEFTTL; +int ip_directedbcast = IPDIRECTEDBCAST; +#ifdef DIAGNOSTIC +int ipprintfs = 0; +#endif + +int ipsec_auth_default_level = IPSEC_AUTH_LEVEL_DEFAULT; +int ipsec_esp_trans_default_level = IPSEC_ESP_TRANS_LEVEL_DEFAULT; +int ipsec_esp_network_default_level = IPSEC_ESP_NETWORK_LEVEL_DEFAULT; + +/* Keep track of memory used for reassembly */ +int ip_maxqueue = 300; +int ip_frags = 0; + +/* from in_pcb.c */ +extern int ipport_firstauto; +extern int ipport_lastauto; +extern int ipport_hifirstauto; +extern int ipport_hilastauto; +extern struct baddynamicports baddynamicports; + +extern struct domain inetdomain; +extern struct protosw inetsw[]; +u_char ip_protox[IPPROTO_MAX]; +int ipqmaxlen = IFQ_MAXLEN; +struct in_ifaddrhead in_ifaddr; +struct ifqueue ipintrq; +struct ipstat ipstat; +#if defined(IPFILTER) || defined(IPFILTER_LKM) +int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, + struct mbuf **)); +#endif + +int ipq_locked; +static __inline int ipq_lock_try __P((void)); +static __inline void ipq_unlock __P((void)); + +static __inline int +ipq_lock_try() +{ + int s; + + s = splimp(); + if (ipq_locked) { + splx(s); + return (0); + } + ipq_locked = 1; + splx(s); + return (1); +} + +#define ipq_lock() ipq_lock_try() + +static __inline void +ipq_unlock() +{ + int s; + + s = splimp(); + ipq_locked = 0; + splx(s); +} + +#if 0 // Now in common layer + +static char *ui8tod( cyg_uint8 n, char *p ) +{ + if( n > 99 ) *p++ = (n/100) + '0'; + if( n > 9 ) *p++ = ((n/10)%10) + '0'; + *p++ = (n%10) + '0'; + return p; +} + +char * +inet_ntoa(ina) + struct in_addr ina; +{ + static char buf[4*sizeof "123"]; + char *p = buf; + unsigned char *ucp = (unsigned char *)&ina; + +// sprintf(buf, "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff, +// ucp[2] & 0xff, ucp[3] & 0xff); + + p = ui8tod( ucp[0] & 0xFF, p); + *p++ = '.'; + p = ui8tod( ucp[1] & 0xFF, p); + *p++ = '.'; + p = ui8tod( ucp[2] & 0xFF, p); + *p++ = '.'; + p = ui8tod( ucp[3] & 0xFF, p); + *p++ = '\0'; + + return (buf); +} +#endif + +/* + * We need to save the IP options in case a protocol wants to respond + * to an incoming packet over the same route if the packet got here + * using IP source routing. This allows connection establishment and + * maintenance when the remote end is on a network that is not known + * to us. + */ +int ip_nhops = 0; +static struct ip_srcrt { + struct in_addr dst; /* final destination */ + char nop; /* one NOP to align */ + char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */ + struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; +} ip_srcrt; + +static void save_rte __P((u_char *, struct in_addr)); +static int ip_weadvertise(u_int32_t); + +/* + * IP initialization: fill in IP protocol switch table. + * All protocols not implemented in kernel go to raw IP protocol handler. + */ +void +ip_init() +{ + register struct protosw *pr; + register int i; + const u_int16_t defbaddynamicports_tcp[] = DEFBADDYNAMICPORTS_TCP; + const u_int16_t defbaddynamicports_udp[] = DEFBADDYNAMICPORTS_UDP; + + pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); + if (pr == 0) + panic("ip_init"); + for (i = 0; i < IPPROTO_MAX; i++) + ip_protox[i] = pr - inetsw; + for (pr = inetdomain.dom_protosw; + pr < inetdomain.dom_protoswNPROTOSW; pr++) + if (pr->pr_domain->dom_family == PF_INET && + pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) + ip_protox[pr->pr_protocol] = pr - inetsw; + LIST_INIT(&ipq); + ipintrq.ifq_maxlen = ipqmaxlen; + TAILQ_INIT(&in_ifaddr); + + /* Fill in list of ports not to allocate dynamically. */ + bzero((void *)&baddynamicports, sizeof(baddynamicports)); + for (i = 0; defbaddynamicports_tcp[i] != 0; i++) + DP_SET(baddynamicports.tcp, defbaddynamicports_tcp[i]); + for (i = 0; defbaddynamicports_udp[i] != 0; i++) + DP_SET(baddynamicports.udp, defbaddynamicports_tcp[i]); +} + +struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; +struct route ipforward_rt; + +void +ipintr() +{ + register struct mbuf *m; + int s; + + if (needqueuedrain) + m_reclaim(); + + while (1) { + /* + * Get next datagram off input queue and get IP header + * in first mbuf. + */ + s = splimp(); + IF_DEQUEUE(&ipintrq, m); + splx(s); + if (m == 0) + return; +#ifdef DIAGNOSTIC + if ((m->m_flags & M_PKTHDR) == 0) + panic("ipintr no HDR"); +#endif + ipv4_input(m, 0, NULL, 0); + } +} + +/* + * Ip input routine. Checksum and byte swap header. If fragmented + * try to reassemble. Process options. Pass to next level. + */ +void +ipv4_input(struct mbuf *m, ...) +{ + register struct ip *ip; + register struct ipq *fp; + struct in_ifaddr *ia; + struct ipqent *ipqe; + int hlen, mff; + va_list ap; + int extra; + + va_start(ap, m); + extra = va_arg(ap, int); + va_end(ap); + + if (extra) { + struct mbuf *newpacket; + + if (!(newpacket = m_split(m, extra, M_NOWAIT))) { + m_freem(m); + return; + } + + newpacket->m_flags |= m->m_flags; + m_freem(m); + m = newpacket; + extra = 0; + } + + /* + * If no IP addresses have been set yet but the interfaces + * are receiving, can't do anything with incoming packets yet. + */ + if (in_ifaddr.tqh_first == 0) + goto bad; + ipstat.ips_total++; + if (m->m_len < sizeof (struct ip) && + (m = m_pullup(m, sizeof (struct ip))) == 0) { + ipstat.ips_toosmall++; + return; + } + ip = mtod(m, struct ip *); + if (ip->ip_v != IPVERSION) { + ipstat.ips_badvers++; + goto bad; + } + hlen = ip->ip_hl << 2; + if (hlen < sizeof(struct ip)) { /* minimum header length */ + ipstat.ips_badhlen++; + goto bad; + } + if (hlen > m->m_len) { + if ((m = m_pullup(m, hlen)) == 0) { + ipstat.ips_badhlen++; + return; + } + ip = mtod(m, struct ip *); + } + if ((ip->ip_sum = in_cksum(m, hlen)) != 0) { + ipstat.ips_badsum++; + goto bad; + } + + /* + * Convert fields to host representation. + */ + NTOHS(ip->ip_len); + if (ip->ip_len < hlen) { + ipstat.ips_badlen++; + goto bad; + } + NTOHS(ip->ip_id); + NTOHS(ip->ip_off); + + /* + * Check that the amount of data in the buffers + * is as at least much as the IP header would have us expect. + * Trim mbufs if longer than we expect. + * Drop packet if shorter than we expect. + */ + if (m->m_pkthdr.len < ip->ip_len) { + ipstat.ips_tooshort++; + goto bad; + } + if (m->m_pkthdr.len > ip->ip_len) { + if (m->m_len == m->m_pkthdr.len) { + m->m_len = ip->ip_len; + m->m_pkthdr.len = ip->ip_len; + } else + m_adj(m, ip->ip_len - m->m_pkthdr.len); + } + +#if defined(IPFILTER) || defined(IPFILTER_LKM) + /* + * Check if we want to allow this packet to be processed. + * Consider it to be bad if not. + */ + { + struct mbuf *m0 = m; + if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) + return; + ip = mtod(m = m0, struct ip *); + } +#endif + + /* + * Process options and, if not destined for us, + * ship it on. ip_dooptions returns 1 when an + * error was detected (causing an icmp message + * to be sent and the original packet to be freed). + */ + ip_nhops = 0; /* for source routed packets */ + if (hlen > sizeof (struct ip) && ip_dooptions(m)) + return; + + /* + * Check our list of addresses, to see if the packet is for us. + */ + if ((ia = in_iawithaddr(ip->ip_dst, m)) != NULL && + (ia->ia_ifp->if_flags & IFF_UP)) + goto ours; + + if (IN_MULTICAST(ip->ip_dst.s_addr)) { + struct in_multi *inm; +#ifdef MROUTING + extern struct socket *ip_mrouter; + + if (m->m_flags & M_EXT) { + if ((m = m_pullup(m, hlen)) == 0) { + ipstat.ips_toosmall++; + return; + } + ip = mtod(m, struct ip *); + } + + if (ip_mrouter) { + /* + * If we are acting as a multicast router, all + * incoming multicast packets are passed to the + * kernel-level multicast forwarding function. + * The packet is returned (relatively) intact; if + * ip_mforward() returns a non-zero value, the packet + * must be discarded, else it may be accepted below. + * + * (The IP ident field is put in the same byte order + * as expected when ip_mforward() is called from + * ip_output().) + */ + ip->ip_id = htons(ip->ip_id); + if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) { + ipstat.ips_cantforward++; + m_freem(m); + return; + } + ip->ip_id = ntohs(ip->ip_id); + + /* + * The process-level routing demon needs to receive + * all multicast IGMP packets, whether or not this + * host belongs to their destination groups. + */ + if (ip->ip_p == IPPROTO_IGMP) + goto ours; + ipstat.ips_forward++; + } +#endif + /* + * See if we belong to the destination multicast group on the + * arrival interface. + */ + IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); + if (inm == NULL) { + ipstat.ips_cantforward++; + m_freem(m); + return; + } + goto ours; + } + if (ip->ip_dst.s_addr == INADDR_BROADCAST || + ip->ip_dst.s_addr == INADDR_ANY) + goto ours; + + /* + * Not for us; forward if possible and desirable. + */ + if (ipforwarding == 0) { + ipstat.ips_cantforward++; + m_freem(m); + } else + ip_forward(m, 0); + return; + +ours: + /* + * If offset or IP_MF are set, must reassemble. + * Otherwise, nothing need be done. + * (We could look in the reassembly queue to see + * if the packet was previously fragmented, + * but it's not worth the time; just let them time out.) + */ + if (ip->ip_off &~ (IP_DF | IP_RF)) { + if (m->m_flags & M_EXT) { /* XXX */ + if ((m = m_pullup(m, hlen)) == 0) { + ipstat.ips_toosmall++; + return; + } + ip = mtod(m, struct ip *); + } + + /* + * Look for queue of fragments + * of this datagram. + */ + ipq_lock(); + for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next) + if (ip->ip_id == fp->ipq_id && + ip->ip_src.s_addr == fp->ipq_src.s_addr && + ip->ip_dst.s_addr == fp->ipq_dst.s_addr && + ip->ip_p == fp->ipq_p) + goto found; + fp = 0; +found: + + /* + * Adjust ip_len to not reflect header, + * set ipqe_mff if more fragments are expected, + * convert offset of this to bytes. + */ + ip->ip_len -= hlen; + mff = (ip->ip_off & IP_MF) != 0; + if (mff) { + /* + * Make sure that fragments have a data length + * that's a non-zero multiple of 8 bytes. + */ + if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) { + ipstat.ips_badfrags++; + ipq_unlock(); + goto bad; + } + } + ip->ip_off <<= 3; + + /* + * If datagram marked as having more fragments + * or if this is not the first fragment, + * attempt reassembly; if it succeeds, proceed. + */ + if (mff || ip->ip_off) { + ipstat.ips_fragments++; + if (ip_frags + 1 > ip_maxqueue) { + ip_flush(); + ipstat.ips_rcvmemdrop++; + ipq_unlock(); + goto bad; + } + + MALLOC(ipqe, struct ipqent *, sizeof (struct ipqent), + M_IPQ, M_NOWAIT); + if (ipqe == NULL) { + ipstat.ips_rcvmemdrop++; + ipq_unlock(); + goto bad; + } + ip_frags++; + ipqe->ipqe_mff = mff; + ipqe->ipqe_ip = ip; + ip = ip_reass(ipqe, fp); + if (ip == 0) { + ipq_unlock(); + return; + } + ipstat.ips_reassembled++; + m = dtom(ip); + hlen = ip->ip_hl << 2; + } else + if (fp) + ip_freef(fp); + ipq_unlock(); + } else + ip->ip_len -= hlen; + + /* + * Switch out to protocol's input routine. + */ + ipstat.ips_delivered++; + (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen, NULL, 0); + return; +bad: + m_freem(m); +} + +struct in_ifaddr * +in_iawithaddr(ina, m) + struct in_addr ina; + register struct mbuf *m; +{ + register struct in_ifaddr *ia; + + for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) { + if ((ina.s_addr == ia->ia_addr.sin_addr.s_addr) || + ((ia->ia_ifp->if_flags & (IFF_LOOPBACK|IFF_LINK1)) == + (IFF_LOOPBACK|IFF_LINK1) && + ia->ia_subnet == (ina.s_addr & ia->ia_subnetmask))) + return ia; + if (m && ((ip_directedbcast == 0) || (ip_directedbcast && + ia->ia_ifp == m->m_pkthdr.rcvif)) && + (ia->ia_ifp->if_flags & IFF_BROADCAST)) { + if (ina.s_addr == ia->ia_broadaddr.sin_addr.s_addr || + ina.s_addr == ia->ia_netbroadcast.s_addr || + /* + * Look for all-0's host part (old broadcast addr), + * either for subnet or net. + */ + ina.s_addr == ia->ia_subnet || + ina.s_addr == ia->ia_net) { + /* Make sure M_BCAST is set */ + m->m_flags |= M_BCAST; + return ia; + } + } + } + + return NULL; +} + +/* + * Take incoming datagram fragment and try to + * reassemble it into whole datagram. If a chain for + * reassembly of this datagram already exists, then it + * is given as fp; otherwise have to make a chain. + */ +struct ip * +ip_reass(ipqe, fp) + register struct ipqent *ipqe; + register struct ipq *fp; +{ + register struct mbuf *m = dtom(ipqe->ipqe_ip); + register struct ipqent *nq, *p, *q; + struct ip *ip; + struct mbuf *t; + int hlen = ipqe->ipqe_ip->ip_hl << 2; + int i, next; + + /* + * Presence of header sizes in mbufs + * would confuse code below. + */ + m->m_data += hlen; + m->m_len -= hlen; + + /* + * If first fragment to arrive, create a reassembly queue. + */ + if (fp == 0) { + if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL) + goto dropfrag; + fp = mtod(t, struct ipq *); + LIST_INSERT_HEAD(&ipq, fp, ipq_q); + fp->ipq_ttl = IPFRAGTTL; + fp->ipq_p = ipqe->ipqe_ip->ip_p; + fp->ipq_id = ipqe->ipqe_ip->ip_id; + LIST_INIT(&fp->ipq_fragq); + fp->ipq_src = ipqe->ipqe_ip->ip_src; + fp->ipq_dst = ipqe->ipqe_ip->ip_dst; + p = NULL; + goto insert; + } + + /* + * Find a segment which begins after this one does. + */ + for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL; + p = q, q = q->ipqe_q.le_next) + if (q->ipqe_ip->ip_off > ipqe->ipqe_ip->ip_off) + break; + + /* + * If there is a preceding segment, it may provide some of + * our data already. If so, drop the data from the incoming + * segment. If it provides all of our data, drop us. + */ + if (p != NULL) { + i = p->ipqe_ip->ip_off + p->ipqe_ip->ip_len - + ipqe->ipqe_ip->ip_off; + if (i > 0) { + if (i >= ipqe->ipqe_ip->ip_len) + goto dropfrag; + m_adj(dtom(ipqe->ipqe_ip), i); + ipqe->ipqe_ip->ip_off += i; + ipqe->ipqe_ip->ip_len -= i; + } + } + + /* + * While we overlap succeeding segments trim them or, + * if they are completely covered, dequeue them. + */ + for (; q != NULL && ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len > + q->ipqe_ip->ip_off; q = nq) { + i = (ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len) - + q->ipqe_ip->ip_off; + if (i < q->ipqe_ip->ip_len) { + q->ipqe_ip->ip_len -= i; + q->ipqe_ip->ip_off += i; + m_adj(dtom(q->ipqe_ip), i); + break; + } + nq = q->ipqe_q.le_next; + m_freem(dtom(q->ipqe_ip)); + LIST_REMOVE(q, ipqe_q); + FREE(q, M_IPQ); + ip_frags--; + } + +insert: + /* + * Stick new segment in its place; + * check for complete reassembly. + */ + if (p == NULL) { + LIST_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q); + } else { + LIST_INSERT_AFTER(p, ipqe, ipqe_q); + } + next = 0; + for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL; + p = q, q = q->ipqe_q.le_next) { + if (q->ipqe_ip->ip_off != next) + return (0); + next += q->ipqe_ip->ip_len; + } + if (p->ipqe_mff) + return (0); + + /* + * Reassembly is complete. Check for a bogus message size and + * concatenate fragments. + */ + q = fp->ipq_fragq.lh_first; + ip = q->ipqe_ip; + if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) { + ipstat.ips_toolong++; + ip_freef(fp); + return (0); + } + m = dtom(q->ipqe_ip); + t = m->m_next; + m->m_next = 0; + m_cat(m, t); + nq = q->ipqe_q.le_next; + FREE(q, M_IPQ); + ip_frags--; + for (q = nq; q != NULL; q = nq) { + t = dtom(q->ipqe_ip); + nq = q->ipqe_q.le_next; + FREE(q, M_IPQ); + ip_frags--; + m_cat(m, t); + } + + /* + * Create header for new ip packet by + * modifying header of first packet; + * dequeue and discard fragment reassembly header. + * Make header visible. + */ + ip->ip_len = next; + ip->ip_ttl = 0; /* xxx */ + ip->ip_sum = 0; + ip->ip_src = fp->ipq_src; + ip->ip_dst = fp->ipq_dst; + LIST_REMOVE(fp, ipq_q); + (void) m_free(dtom(fp)); + m->m_len += (ip->ip_hl << 2); + m->m_data -= (ip->ip_hl << 2); + /* some debugging cruft by sklower, below, will go away soon */ + if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */ + register int plen = 0; + for (t = m; m; m = m->m_next) + plen += m->m_len; + t->m_pkthdr.len = plen; + } + return (ip); + +dropfrag: + ipstat.ips_fragdropped++; + m_freem(m); + FREE(ipqe, M_IPQ); + ip_frags--; + return (0); +} + +/* + * Free a fragment reassembly header and all + * associated datagrams. + */ +void +ip_freef(fp) + struct ipq *fp; +{ + register struct ipqent *q, *p; + + for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) { + p = q->ipqe_q.le_next; + m_freem(dtom(q->ipqe_ip)); + LIST_REMOVE(q, ipqe_q); + FREE(q, M_IPQ); + ip_frags--; + } + LIST_REMOVE(fp, ipq_q); + (void) m_free(dtom(fp)); +} + +/* + * IP timer processing; + * if a timer expires on a reassembly + * queue, discard it. + */ +void +ip_slowtimo() +{ + register struct ipq *fp, *nfp; + int s = splsoftnet(); + + ipq_lock(); + for (fp = ipq.lh_first; fp != NULL; fp = nfp) { + nfp = fp->ipq_q.le_next; + if (--fp->ipq_ttl == 0) { + ipstat.ips_fragtimeout++; + ip_freef(fp); + } + } + ipq_unlock(); + splx(s); +} + +/* + * Drain off all datagram fragments. + */ +void +ip_drain() +{ + + if (ipq_lock_try() == 0) + return; + while (ipq.lh_first != NULL) { + ipstat.ips_fragdropped++; + ip_freef(ipq.lh_first); + } + ipq_unlock(); +} + +/* + * Flush a bunch of datagram fragments, till we are down to 75%. + */ +void +ip_flush() +{ + int max = 50; + + /* ipq already locked */ + while (ipq.lh_first != NULL && ip_frags > ip_maxqueue * 3 / 4 && --max) { + ipstat.ips_fragdropped++; + ip_freef(ipq.lh_first); + } +} + +/* + * Do option processing on a datagram, + * possibly discarding it if bad options are encountered, + * or forwarding it if source-routed. + * Returns 1 if packet has been forwarded/freed, + * 0 if the packet should be processed further. + */ +int +ip_dooptions(m) + struct mbuf *m; +{ + register struct ip *ip = mtod(m, struct ip *); + register u_char *cp; + register struct ip_timestamp *ipt; + register struct in_ifaddr *ia; + int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; + struct in_addr *sin, dst; + n_time ntime; + + dst = ip->ip_dst; + cp = (u_char *)(ip + 1); + cnt = (ip->ip_hl << 2) - sizeof (struct ip); + for (; cnt > 0; cnt -= optlen, cp += optlen) { + opt = cp[IPOPT_OPTVAL]; + if (opt == IPOPT_EOL) + break; + if (opt == IPOPT_NOP) + optlen = 1; + else { + optlen = cp[IPOPT_OLEN]; + if (optlen <= 0 || optlen > cnt) { + code = &cp[IPOPT_OLEN] - (u_char *)ip; + goto bad; + } + } + switch (opt) { + + default: + break; + + /* + * Source routing with record. + * Find interface with current destination address. + * If none on this machine then drop if strictly routed, + * or do nothing if loosely routed. + * Record interface address and bring up next address + * component. If strictly routed make sure next + * address is on directly accessible net. + */ + case IPOPT_LSRR: + case IPOPT_SSRR: + if (!ip_dosourceroute) { +#ifndef __ECOS + char buf[4*sizeof "123"]; + + strcpy(buf, inet_ntoa(ip->ip_dst)); + log(LOG_WARNING, + "attempted source route from %s to %s\n", + inet_ntoa(ip->ip_src), buf); +#endif + type = ICMP_UNREACH; + code = ICMP_UNREACH_SRCFAIL; + goto bad; + } + if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { + code = &cp[IPOPT_OFFSET] - (u_char *)ip; + goto bad; + } + ipaddr.sin_addr = ip->ip_dst; + ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr))); + if (ia == 0) { + if (opt == IPOPT_SSRR) { + type = ICMP_UNREACH; + code = ICMP_UNREACH_SRCFAIL; + goto bad; + } + /* + * Loose routing, and not at next destination + * yet; nothing to do except forward. + */ + break; + } + off--; /* 0 origin */ + if (off > optlen - sizeof(struct in_addr)) { + /* + * End of source route. Should be for us. + */ + save_rte(cp, ip->ip_src); + break; + } + + /* + * locate outgoing interface + */ + bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, + sizeof(ipaddr.sin_addr)); + if (opt == IPOPT_SSRR) { +#define INA struct in_ifaddr * +#define SA struct sockaddr * + if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) + ia = (INA)ifa_ifwithnet((SA)&ipaddr); + } else + ia = ip_rtaddr(ipaddr.sin_addr); + if (ia == 0) { + type = ICMP_UNREACH; + code = ICMP_UNREACH_SRCFAIL; + goto bad; + } + ip->ip_dst = ipaddr.sin_addr; + bcopy((caddr_t)&ia->ia_addr.sin_addr, + (caddr_t)(cp + off), sizeof(struct in_addr)); + cp[IPOPT_OFFSET] += sizeof(struct in_addr); + /* + * Let ip_intr's mcast routing check handle mcast pkts + */ + forward = !IN_MULTICAST(ip->ip_dst.s_addr); + break; + + case IPOPT_RR: + if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { + code = &cp[IPOPT_OFFSET] - (u_char *)ip; + goto bad; + } + + /* + * If no space remains, ignore. + */ + off--; /* 0 origin */ + if (off > optlen - sizeof(struct in_addr)) + break; + bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, + sizeof(ipaddr.sin_addr)); + /* + * locate outgoing interface; if we're the destination, + * use the incoming interface (should be same). + */ + if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && + (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { + type = ICMP_UNREACH; + code = ICMP_UNREACH_HOST; + goto bad; + } + bcopy((caddr_t)&ia->ia_addr.sin_addr, + (caddr_t)(cp + off), sizeof(struct in_addr)); + cp[IPOPT_OFFSET] += sizeof(struct in_addr); + break; + + case IPOPT_TS: + code = cp - (u_char *)ip; + ipt = (struct ip_timestamp *)cp; + if (ipt->ipt_ptr < 5 || ipt->ipt_len < 5) + goto bad; + if (ipt->ipt_ptr - 1 + sizeof(n_time) > ipt->ipt_len) { + if (++ipt->ipt_oflw == 0) + goto bad; + break; + } + sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); + switch (ipt->ipt_flg) { + + case IPOPT_TS_TSONLY: + break; + + case IPOPT_TS_TSANDADDR: + if (ipt->ipt_ptr - 1 + sizeof(n_time) + + sizeof(struct in_addr) > ipt->ipt_len) + goto bad; + ipaddr.sin_addr = dst; + ia = (INA)ifaof_ifpforaddr((SA)&ipaddr, + m->m_pkthdr.rcvif); + if (ia == 0) + continue; + bcopy((caddr_t)&ia->ia_addr.sin_addr, + (caddr_t)sin, sizeof(struct in_addr)); + ipt->ipt_ptr += sizeof(struct in_addr); + break; + + case IPOPT_TS_PRESPEC: + if (ipt->ipt_ptr - 1 + sizeof(n_time) + + sizeof(struct in_addr) > ipt->ipt_len) + goto bad; + bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, + sizeof(struct in_addr)); + if (ifa_ifwithaddr((SA)&ipaddr) == 0) + continue; + ipt->ipt_ptr += sizeof(struct in_addr); + break; + + default: + goto bad; + } + ntime = iptime(); + bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, + sizeof(n_time)); + ipt->ipt_ptr += sizeof(n_time); + } + } + if (forward && ipforwarding) { + ip_forward(m, 1); + return (1); + } + return (0); +bad: + ip->ip_len -= ip->ip_hl << 2; /* XXX icmp_error adds in hdr length */ + HTONS(ip->ip_len); /* XXX because ip_input changed these three */ + HTONS(ip->ip_id); + HTONS(ip->ip_off); + icmp_error(m, type, code, 0, 0); + ipstat.ips_badoptions++; + return (1); +} + +/* + * Given address of next destination (final or next hop), + * return internet address info of interface to be used to get there. + */ +struct in_ifaddr * +ip_rtaddr(dst) + struct in_addr dst; +{ + register struct sockaddr_in *sin; + + sin = satosin(&ipforward_rt.ro_dst); + + if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) { + if (ipforward_rt.ro_rt) { + RTFREE(ipforward_rt.ro_rt); + ipforward_rt.ro_rt = 0; + } + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_addr = dst; + + rtalloc(&ipforward_rt); + } + if (ipforward_rt.ro_rt == 0) + return ((struct in_ifaddr *)0); + return (ifatoia(ipforward_rt.ro_rt->rt_ifa)); +} + +/* + * Save incoming source route for use in replies, + * to be picked up later by ip_srcroute if the receiver is interested. + */ +void +save_rte(option, dst) + u_char *option; + struct in_addr dst; +{ + unsigned olen; + + olen = option[IPOPT_OLEN]; +#ifdef DIAGNOSTIC + if (ipprintfs) + printf("save_rte: olen %d\n", olen); +#endif /* 0 */ + if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) + return; + bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen); + ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); + ip_srcrt.dst = dst; +} + +/* + * Check whether we do proxy ARP for this address and we point to ourselves. + * Code shamelessly copied from arplookup(). + */ +static int +ip_weadvertise(addr) + u_int32_t addr; +{ + register struct rtentry *rt; + register struct ifnet *ifp; + register struct ifaddr *ifa; + struct sockaddr_inarp sin; + + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = addr; + sin.sin_other = SIN_PROXY; + rt = rtalloc1(sintosa(&sin), 0); + if (rt == 0) + return 0; + + RTFREE(rt); + + if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 || + rt->rt_gateway->sa_family != AF_LINK) + return 0; + + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; + ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family) + continue; + + if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr), + LLADDR((struct sockaddr_dl *)rt->rt_gateway), + ETHER_ADDR_LEN)) + return 1; + } + + return 0; +} + +/* + * Retrieve incoming source route for use in replies, + * in the same form used by setsockopt. + * The first hop is placed before the options, will be removed later. + */ +struct mbuf * +ip_srcroute() +{ + register struct in_addr *p, *q; + register struct mbuf *m; + + if (ip_nhops == 0) + return ((struct mbuf *)0); + m = m_get(M_DONTWAIT, MT_SOOPTS); + if (m == 0) + return ((struct mbuf *)0); + +#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) + + /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */ + m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) + + OPTSIZ; +#ifdef DIAGNOSTIC + if (ipprintfs) + printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len); +#endif + + /* + * First save first hop for return route + */ + p = &ip_srcrt.route[ip_nhops - 1]; + *(mtod(m, struct in_addr *)) = *p--; +#ifdef DIAGNOSTIC + if (ipprintfs) + printf(" hops %x", ntohl(mtod(m, struct in_addr *)->s_addr)); +#endif + + /* + * Copy option fields and padding (nop) to mbuf. + */ + ip_srcrt.nop = IPOPT_NOP; + ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; + bcopy((caddr_t)&ip_srcrt.nop, + mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ); + q = (struct in_addr *)(mtod(m, caddr_t) + + sizeof(struct in_addr) + OPTSIZ); +#undef OPTSIZ + /* + * Record return path as an IP source route, + * reversing the path (pointers are now aligned). + */ + while (p >= ip_srcrt.route) { +#ifdef DIAGNOSTIC + if (ipprintfs) + printf(" %x", ntohl(q->s_addr)); +#endif + *q++ = *p--; + } + /* + * Last hop goes to final destination. + */ + *q = ip_srcrt.dst; +#ifdef DIAGNOSTIC + if (ipprintfs) + printf(" %x\n", ntohl(q->s_addr)); +#endif + return (m); +} + +/* + * Strip out IP options, at higher + * level protocol in the kernel. + * Second argument is buffer to which options + * will be moved, and return value is their length. + * XXX should be deleted; last arg currently ignored. + */ +void +ip_stripoptions(m, mopt) + register struct mbuf *m; + struct mbuf *mopt; +{ + register int i; + struct ip *ip = mtod(m, struct ip *); + register caddr_t opts; + int olen; + + olen = (ip->ip_hl<<2) - sizeof (struct ip); + opts = (caddr_t)(ip + 1); + i = m->m_len - (sizeof (struct ip) + olen); + bcopy(opts + olen, opts, (unsigned)i); + m->m_len -= olen; + if (m->m_flags & M_PKTHDR) + m->m_pkthdr.len -= olen; + ip->ip_hl = sizeof(struct ip) >> 2; +} + +int inetctlerrmap[PRC_NCMDS] = { + 0, 0, 0, 0, + 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, + EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, + EMSGSIZE, EHOSTUNREACH, 0, 0, + 0, 0, 0, 0, + ENOPROTOOPT +}; + +/* + * Forward a packet. If some error occurs return the sender + * an icmp packet. Note we can't always generate a meaningful + * icmp message because icmp doesn't have a large enough repertoire + * of codes and types. + * + * If not forwarding, just drop the packet. This could be confusing + * if ipforwarding was zero but some routing protocol was advancing + * us as a gateway to somewhere. However, we must let the routing + * protocol deal with that. + * + * The srcrt parameter indicates whether the packet is being forwarded + * via a source route. + */ +void +ip_forward(m, srcrt) + struct mbuf *m; + int srcrt; +{ + register struct ip *ip = mtod(m, struct ip *); + register struct sockaddr_in *sin; + register struct rtentry *rt; + int error, type = 0, code = 0; + struct mbuf *mcopy; + n_long dest; + struct ifnet *destifp; +#if 0 /*KAME IPSEC*/ + struct ifnet dummyifp; +#endif + + dest = 0; +#ifdef DIAGNOSTIC + if (ipprintfs) + printf("forward: src %x dst %x ttl %x\n", ip->ip_src.s_addr, + ip->ip_dst.s_addr, ip->ip_ttl); +#endif + if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) { + ipstat.ips_cantforward++; + m_freem(m); + return; + } + HTONS(ip->ip_id); + if (ip->ip_ttl <= IPTTLDEC) { + icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); + return; + } + ip->ip_ttl -= IPTTLDEC; + + sin = satosin(&ipforward_rt.ro_dst); + if ((rt = ipforward_rt.ro_rt) == 0 || + ip->ip_dst.s_addr != sin->sin_addr.s_addr) { + if (ipforward_rt.ro_rt) { + RTFREE(ipforward_rt.ro_rt); + ipforward_rt.ro_rt = 0; + } + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_addr = ip->ip_dst; + + rtalloc(&ipforward_rt); + if (ipforward_rt.ro_rt == 0) { + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); + return; + } + rt = ipforward_rt.ro_rt; + } + + /* + * Save at most 68 bytes of the packet in case + * we need to generate an ICMP message to the src. + */ + mcopy = m_copy(m, 0, imin((int)ip->ip_len, 68)); + + /* + * If forwarding packet using same interface that it came in on, + * perhaps should send a redirect to sender to shortcut a hop. + * Only send redirect if source is sending directly to us, + * and if packet was not source routed (or has any options). + * Also, don't send redirect if forwarding using a default route + * or a route modified by a redirect. + * Don't send redirect if we advertise destination's arp address + * as ours (proxy arp). + */ + if (rt->rt_ifp == m->m_pkthdr.rcvif && + (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && + satosin(rt_key(rt))->sin_addr.s_addr != 0 && + ipsendredirects && !srcrt && + !ip_weadvertise(satosin(rt_key(rt))->sin_addr.s_addr)) { + if (rt->rt_ifa && + (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) == + ifatoia(rt->rt_ifa)->ia_subnet) { + if (rt->rt_flags & RTF_GATEWAY) + dest = satosin(rt->rt_gateway)->sin_addr.s_addr; + else + dest = ip->ip_dst.s_addr; + /* Router requirements says to only send host redirects */ + type = ICMP_REDIRECT; + code = ICMP_REDIRECT_HOST; +#ifdef DIAGNOSTIC + if (ipprintfs) + printf("redirect (%d) to %x\n", code, (u_int32_t)dest); +#endif + } + } + +#if 0 /*KAME IPSEC*/ + m->m_pkthdr.rcvif = NULL; +#endif /*IPSEC*/ + error = ip_output(m, (struct mbuf *)0, &ipforward_rt, + (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), + 0, NULL, NULL); + if (error) + ipstat.ips_cantforward++; + else { + ipstat.ips_forward++; + if (type) + ipstat.ips_redirectsent++; + else { + if (mcopy) + m_freem(mcopy); + return; + } + } + if (mcopy == NULL) + return; + destifp = NULL; + + switch (error) { + + case 0: /* forwarded, but need redirect */ + /* type, code set above */ + break; + + case ENETUNREACH: /* shouldn't happen, checked above */ + case EHOSTUNREACH: + case ENETDOWN: + case EHOSTDOWN: + default: + type = ICMP_UNREACH; + code = ICMP_UNREACH_HOST; + break; + + case EMSGSIZE: + type = ICMP_UNREACH; + code = ICMP_UNREACH_NEEDFRAG; +#if 1 /*KAME IPSEC*/ + if (ipforward_rt.ro_rt) + destifp = ipforward_rt.ro_rt->rt_ifp; +#else + /* + * If the packet is routed over IPsec tunnel, tell the + * originator the tunnel MTU. + * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz + * XXX quickhack!!! + */ + if (ipforward_rt.ro_rt) { + struct secpolicy *sp; + int ipsecerror; + int ipsechdr; + struct route *ro; + + sp = ipsec4_getpolicybyaddr(mcopy, + IP_FORWARDING, + &ipsecerror); + + if (sp == NULL) + destifp = ipforward_rt.ro_rt->rt_ifp; + else { + /* count IPsec header size */ + ipsechdr = ipsec4_hdrsiz(mcopy, NULL); + + /* + * find the correct route for outer IPv4 + * header, compute tunnel MTU. + * + * XXX BUG ALERT + * The "dummyifp" code relies upon the fact + * that icmp_error() touches only ifp->if_mtu. + */ + /*XXX*/ + destifp = NULL; + if (sp->req != NULL + && sp->req->sa != NULL) { + ro = &sp->req->sa->saidx->sa_route; + if (ro->ro_rt && ro->ro_rt->rt_ifp) { + dummyifp.if_mtu = + ro->ro_rt->rt_ifp->if_mtu; + dummyifp.if_mtu -= ipsechdr; + destifp = &dummyifp; + } + } + + key_freesp(sp); + } + } +#endif /*IPSEC*/ + ipstat.ips_cantfrag++; + break; + + case ENOBUFS: + type = ICMP_SOURCEQUENCH; + code = 0; + break; + } + + icmp_error(mcopy, type, code, dest, destifp); +} + +#ifdef CYGPKG_NET_SYSCTL +int +ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; +{ + /* All sysctl names at this level are terminal. */ + if (namelen != 1) + return (ENOTDIR); + + switch (name[0]) { + case IPCTL_FORWARDING: + return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding)); + case IPCTL_SENDREDIRECTS: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ipsendredirects)); + case IPCTL_DEFTTL: + return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl)); +#ifdef notyet + case IPCTL_DEFMTU: + return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu)); +#endif + case IPCTL_SOURCEROUTE: + /* + * Don't allow this to change in a secure environment. + */ + if (newp && securelevel > 0) + return (EPERM); + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ip_dosourceroute)); + case IPCTL_DIRECTEDBCAST: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ip_directedbcast)); + case IPCTL_IPPORT_FIRSTAUTO: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ipport_firstauto)); + case IPCTL_IPPORT_LASTAUTO: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ipport_lastauto)); + case IPCTL_IPPORT_HIFIRSTAUTO: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ipport_hifirstauto)); + case IPCTL_IPPORT_HILASTAUTO: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ipport_hilastauto)); + case IPCTL_IPPORT_MAXQUEUE: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ip_maxqueue)); + case IPCTL_ENCDEBUG: + return (sysctl_int(oldp, oldlenp, newp, newlen, &encdebug)); + default: + return (EOPNOTSUPP); + } + /* NOTREACHED */ +} +#endif // CYGPKG_NET_SYSCTL diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/ip_output.c b/ecos/packages/net/tcpip/current/src/sys/netinet/ip_output.c new file mode 100644 index 0000000..40f125a --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/ip_output.c @@ -0,0 +1,1757 @@ +//========================================================================== +// +// sys/netinet/ip_output.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: ip_output.c,v 1.57 1999/12/10 08:55:23 angelos Exp $ */ +/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/kernel.h> +#ifndef __ECOS +#include <sys/proc.h> + +#include <vm/vm.h> +#include <sys/proc.h> +#endif + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/in_var.h> +#include <netinet/ip_var.h> + +#ifdef vax +#include <machine/mtpr.h> +#endif + +#include <machine/stdarg.h> + +#ifdef IPSEC +#include <netinet/ip_ah.h> +#include <netinet/ip_esp.h> +#include <netinet/udp.h> +#include <netinet/tcp.h> +#include <net/pfkeyv2.h> + +#ifdef ENCDEBUG +#define DPRINTF(x) do { if (encdebug) printf x ; } while (0) +#else +#define DPRINTF(x) +#endif + +#ifndef offsetof +#define offsetof(s, e) ((int)&((s *)0)->e) +#endif + +extern u_int8_t get_sa_require __P((struct inpcb *)); + +#endif /* IPSEC */ + +static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); +static void ip_mloopback + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); +#if defined(IPFILTER) || defined(IPFILTER_LKM) +int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); +#endif + +#ifdef IPSEC +extern int ipsec_auth_default_level; +extern int ipsec_esp_trans_default_level; +extern int ipsec_esp_network_default_level; + +extern int pfkeyv2_acquire(struct tdb *, int); +#endif + +#ifndef RAMDOM_IP_ID +u_short ip_id; +#endif + +/* + * IP output. The packet in mbuf chain m contains a skeletal IP + * header (with len, off, ttl, proto, tos, src, dst). + * The mbuf chain containing the packet will be freed. + * The mbuf opt, if present, will not be freed. + */ +int +#if __STDC__ +ip_output(struct mbuf *m0, ...) +#else +ip_output(m0, va_alist) + struct mbuf *m0; + va_dcl +#endif +{ + register struct ip *ip, *mhip; + register struct ifnet *ifp; + register struct mbuf *m = m0; + register int hlen = sizeof (struct ip); + int len, off, error = 0; + struct route iproute; + struct sockaddr_in *dst; + struct in_ifaddr *ia; + struct mbuf *opt; + struct route *ro; + int flags; + struct ip_moptions *imo; + va_list ap; +#ifdef IPSEC + union sockaddr_union sunion; + struct mbuf *mp; + struct udphdr *udp; + struct tcphdr *tcp; + struct inpcb *inp; + + struct route_enc re0, *re = &re0; + struct sockaddr_encap *ddst, *gw; + u_int8_t sa_require, sa_have = 0; + struct tdb *tdb, *t; + int s, ip6flag; + +#ifdef INET6 + struct ip6_hdr *ip6; +#endif /* INET6 */ +#endif /* IPSEC */ + + va_start(ap, m0); + opt = va_arg(ap, struct mbuf *); + ro = va_arg(ap, struct route *); + flags = va_arg(ap, int); + imo = va_arg(ap, struct ip_moptions *); +#ifdef IPSEC + inp = va_arg(ap, struct inpcb *); +#endif /* IPSEC */ + va_end(ap); + +#ifdef DIAGNOSTIC + if ((m->m_flags & M_PKTHDR) == 0) + panic("ip_output no HDR"); +#endif + if (opt) { + m = ip_insertoptions(m, opt, &len); + hlen = len; + } + ip = mtod(m, struct ip *); + /* + * Fill in IP header. + */ + if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) { + ip->ip_v = IPVERSION; + ip->ip_off &= IP_DF; +#ifdef RANDOM_IP_ID + ip->ip_id = ip_randomid(); +#else + ip->ip_id = htons(ip_id++); +#endif + ip->ip_hl = hlen >> 2; + ipstat.ips_localout++; + } else { + hlen = ip->ip_hl << 2; + } + + /* + * Route packet. + */ + if (ro == 0) { + ro = &iproute; + bzero((caddr_t)ro, sizeof (*ro)); + } + dst = satosin(&ro->ro_dst); + /* + * If there is a cached route, + * check that it is to the same destination + * and is still up. If not, free it and try again. + */ + if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || + dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { + RTFREE(ro->ro_rt); + ro->ro_rt = (struct rtentry *)0; + } + if (ro->ro_rt == 0) { + dst->sin_family = AF_INET; + dst->sin_len = sizeof(*dst); + dst->sin_addr = ip->ip_dst; + } + /* + * If routing to interface only, + * short circuit routing lookup. + */ + if (flags & IP_ROUTETOIF) { + if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 && + (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) { + ipstat.ips_noroute++; + error = ENETUNREACH; + goto bad; + } + ifp = ia->ia_ifp; + ip->ip_ttl = 1; + } else { + if (ro->ro_rt == 0) + rtalloc(ro); + if (ro->ro_rt == 0) { + ipstat.ips_noroute++; + error = EHOSTUNREACH; + goto bad; + } + ia = ifatoia(ro->ro_rt->rt_ifa); + ifp = ro->ro_rt->rt_ifp; + ro->ro_rt->rt_use++; + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst = satosin(ro->ro_rt->rt_gateway); + } + if (IN_MULTICAST(ip->ip_dst.s_addr)) { + struct in_multi *inm; + + m->m_flags |= M_MCAST; + /* + * IP destination address is multicast. Make sure "dst" + * still points to the address in "ro". (It may have been + * changed to point to a gateway address, above.) + */ + dst = satosin(&ro->ro_dst); + /* + * See if the caller provided any multicast options + */ + if (imo != NULL) { + ip->ip_ttl = imo->imo_multicast_ttl; + if (imo->imo_multicast_ifp != NULL) + ifp = imo->imo_multicast_ifp; + } else + ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL; + /* + * Confirm that the outgoing interface supports multicast. + */ + if ((ifp->if_flags & IFF_MULTICAST) == 0) { + ipstat.ips_noroute++; + error = ENETUNREACH; + goto bad; + } + /* + * If source address not specified yet, use address + * of outgoing interface. + */ + if (ip->ip_src.s_addr == INADDR_ANY) { + register struct in_ifaddr *ia; + + for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) + if (ia->ia_ifp == ifp) { + ip->ip_src = ia->ia_addr.sin_addr; + break; + } + } + + IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm); + if (inm != NULL && + (imo == NULL || imo->imo_multicast_loop)) { + /* + * If we belong to the destination multicast group + * on the outgoing interface, and the caller did not + * forbid loopback, loop back a copy. + */ + ip_mloopback(ifp, m, dst); + } +#ifdef MROUTING + else { + /* + * If we are acting as a multicast router, perform + * multicast forwarding as if the packet had just + * arrived on the interface to which we are about + * to send. The multicast forwarding function + * recursively calls this function, using the + * IP_FORWARDING flag to prevent infinite recursion. + * + * Multicasts that are looped back by ip_mloopback(), + * above, will be forwarded by the ip_input() routine, + * if necessary. + */ + extern struct socket *ip_mrouter; + + if (ip_mrouter && (flags & IP_FORWARDING) == 0) { + if (ip_mforward(m, ifp) != 0) { + m_freem(m); + goto done; + } + } + } +#endif + /* + * Multicasts with a time-to-live of zero may be looped- + * back, above, but must not be transmitted on a network. + * Also, multicasts addressed to the loopback interface + * are not sent -- the above call to ip_mloopback() will + * loop back a copy if this host actually belongs to the + * destination group on the loopback interface. + */ + if (ip->ip_ttl == 0 || (ifp->if_flags & IFF_LOOPBACK) != 0) { + m_freem(m); + goto done; + } + + goto sendit; + } +#ifndef notdef + /* + * If source address not specified yet, use address + * of outgoing interface. + */ + if (ip->ip_src.s_addr == INADDR_ANY) + ip->ip_src = ia->ia_addr.sin_addr; +#endif + /* + * Look for broadcast address and + * and verify user is allowed to send + * such a packet. + */ + if (in_broadcast(dst->sin_addr, ifp)) { + if ((ifp->if_flags & IFF_BROADCAST) == 0) { + error = EADDRNOTAVAIL; + goto bad; + } + if ((flags & IP_ALLOWBROADCAST) == 0) { + error = EACCES; + goto bad; + } + /* don't allow broadcast messages to be fragmented */ + if ((u_int16_t)ip->ip_len > ifp->if_mtu) { + error = EMSGSIZE; + goto bad; + } + m->m_flags |= M_BCAST; + } else + m->m_flags &= ~M_BCAST; + +sendit: +#ifdef IPSEC + /* + * Check if the packet needs encapsulation. + */ + if (!(flags & IP_ENCAPSULATED) && + (inp == NULL || + inp->inp_seclevel[SL_AUTH] != IPSEC_LEVEL_BYPASS || + inp->inp_seclevel[SL_ESP_TRANS] != IPSEC_LEVEL_BYPASS || + inp->inp_seclevel[SL_ESP_NETWORK] != IPSEC_LEVEL_BYPASS)) { + if (inp == NULL) + sa_require = get_sa_require(inp); + else + sa_require = inp->inp_secrequire; + + bzero((caddr_t) re, sizeof(*re)); + + /* + * splnet is chosen over spltdb because we are not allowed to + * lower the level, and udp_output calls us in splnet(). + */ + s = splnet(); + + /* + * Check if there was an outgoing SA bound to the flow + * from a transport protocol. + */ + if (inp && inp->inp_tdb && + (inp->inp_tdb->tdb_dst.sin.sin_addr.s_addr == INADDR_ANY || + !bcmp(&inp->inp_tdb->tdb_dst.sin.sin_addr, + &ip->ip_dst, sizeof(ip->ip_dst)))) { + tdb = inp->inp_tdb; + goto have_tdb; + } + + if (!ipsec_in_use) { + splx(s); + goto no_encap; + } + + ddst = (struct sockaddr_encap *) &re->re_dst; + ddst->sen_family = PF_KEY; + ddst->sen_len = SENT_IP4_LEN; + ddst->sen_type = SENT_IP4; + ddst->sen_ip_src = ip->ip_src; + ddst->sen_ip_dst = ip->ip_dst; + ddst->sen_proto = ip->ip_p; + + switch (ip->ip_p) { + case IPPROTO_UDP: + if (m->m_len < hlen + 2 * sizeof(u_int16_t)) { + if ((m = m_pullup(m, hlen + 2 * + sizeof(u_int16_t))) == 0) + return ENOBUFS; + ip = mtod(m, struct ip *); + } + udp = (struct udphdr *) (mtod(m, u_char *) + hlen); + ddst->sen_sport = ntohs(udp->uh_sport); + ddst->sen_dport = ntohs(udp->uh_dport); + break; + + case IPPROTO_TCP: + if (m->m_len < hlen + 2 * sizeof(u_int16_t)) { + if ((m = m_pullup(m, hlen + 2 * + sizeof(u_int16_t))) == 0) + return ENOBUFS; + ip = mtod(m, struct ip *); + } + tcp = (struct tcphdr *) (mtod(m, u_char *) + hlen); + ddst->sen_sport = ntohs(tcp->th_sport); + ddst->sen_dport = ntohs(tcp->th_dport); + break; + + default: + ddst->sen_sport = 0; + ddst->sen_dport = 0; + } + + rtalloc((struct route *) re); + if (re->re_rt == NULL) { + splx(s); + goto no_encap; + } + + gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway); + + /* Sanity check */ + if (gw == NULL || ((gw->sen_type != SENT_IPSP) && + (gw->sen_type != SENT_IPSP6))) { + splx(s); + DPRINTF(("ip_output(): no gw or gw data not IPSP\n")); + + if (re->re_rt) + RTFREE(re->re_rt); + error = EHOSTUNREACH; + m_freem(m); + goto done; + } + + /* + * There might be a specific route, that tells us to avoid + * doing IPsec; this is useful for specific routes that we + * don't want to have IPsec applied on, like the key + * management ports. + */ + + if ((gw != NULL) && (gw->sen_ipsp_sproto == 0) && + (gw->sen_ipsp_spi == 0)) { + if ((gw->sen_family == AF_INET) && + (gw->sen_ipsp_dst.s_addr == 0)) { + splx(s); + goto no_encap; + } + +#ifdef INET6 + if ((gw->sen_family == AF_INET6) && + IN6_IS_ADDR_UNSPECIFIED(&gw->sen_ipsp6_dst)) { + splx(s); + goto no_encap; + } +#endif /* INET6 */ + } + + /* + * At this point we have an IPSP "gateway" (tunnel) spec. + * Use the destination of the tunnel and the SPI to + * look up the necessary Tunnel Control Block. Look it up, + * and then pass it, along with the packet and the gw, + * to the appropriate transformation. + */ + bzero(&sunion, sizeof(sunion)); + + if (gw->sen_type == SENT_IPSP) { + sunion.sin.sin_family = AF_INET; + sunion.sin.sin_len = sizeof(struct sockaddr_in); + sunion.sin.sin_addr = gw->sen_ipsp_dst; + } +#ifdef INET6 + if (gw->sen_type == SENT_IPSP6) { + sunion.sin6.sin6_family = AF_INET6; + sunion.sin6.sin6_len = sizeof(struct sockaddr_in6); + sunion.sin6.sin6_addr = gw->sen_ipsp6_dst; + } +#endif /* INET6 */ + + tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion, + gw->sen_ipsp_sproto); + + /* + * For VPNs a route with a reserved SPI is used to + * indicate the need for an SA when none is established. + */ + if (((ntohl(gw->sen_ipsp_spi) == SPI_LOCAL_USE) && + (gw->sen_type == SENT_IPSP)) || + ((ntohl(gw->sen_ipsp6_spi) == SPI_LOCAL_USE) && + (gw->sen_type == SENT_IPSP6))) { + if (tdb == NULL) { + /* + * XXX We should construct a TDB from system + * default (which should be tunable via sysctl). + * For now, drop packet and ignore SPD entry. + */ + splx(s); + goto no_encap; + } + else { + if (tdb->tdb_authalgxform) + sa_require = NOTIFY_SATYPE_AUTH; + if (tdb->tdb_encalgxform) + sa_require |= NOTIFY_SATYPE_CONF; + if (tdb->tdb_flags & TDBF_TUNNELING) + sa_require |= NOTIFY_SATYPE_TUNNEL; + } + + /* PF_KEYv2 notification message */ + if (tdb && tdb->tdb_satype != SADB_X_SATYPE_BYPASS) + if ((error = pfkeyv2_acquire(tdb, 0)) != 0) + return error; + + splx(s); + + /* + * When sa_require is set, the packet will be dropped + * at no_encap. + */ + goto no_encap; + } + + have_tdb: + + ip->ip_len = htons((u_short) ip->ip_len); + ip->ip_off = htons((u_short) ip->ip_off); + ip->ip_sum = 0; + + /* + * Now we check if this tdb has all the transforms which + * are requried by the socket or our default policy. + */ + SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb); + + if (sa_require & ~sa_have) + goto no_encap; + + if (tdb == NULL) { + splx(s); + if (gw->sen_type == SENT_IPSP) + DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto)); +#ifdef INET6 + else + DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet6_ntoa4(gw->sen_ipsp6_dst), ntohl(gw->sen_ipsp6_spi), gw->sen_ipsp6_sproto)); +#endif /* INET6 */ + + if (re->re_rt) + RTFREE(re->re_rt); + error = EHOSTUNREACH; + m_freem(m); + goto done; + } + + for (t = tdb; t != NULL; t = t->tdb_onext) + if ((t->tdb_sproto == IPPROTO_ESP && !esp_enable) || + (t->tdb_sproto == IPPROTO_AH && !ah_enable)) { + DPRINTF(("ip_output(): IPSec outbound packet dropped due to policy\n")); + + if (re->re_rt) + RTFREE(re->re_rt); + error = EHOSTUNREACH; + m_freem(m); + goto done; + } + + while (tdb && tdb->tdb_xform) { + /* Check if the SPI is invalid */ + if (tdb->tdb_flags & TDBF_INVALID) { + splx(s); + DPRINTF(("ip_output(): attempt to use invalid SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), tdb->tdb_sproto)); + m_freem(m); + if (re->re_rt) + RTFREE(re->re_rt); + return ENXIO; + } + +#ifndef INET6 + /* Sanity check */ + if (tdb->tdb_dst.sa.sa_family != AF_INET) { + splx(s); + DPRINTF(("ip_output(): attempt to use SA %s/%08x/%u for protocol family %d\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), tdb->tdb_sproto, tdb->tdb_dst.sa.sa_family)); + m_freem(m); + if (re->re_rt) + RTFREE(re->re_rt); + return ENXIO; + } +#endif /* INET6 */ + + /* Register first use, setup expiration timer */ + if (tdb->tdb_first_use == 0) { + tdb->tdb_first_use = time.tv_sec; + tdb_expiration(tdb, TDBEXP_TIMEOUT); + } + + /* Check for tunneling */ + if (((tdb->tdb_dst.sa.sa_family == AF_INET) && + (tdb->tdb_dst.sin.sin_addr.s_addr != + INADDR_ANY) && + (tdb->tdb_dst.sin.sin_addr.s_addr != + ip->ip_dst.s_addr)) || + (tdb->tdb_dst.sa.sa_family == AF_INET6) || + ((tdb->tdb_flags & TDBF_TUNNELING) && + (tdb->tdb_xform->xf_type != XF_IP4))) { + /* Fix length and checksum */ + ip->ip_len = htons(m->m_pkthdr.len); + ip->ip_sum = in_cksum(m, ip->ip_hl << 2); + error = ipe4_output(m, tdb, &mp, + ip->ip_hl << 2, + offsetof(struct ip, ip_p)); + if (mp == NULL) + error = EFAULT; + if (error) { + splx(s); + if (re->re_rt) + RTFREE(re->re_rt); + return error; + } + if (tdb->tdb_dst.sa.sa_family == AF_INET) + ip6flag = 0; +#ifdef INET6 + if (tdb->tdb_dst.sa.sa_family == AF_INET6) + ip6flag = 1; +#endif /* INET6 */ + m = mp; + mp = NULL; + } + + if ((tdb->tdb_xform->xf_type == XF_IP4) && + (tdb->tdb_dst.sa.sa_family == AF_INET)) { + ip = mtod(m, struct ip *); + ip->ip_len = htons(m->m_pkthdr.len); + ip->ip_sum = in_cksum(m, ip->ip_hl << 2); + } + +#ifdef INET6 + if ((tdb->tdb_xform->xf_type == XF_IP4) && + (tdb->tdb_dst.sa.sa_family == AF_INET6)) { + ip6 = mtod(m, struct ip6_hdr *); + ip6->ip6_plen = htons(m->m_pkthdr.len); + } +#endif /* INET6 */ + +#ifdef INET6 + /* + * This assumes that there is only just an IPv6 + * header prepended. + */ + if (ip6flag) + error = (*(tdb->tdb_xform->xf_output))(m, tdb, &mp, sizeof(struct ip6_hdr), offsetof(struct ip6_hdr, ip6_nxt)); +#endif /* INET6 */ + + if (!ip6flag) + error = (*(tdb->tdb_xform->xf_output))(m, tdb, &mp, ip->ip_hl << 2, offsetof(struct ip, ip_p)); + if (!error && mp == NULL) + error = EFAULT; + if (error) { + splx(s); + if (mp != NULL) + m_freem(mp); + if (re->re_rt) + RTFREE(re->re_rt); + return error; + } + + m = mp; + mp = NULL; + + if (!ip6flag) { + ip = mtod(m, struct ip *); + ip->ip_len = htons(m->m_pkthdr.len); + } + +#ifdef INET6 + if (ip6flag) { + ip6 = mtod(m, struct ip6_hdr *); + ip6->ip6_plen = htons(m->m_pkthdr.len); + } +#endif /* INET6 */ + tdb = tdb->tdb_onext; + } + splx(s); + + if (!ip6flag) + ip->ip_sum = in_cksum(m, ip->ip_hl << 2); + + /* + * At this point, m is pointing to an mbuf chain with the + * processed packet. Call ourselves recursively, but + * bypass the encap code. + */ + if (re->re_rt) + RTFREE(re->re_rt); + + if (!ip6flag) { + ip = mtod(m, struct ip *); + NTOHS(ip->ip_len); + NTOHS(ip->ip_off); + + return ip_output(m, NULL, NULL, + IP_ENCAPSULATED | IP_RAWOUTPUT, + NULL, NULL); + } + +#ifdef INET6 + if (ip6flag) { + ip6 = mtod(m, struct ip6_hdr *); + NTOHS(ip6->ip6_plen); + + /* Naturally, ip6_output() has to honor those two flags */ + return ip6_output(m, NULL, NULL, + IP_ENCAPSULATED | IP_RAWOUTPUT, + NULL, NULL); + } +#endif /* INET6 */ + +no_encap: + /* This is for possible future use, don't move or delete */ + if (re->re_rt) + RTFREE(re->re_rt); + /* No IPSec processing though it was required, drop packet */ + if (sa_require) { + error = EHOSTUNREACH; + m_freem(m); + goto done; + } + } +#endif /* IPSEC */ + +#if defined(IPFILTER) || defined(IPFILTER_LKM) + /* + * looks like most checking has been done now...do a filter check + */ + { + struct mbuf *m0 = m; + if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m0)) { + error = EHOSTUNREACH; + goto done; + } else + ip = mtod(m = m0, struct ip *); + } +#endif + /* + * If small enough for interface, can just send directly. + */ + if ((u_int16_t)ip->ip_len <= ifp->if_mtu) { + ip->ip_len = htons((u_int16_t)ip->ip_len); + ip->ip_off = htons((u_int16_t)ip->ip_off); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m, hlen); + error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt); + goto done; + } + + /* + * Too large for interface; fragment if possible. + * Must be able to put at least 8 bytes per fragment. + */ +#if 0 + /* + * If IPsec packet is too big for the interface, try fragment it. + * XXX This really is a quickhack. May be inappropriate. + * XXX fails if somebody is sending AH'ed packet, with: + * sizeof(packet without AH) < mtu < sizeof(packet with AH) + */ + if (sab && ip->ip_p != IPPROTO_AH && (flags & IP_FORWARDING) == 0) + ip->ip_off &= ~IP_DF; +#endif /*IPSEC*/ + if (ip->ip_off & IP_DF) { + error = EMSGSIZE; + ipstat.ips_cantfrag++; + goto bad; + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; + goto bad; + } + + { + int mhlen, firstlen = len; + struct mbuf **mnext = &m->m_nextpkt; + + /* + * Loop through length of segment after first fragment, + * make new header and copy data of each part and link onto chain. + */ + m0 = m; + mhlen = sizeof (struct ip); + for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { + MGETHDR(m, M_DONTWAIT, MT_HEADER); + if (m == 0) { + error = ENOBUFS; + ipstat.ips_odropped++; + goto sendorfree; + } + *mnext = m; + mnext = &m->m_nextpkt; + m->m_data += max_linkhdr; + mhip = mtod(m, struct ip *); + *mhip = *ip; + if (hlen > sizeof (struct ip)) { + mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); + mhip->ip_hl = mhlen >> 2; + } + m->m_len = mhlen; + mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); + if (ip->ip_off & IP_MF) + mhip->ip_off |= IP_MF; + if (off + len >= (u_int16_t)ip->ip_len) + len = (u_int16_t)ip->ip_len - off; + else + mhip->ip_off |= IP_MF; + mhip->ip_len = htons((u_int16_t)(len + mhlen)); + m->m_next = m_copy(m0, off, len); + if (m->m_next == 0) { + error = ENOBUFS; /* ??? */ + ipstat.ips_odropped++; + goto sendorfree; + } + m->m_pkthdr.len = mhlen + len; + m->m_pkthdr.rcvif = (struct ifnet *)0; + mhip->ip_off = htons((u_int16_t)mhip->ip_off); + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + ipstat.ips_ofragments++; + } + /* + * Update first fragment by trimming what's been copied out + * and updating header, then send each fragment (in order). + */ + m = m0; + m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len); + m->m_pkthdr.len = hlen + firstlen; + ip->ip_len = htons((u_int16_t)m->m_pkthdr.len); + ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF)); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m, hlen); +sendorfree: + for (m = m0; m; m = m0) { + m0 = m->m_nextpkt; + m->m_nextpkt = 0; + if (error == 0) + error = (*ifp->if_output)(ifp, m, sintosa(dst), + ro->ro_rt); + else + m_freem(m); + } + + if (error == 0) + ipstat.ips_fragmented++; + } +done: + if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) + RTFREE(ro->ro_rt); + return (error); +bad: + m_freem(m0); + goto done; +} + +/* + * Insert IP options into preformed packet. + * Adjust IP destination as required for IP source routing, + * as indicated by a non-zero in_addr at the start of the options. + */ +static struct mbuf * +ip_insertoptions(m, opt, phlen) + register struct mbuf *m; + struct mbuf *opt; + int *phlen; +{ + register struct ipoption *p = mtod(opt, struct ipoption *); + struct mbuf *n; + register struct ip *ip = mtod(m, struct ip *); + unsigned optlen; + + optlen = opt->m_len - sizeof(p->ipopt_dst); + if (optlen + (u_int16_t)ip->ip_len > IP_MAXPACKET) + return (m); /* XXX should fail */ + if (p->ipopt_dst.s_addr) + ip->ip_dst = p->ipopt_dst; + if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) { + MGETHDR(n, M_DONTWAIT, MT_HEADER); + if (n == 0) + return (m); + n->m_pkthdr.len = m->m_pkthdr.len + optlen; + m->m_len -= sizeof(struct ip); + m->m_data += sizeof(struct ip); + n->m_next = m; + m = n; + m->m_len = optlen + sizeof(struct ip); + m->m_data += max_linkhdr; + bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); + } else { + m->m_data -= optlen; + m->m_len += optlen; + m->m_pkthdr.len += optlen; + ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); + } + ip = mtod(m, struct ip *); + bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen); + *phlen = sizeof(struct ip) + optlen; + ip->ip_len += optlen; + return (m); +} + +/* + * Copy options from ip to jp, + * omitting those not copied during fragmentation. + */ +int +ip_optcopy(ip, jp) + struct ip *ip, *jp; +{ + register u_char *cp, *dp; + int opt, optlen, cnt; + + cp = (u_char *)(ip + 1); + dp = (u_char *)(jp + 1); + cnt = (ip->ip_hl << 2) - sizeof (struct ip); + for (; cnt > 0; cnt -= optlen, cp += optlen) { + opt = cp[0]; + if (opt == IPOPT_EOL) + break; + if (opt == IPOPT_NOP) { + /* Preserve for IP mcast tunnel's LSRR alignment. */ + *dp++ = IPOPT_NOP; + optlen = 1; + continue; + } else + optlen = cp[IPOPT_OLEN]; + /* bogus lengths should have been caught by ip_dooptions */ + if (optlen > cnt) + optlen = cnt; + if (IPOPT_COPIED(opt)) { + bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen); + dp += optlen; + } + } + for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++) + *dp++ = IPOPT_EOL; + return (optlen); +} + +/* + * IP socket option processing. + */ +int +ip_ctloutput(op, so, level, optname, mp) + int op; + struct socket *so; + int level, optname; + struct mbuf **mp; +{ + register struct inpcb *inp = sotoinpcb(so); + register struct mbuf *m = *mp; + register int optval = 0; +#ifdef IPSEC + struct proc *p = curproc; /* XXX */ + struct tdb *tdb; + struct tdb_ident *tdbip, tdbi; + int s; +#endif + int error = 0; + + if (level != IPPROTO_IP) { + error = EINVAL; + if (op == PRCO_SETOPT && *mp) + (void) m_free(*mp); + } else switch (op) { + + case PRCO_SETOPT: + switch (optname) { + case IP_OPTIONS: +#ifdef notyet + case IP_RETOPTS: + return (ip_pcbopts(optname, &inp->inp_options, m)); +#else + return (ip_pcbopts(&inp->inp_options, m)); +#endif + + case IP_TOS: + case IP_TTL: + case IP_RECVOPTS: + case IP_RECVRETOPTS: + case IP_RECVDSTADDR: + if (m == NULL || m->m_len != sizeof(int)) + error = EINVAL; + else { + optval = *mtod(m, int *); + switch (optname) { + + case IP_TOS: + inp->inp_ip.ip_tos = optval; + break; + + case IP_TTL: + inp->inp_ip.ip_ttl = optval; + break; +#define OPTSET(bit) \ + if (optval) \ + inp->inp_flags |= bit; \ + else \ + inp->inp_flags &= ~bit; + + case IP_RECVOPTS: + OPTSET(INP_RECVOPTS); + break; + + case IP_RECVRETOPTS: + OPTSET(INP_RECVRETOPTS); + break; + + case IP_RECVDSTADDR: + OPTSET(INP_RECVDSTADDR); + break; + } + } + break; +#undef OPTSET + + case IP_MULTICAST_IF: + case IP_MULTICAST_TTL: + case IP_MULTICAST_LOOP: + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + error = ip_setmoptions(optname, &inp->inp_moptions, m); + break; + + case IP_PORTRANGE: + if (m == 0 || m->m_len != sizeof(int)) + error = EINVAL; + else { + optval = *mtod(m, int *); + + switch (optval) { + + case IP_PORTRANGE_DEFAULT: + inp->inp_flags &= ~(INP_LOWPORT); + inp->inp_flags &= ~(INP_HIGHPORT); + break; + + case IP_PORTRANGE_HIGH: + inp->inp_flags &= ~(INP_LOWPORT); + inp->inp_flags |= INP_HIGHPORT; + break; + + case IP_PORTRANGE_LOW: + inp->inp_flags &= ~(INP_HIGHPORT); + inp->inp_flags |= INP_LOWPORT; + break; + + default: + + error = EINVAL; + break; + } + } + break; + case IPSEC_OUTSA: +#ifndef IPSEC + error = EINVAL; +#else + s = spltdb(); + if (m == 0 || m->m_len != sizeof(struct tdb_ident)) { + error = EINVAL; + } else { + tdbip = mtod(m, struct tdb_ident *); + tdb = gettdb(tdbip->spi, &tdbip->dst, + tdbip->proto); + if (tdb == NULL) + error = ESRCH; + else + tdb_add_inp(tdb, inp); + } + splx(s); +#endif /* IPSEC */ + break; + + case IP_AUTH_LEVEL: + case IP_ESP_TRANS_LEVEL: + case IP_ESP_NETWORK_LEVEL: +#ifndef IPSEC + error = EINVAL; +#else + if (m == 0 || m->m_len != sizeof(int)) { + error = EINVAL; + break; + } + optval = *mtod(m, u_char *); + + if (optval < IPSEC_LEVEL_BYPASS || + optval > IPSEC_LEVEL_UNIQUE) { + error = EINVAL; + break; + } + + switch (optname) { + case IP_AUTH_LEVEL: + if (optval < ipsec_auth_default_level && + suser(p->p_ucred, &p->p_acflag)) { + error = EACCES; + break; + } + inp->inp_seclevel[SL_AUTH] = optval; + break; + + case IP_ESP_TRANS_LEVEL: + if (optval < ipsec_esp_trans_default_level && + suser(p->p_ucred, &p->p_acflag)) { + error = EACCES; + break; + } + inp->inp_seclevel[SL_ESP_TRANS] = optval; + break; + + case IP_ESP_NETWORK_LEVEL: + if (optval < ipsec_esp_network_default_level && + suser(p->p_ucred, &p->p_acflag)) { + error = EACCES; + break; + } + inp->inp_seclevel[SL_ESP_NETWORK] = optval; + break; + } + if (!error) + inp->inp_secrequire = get_sa_require(inp); +#endif + break; + + default: + error = ENOPROTOOPT; + break; + } + if (m) + (void)m_free(m); + break; + + case PRCO_GETOPT: + switch (optname) { + case IP_OPTIONS: + case IP_RETOPTS: + *mp = m = m_get(M_WAIT, MT_SOOPTS); + if (inp->inp_options) { + m->m_len = inp->inp_options->m_len; + bcopy(mtod(inp->inp_options, caddr_t), + mtod(m, caddr_t), (unsigned)m->m_len); + } else + m->m_len = 0; + break; + + case IP_TOS: + case IP_TTL: + case IP_RECVOPTS: + case IP_RECVRETOPTS: + case IP_RECVDSTADDR: + *mp = m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = sizeof(int); + switch (optname) { + + case IP_TOS: + optval = inp->inp_ip.ip_tos; + break; + + case IP_TTL: + optval = inp->inp_ip.ip_ttl; + break; + +#define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0) + + case IP_RECVOPTS: + optval = OPTBIT(INP_RECVOPTS); + break; + + case IP_RECVRETOPTS: + optval = OPTBIT(INP_RECVRETOPTS); + break; + + case IP_RECVDSTADDR: + optval = OPTBIT(INP_RECVDSTADDR); + break; + } + *mtod(m, int *) = optval; + break; + + case IP_MULTICAST_IF: + case IP_MULTICAST_TTL: + case IP_MULTICAST_LOOP: + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + error = ip_getmoptions(optname, inp->inp_moptions, mp); + break; + + case IP_PORTRANGE: + *mp = m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = sizeof(int); + + if (inp->inp_flags & INP_HIGHPORT) + optval = IP_PORTRANGE_HIGH; + else if (inp->inp_flags & INP_LOWPORT) + optval = IP_PORTRANGE_LOW; + else + optval = 0; + + *mtod(m, int *) = optval; + break; + + case IPSEC_OUTSA: +#ifndef IPSEC + error = EINVAL; +#else + s = spltdb(); + if (inp->inp_tdb == NULL) { + error = ENOENT; + } else { + tdbi.spi = inp->inp_tdb->tdb_spi; + tdbi.dst = inp->inp_tdb->tdb_dst; + tdbi.proto = inp->inp_tdb->tdb_sproto; + *mp = m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = sizeof(tdbi); + bcopy((caddr_t)&tdbi, mtod(m, caddr_t), + (unsigned)m->m_len); + } + splx(s); +#endif /* IPSEC */ + break; + + case IP_AUTH_LEVEL: + case IP_ESP_TRANS_LEVEL: + case IP_ESP_NETWORK_LEVEL: +#ifndef IPSEC + *mtod(m, int *) = IPSEC_LEVEL_NONE; +#else + switch (optname) { + case IP_AUTH_LEVEL: + optval = inp->inp_seclevel[SL_AUTH]; + break; + + case IP_ESP_TRANS_LEVEL: + optval = inp->inp_seclevel[SL_ESP_TRANS]; + break; + + case IP_ESP_NETWORK_LEVEL: + optval = inp->inp_seclevel[SL_ESP_NETWORK]; + break; + } + *mtod(m, int *) = optval; +#endif + break; + default: + error = ENOPROTOOPT; + break; + } + break; + } + return (error); +} + +/* + * Set up IP options in pcb for insertion in output packets. + * Store in mbuf with pointer in pcbopt, adding pseudo-option + * with destination address if source routed. + */ +int +#ifdef notyet +ip_pcbopts(optname, pcbopt, m) + int optname; +#else +ip_pcbopts(pcbopt, m) +#endif + struct mbuf **pcbopt; + register struct mbuf *m; +{ + register int cnt, optlen; + register u_char *cp; + u_char opt; + + /* turn off any old options */ + if (*pcbopt) + (void)m_free(*pcbopt); + *pcbopt = 0; + if (m == (struct mbuf *)0 || m->m_len == 0) { + /* + * Only turning off any previous options. + */ + if (m) + (void)m_free(m); + return (0); + } + +#ifndef vax + if (m->m_len % sizeof(int32_t)) + goto bad; +#endif + /* + * IP first-hop destination address will be stored before + * actual options; move other options back + * and clear it when none present. + */ + if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN]) + goto bad; + cnt = m->m_len; + m->m_len += sizeof(struct in_addr); + cp = mtod(m, u_char *) + sizeof(struct in_addr); + ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt); + bzero(mtod(m, caddr_t), sizeof(struct in_addr)); + + for (; cnt > 0; cnt -= optlen, cp += optlen) { + opt = cp[IPOPT_OPTVAL]; + if (opt == IPOPT_EOL) + break; + if (opt == IPOPT_NOP) + optlen = 1; + else { + optlen = cp[IPOPT_OLEN]; + if (optlen <= IPOPT_OLEN || optlen > cnt) + goto bad; + } + switch (opt) { + + default: + break; + + case IPOPT_LSRR: + case IPOPT_SSRR: + /* + * user process specifies route as: + * ->A->B->C->D + * D must be our final destination (but we can't + * check that since we may not have connected yet). + * A is first hop destination, which doesn't appear in + * actual IP option, but is stored before the options. + */ + if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr)) + goto bad; + m->m_len -= sizeof(struct in_addr); + cnt -= sizeof(struct in_addr); + optlen -= sizeof(struct in_addr); + cp[IPOPT_OLEN] = optlen; + /* + * Move first hop before start of options. + */ + bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t), + sizeof(struct in_addr)); + /* + * Then copy rest of options back + * to close up the deleted entry. + */ + ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] + + sizeof(struct in_addr)), + (caddr_t)&cp[IPOPT_OFFSET+1], + (unsigned)cnt + sizeof(struct in_addr)); + break; + } + } + if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr)) + goto bad; + *pcbopt = m; + return (0); + +bad: + (void)m_free(m); + return (EINVAL); +} + +/* + * Set the IP multicast options in response to user setsockopt(). + */ +int +ip_setmoptions(optname, imop, m) + int optname; + struct ip_moptions **imop; + struct mbuf *m; +{ + register int error = 0; + u_char loop; + register int i; + struct in_addr addr; + register struct ip_mreq *mreq; + register struct ifnet *ifp; + register struct ip_moptions *imo = *imop; + struct route ro; + register struct sockaddr_in *dst; + + if (imo == NULL) { + /* + * No multicast option buffer attached to the pcb; + * allocate one and initialize to default values. + */ + imo = (struct ip_moptions *)malloc(sizeof(*imo), M_IPMOPTS, + M_WAITOK); + + if (imo == NULL) + return (ENOBUFS); + *imop = imo; + imo->imo_multicast_ifp = NULL; + imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; + imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; + imo->imo_num_memberships = 0; + } + + switch (optname) { + + case IP_MULTICAST_IF: + /* + * Select the interface for outgoing multicast packets. + */ + if (m == NULL || m->m_len != sizeof(struct in_addr)) { + error = EINVAL; + break; + } + addr = *(mtod(m, struct in_addr *)); + /* + * INADDR_ANY is used to remove a previous selection. + * When no interface is selected, a default one is + * chosen every time a multicast packet is sent. + */ + if (addr.s_addr == INADDR_ANY) { + imo->imo_multicast_ifp = NULL; + break; + } + /* + * The selected interface is identified by its local + * IP address. Find the interface and confirm that + * it supports multicasting. + */ + INADDR_TO_IFP(addr, ifp); + if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) { + error = EADDRNOTAVAIL; + break; + } + imo->imo_multicast_ifp = ifp; + break; + + case IP_MULTICAST_TTL: + /* + * Set the IP time-to-live for outgoing multicast packets. + */ + if (m == NULL || m->m_len != 1) { + error = EINVAL; + break; + } + imo->imo_multicast_ttl = *(mtod(m, u_char *)); + break; + + case IP_MULTICAST_LOOP: + /* + * Set the loopback flag for outgoing multicast packets. + * Must be zero or one. + */ + if (m == NULL || m->m_len != 1 || + (loop = *(mtod(m, u_char *))) > 1) { + error = EINVAL; + break; + } + imo->imo_multicast_loop = loop; + break; + + case IP_ADD_MEMBERSHIP: + /* + * Add a multicast group membership. + * Group must be a valid IP multicast address. + */ + if (m == NULL || m->m_len != sizeof(struct ip_mreq)) { + error = EINVAL; + break; + } + mreq = mtod(m, struct ip_mreq *); + if (!IN_MULTICAST(mreq->imr_multiaddr.s_addr)) { + error = EINVAL; + break; + } + /* + * If no interface address was provided, use the interface of + * the route to the given multicast address. + */ + if (mreq->imr_interface.s_addr == INADDR_ANY) { + ro.ro_rt = NULL; + dst = satosin(&ro.ro_dst); + dst->sin_len = sizeof(*dst); + dst->sin_family = AF_INET; + dst->sin_addr = mreq->imr_multiaddr; + rtalloc(&ro); + if (ro.ro_rt == NULL) { + error = EADDRNOTAVAIL; + break; + } + ifp = ro.ro_rt->rt_ifp; + rtfree(ro.ro_rt); + } else { + INADDR_TO_IFP(mreq->imr_interface, ifp); + } + /* + * See if we found an interface, and confirm that it + * supports multicast. + */ + if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) { + error = EADDRNOTAVAIL; + break; + } + /* + * See if the membership already exists or if all the + * membership slots are full. + */ + for (i = 0; i < imo->imo_num_memberships; ++i) { + if (imo->imo_membership[i]->inm_ifp == ifp && + imo->imo_membership[i]->inm_addr.s_addr + == mreq->imr_multiaddr.s_addr) + break; + } + if (i < imo->imo_num_memberships) { + error = EADDRINUSE; + break; + } + if (i == IP_MAX_MEMBERSHIPS) { + error = ETOOMANYREFS; + break; + } + /* + * Everything looks good; add a new record to the multicast + * address list for the given interface. + */ + if ((imo->imo_membership[i] = + in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) { + error = ENOBUFS; + break; + } + ++imo->imo_num_memberships; + break; + + case IP_DROP_MEMBERSHIP: + /* + * Drop a multicast group membership. + * Group must be a valid IP multicast address. + */ + if (m == NULL || m->m_len != sizeof(struct ip_mreq)) { + error = EINVAL; + break; + } + mreq = mtod(m, struct ip_mreq *); + if (!IN_MULTICAST(mreq->imr_multiaddr.s_addr)) { + error = EINVAL; + break; + } + /* + * If an interface address was specified, get a pointer + * to its ifnet structure. + */ + if (mreq->imr_interface.s_addr == INADDR_ANY) + ifp = NULL; + else { + INADDR_TO_IFP(mreq->imr_interface, ifp); + if (ifp == NULL) { + error = EADDRNOTAVAIL; + break; + } + } + /* + * Find the membership in the membership array. + */ + for (i = 0; i < imo->imo_num_memberships; ++i) { + if ((ifp == NULL || + imo->imo_membership[i]->inm_ifp == ifp) && + imo->imo_membership[i]->inm_addr.s_addr == + mreq->imr_multiaddr.s_addr) + break; + } + if (i == imo->imo_num_memberships) { + error = EADDRNOTAVAIL; + break; + } + /* + * Give up the multicast address record to which the + * membership points. + */ + in_delmulti(imo->imo_membership[i]); + /* + * Remove the gap in the membership array. + */ + for (++i; i < imo->imo_num_memberships; ++i) + imo->imo_membership[i-1] = imo->imo_membership[i]; + --imo->imo_num_memberships; + break; + + default: + error = EOPNOTSUPP; + break; + } + + /* + * If all options have default values, no need to keep the mbuf. + */ + if (imo->imo_multicast_ifp == NULL && + imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL && + imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP && + imo->imo_num_memberships == 0) { + free(*imop, M_IPMOPTS); + *imop = NULL; + } + + return (error); +} + +/* + * Return the IP multicast options in response to user getsockopt(). + */ +int +ip_getmoptions(optname, imo, mp) + int optname; + register struct ip_moptions *imo; + register struct mbuf **mp; +{ + u_char *ttl; + u_char *loop; + struct in_addr *addr; + struct in_ifaddr *ia; + + *mp = m_get(M_WAIT, MT_SOOPTS); + + switch (optname) { + + case IP_MULTICAST_IF: + addr = mtod(*mp, struct in_addr *); + (*mp)->m_len = sizeof(struct in_addr); + if (imo == NULL || imo->imo_multicast_ifp == NULL) + addr->s_addr = INADDR_ANY; + else { + IFP_TO_IA(imo->imo_multicast_ifp, ia); + addr->s_addr = (ia == NULL) ? INADDR_ANY + : ia->ia_addr.sin_addr.s_addr; + } + return (0); + + case IP_MULTICAST_TTL: + ttl = mtod(*mp, u_char *); + (*mp)->m_len = 1; + *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL + : imo->imo_multicast_ttl; + return (0); + + case IP_MULTICAST_LOOP: + loop = mtod(*mp, u_char *); + (*mp)->m_len = 1; + *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP + : imo->imo_multicast_loop; + return (0); + + default: + return (EOPNOTSUPP); + } +} + +/* + * Discard the IP multicast options. + */ +void +ip_freemoptions(imo) + register struct ip_moptions *imo; +{ + register int i; + + if (imo != NULL) { + for (i = 0; i < imo->imo_num_memberships; ++i) + in_delmulti(imo->imo_membership[i]); + free(imo, M_IPMOPTS); + } +} + +/* + * Routine called from ip_output() to loop back a copy of an IP multicast + * packet to the input queue of a specified interface. Note that this + * calls the output routine of the loopback "driver", but with an interface + * pointer that might NOT be &loif -- easier than replicating that code here. + */ +static void +ip_mloopback(ifp, m, dst) + struct ifnet *ifp; + register struct mbuf *m; + register struct sockaddr_in *dst; +{ + register struct ip *ip; + struct mbuf *copym; + + copym = m_copy(m, 0, M_COPYALL); + if (copym != NULL) { + /* + * We don't bother to fragment if the IP length is greater + * than the interface's MTU. Can this possibly matter? + */ + ip = mtod(copym, struct ip *); + ip->ip_len = htons((u_int16_t)ip->ip_len); + ip->ip_off = htons((u_int16_t)ip->ip_off); + ip->ip_sum = 0; + ip->ip_sum = in_cksum(copym, ip->ip_hl << 2); + (void) looutput(ifp, copym, sintosa(dst), NULL); + } +} diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/raw_ip.c b/ecos/packages/net/tcpip/current/src/sys/netinet/raw_ip.c new file mode 100644 index 0000000..06d86e1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/raw_ip.c @@ -0,0 +1,522 @@ +//========================================================================== +// +// sys/netinet/raw_ip.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: raw_ip.c,v 1.19 1999/09/23 07:20:35 deraadt Exp $ */ +/* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#include <sys/socketvar.h> +#include <sys/errno.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_mroute.h> +#include <netinet/ip_var.h> +#include <netinet/in_pcb.h> +#include <netinet/in_var.h> +#include <netinet/ip_icmp.h> + +#ifdef IPSEC +extern int check_ipsec_policy __P((struct inpcb *, u_int32_t)); +#endif + +#include <machine/stdarg.h> + +struct inpcbtable rawcbtable; + +/* + * Nominal space allocated to a raw ip socket. + */ +#define RIPSNDQ 8192 +#define RIPRCVQ 8192 + +/* + * Raw interface to IP protocol. + */ + +/* + * Initialize raw connection block q. + */ +void +rip_init() +{ + + in_pcbinit(&rawcbtable, 1); +} + +struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; + +/* + * Setup generic address and protocol structures + * for raw_input routine, then pass them along with + * mbuf chain. + */ +void +#if __STDC__ +rip_input(struct mbuf *m, ...) +#else +rip_input(m, va_alist) + struct mbuf *m; + va_dcl +#endif +{ + register struct ip *ip = mtod(m, struct ip *); + register struct inpcb *inp; + struct socket *last = 0; + + ripsrc.sin_addr = ip->ip_src; + for (inp = rawcbtable.inpt_queue.cqh_first; + inp != (struct inpcb *)&rawcbtable.inpt_queue; + inp = inp->inp_queue.cqe_next) { + if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) + continue; + if (inp->inp_laddr.s_addr && + inp->inp_laddr.s_addr != ip->ip_dst.s_addr) + continue; + if (inp->inp_faddr.s_addr && + inp->inp_faddr.s_addr != ip->ip_src.s_addr) + continue; + if (last) { + struct mbuf *n; + if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { + if (sbappendaddr(&last->so_rcv, + sintosa(&ripsrc), n, + (struct mbuf *)0) == 0) + /* should notify about lost packet */ + m_freem(n); + else + sorwakeup(last); + } + } + last = inp->inp_socket; + } + if (last) { + if (sbappendaddr(&last->so_rcv, sintosa(&ripsrc), m, + (struct mbuf *)0) == 0) + m_freem(m); + else + sorwakeup(last); + } else { + if (ip->ip_p != IPPROTO_ICMP) + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0); + else + m_freem(m); + ipstat.ips_noproto++; + ipstat.ips_delivered--; + } +} + +/* + * Generate IP header and pass packet to ip_output. + * Tack on options user may have setup with control call. + */ +int +#if __STDC__ +rip_output(struct mbuf *m, ...) +#else +rip_output(m, va_alist) + struct mbuf *m; + va_dcl +#endif +{ + struct socket *so; + u_long dst; + register struct ip *ip; + register struct inpcb *inp; + int flags; + va_list ap; + + va_start(ap, m); + so = va_arg(ap, struct socket *); + dst = va_arg(ap, u_long); + va_end(ap); + + inp = sotoinpcb(so); + flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; + + /* + * If the user handed us a complete IP packet, use it. + * Otherwise, allocate an mbuf for a header and fill it in. + */ + if ((inp->inp_flags & INP_HDRINCL) == 0) { + if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { + m_freem(m); + return (EMSGSIZE); + } + M_PREPEND(m, sizeof(struct ip), M_WAIT); + ip = mtod(m, struct ip *); + ip->ip_tos = 0; + ip->ip_off = 0; + ip->ip_p = inp->inp_ip.ip_p; + ip->ip_len = m->m_pkthdr.len; + ip->ip_src = inp->inp_laddr; + ip->ip_dst.s_addr = dst; + ip->ip_ttl = MAXTTL; + } else { + if (m->m_pkthdr.len > IP_MAXPACKET) { + m_freem(m); + return (EMSGSIZE); + } + ip = mtod(m, struct ip *); + NTOHS(ip->ip_len); + NTOHS(ip->ip_off); + /* + * don't allow both user specified and setsockopt options, + * and don't allow packet length sizes that will crash + */ + if ((ip->ip_hl != (sizeof (*ip) >> 2) && inp->inp_options) || + ip->ip_len > m->m_pkthdr.len || + ip->ip_len < ip->ip_hl << 2) { + m_freem(m); + return (EINVAL); + } + if (ip->ip_id == 0) { +#ifdef RANDOM_IP_ID + ip->ip_id = ip_randomid(); +#else + ip->ip_id = htons(ip_id++); +#endif + } + /* XXX prevent ip_output from overwriting header fields */ + flags |= IP_RAWOUTPUT; + ipstat.ips_rawout++; + } +#ifdef INET6 + /* + * A thought: Even though raw IP shouldn't be able to set IPv6 + * multicast options, if it does, the last parameter to + * ip_output should be guarded against v6/v4 problems. + */ +#endif + return (ip_output(m, inp->inp_options, &inp->inp_route, flags, + inp->inp_moptions, inp)); +} + +/* + * Raw IP socket option processing. + */ +int +rip_ctloutput(op, so, level, optname, m) + int op; + struct socket *so; + int level, optname; + struct mbuf **m; +{ + register struct inpcb *inp = sotoinpcb(so); + register int error; + + if (level != IPPROTO_IP) { + if (op == PRCO_SETOPT && *m) + (void) m_free(*m); + return (EINVAL); + } + + switch (optname) { + + case IP_HDRINCL: + error = 0; + if (op == PRCO_SETOPT) { + if (*m == 0 || (*m)->m_len < sizeof (int)) + error = EINVAL; + else if (*mtod(*m, int *)) + inp->inp_flags |= INP_HDRINCL; + else + inp->inp_flags &= ~INP_HDRINCL; + if (*m) + (void)m_free(*m); + } else { + *m = m_get(M_WAIT, M_SOOPTS); + (*m)->m_len = sizeof(int); + *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL; + } + return (error); + + case MRT_INIT: + case MRT_DONE: + case MRT_ADD_VIF: + case MRT_DEL_VIF: + case MRT_ADD_MFC: + case MRT_DEL_MFC: + case MRT_VERSION: + case MRT_ASSERT: +#ifdef MROUTING + switch (op) { + case PRCO_SETOPT: + error = ip_mrouter_set(optname, so, m); + break; + case PRCO_GETOPT: + error = ip_mrouter_get(optname, so, m); + break; + default: + error = EINVAL; + break; + } + return (error); +#else + if (op == PRCO_SETOPT && *m) + m_free(*m); + return (EOPNOTSUPP); +#endif + } + return (ip_ctloutput(op, so, level, optname, m)); +} + +u_long rip_sendspace = RIPSNDQ; +u_long rip_recvspace = RIPRCVQ; + +/*ARGSUSED*/ +int +rip_usrreq(so, req, m, nam, control) + register struct socket *so; + int req; + struct mbuf *m, *nam, *control; +{ + register int error = 0; + register struct inpcb *inp = sotoinpcb(so); +#ifdef MROUTING + extern struct socket *ip_mrouter; +#endif + if (req == PRU_CONTROL) + return (in_control(so, (u_long)m, (caddr_t)nam, + (struct ifnet *)control)); + + if (inp == NULL && req != PRU_ATTACH) { + error = EINVAL; + goto release; + } + + switch (req) { + + case PRU_ATTACH: + if (inp) + panic("rip_attach"); +#ifndef __ECOS + if ((so->so_state & SS_PRIV) == 0) { + error = EACCES; + break; + } +#endif + if ((error = soreserve(so, rip_sendspace, rip_recvspace)) || + (error = in_pcballoc(so, &rawcbtable))) + break; + inp = (struct inpcb *)so->so_pcb; + inp->inp_ip.ip_p = (long)nam; + break; + + case PRU_DISCONNECT: + if ((so->so_state & SS_ISCONNECTED) == 0) { + error = ENOTCONN; + break; + } + /* FALLTHROUGH */ + case PRU_ABORT: + soisdisconnected(so); + /* FALLTHROUGH */ + case PRU_DETACH: + if (inp == 0) + panic("rip_detach"); +#ifdef MROUTING + if (so == ip_mrouter) + ip_mrouter_done(); +#endif + in_pcbdetach(inp); + break; + + case PRU_BIND: + { + struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); + + if (nam->m_len != sizeof(*addr)) { + error = EINVAL; + break; + } + if ((ifnet.tqh_first == 0) || + ((addr->sin_family != AF_INET) && + (addr->sin_family != AF_IMPLINK)) || + (addr->sin_addr.s_addr && + ifa_ifwithaddr(sintosa(addr)) == 0)) { + error = EADDRNOTAVAIL; + break; + } + inp->inp_laddr = addr->sin_addr; + break; + } + case PRU_CONNECT: + { + struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); + + if (nam->m_len != sizeof(*addr)) { + error = EINVAL; + break; + } + if (ifnet.tqh_first == 0) { + error = EADDRNOTAVAIL; + break; + } + if ((addr->sin_family != AF_INET) && + (addr->sin_family != AF_IMPLINK)) { + error = EAFNOSUPPORT; + break; + } + inp->inp_faddr = addr->sin_addr; + soisconnected(so); + break; + } + + case PRU_CONNECT2: + error = EOPNOTSUPP; + break; + + /* + * Mark the connection as being incapable of further input. + */ + case PRU_SHUTDOWN: + socantsendmore(so); + break; + + /* + * Ship a packet out. The appropriate raw output + * routine handles any massaging necessary. + */ + case PRU_SEND: + { + register u_int32_t dst; + + if (so->so_state & SS_ISCONNECTED) { + if (nam) { + error = EISCONN; + break; + } + dst = inp->inp_faddr.s_addr; + } else { + if (nam == NULL) { + error = ENOTCONN; + break; + } + dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr; + } +#ifdef IPSEC + if (!(error = check_ipsec_policy(inp, dst))) +#endif + error = rip_output(m, so, dst); + m = NULL; + break; + } + + case PRU_SENSE: + /* + * stat: don't bother with a blocksize. + */ + return (0); + + /* + * Not supported. + */ + case PRU_RCVOOB: + case PRU_RCVD: + case PRU_LISTEN: + case PRU_ACCEPT: + case PRU_SENDOOB: + error = EOPNOTSUPP; + break; + + case PRU_SOCKADDR: + in_setsockaddr(inp, nam); + break; + + case PRU_PEERADDR: + in_setpeeraddr(inp, nam); + break; + + default: + panic("rip_usrreq"); + } +release: + if (m != NULL) + m_freem(m); + return (error); +} diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_debug.c b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_debug.c new file mode 100644 index 0000000..a4627b6 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_debug.c @@ -0,0 +1,235 @@ +//========================================================================== +// +// sys/netinet/tcp_debug.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_debug.c,v 1.6 1999/12/08 06:50:20 itojun Exp $ */ +/* $NetBSD: tcp_debug.c,v 1.10 1996/02/13 23:43:36 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_debug.c 8.1 (Berkeley) 6/10/93 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#ifdef TCPDEBUG +/* load symbolic names */ +#define PRUREQUESTS +#define TCPSTATES +#define TCPTIMERS +#define TANAMES + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/protosw.h> +#include <sys/errno.h> + +#include <net/route.h> +#include <net/if.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_fsm.h> +#include <netinet/tcp_seq.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/tcpip.h> +#include <netinet/tcp_debug.h> + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#include <netinet6/ip6.h> +#endif /* INET6 */ + +#ifdef TCPDEBUG +int tcpconsdebug = 1; +#endif +/* + * Tcp debug routines + */ +void +tcp_trace(act, ostate, tp, headers, req, len) + short act, ostate; + struct tcpcb *tp; + caddr_t headers; + int req; + int len; +{ +#ifdef TCPDEBUG + tcp_seq seq, ack; + int flags; +#endif + struct tcp_debug *td = &tcp_debug[tcp_debx++]; + struct tcpiphdr *ti = (struct tcpiphdr *)headers; +#ifdef INET6 + struct tcphdr *th; + struct tcpipv6hdr *ti6 = (struct tcpipv6hdr *)ti; +#endif + + if (tcp_debx == TCP_NDEBUG) + tcp_debx = 0; + td->td_time = iptime(); + td->td_act = act; + td->td_ostate = ostate; + td->td_tcb = (caddr_t)tp; + if (tp) + td->td_cb = *tp; + else + bzero((caddr_t)&td->td_cb, sizeof (*tp)); +#ifdef INET6 + if (tp->pf == PF_INET6) { + if (ti) { + th = &ti6->ti6_t; + td->td_ti6 = *ti6; + } else { + bzero(&td->td_ti6, sizeof(struct tcpipv6hdr)); + } + } else { + if (ti) { + th = &ti->ti_t; + td->td_ti = *ti; + } else { + bzero(&td->td_ti, sizeof(struct tcpiphdr)); + } + } +#else /* INET6 */ + if (ti) + td->td_ti = *ti; + else + bzero((caddr_t)&td->td_ti, sizeof (*ti)); +#endif /* INET6 */ + + td->td_req = req; +#ifdef TCPDEBUG + if (tcpconsdebug == 0) + return; + if (tp) + printf("%x %s:", tp, tcpstates[ostate]); + else + printf("???????? "); + printf("%s ", tanames[act]); + switch (act) { + + case TA_INPUT: + case TA_OUTPUT: + case TA_DROP: + if (ti == 0) + break; + seq = th->th_seq; + ack = th->th_ack; + if (act == TA_OUTPUT) { + seq = ntohl(seq); + ack = ntohl(ack); + } + if (len) + printf("[%x..%x)", seq, seq+len); + else + printf("%x", seq); + printf("@%x, urp=%x", ack, th->th_urp); + flags = th->th_flags; + if (flags) { +#ifndef lint + char *cp = "<"; +#define pf(f) { if (th->th_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } + pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG); +#endif + printf(">"); + } + break; + + case TA_USER: + printf("%s", prurequests[req&0xff]); + if ((req & 0xff) == PRU_SLOWTIMO) + printf("<%s>", tcptimers[req>>8]); + break; + } + if (tp) + printf(" -> %s", tcpstates[tp->t_state]); + /* print out internal state of tp !?! */ + printf("\n"); + if (tp == 0) + return; + printf("\trcv_(nxt,wnd,up) (%x,%x,%x) snd_(una,nxt,max) (%x,%x,%x)\n", + tp->rcv_nxt, tp->rcv_wnd, tp->rcv_up, tp->snd_una, tp->snd_nxt, + tp->snd_max); + printf("\tsnd_(wl1,wl2,wnd) (%x,%x,%x)\n", + tp->snd_wl1, tp->snd_wl2, tp->snd_wnd); +#endif /* TCPDEBUG */ +} +#endif diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_input.c b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_input.c new file mode 100644 index 0000000..b7a4ad9 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_input.c @@ -0,0 +1,2996 @@ +//========================================================================== +// +// sys/netinet/tcp_input.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_input.c,v 1.54 1999/12/15 16:37:20 provos Exp $ */ +/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_input.c 8.5 (Berkeley) 4/10/94 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#ifndef TUBA_INCLUDE +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/errno.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_fsm.h> +#include <netinet/tcp_seq.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/tcpip.h> +#include <netinet/tcp_debug.h> +#ifndef __ECOS +#include <dev/rndvar.h> +#endif +#include <machine/stdarg.h> +#ifndef __ECOS +#include <sys/md5k.h> +#endif + +#ifdef IPSEC +#include <netinet/ip_ipsp.h> +#endif /* IPSEC */ + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#include <sys/domain.h> +#include <netinet6/in6_var.h> +#include <netinet/ip6.h> +#include <netinet6/ip6_var.h> +#include <netinet6/tcpipv6.h> +#include <netinet/icmp6.h> +#include <netinet6/nd6.h> + +#ifndef CREATE_IPV6_MAPPED +#define CREATE_IPV6_MAPPED(a6, a4) \ +do { \ + bzero(&(a6), sizeof(a6)); \ + (a6).s6_addr[10] = (a6).s6_addr[11] = 0xff; \ + *(u_int32_t *)&(a6).s6_addr[12] = (a4); \ +} while (0) +#endif + +struct tcpiphdr tcp_saveti; +struct tcpipv6hdr tcp_saveti6; + +/* for the packet header length in the mbuf */ +#define M_PH_LEN(m) (((struct mbuf *)(m))->m_pkthdr.len) +#define M_V6_LEN(m) (M_PH_LEN(m) - sizeof(struct ip6_hdr)) +#define M_V4_LEN(m) (M_PH_LEN(m) - sizeof(struct ip)) +#endif /* INET6 */ + +int tcprexmtthresh = 3; +struct tcpiphdr tcp_saveti; +int tcptv_keep_init = TCPTV_KEEP_INIT; + +extern u_long sb_max; + +#endif /* TUBA_INCLUDE */ +#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) + +/* for modulo comparisons of timestamps */ +#define TSTMP_LT(a,b) ((int)((a)-(b)) < 0) +#define TSTMP_GEQ(a,b) ((int)((a)-(b)) >= 0) + +/* + * Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. + */ +#ifdef INET6 +#define ND6_HINT(tp) \ +do { \ + if (tp && tp->t_inpcb && (tp->t_inpcb->inp_flags & INP_IPV6) \ + && !(tp->t_inpcb->inp_flags & INP_IPV6_MAPPED) \ + && tp->t_inpcb->inp_route6.ro_rt) { \ + nd6_nud_hint(tp->t_inpcb->inp_route6.ro_rt, NULL); \ + } \ +} while (0) +#else +#define ND6_HINT(tp) +#endif + +/* + * Insert segment ti into reassembly queue of tcp with + * control block tp. Return TH_FIN if reassembly now includes + * a segment with FIN. The macro form does the common case inline + * (segment is the next to be received on an established connection, + * and the queue is empty), avoiding linkage into and removal + * from the queue and repetition of various conversions. + * Set DELACK for segments received in order, but ack immediately + * when segments are out of order (so fast retransmit can work). + */ + +#ifndef TUBA_INCLUDE + +int +tcp_reass(tp, th, m, tlen) + register struct tcpcb *tp; + register struct tcphdr *th; + struct mbuf *m; + int *tlen; +{ + register struct ipqent *p, *q, *nq, *tiqe; + struct socket *so = tp->t_inpcb->inp_socket; + int flags; + + /* + * Call with th==0 after become established to + * force pre-ESTABLISHED data up to user socket. + */ + if (th == 0) + goto present; + + /* + * Allocate a new queue entry, before we throw away any data. + * If we can't, just drop the packet. XXX + */ + MALLOC(tiqe, struct ipqent *, sizeof (struct ipqent), M_IPQ, M_NOWAIT); + if (tiqe == NULL) { + tcpstat.tcps_rcvmemdrop++; + m_freem(m); + return (0); + } + + /* + * Find a segment which begins after this one does. + */ + for (p = NULL, q = tp->segq.lh_first; q != NULL; + p = q, q = q->ipqe_q.le_next) + if (SEQ_GT(q->ipqe_tcp->th_seq, th->th_seq)) + break; + + /* + * If there is a preceding segment, it may provide some of + * our data already. If so, drop the data from the incoming + * segment. If it provides all of our data, drop us. + */ + if (p != NULL) { + register struct tcphdr *phdr = p->ipqe_tcp; + register int i; + + /* conversion to int (in i) handles seq wraparound */ + i = phdr->th_seq + phdr->th_reseqlen - th->th_seq; + if (i > 0) { + if (i >= *tlen) { + tcpstat.tcps_rcvduppack++; + tcpstat.tcps_rcvdupbyte += *tlen; + m_freem(m); + FREE(tiqe, M_IPQ); + return (0); + } + m_adj(m, i); + *tlen -= i; + th->th_seq += i; + } + } + tcpstat.tcps_rcvoopack++; + tcpstat.tcps_rcvoobyte += *tlen; + + /* + * While we overlap succeeding segments trim them or, + * if they are completely covered, dequeue them. + */ + for (; q != NULL; q = nq) { + register struct tcphdr *qhdr = q->ipqe_tcp; + register int i = (th->th_seq + *tlen) - qhdr->th_seq; + + if (i <= 0) + break; + if (i < qhdr->th_reseqlen) { + qhdr->th_seq += i; + qhdr->th_reseqlen -= i; + m_adj(q->ipqe_m, i); + break; + } + nq = q->ipqe_q.le_next; + m_freem(q->ipqe_m); + LIST_REMOVE(q, ipqe_q); + FREE(q, M_IPQ); + } + + /* Insert the new fragment queue entry into place. */ + tiqe->ipqe_m = m; + th->th_reseqlen = *tlen; + tiqe->ipqe_tcp = th; + if (p == NULL) { + LIST_INSERT_HEAD(&tp->segq, tiqe, ipqe_q); + } else { + LIST_INSERT_AFTER(p, tiqe, ipqe_q); + } + +present: + /* + * Present data to user, advancing rcv_nxt through + * completed sequence space. + */ + if (TCPS_HAVEESTABLISHED(tp->t_state) == 0) + return (0); + q = tp->segq.lh_first; + if (q == NULL || q->ipqe_tcp->th_seq != tp->rcv_nxt) + return (0); + if (tp->t_state == TCPS_SYN_RECEIVED && q->ipqe_tcp->th_reseqlen) + return (0); + do { + tp->rcv_nxt += q->ipqe_tcp->th_reseqlen; + flags = q->ipqe_tcp->th_flags & TH_FIN; + + nq = q->ipqe_q.le_next; + LIST_REMOVE(q, ipqe_q); + ND6_HINT(tp); + if (so->so_state & SS_CANTRCVMORE) + m_freem(q->ipqe_m); + else + sbappend(&so->so_rcv, q->ipqe_m); + FREE(q, M_IPQ); + q = nq; + } while (q != NULL && q->ipqe_tcp->th_seq == tp->rcv_nxt); + sorwakeup(so); + return (flags); +} + +/* + * First check for a port-specific bomb. We do not want to drop half-opens + * for other ports if this is the only port being bombed. We only check + * the bottom 40 half open connections, to avoid wasting too much time. + * + * Or, otherwise it is more likely a generic syn bomb, so delete the oldest + * half-open connection. + */ +void +tcpdropoldhalfopen(avoidtp, port) + struct tcpcb *avoidtp; + u_int16_t port; +{ + register struct inpcb *inp; + register struct tcpcb *tp; + int ncheck = 40; + int s; + + s = splnet(); + inp = tcbtable.inpt_queue.cqh_first; + if (inp) /* XXX */ + for (; inp != (struct inpcb *)&tcbtable.inpt_queue && --ncheck; + inp = inp->inp_queue.cqe_prev) { + if ((tp = (struct tcpcb *)inp->inp_ppcb) && + tp != avoidtp && + tp->t_state == TCPS_SYN_RECEIVED && + port == inp->inp_lport) { + tcp_close(tp); + goto done; + } + } + + inp = tcbtable.inpt_queue.cqh_first; + if (inp) /* XXX */ + for (; inp != (struct inpcb *)&tcbtable.inpt_queue; + inp = inp->inp_queue.cqe_prev) { + if ((tp = (struct tcpcb *)inp->inp_ppcb) && + tp != avoidtp && + tp->t_state == TCPS_SYN_RECEIVED) { + tcp_close(tp); + goto done; + } + } +done: + splx(s); +} + +#if defined(INET6) && !defined(TCP6) +int +tcp6_input(mp, offp, proto) + struct mbuf **mp; + int *offp, proto; +{ + struct mbuf *m = *mp; + +#if defined(NFAITH) && 0 < NFAITH + if (m->m_pkthdr.rcvif) { + if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { + /* XXX send icmp6 host/port unreach? */ + m_freem(m); + return IPPROTO_DONE; + } + } +#endif + + /* + * draft-itojun-ipv6-tcp-to-anycast + * better place to put this in? + */ + if (m->m_flags & M_ANYCAST6) { + if (m->m_len >= sizeof(struct ip6_hdr)) { + struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); + icmp6_error(m, ICMP6_DST_UNREACH, + ICMP6_DST_UNREACH_ADDR, + (caddr_t)&ip6->ip6_dst - (caddr_t)ip6); + } else + m_freem(m); + return IPPROTO_DONE; + } + + tcp_input(m, *offp, proto); + return IPPROTO_DONE; +} +#endif + +/* + * TCP input routine, follows pages 65-76 of the + * protocol specification dated September, 1981 very closely. + */ +void +#if __STDC__ +tcp_input(struct mbuf *m, ...) +#else +tcp_input(m, va_alist) + register struct mbuf *m; +#endif +{ + register struct tcpiphdr *ti; + register struct inpcb *inp; + caddr_t optp = NULL; + int optlen = 0; + int len, tlen, off; + register struct tcpcb *tp = 0; + register int tiflags; + struct socket *so = NULL; + int todrop, acked, ourfinisacked, needoutput = 0; + int hdroptlen = 0; + short ostate = 0; + struct in_addr laddr; + int dropsocket = 0; + int iss = 0; + u_long tiwin; + u_int32_t ts_val, ts_ecr; + int ts_present = 0; + int iphlen; + va_list ap; + register struct tcphdr *th; +#ifdef IPSEC + struct tdb *tdb = NULL; +#endif /* IPSEC */ +#ifdef INET6 + struct in6_addr laddr6; + unsigned short is_ipv6; /* Type of incoming datagram. */ + struct ip6_hdr *ipv6 = NULL; +#endif /* INET6 */ + + va_start(ap, m); + iphlen = va_arg(ap, int); + va_end(ap); + + tcpstat.tcps_rcvtotal++; + +#ifdef IPSEC + /* Save the last SA which was used to process the mbuf */ + if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) { + struct tdb_ident *tdbi = m->m_pkthdr.tdbi; + /* XXX gettdb() should really be called at spltdb(). */ + /* XXX this is splsoftnet(), currently they are the same. */ + tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); + free(m->m_pkthdr.tdbi, M_TEMP); + m->m_pkthdr.tdbi = NULL; + } +#endif /* IPSEC */ +#ifdef INET6 + /* + * Before we do ANYTHING, we have to figure out if it's TCP/IPv6 or + * TCP/IPv4. + */ + is_ipv6 = mtod(m, struct ip *)->ip_v == 6; +#endif /* INET6 */ + + /* + * Get IP and TCP header together in first mbuf. + * Note: IP leaves IP header in first mbuf. + */ +#ifndef INET6 + ti = mtod(m, struct tcpiphdr *); +#else /* INET6 */ + if (!is_ipv6) +#endif /* INET6 */ + if (iphlen > sizeof (struct ip)) { +#if 0 /*XXX*/ + ip_stripoptions(m, (struct mbuf *)0); +#else +#ifdef __ECOS + diag_printf("extension headers are not allowed\n"); +#else + printf("extension headers are not allowed\n"); +#endif + m_freem(m); + return; +#endif + } + if (m->m_len < iphlen + sizeof(struct tcphdr)) { + if ((m = m_pullup2(m, iphlen + sizeof(struct tcphdr))) == 0) { + tcpstat.tcps_rcvshort++; + return; + } +#ifndef INET6 + ti = mtod(m, struct tcpiphdr *); +#endif /* INET6 */ + } + + tlen = m->m_pkthdr.len - iphlen; + +#ifdef INET6 + /* + * After that, do initial segment processing which is still very + * dependent on what IP version you're using. + */ + + if (is_ipv6) { +#ifdef DIAGNOSTIC + if (iphlen < sizeof(struct ip6_hdr)) { + m_freem(m); + return; + } +#endif /* DIAGNOSTIC */ + + /* strip off any options */ + if (iphlen > sizeof(struct ip6_hdr)) { +#if 0 /*XXX*/ + ipv6_stripoptions(m, iphlen); +#else +#ifdef __ECOS + diag_printf("extension headers are not allowed\n"); +#else + printf("extension headers are not allowed\n"); +#endif + m_freem(m); + return; +#endif + iphlen = sizeof(struct ip6_hdr); + } + + ti = NULL; + ipv6 = mtod(m, struct ip6_hdr *); + + if (in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr), tlen)) { + tcpstat.tcps_rcvbadsum++; + goto drop; + } /* endif in6_cksum */ + } else { + ti = mtod(m, struct tcpiphdr *); +#endif /* INET6 */ + + /* + * Checksum extended TCP header and data. + */ +#ifndef INET6 + tlen = ((struct ip *)ti)->ip_len; +#endif /* INET6 */ + len = sizeof (struct ip) + tlen; + bzero(ti->ti_x1, sizeof ti->ti_x1); + ti->ti_len = (u_int16_t)tlen; + HTONS(ti->ti_len); + if ((ti->ti_sum = in_cksum(m, len)) != 0) { + tcpstat.tcps_rcvbadsum++; + goto drop; + } +#ifdef INET6 + } +#endif /* INET6 */ +#endif /* TUBA_INCLUDE */ + + th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen); + + /* + * Check that TCP offset makes sense, + * pull out TCP options and adjust length. XXX + */ + off = th->th_off << 2; + if (off < sizeof (struct tcphdr) || off > tlen) { + tcpstat.tcps_rcvbadoff++; + goto drop; + } + tlen -= off; + if (off > sizeof (struct tcphdr)) { + if (m->m_len < iphlen + off) { + if ((m = m_pullup2(m, iphlen + off)) == 0) { + tcpstat.tcps_rcvshort++; + return; + } +#ifdef INET6 + if (is_ipv6) + ipv6 = mtod(m, struct ip6_hdr *); + else +#endif /* INET6 */ + ti = mtod(m, struct tcpiphdr *); + th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen); + } + optlen = off - sizeof (struct tcphdr); + optp = mtod(m, caddr_t) + iphlen + sizeof(struct tcphdr); + /* + * Do quick retrieval of timestamp options ("options + * prediction?"). If timestamp is the only option and it's + * formatted as recommended in RFC 1323 appendix A, we + * quickly get the values now and not bother calling + * tcp_dooptions(), etc. + */ + if ((optlen == TCPOLEN_TSTAMP_APPA || + (optlen > TCPOLEN_TSTAMP_APPA && + optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && + *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && + (th->th_flags & TH_SYN) == 0) { + ts_present = 1; + ts_val = ntohl(*(u_int32_t *)(optp + 4)); + ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); + optp = NULL; /* we've parsed the options */ + } + } + tiflags = th->th_flags; + + /* + * Convert TCP protocol specific fields to host format. + */ + NTOHL(th->th_seq); + NTOHL(th->th_ack); + NTOHS(th->th_win); + NTOHS(th->th_urp); + + /* + * Locate pcb for segment. + */ +findpcb: +#ifdef INET6 + if (is_ipv6) { + inp = in6_pcbhashlookup(&tcbtable, &ipv6->ip6_src, th->th_sport, + &ipv6->ip6_dst, th->th_dport); + } else +#endif /* INET6 */ + inp = in_pcbhashlookup(&tcbtable, ti->ti_src, ti->ti_sport, + ti->ti_dst, ti->ti_dport); + if (inp == 0) { + ++tcpstat.tcps_pcbhashmiss; +#ifdef INET6 + if (is_ipv6) + inp = in_pcblookup(&tcbtable, &ipv6->ip6_src, + th->th_sport, &ipv6->ip6_dst, th->th_dport, + INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); + else +#endif /* INET6 */ + inp = in_pcblookup(&tcbtable, &ti->ti_src, ti->ti_sport, + &ti->ti_dst, ti->ti_dport, INPLOOKUP_WILDCARD); + /* + * If the state is CLOSED (i.e., TCB does not exist) then + * all data in the incoming segment is discarded. + * If the TCB exists but is in CLOSED state, it is embryonic, + * but should either do a listen or a connect soon. + */ + if (inp == 0) { + ++tcpstat.tcps_noport; + goto dropwithreset; + } + } + + tp = intotcpcb(inp); + if (tp == 0) + goto dropwithreset; + if (tp->t_state == TCPS_CLOSED) + goto drop; + + /* Unscale the window into a 32-bit value. */ + if ((tiflags & TH_SYN) == 0) + tiwin = th->th_win << tp->snd_scale; + else + tiwin = th->th_win; + + so = inp->inp_socket; + if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { + if (so->so_options & SO_DEBUG) { + ostate = tp->t_state; +#ifdef INET6 + if (is_ipv6) + tcp_saveti6 = *(mtod(m, struct tcpipv6hdr *)); + else +#endif /* INET6 */ + tcp_saveti = *ti; + } + if (so->so_options & SO_ACCEPTCONN) { + struct socket *so1; + + so1 = sonewconn(so, 0); + if (so1 == NULL) { + tcpdropoldhalfopen(tp, th->th_dport); + so1 = sonewconn(so, 0); + if (so1 == NULL) + goto drop; + } + so = so1; + /* + * This is ugly, but .... + * + * Mark socket as temporary until we're + * committed to keeping it. The code at + * ``drop'' and ``dropwithreset'' check the + * flag dropsocket to see if the temporary + * socket created here should be discarded. + * We mark the socket as discardable until + * we're committed to it below in TCPS_LISTEN. + */ + dropsocket++; +#ifdef IPSEC + /* + * We need to copy the required security levels + * from the old pcb. + */ + { + struct inpcb *newinp = (struct inpcb *)so->so_pcb; + bcopy(inp->inp_seclevel, newinp->inp_seclevel, + sizeof(inp->inp_seclevel)); + newinp->inp_secrequire = inp->inp_secrequire; + } +#endif /* IPSEC */ +#ifdef INET6 + /* + * inp still has the OLD in_pcb stuff, set the + * v6-related flags on the new guy, too. This is + * done particularly for the case where an AF_INET6 + * socket is bound only to a port, and a v4 connection + * comes in on that port. + * we also copy the flowinfo from the original pcb + * to the new one. + */ + { + int flags = inp->inp_flags; + struct inpcb *oldinpcb = inp; + + inp = (struct inpcb *)so->so_pcb; + inp->inp_flags |= (flags & (INP_IPV6 | INP_IPV6_UNDEC + | INP_IPV6_MAPPED)); + if ((inp->inp_flags & INP_IPV6) && + !(inp->inp_flags & INP_IPV6_MAPPED)) { + inp->inp_ipv6.ip6_hlim = + oldinpcb->inp_ipv6.ip6_hlim; + inp->inp_ipv6.ip6_flow = + oldinpcb->inp_ipv6.ip6_flow; + } + } +#else /* INET6 */ + inp = (struct inpcb *)so->so_pcb; +#endif /* INET6 */ + inp->inp_lport = th->th_dport; +#ifdef INET6 + if (is_ipv6) { + inp->inp_laddr6 = ipv6->ip6_dst; + inp->inp_fflowinfo = htonl(0x0fffffff) & + ipv6->ip6_flow; + + /*inp->inp_options = ip6_srcroute();*/ /* soon. */ + /* still need to tweak outbound options + processing to include this mbuf in + the right place and put the correct + NextHdr values in the right places. + XXX rja */ + } else { + if (inp->inp_flags & INP_IPV6) {/* v4 to v6 socket */ + CREATE_IPV6_MAPPED(inp->inp_laddr6, + ti->ti_dst.s_addr); + } else { +#endif /* INET6 */ + inp->inp_laddr = ti->ti_dst; + inp->inp_options = ip_srcroute(); +#ifdef INET6 + } + } +#endif /* INET6 */ + in_pcbrehash(inp); + tp = intotcpcb(inp); + tp->t_state = TCPS_LISTEN; + + /* Compute proper scaling value from buffer space + */ + while (tp->request_r_scale < TCP_MAX_WINSHIFT && + TCP_MAXWIN << tp->request_r_scale < so->so_rcv.sb_hiwat) + tp->request_r_scale++; + } + } + +#ifdef IPSEC + /* Check if this socket requires security for incoming packets */ + if ((inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_REQUIRE && + !(m->m_flags & M_AUTH)) || + (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE && + !(m->m_flags & M_CONF))) { +#ifdef notyet +#ifdef INET6 + if (is_ipv6) + icmp6_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0); + else +#endif /* INET6 */ + icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0); +#endif /* notyet */ + tcpstat.tcps_rcvnosec++; + goto drop; + } + /* Use tdb_bind_out for this inp's outbound communication */ + if (tdb) + tdb_add_inp(tdb, inp); +#endif /*IPSEC */ + + /* + * Segment received on connection. + * Reset idle time and keep-alive timer. + */ + tp->t_idle = 0; + if (tp->t_state != TCPS_SYN_RECEIVED) + tp->t_timer[TCPT_KEEP] = tcp_keepidle; + +#ifdef TCP_SACK + if (!tp->sack_disable) + tcp_del_sackholes(tp, th); /* Delete stale SACK holes */ +#endif /* TCP_SACK */ + + /* + * Process options if not in LISTEN state, + * else do it below (after getting remote address). + */ + if (optp && tp->t_state != TCPS_LISTEN) + tcp_dooptions(tp, optp, optlen, th, + &ts_present, &ts_val, &ts_ecr); + +#ifdef TCP_SACK + if (!tp->sack_disable) { + tp->rcv_laststart = th->th_seq; /* last rec'vd segment*/ + tp->rcv_lastend = th->th_seq + tlen; + } +#endif /* TCP_SACK */ + /* + * Header prediction: check for the two common cases + * of a uni-directional data xfer. If the packet has + * no control flags, is in-sequence, the window didn't + * change and we're not retransmitting, it's a + * candidate. If the length is zero and the ack moved + * forward, we're the sender side of the xfer. Just + * free the data acked & wake any higher level process + * that was blocked waiting for space. If the length + * is non-zero and the ack didn't move, we're the + * receiver side. If we're getting packets in-order + * (the reassembly queue is empty), add the data to + * the socket buffer and note that we need a delayed ack. + */ + if (tp->t_state == TCPS_ESTABLISHED && + (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && + (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && + th->th_seq == tp->rcv_nxt && + tiwin && tiwin == tp->snd_wnd && + tp->snd_nxt == tp->snd_max) { + + /* + * If last ACK falls within this segment's sequence numbers, + * record the timestamp. + * Fix from Braden, see Stevens p. 870 + */ + if (ts_present && SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { + tp->ts_recent_age = tcp_now; + tp->ts_recent = ts_val; + } + + if (tlen == 0) { + if (SEQ_GT(th->th_ack, tp->snd_una) && + SEQ_LEQ(th->th_ack, tp->snd_max) && + tp->snd_cwnd >= tp->snd_wnd && + tp->t_dupacks == 0) { + /* + * this is a pure ack for outstanding data. + */ + ++tcpstat.tcps_predack; + if (ts_present) + tcp_xmit_timer(tp, tcp_now-ts_ecr+1); + else if (tp->t_rtt && + SEQ_GT(th->th_ack, tp->t_rtseq)) + tcp_xmit_timer(tp, tp->t_rtt); + acked = th->th_ack - tp->snd_una; + tcpstat.tcps_rcvackpack++; + tcpstat.tcps_rcvackbyte += acked; + ND6_HINT(tp); + sbdrop(&so->so_snd, acked); + tp->snd_una = th->th_ack; +#if defined(TCP_SACK) || defined(TCP_NEWRENO) + /* + * We want snd_last to track snd_una so + * as to avoid sequence wraparound problems + * for very large transfers. + */ + tp->snd_last = tp->snd_una; +#endif /* TCP_SACK or TCP_NEWRENO */ +#if defined(TCP_SACK) && defined(TCP_FACK) + tp->snd_fack = tp->snd_una; + tp->retran_data = 0; +#endif /* TCP_FACK */ + m_freem(m); + + /* + * If all outstanding data are acked, stop + * retransmit timer, otherwise restart timer + * using current (possibly backed-off) value. + * If process is waiting for space, + * wakeup/selwakeup/signal. If data + * are ready to send, let tcp_output + * decide between more output or persist. + */ + if (tp->snd_una == tp->snd_max) + tp->t_timer[TCPT_REXMT] = 0; + else if (tp->t_timer[TCPT_PERSIST] == 0) + tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; + + if (sb_notify(&so->so_snd)) + sowwakeup(so); + if (so->so_snd.sb_cc) + (void) tcp_output(tp); + return; + } + } else if (th->th_ack == tp->snd_una && + tp->segq.lh_first == NULL && + tlen <= sbspace(&so->so_rcv)) { + /* + * This is a pure, in-sequence data packet + * with nothing on the reassembly queue and + * we have enough buffer space to take it. + */ +#ifdef TCP_SACK + /* Clean receiver SACK report if present */ + if (!tp->sack_disable && tp->rcv_numsacks) + tcp_clean_sackreport(tp); +#endif /* TCP_SACK */ + ++tcpstat.tcps_preddat; + tp->rcv_nxt += tlen; + tcpstat.tcps_rcvpack++; + tcpstat.tcps_rcvbyte += tlen; + ND6_HINT(tp); + /* + * Drop TCP, IP headers and TCP options then add data + * to socket buffer. + */ + m_adj(m, iphlen + off); + sbappend(&so->so_rcv, m); + sorwakeup(so); + if (th->th_flags & TH_PUSH) + tp->t_flags |= TF_ACKNOW; + else + tp->t_flags |= TF_DELACK; + return; + } + } + + /* + * Compute mbuf offset to TCP data segment. + */ + hdroptlen = iphlen + off; + + /* + * Calculate amount of space in receive window, + * and then do TCP input processing. + * Receive window is amount of space in rcv queue, + * but not less than advertised window. + */ + { int win; + + win = sbspace(&so->so_rcv); + if (win < 0) + win = 0; + tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt)); + } + + switch (tp->t_state) { + + /* + * If the state is LISTEN then ignore segment if it contains an RST. + * If the segment contains an ACK then it is bad and send a RST. + * If it does not contain a SYN then it is not interesting; drop it. + * If it is from this socket, drop it, it must be forged. + * Don't bother responding if the destination was a broadcast. + * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial + * tp->iss, and send a segment: + * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK> + * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. + * Fill in remote peer address fields if not previously specified. + * Enter SYN_RECEIVED state, and process any other fields of this + * segment in this state. + */ + case TCPS_LISTEN: { + struct mbuf *am; + register struct sockaddr_in *sin; +#ifdef INET6 + register struct sockaddr_in6 *sin6; +#endif /* INET6 */ + + if (tiflags & TH_RST) + goto drop; + if (tiflags & TH_ACK) + goto dropwithreset; + if ((tiflags & TH_SYN) == 0) + goto drop; + if (th->th_dport == th->th_sport) { +#ifdef INET6 + if (is_ipv6) { + if (IN6_ARE_ADDR_EQUAL(&ipv6->ip6_src, &ipv6->ip6_dst)) + goto drop; + } else { +#endif /* INET6 */ + if (ti->ti_dst.s_addr == ti->ti_src.s_addr) + goto drop; +#ifdef INET6 + } +#endif /* INET6 */ + } + + /* + * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN + * in_broadcast() should never return true on a received + * packet with M_BCAST not set. + */ + if (m->m_flags & (M_BCAST|M_MCAST)) + goto drop; +#ifdef INET6 + if (is_ipv6) { + /* XXX What about IPv6 Anycasting ?? :-( rja */ + if (IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst)) + goto drop; + } else +#endif /* INET6 */ + if (IN_MULTICAST(ti->ti_dst.s_addr)) + goto drop; + am = m_get(M_DONTWAIT, MT_SONAME); /* XXX */ + if (am == NULL) + goto drop; +#ifdef INET6 + if (is_ipv6) { + /* + * This is probably the place to set the tp->pf value. + * (Don't forget to do it in the v4 code as well!) + * + * Also, remember to blank out things like flowlabel, or + * set flowlabel for accepted sockets in v6. + * + * FURTHERMORE, this is PROBABLY the place where the whole + * business of key munging is set up for passive + * connections. + */ + am->m_len = sizeof(struct sockaddr_in6); + sin6 = mtod(am, struct sockaddr_in6 *); + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(struct sockaddr_in6); + sin6->sin6_addr = ipv6->ip6_src; + sin6->sin6_port = th->th_sport; + sin6->sin6_flowinfo = htonl(0x0fffffff) & + inp->inp_ipv6.ip6_flow; + laddr6 = inp->inp_laddr6; + if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) + inp->inp_laddr6 = ipv6->ip6_dst; + /* This is a good optimization. */ + if (in6_pcbconnect(inp, am)) { + inp->inp_laddr6 = laddr6; + (void) m_free(am); + goto drop; + } /* endif in6_pcbconnect() */ + tp->pf = PF_INET6; + } else { + /* + * Letting v4 incoming datagrams to reach valid + * PF_INET6 sockets causes some overhead here. + */ + if (inp->inp_flags & INP_IPV6) { + if (!(inp->inp_flags & (INP_IPV6_UNDEC|INP_IPV6_MAPPED))) { + (void) m_free(am); + goto drop; + } + + am->m_len = sizeof(struct sockaddr_in6); + + sin6 = mtod(am, struct sockaddr_in6 *); + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(*sin6); + CREATE_IPV6_MAPPED(sin6->sin6_addr, ti->ti_src.s_addr); + sin6->sin6_port = th->th_sport; + sin6->sin6_flowinfo = 0; + + laddr6 = inp->inp_laddr6; + if (inp->inp_laddr.s_addr == INADDR_ANY) + CREATE_IPV6_MAPPED(inp->inp_laddr6, ti->ti_dst.s_addr); + + /* + * The pcb initially has the v6 default hoplimit + * set. We're sending v4 packets so we need to set + * the v4 ttl and tos. + */ + inp->inp_ip.ip_ttl = ip_defttl; + inp->inp_ip.ip_tos = 0; + + if (in6_pcbconnect(inp, am)) { + inp->inp_laddr6 = laddr6; + (void) m_freem(am); + goto drop; + } + tp->pf = PF_INET; + } else { +#endif /* INET6 */ + am->m_len = sizeof (struct sockaddr_in); + sin = mtod(am, struct sockaddr_in *); + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_addr = ti->ti_src; + sin->sin_port = ti->ti_sport; + bzero((caddr_t)sin->sin_zero, sizeof(sin->sin_zero)); + laddr = inp->inp_laddr; + if (inp->inp_laddr.s_addr == INADDR_ANY) + inp->inp_laddr = ti->ti_dst; + if (in_pcbconnect(inp, am)) { + inp->inp_laddr = laddr; + (void) m_free(am); + goto drop; + } + (void) m_free(am); + tp->pf = PF_INET; +#ifdef INET6 + } /* if (inp->inp_flags & INP_IPV6) */ + } /* if (is_ipv6) */ +#endif /* INET6 */ + tp->t_template = tcp_template(tp); + if (tp->t_template == 0) { + tp = tcp_drop(tp, ENOBUFS); + dropsocket = 0; /* socket is already gone */ + goto drop; + } + if (optp) + tcp_dooptions(tp, optp, optlen, th, + &ts_present, &ts_val, &ts_ecr); +#ifdef TCP_SACK + /* + * If peer did not send a SACK_PERMITTED option (i.e., if + * tcp_dooptions() did not set TF_SACK_PERMIT), set + * sack_disable to 1 if it is currently 0. + */ + if (!tp->sack_disable) + if ((tp->t_flags & TF_SACK_PERMIT) == 0) + tp->sack_disable = 1; +#endif + + if (iss) + tp->iss = iss; + else + tp->iss = tcp_iss; +#ifdef TCP_COMPAT_42 + tcp_iss += TCP_ISSINCR/2; +#else /* TCP_COMPAT_42 */ + tcp_iss += arc4random() % TCP_ISSINCR + 1; +#endif /* !TCP_COMPAT_42 */ + tp->irs = th->th_seq; + tcp_sendseqinit(tp); +#if defined (TCP_SACK) || defined (TCP_NEWRENO) + tp->snd_last = tp->snd_una; +#endif /* TCP_SACK || TCP_NEWRENO */ +#if defined(TCP_SACK) && defined(TCP_FACK) + tp->snd_fack = tp->snd_una; + tp->retran_data = 0; + tp->snd_awnd = 0; +#endif /* TCP_FACK */ + tcp_rcvseqinit(tp); + tp->t_flags |= TF_ACKNOW; + tp->t_state = TCPS_SYN_RECEIVED; + tp->t_timer[TCPT_KEEP] = tcptv_keep_init; + dropsocket = 0; /* committed to socket */ + tcpstat.tcps_accepts++; + goto trimthenstep6; + } + + /* + * If the state is SYN_RECEIVED: + * if seg contains SYN/ACK, send an RST. + * if seg contains an ACK, but not for our SYN/ACK, send an RST + */ + + case TCPS_SYN_RECEIVED: + if (tiflags & TH_ACK) { + if (tiflags & TH_SYN) { + tcpstat.tcps_badsyn++; + goto dropwithreset; + } + if (SEQ_LEQ(th->th_ack, tp->snd_una) || + SEQ_GT(th->th_ack, tp->snd_max)) + goto dropwithreset; + } + break; + + /* + * If the state is SYN_SENT: + * if seg contains an ACK, but not for our SYN, drop the input. + * if seg contains a RST, then drop the connection. + * if seg does not contain SYN, then drop it. + * Otherwise this is an acceptable SYN segment + * initialize tp->rcv_nxt and tp->irs + * if seg contains ack then advance tp->snd_una + * if SYN has been acked change to ESTABLISHED else SYN_RCVD state + * arrange for segment to be acked (eventually) + * continue processing rest of data/controls, beginning with URG + */ + case TCPS_SYN_SENT: + if ((tiflags & TH_ACK) && + (SEQ_LEQ(th->th_ack, tp->iss) || + SEQ_GT(th->th_ack, tp->snd_max))) + goto dropwithreset; + if (tiflags & TH_RST) { + if (tiflags & TH_ACK) + tp = tcp_drop(tp, ECONNREFUSED); + goto drop; + } + if ((tiflags & TH_SYN) == 0) + goto drop; + if (tiflags & TH_ACK) { + tp->snd_una = th->th_ack; + if (SEQ_LT(tp->snd_nxt, tp->snd_una)) + tp->snd_nxt = tp->snd_una; + } + tp->t_timer[TCPT_REXMT] = 0; + tp->irs = th->th_seq; + tcp_rcvseqinit(tp); + tp->t_flags |= TF_ACKNOW; +#ifdef TCP_SACK + /* + * If we've sent a SACK_PERMITTED option, and the peer + * also replied with one, then TF_SACK_PERMIT should have + * been set in tcp_dooptions(). If it was not, disable SACKs. + */ + if (!tp->sack_disable) + if ((tp->t_flags & TF_SACK_PERMIT) == 0) + tp->sack_disable = 1; +#endif + if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { + tcpstat.tcps_connects++; + soisconnected(so); + tp->t_state = TCPS_ESTABLISHED; + /* Do window scaling on this connection? */ + if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == + (TF_RCVD_SCALE|TF_REQ_SCALE)) { + tp->snd_scale = tp->requested_s_scale; + tp->rcv_scale = tp->request_r_scale; + } + (void) tcp_reass(tp, (struct tcphdr *)0, + (struct mbuf *)0, &tlen); + /* + * if we didn't have to retransmit the SYN, + * use its rtt as our initial srtt & rtt var. + */ + if (tp->t_rtt) + tcp_xmit_timer(tp, tp->t_rtt); + /* + * Since new data was acked (the SYN), open the + * congestion window by one MSS. We do this + * here, because we won't go through the normal + * ACK processing below. And since this is the + * start of the connection, we know we are in + * the exponential phase of slow-start. + */ + tp->snd_cwnd += tp->t_maxseg; + } else + tp->t_state = TCPS_SYN_RECEIVED; + +trimthenstep6: + /* + * Advance ti->ti_seq to correspond to first data byte. + * If data, trim to stay within window, + * dropping FIN if necessary. + */ + th->th_seq++; + if (tlen > tp->rcv_wnd) { + todrop = tlen - tp->rcv_wnd; + m_adj(m, -todrop); + tlen = tp->rcv_wnd; + tiflags &= ~TH_FIN; + tcpstat.tcps_rcvpackafterwin++; + tcpstat.tcps_rcvbyteafterwin += todrop; + } + tp->snd_wl1 = th->th_seq - 1; + tp->rcv_up = th->th_seq; + goto step6; + } + + /* + * States other than LISTEN or SYN_SENT. + * First check timestamp, if present. + * Then check that at least some bytes of segment are within + * receive window. If segment begins before rcv_nxt, + * drop leading data (and SYN); if nothing left, just ack. + * + * RFC 1323 PAWS: If we have a timestamp reply on this segment + * and it's less than ts_recent, drop it. + */ + if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent && + TSTMP_LT(ts_val, tp->ts_recent)) { + + /* Check to see if ts_recent is over 24 days old. */ + if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) { + /* + * Invalidate ts_recent. If this segment updates + * ts_recent, the age will be reset later and ts_recent + * will get a valid value. If it does not, setting + * ts_recent to zero will at least satisfy the + * requirement that zero be placed in the timestamp + * echo reply when ts_recent isn't valid. The + * age isn't reset until we get a valid ts_recent + * because we don't want out-of-order segments to be + * dropped when ts_recent is old. + */ + tp->ts_recent = 0; + } else { + tcpstat.tcps_rcvduppack++; + tcpstat.tcps_rcvdupbyte += tlen; + tcpstat.tcps_pawsdrop++; + goto dropafterack; + } + } + + todrop = tp->rcv_nxt - th->th_seq; + if (todrop > 0) { + if (tiflags & TH_SYN) { + tiflags &= ~TH_SYN; + th->th_seq++; + if (th->th_urp > 1) + th->th_urp--; + else + tiflags &= ~TH_URG; + todrop--; + } + if (todrop >= tlen || + (todrop == tlen && (tiflags & TH_FIN) == 0)) { + /* + * Any valid FIN must be to the left of the + * window. At this point, FIN must be a + * duplicate or out-of-sequence, so drop it. + */ + tiflags &= ~TH_FIN; + /* + * Send ACK to resynchronize, and drop any data, + * but keep on processing for RST or ACK. + */ + tp->t_flags |= TF_ACKNOW; + tcpstat.tcps_rcvdupbyte += todrop = tlen; + tcpstat.tcps_rcvduppack++; + } else { + tcpstat.tcps_rcvpartduppack++; + tcpstat.tcps_rcvpartdupbyte += todrop; + } + hdroptlen += todrop; /* drop from head afterwards */ + th->th_seq += todrop; + tlen -= todrop; + if (th->th_urp > todrop) + th->th_urp -= todrop; + else { + tiflags &= ~TH_URG; + th->th_urp = 0; + } + } + + /* + * If new data are received on a connection after the + * user processes are gone, then RST the other end. + */ + if ((so->so_state & SS_NOFDREF) && + tp->t_state > TCPS_CLOSE_WAIT && tlen) { + tp = tcp_close(tp); + tcpstat.tcps_rcvafterclose++; + goto dropwithreset; + } + + /* + * If segment ends after window, drop trailing data + * (and PUSH and FIN); if nothing left, just ACK. + */ + todrop = (th->th_seq + tlen) - (tp->rcv_nxt+tp->rcv_wnd); + if (todrop > 0) { + tcpstat.tcps_rcvpackafterwin++; + if (todrop >= tlen) { + tcpstat.tcps_rcvbyteafterwin += tlen; + /* + * If a new connection request is received + * while in TIME_WAIT, drop the old connection + * and start over if the sequence numbers + * are above the previous ones. + */ + if (tiflags & TH_SYN && + tp->t_state == TCPS_TIME_WAIT && + SEQ_GT(th->th_seq, tp->rcv_nxt)) { + iss = tp->snd_nxt + TCP_ISSINCR; + tp = tcp_close(tp); + goto findpcb; + } + /* + * If window is closed can only take segments at + * window edge, and have to drop data and PUSH from + * incoming segments. Continue processing, but + * remember to ack. Otherwise, drop segment + * and ack. + */ + if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) { + tp->t_flags |= TF_ACKNOW; + tcpstat.tcps_rcvwinprobe++; + } else + goto dropafterack; + } else + tcpstat.tcps_rcvbyteafterwin += todrop; + m_adj(m, -todrop); + tlen -= todrop; + tiflags &= ~(TH_PUSH|TH_FIN); + } + + /* + * If last ACK falls within this segment's sequence numbers, + * record its timestamp. + * Fix from Braden, see Stevens p. 870 + */ + if (ts_present && TSTMP_GEQ(ts_val, tp->ts_recent) && + SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { + tp->ts_recent_age = tcp_now; + tp->ts_recent = ts_val; + } + + /* + * If the RST bit is set examine the state: + * SYN_RECEIVED STATE: + * If passive open, return to LISTEN state. + * If active open, inform user that connection was refused. + * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: + * Inform user that connection was reset, and close tcb. + * CLOSING, LAST_ACK, TIME_WAIT STATES + * Close the tcb. + */ + if (tiflags & TH_RST) { +#ifndef INET6 + if (ti->ti_seq != tp->last_ack_sent) +#else + if (th->th_seq != tp->last_ack_sent) +#endif + goto drop; + + switch (tp->t_state) { + case TCPS_SYN_RECEIVED: + so->so_error = ECONNREFUSED; + goto close; + + case TCPS_ESTABLISHED: + case TCPS_FIN_WAIT_1: + case TCPS_FIN_WAIT_2: + case TCPS_CLOSE_WAIT: + so->so_error = ECONNRESET; + close: + tp->t_state = TCPS_CLOSED; + tcpstat.tcps_drops++; + tp = tcp_close(tp); + goto drop; + case TCPS_CLOSING: + case TCPS_LAST_ACK: + case TCPS_TIME_WAIT: + tp = tcp_close(tp); + goto drop; + } + } + + /* + * If a SYN is in the window, then this is an + * error and we send an RST and drop the connection. + */ + if (tiflags & TH_SYN) { + tp = tcp_drop(tp, ECONNRESET); + goto dropwithreset; + } + + /* + * If the ACK bit is off we drop the segment and return. + */ + if ((tiflags & TH_ACK) == 0) { + if (tp->t_flags & TF_ACKNOW) + goto dropafterack; + else + goto drop; + } + + /* + * Ack processing. + */ + switch (tp->t_state) { + + /* + * In SYN_RECEIVED state, the ack ACKs our SYN, so enter + * ESTABLISHED state and continue processing. + * The ACK was checked above. + */ + case TCPS_SYN_RECEIVED: + tcpstat.tcps_connects++; + soisconnected(so); + tp->t_state = TCPS_ESTABLISHED; + /* Do window scaling? */ + if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == + (TF_RCVD_SCALE|TF_REQ_SCALE)) { + tp->snd_scale = tp->requested_s_scale; + tp->rcv_scale = tp->request_r_scale; + } + (void) tcp_reass(tp, (struct tcphdr *)0, (struct mbuf *)0, + &tlen); + tp->snd_wl1 = th->th_seq - 1; + /* fall into ... */ + + /* + * In ESTABLISHED state: drop duplicate ACKs; ACK out of range + * ACKs. If the ack is in the range + * tp->snd_una < ti->ti_ack <= tp->snd_max + * then advance tp->snd_una to ti->ti_ack and drop + * data from the retransmission queue. If this ACK reflects + * more up to date window information we update our window information. + */ + case TCPS_ESTABLISHED: + case TCPS_FIN_WAIT_1: + case TCPS_FIN_WAIT_2: + case TCPS_CLOSE_WAIT: + case TCPS_CLOSING: + case TCPS_LAST_ACK: + case TCPS_TIME_WAIT: + if (SEQ_LEQ(th->th_ack, tp->snd_una)) { + /* + * Duplicate/old ACK processing. + * Increments t_dupacks: + * Pure duplicate (same seq/ack/window, no data) + * Doesn't affect t_dupacks: + * Data packets. + * Normal window updates (window opens) + * Resets t_dupacks: + * New data ACKed. + * Window shrinks + * Old ACK + */ + if (tlen) + break; + /* + * If we get an old ACK, there is probably packet + * reordering going on. Be conservative and reset + * t_dupacks so that we are less agressive in + * doing a fast retransmit. + */ + if (th->th_ack != tp->snd_una) { + tp->t_dupacks = 0; + break; + } + if (tiwin == tp->snd_wnd) { + tcpstat.tcps_rcvdupack++; + /* + * If we have outstanding data (other than + * a window probe), this is a completely + * duplicate ack (ie, window info didn't + * change), the ack is the biggest we've + * seen and we've seen exactly our rexmt + * threshhold of them, assume a packet + * has been dropped and retransmit it. + * Kludge snd_nxt & the congestion + * window so we send only this one + * packet. + * + * We know we're losing at the current + * window size so do congestion avoidance + * (set ssthresh to half the current window + * and pull our congestion window back to + * the new ssthresh). + * + * Dup acks mean that packets have left the + * network (they're now cached at the receiver) + * so bump cwnd by the amount in the receiver + * to keep a constant cwnd packets in the + * network. + */ + if (tp->t_timer[TCPT_REXMT] == 0) + tp->t_dupacks = 0; +#if defined(TCP_SACK) && defined(TCP_FACK) + /* + * In FACK, can enter fast rec. if the receiver + * reports a reass. queue longer than 3 segs. + */ + else if (++tp->t_dupacks == tcprexmtthresh || + ((SEQ_GT(tp->snd_fack, tcprexmtthresh * + tp->t_maxseg + tp->snd_una)) && + SEQ_GT(tp->snd_una, tp->snd_last))) { +#else + else if (++tp->t_dupacks == tcprexmtthresh) { +#endif /* TCP_FACK */ + tcp_seq onxt = tp->snd_nxt; + u_long win = + ulmin(tp->snd_wnd, tp->snd_cwnd) / + 2 / tp->t_maxseg; + +#if defined(TCP_SACK) || defined(TCP_NEWRENO) + if (SEQ_LT(th->th_ack, tp->snd_last)){ + /* + * False fast retx after + * timeout. Do not cut window. + */ + tp->snd_cwnd += tp->t_maxseg; + tp->t_dupacks = 0; + (void) tcp_output(tp); + goto drop; + } +#endif + if (win < 2) + win = 2; + tp->snd_ssthresh = win * tp->t_maxseg; +#if defined(TCP_SACK) || defined(TCP_NEWRENO) + tp->snd_last = tp->snd_max; +#endif +#ifdef TCP_SACK + if (!tp->sack_disable) { + tp->t_timer[TCPT_REXMT] = 0; + tp->t_rtt = 0; + tcpstat.tcps_sndrexmitfast++; +#if defined(TCP_SACK) && defined(TCP_FACK) + (void) tcp_output(tp); + /* + * During FR, snd_cwnd is held + * constant for FACK. + */ + tp->snd_cwnd = tp->snd_ssthresh; + tp->t_dupacks = tcprexmtthresh; +#else + /* + * tcp_output() will send + * oldest SACK-eligible rtx. + */ + (void) tcp_output(tp); + tp->snd_cwnd = tp->snd_ssthresh+ + tp->t_maxseg * tp->t_dupacks; +#endif /* TCP_FACK */ + goto drop; + } +#endif /* TCP_SACK */ + tp->t_timer[TCPT_REXMT] = 0; + tp->t_rtt = 0; + tp->snd_nxt = th->th_ack; + tp->snd_cwnd = tp->t_maxseg; + tcpstat.tcps_sndrexmitfast++; + (void) tcp_output(tp); + + tp->snd_cwnd = tp->snd_ssthresh + + tp->t_maxseg * tp->t_dupacks; + if (SEQ_GT(onxt, tp->snd_nxt)) + tp->snd_nxt = onxt; + goto drop; + } else if (tp->t_dupacks > tcprexmtthresh) { +#if defined(TCP_SACK) && defined(TCP_FACK) + /* + * while (awnd < cwnd) + * sendsomething(); + */ + if (!tp->sack_disable) { + if (tp->snd_awnd < tp->snd_cwnd) + tcp_output(tp); + goto drop; + } +#endif /* TCP_FACK */ + tp->snd_cwnd += tp->t_maxseg; + (void) tcp_output(tp); + goto drop; + } + } else if (tiwin < tp->snd_wnd) { + /* + * The window was retracted! Previous dup + * ACKs may have been due to packets arriving + * after the shrunken window, not a missing + * packet, so play it safe and reset t_dupacks + */ + tp->t_dupacks = 0; + } + break; + } + /* + * If the congestion window was inflated to account + * for the other side's cached packets, retract it. + */ +#ifdef TCP_NEWRENO + if (tp->t_dupacks >= tcprexmtthresh && !tcp_newreno(tp, th)) { + /* Out of fast recovery */ + tp->snd_cwnd = tp->snd_ssthresh; + /* + * Window inflation should have left us with approx. + * snd_ssthresh outstanding data. But in case we + * would be inclined to send a burst, better to do + * it via the slow start mechanism. + */ + if (tcp_seq_subtract(tp->snd_max, th->th_ack) < + tp->snd_ssthresh) + tp->snd_cwnd = tcp_seq_subtract(tp->snd_max, + th->th_ack) + tp->t_maxseg; + tp->t_dupacks = 0; + } +#elif defined(TCP_SACK) + if (!tp->sack_disable) { + if (tp->t_dupacks >= tcprexmtthresh) { + /* Check for a partial ACK */ + if (tcp_sack_partialack(tp, th)) { +#if defined(TCP_SACK) && defined(TCP_FACK) + /* Force call to tcp_output */ + if (tp->snd_awnd < tp->snd_cwnd) + needoutput = 1; +#else + tp->snd_cwnd += tp->t_maxseg; + needoutput = 1; +#endif /* TCP_FACK */ + } else { + /* Out of fast recovery */ + tp->snd_cwnd = tp->snd_ssthresh; + if (tcp_seq_subtract(tp->snd_max, + th->th_ack) < tp->snd_ssthresh) + tp->snd_cwnd = + tcp_seq_subtract(tp->snd_max, + th->th_ack) + tp->t_maxseg; + tp->t_dupacks = 0; +#if defined(TCP_SACK) && defined(TCP_FACK) + if (SEQ_GT(th->th_ack, tp->snd_fack)) + tp->snd_fack = th->th_ack; +#endif /* TCP_FACK */ + } + } + } else { + if (tp->t_dupacks >= tcprexmtthresh && + !tcp_newreno(tp, th)) { + /* Out of fast recovery */ + tp->snd_cwnd = tp->snd_ssthresh; + if (tcp_seq_subtract(tp->snd_max, th->th_ack) < + tp->snd_ssthresh) + tp->snd_cwnd = + tcp_seq_subtract(tp->snd_max, + th->th_ack) + tp->t_maxseg; + tp->t_dupacks = 0; + } + } +#else /* else neither TCP_NEWRENO nor TCP_SACK */ + if (tp->t_dupacks >= tcprexmtthresh && + tp->snd_cwnd > tp->snd_ssthresh) + tp->snd_cwnd = tp->snd_ssthresh; + tp->t_dupacks = 0; +#endif + if (SEQ_GT(th->th_ack, tp->snd_max)) { + tcpstat.tcps_rcvacktoomuch++; + goto dropafterack; + } + acked = th->th_ack - tp->snd_una; + tcpstat.tcps_rcvackpack++; + tcpstat.tcps_rcvackbyte += acked; + + /* + * If we have a timestamp reply, update smoothed + * round trip time. If no timestamp is present but + * transmit timer is running and timed sequence + * number was acked, update smoothed round trip time. + * Since we now have an rtt measurement, cancel the + * timer backoff (cf., Phil Karn's retransmit alg.). + * Recompute the initial retransmit timer. + */ + if (ts_present) + tcp_xmit_timer(tp, tcp_now-ts_ecr+1); + else if (tp->t_rtt && SEQ_GT(th->th_ack, tp->t_rtseq)) + tcp_xmit_timer(tp,tp->t_rtt); + + /* + * If all outstanding data is acked, stop retransmit + * timer and remember to restart (more output or persist). + * If there is more data to be acked, restart retransmit + * timer, using current (possibly backed-off) value. + */ + if (th->th_ack == tp->snd_max) { + tp->t_timer[TCPT_REXMT] = 0; + needoutput = 1; + } else if (tp->t_timer[TCPT_PERSIST] == 0) + tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; + /* + * When new data is acked, open the congestion window. + * If the window gives us less than ssthresh packets + * in flight, open exponentially (maxseg per packet). + * Otherwise open linearly: maxseg per window + * (maxseg^2 / cwnd per packet). + */ + { + register u_int cw = tp->snd_cwnd; + register u_int incr = tp->t_maxseg; + + if (cw > tp->snd_ssthresh) + incr = incr * incr / cw; +#if defined (TCP_NEWRENO) || defined (TCP_SACK) + if (SEQ_GEQ(th->th_ack, tp->snd_last)) +#endif + tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale); + } + ND6_HINT(tp); + if (acked > so->so_snd.sb_cc) { + tp->snd_wnd -= so->so_snd.sb_cc; + sbdrop(&so->so_snd, (int)so->so_snd.sb_cc); + ourfinisacked = 1; + } else { + sbdrop(&so->so_snd, acked); + tp->snd_wnd -= acked; + ourfinisacked = 0; + } + if (sb_notify(&so->so_snd)) + sowwakeup(so); + tp->snd_una = th->th_ack; + if (SEQ_LT(tp->snd_nxt, tp->snd_una)) + tp->snd_nxt = tp->snd_una; +#if defined (TCP_SACK) && defined (TCP_FACK) + if (SEQ_GT(tp->snd_una, tp->snd_fack)) + tp->snd_fack = tp->snd_una; +#endif + + switch (tp->t_state) { + + /* + * In FIN_WAIT_1 STATE in addition to the processing + * for the ESTABLISHED state if our FIN is now acknowledged + * then enter FIN_WAIT_2. + */ + case TCPS_FIN_WAIT_1: + if (ourfinisacked) { + /* + * If we can't receive any more + * data, then closing user can proceed. + * Starting the timer is contrary to the + * specification, but if we don't get a FIN + * we'll hang forever. + */ + if (so->so_state & SS_CANTRCVMORE) { + soisdisconnected(so); + tp->t_timer[TCPT_2MSL] = tcp_maxidle; + } + tp->t_state = TCPS_FIN_WAIT_2; + } + break; + + /* + * In CLOSING STATE in addition to the processing for + * the ESTABLISHED state if the ACK acknowledges our FIN + * then enter the TIME-WAIT state, otherwise ignore + * the segment. + */ + case TCPS_CLOSING: + if (ourfinisacked) { + tp->t_state = TCPS_TIME_WAIT; + tcp_canceltimers(tp); + tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; + soisdisconnected(so); + } + break; + + /* + * In LAST_ACK, we may still be waiting for data to drain + * and/or to be acked, as well as for the ack of our FIN. + * If our FIN is now acknowledged, delete the TCB, + * enter the closed state and return. + */ + case TCPS_LAST_ACK: + if (ourfinisacked) { + tp = tcp_close(tp); + goto drop; + } + break; + + /* + * In TIME_WAIT state the only thing that should arrive + * is a retransmission of the remote FIN. Acknowledge + * it and restart the finack timer. + */ + case TCPS_TIME_WAIT: + tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; + goto dropafterack; + } + } + +step6: + /* + * Update window information. + * Don't look at window if no ACK: TAC's send garbage on first SYN. + */ + if ((tiflags & TH_ACK) && (SEQ_LT(tp->snd_wl1, th->th_seq) || + (tp->snd_wl1 == th->th_seq && SEQ_LT(tp->snd_wl2, th->th_ack)) || + (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))) { + /* keep track of pure window updates */ + if (tlen == 0 && + tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) + tcpstat.tcps_rcvwinupd++; + tp->snd_wnd = tiwin; + tp->snd_wl1 = th->th_seq; + tp->snd_wl2 = th->th_ack; + if (tp->snd_wnd > tp->max_sndwnd) + tp->max_sndwnd = tp->snd_wnd; + needoutput = 1; + } + + /* + * Process segments with URG. + */ + if ((tiflags & TH_URG) && th->th_urp && + TCPS_HAVERCVDFIN(tp->t_state) == 0) { + /* + * This is a kludge, but if we receive and accept + * random urgent pointers, we'll crash in + * soreceive. It's hard to imagine someone + * actually wanting to send this much urgent data. + */ + if (th->th_urp + so->so_rcv.sb_cc > sb_max) { + th->th_urp = 0; /* XXX */ + tiflags &= ~TH_URG; /* XXX */ + goto dodata; /* XXX */ + } + /* + * If this segment advances the known urgent pointer, + * then mark the data stream. This should not happen + * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since + * a FIN has been received from the remote side. + * In these states we ignore the URG. + * + * According to RFC961 (Assigned Protocols), + * the urgent pointer points to the last octet + * of urgent data. We continue, however, + * to consider it to indicate the first octet + * of data past the urgent section as the original + * spec states (in one of two places). + */ + if (SEQ_GT(th->th_seq+th->th_urp, tp->rcv_up)) { + tp->rcv_up = th->th_seq + th->th_urp; + so->so_oobmark = so->so_rcv.sb_cc + + (tp->rcv_up - tp->rcv_nxt) - 1; + if (so->so_oobmark == 0) + so->so_state |= SS_RCVATMARK; + sohasoutofband(so); + tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA); + } + /* + * Remove out of band data so doesn't get presented to user. + * This can happen independent of advancing the URG pointer, + * but if two URG's are pending at once, some out-of-band + * data may creep in... ick. + */ + if (th->th_urp <= (u_int16_t) tlen +#ifdef SO_OOBINLINE + && (so->so_options & SO_OOBINLINE) == 0 +#endif + ) + tcp_pulloutofband(so, th->th_urp, m, hdroptlen); + } else + /* + * If no out of band data is expected, + * pull receive urgent pointer along + * with the receive window. + */ + if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) + tp->rcv_up = tp->rcv_nxt; +dodata: /* XXX */ + + /* + * Process the segment text, merging it into the TCP sequencing queue, + * and arranging for acknowledgment of receipt if necessary. + * This process logically involves adjusting tp->rcv_wnd as data + * is presented to the user (this happens in tcp_usrreq.c, + * case PRU_RCVD). If a FIN has already been received on this + * connection then we just ignore the text. + */ + if ((tlen || (tiflags & TH_FIN)) && + TCPS_HAVERCVDFIN(tp->t_state) == 0) { + if (th->th_seq == tp->rcv_nxt && tp->segq.lh_first == NULL && + tp->t_state == TCPS_ESTABLISHED) { + if (th->th_flags & TH_PUSH) + tp->t_flags |= TF_ACKNOW; + else + tp->t_flags |= TF_DELACK; + tp->rcv_nxt += tlen; + tiflags = th->th_flags & TH_FIN; + tcpstat.tcps_rcvpack++; + tcpstat.tcps_rcvbyte += tlen; + ND6_HINT(tp); + m_adj(m, hdroptlen); + sbappend(&so->so_rcv, m); + sorwakeup(so); + } else { + m_adj(m, hdroptlen); + tiflags = tcp_reass(tp, th, m, &tlen); + tp->t_flags |= TF_ACKNOW; + } +#ifdef TCP_SACK + if (!tp->sack_disable) + tcp_update_sack_list(tp); +#endif + + /* + * variable len never referenced again in modern BSD, + * so why bother computing it ?? + */ +#if 0 + /* + * Note the amount of data that peer has sent into + * our window, in order to estimate the sender's + * buffer size. + */ + len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt); +#endif /* 0 */ + } else { + m_freem(m); + tiflags &= ~TH_FIN; + } + + /* + * If FIN is received ACK the FIN and let the user know + * that the connection is closing. Ignore a FIN received before + * the connection is fully established. + */ + if ((tiflags & TH_FIN) && TCPS_HAVEESTABLISHED(tp->t_state)) { + if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { + socantrcvmore(so); + tp->t_flags |= TF_ACKNOW; + tp->rcv_nxt++; + } + switch (tp->t_state) { + + /* + * In ESTABLISHED STATE enter the CLOSE_WAIT state. + */ + case TCPS_ESTABLISHED: + tp->t_state = TCPS_CLOSE_WAIT; + break; + + /* + * If still in FIN_WAIT_1 STATE FIN has not been acked so + * enter the CLOSING state. + */ + case TCPS_FIN_WAIT_1: + tp->t_state = TCPS_CLOSING; + break; + + /* + * In FIN_WAIT_2 state enter the TIME_WAIT state, + * starting the time-wait timer, turning off the other + * standard timers. + */ + case TCPS_FIN_WAIT_2: + tp->t_state = TCPS_TIME_WAIT; + tcp_canceltimers(tp); + tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; + soisdisconnected(so); + break; + + /* + * In TIME_WAIT state restart the 2 MSL time_wait timer. + */ + case TCPS_TIME_WAIT: + tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; + break; + } + } +#ifdef TCPDEBUG + if (so->so_options & SO_DEBUG) { +#ifdef INET6 + if (tp->pf == PF_INET6) + tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen); + else +#endif /* INET6 */ + tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen); + } +#endif /* TCPDEBUG */ + + /* + * Return any desired output. + */ + if (needoutput || (tp->t_flags & TF_ACKNOW)) { + (void) tcp_output(tp); + } + return; + +dropafterack: + /* + * Generate an ACK dropping incoming segment if it occupies + * sequence space, where the ACK reflects our state. + */ + if (tiflags & TH_RST) + goto drop; + m_freem(m); + tp->t_flags |= TF_ACKNOW; + (void) tcp_output(tp); + return; + +dropwithreset: + /* + * Generate a RST, dropping incoming segment. + * Make ACK acceptable to originator of segment. + * Don't bother to respond if destination was broadcast/multicast. + */ + if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST)) + goto drop; +#ifdef INET6 + if (is_ipv6) { + /* For following calls to tcp_respond */ + ti = mtod(m, struct tcpiphdr *); + if (IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst)) + goto drop; + } else { +#endif /* INET6 */ + if (IN_MULTICAST(ti->ti_dst.s_addr)) + goto drop; +#ifdef INET6 + } +#endif /* INET6 */ + if (tiflags & TH_ACK) + tcp_respond(tp, (caddr_t) ti, m, (tcp_seq)0, th->th_ack, TH_RST); + else { + if (tiflags & TH_SYN) + tlen++; + tcp_respond(tp, (caddr_t) ti, m, th->th_seq+tlen, (tcp_seq)0, + TH_RST|TH_ACK); + } + /* destroy temporarily created socket */ + if (dropsocket) + (void) soabort(so); + return; + +drop: + /* + * Drop space held by incoming segment and return. + */ +#ifdef TCPDEBUG + if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) { +#ifdef INET6 + if (tp->pf == PF_INET6) + tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen); + else +#endif /* INET6 */ + tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen); + } +#endif /* TCPDEBUG */ + + m_freem(m); + /* destroy temporarily created socket */ + if (dropsocket) + (void) soabort(so); + return; +#ifndef TUBA_INCLUDE +} + +void +tcp_dooptions(tp, cp, cnt, th, ts_present, ts_val, ts_ecr) + struct tcpcb *tp; + u_char *cp; + int cnt; + struct tcphdr *th; + int *ts_present; + u_int32_t *ts_val, *ts_ecr; +{ + u_int16_t mss = 0; + int opt, optlen; + + for (; cnt > 0; cnt -= optlen, cp += optlen) { + opt = cp[0]; + if (opt == TCPOPT_EOL) + break; + if (opt == TCPOPT_NOP) + optlen = 1; + else { + optlen = cp[1]; + if (optlen <= 0) + break; + } + switch (opt) { + + default: + continue; + + case TCPOPT_MAXSEG: + if (optlen != TCPOLEN_MAXSEG) + continue; + if (!(th->th_flags & TH_SYN)) + continue; + bcopy((char *) cp + 2, (char *) &mss, sizeof(mss)); + NTOHS(mss); + break; + + case TCPOPT_WINDOW: + if (optlen != TCPOLEN_WINDOW) + continue; + if (!(th->th_flags & TH_SYN)) + continue; + tp->t_flags |= TF_RCVD_SCALE; + tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); + break; + + case TCPOPT_TIMESTAMP: + if (optlen != TCPOLEN_TIMESTAMP) + continue; + *ts_present = 1; + bcopy((char *)cp + 2, (char *) ts_val, sizeof(*ts_val)); + NTOHL(*ts_val); + bcopy((char *)cp + 6, (char *) ts_ecr, sizeof(*ts_ecr)); + NTOHL(*ts_ecr); + + /* + * A timestamp received in a SYN makes + * it ok to send timestamp requests and replies. + */ + if (th->th_flags & TH_SYN) { + tp->t_flags |= TF_RCVD_TSTMP; + tp->ts_recent = *ts_val; + tp->ts_recent_age = tcp_now; + } + break; + +#ifdef TCP_SACK + case TCPOPT_SACK_PERMITTED: + if (tp->sack_disable || optlen!=TCPOLEN_SACK_PERMITTED) + continue; + if (th->th_flags & TH_SYN) + /* MUST only be set on SYN */ + tp->t_flags |= TF_SACK_PERMIT; + break; + case TCPOPT_SACK: + if (tcp_sack_option(tp, th, cp, optlen)) + continue; + break; +#endif + } + } + /* Update t_maxopd and t_maxseg after all options are processed */ + if (th->th_flags & TH_SYN) + (void) tcp_mss(tp, mss); /* sets t_maxseg */ +} + +#if defined(TCP_SACK) || defined(TCP_NEWRENO) +u_long +tcp_seq_subtract(a, b) + u_long a, b; +{ + return ((long)(a - b)); +} +#endif + + +#ifdef TCP_SACK +/* + * This function is called upon receipt of new valid data (while not in header + * prediction mode), and it updates the ordered list of sacks. + */ +void +tcp_update_sack_list(tp) + struct tcpcb *tp; +{ + /* + * First reported block MUST be the most recent one. Subsequent + * blocks SHOULD be in the order in which they arrived at the + * receiver. These two conditions make the implementation fully + * compliant with RFC 2018. + */ + int i, j = 0, count = 0, lastpos = -1; + struct sackblk sack, firstsack, temp[MAX_SACK_BLKS]; + + /* First clean up current list of sacks */ + for (i = 0; i < tp->rcv_numsacks; i++) { + sack = tp->sackblks[i]; + if (sack.start == 0 && sack.end == 0) { + count++; /* count = number of blocks to be discarded */ + continue; + } + if (SEQ_LEQ(sack.end, tp->rcv_nxt)) { + tp->sackblks[i].start = tp->sackblks[i].end = 0; + count++; + } else { + temp[j].start = tp->sackblks[i].start; + temp[j++].end = tp->sackblks[i].end; + } + } + tp->rcv_numsacks -= count; + if (tp->rcv_numsacks == 0) { /* no sack blocks currently (fast path) */ + tcp_clean_sackreport(tp); + if (SEQ_LT(tp->rcv_nxt, tp->rcv_laststart)) { + /* ==> need first sack block */ + tp->sackblks[0].start = tp->rcv_laststart; + tp->sackblks[0].end = tp->rcv_lastend; + tp->rcv_numsacks = 1; + } + return; + } + /* Otherwise, sack blocks are already present. */ + for (i = 0; i < tp->rcv_numsacks; i++) + tp->sackblks[i] = temp[i]; /* first copy back sack list */ + if (SEQ_GEQ(tp->rcv_nxt, tp->rcv_lastend)) + return; /* sack list remains unchanged */ + /* + * From here, segment just received should be (part of) the 1st sack. + * Go through list, possibly coalescing sack block entries. + */ + firstsack.start = tp->rcv_laststart; + firstsack.end = tp->rcv_lastend; + for (i = 0; i < tp->rcv_numsacks; i++) { + sack = tp->sackblks[i]; + if (SEQ_LT(sack.end, firstsack.start) || + SEQ_GT(sack.start, firstsack.end)) + continue; /* no overlap */ + if (sack.start == firstsack.start && sack.end == firstsack.end){ + /* + * identical block; delete it here since we will + * move it to the front of the list. + */ + tp->sackblks[i].start = tp->sackblks[i].end = 0; + lastpos = i; /* last posn with a zero entry */ + continue; + } + if (SEQ_LEQ(sack.start, firstsack.start)) + firstsack.start = sack.start; /* merge blocks */ + if (SEQ_GEQ(sack.end, firstsack.end)) + firstsack.end = sack.end; /* merge blocks */ + tp->sackblks[i].start = tp->sackblks[i].end = 0; + lastpos = i; /* last posn with a zero entry */ + } + if (lastpos != -1) { /* at least one merge */ + for (i = 0, j = 1; i < tp->rcv_numsacks; i++) { + sack = tp->sackblks[i]; + if (sack.start == 0 && sack.end == 0) + continue; + temp[j++] = sack; + } + tp->rcv_numsacks = j; /* including first blk (added later) */ + for (i = 1; i < tp->rcv_numsacks; i++) /* now copy back */ + tp->sackblks[i] = temp[i]; + } else { /* no merges -- shift sacks by 1 */ + if (tp->rcv_numsacks < MAX_SACK_BLKS) + tp->rcv_numsacks++; + for (i = tp->rcv_numsacks-1; i > 0; i--) + tp->sackblks[i] = tp->sackblks[i-1]; + } + tp->sackblks[0] = firstsack; + return; +} + +/* + * Process the TCP SACK option. Returns 1 if tcp_dooptions() should continue, + * and 0 otherwise, if the option was fine. tp->snd_holes is an ordered list + * of holes (oldest to newest, in terms of the sequence space). + */ +int +tcp_sack_option(tp, th, cp, optlen) + struct tcpcb *tp; + struct tcphdr *th; + u_char *cp; + int optlen; +{ + int tmp_olen; + u_char *tmp_cp; + struct sackhole *cur, *p, *temp; + + if (tp->sack_disable) + return 1; + + /* Note: TCPOLEN_SACK must be 2*sizeof(tcp_seq) */ + if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0) + return 1; + tmp_cp = cp + 2; + tmp_olen = optlen - 2; + if (tp->snd_numholes < 0) + tp->snd_numholes = 0; + if (tp->t_maxseg == 0) + panic("tcp_sack_option"); /* Should never happen */ + while (tmp_olen > 0) { + struct sackblk sack; + + bcopy((char *) tmp_cp, (char *) &(sack.start), sizeof(tcp_seq)); + NTOHL(sack.start); + bcopy((char *) tmp_cp + sizeof(tcp_seq), + (char *) &(sack.end), sizeof(tcp_seq)); + NTOHL(sack.end); + tmp_olen -= TCPOLEN_SACK; + tmp_cp += TCPOLEN_SACK; + if (SEQ_LEQ(sack.end, sack.start)) + continue; /* bad SACK fields */ + if (SEQ_LEQ(sack.end, tp->snd_una)) + continue; /* old block */ +#if defined(TCP_SACK) && defined(TCP_FACK) + /* Updates snd_fack. */ + if (SEQ_GEQ(sack.end, tp->snd_fack)) + tp->snd_fack = sack.end; +#endif /* TCP_FACK */ + if (SEQ_GT(th->th_ack, tp->snd_una)) { + if (SEQ_LT(sack.start, th->th_ack)) + continue; + } else { + if (SEQ_LT(sack.start, tp->snd_una)) + continue; + } + if (SEQ_GT(sack.end, tp->snd_max)) + continue; + if (tp->snd_holes == 0) { /* first hole */ + tp->snd_holes = (struct sackhole *) + malloc(sizeof(struct sackhole), M_PCB, M_NOWAIT); + if (tp->snd_holes == NULL) { + /* ENOBUFS, so ignore SACKed block for now*/ + continue; + } + cur = tp->snd_holes; + cur->start = th->th_ack; + cur->end = sack.start; + cur->rxmit = cur->start; + cur->next = 0; + tp->snd_numholes = 1; + tp->rcv_lastsack = sack.end; + /* + * dups is at least one. If more data has been + * SACKed, it can be greater than one. + */ + cur->dups = min(tcprexmtthresh, + ((sack.end - cur->end)/tp->t_maxseg)); + if (cur->dups < 1) + cur->dups = 1; + continue; /* with next sack block */ + } + /* Go thru list of holes: p = previous, cur = current */ + p = cur = tp->snd_holes; + while (cur) { + if (SEQ_LEQ(sack.end, cur->start)) + /* SACKs data before the current hole */ + break; /* no use going through more holes */ + if (SEQ_GEQ(sack.start, cur->end)) { + /* SACKs data beyond the current hole */ + cur->dups++; + if ( ((sack.end - cur->end)/tp->t_maxseg) >= + tcprexmtthresh) + cur->dups = tcprexmtthresh; + p = cur; + cur = cur->next; + continue; + } + if (SEQ_LEQ(sack.start, cur->start)) { + /* Data acks at least the beginning of hole */ +#if defined(TCP_SACK) && defined(TCP_FACK) + if (SEQ_GT(sack.end, cur->rxmit)) + tp->retran_data -= + tcp_seq_subtract(cur->rxmit, + cur->start); + else + tp->retran_data -= + tcp_seq_subtract(sack.end, + cur->start); +#endif /* TCP_FACK */ + if (SEQ_GEQ(sack.end,cur->end)){ + /* Acks entire hole, so delete hole */ + if (p != cur) { + p->next = cur->next; + free(cur, M_PCB); + cur = p->next; + } else { + cur=cur->next; + free(p, M_PCB); + p = cur; + tp->snd_holes = p; + } + tp->snd_numholes--; + continue; + } + /* otherwise, move start of hole forward */ + cur->start = sack.end; + cur->rxmit = max (cur->rxmit, cur->start); + p = cur; + cur = cur->next; + continue; + } + /* move end of hole backward */ + if (SEQ_GEQ(sack.end, cur->end)) { +#if defined(TCP_SACK) && defined(TCP_FACK) + if (SEQ_GT(cur->rxmit, sack.start)) + tp->retran_data -= + tcp_seq_subtract(cur->rxmit, + sack.start); +#endif /* TCP_FACK */ + cur->end = sack.start; + cur->rxmit = min (cur->rxmit, cur->end); + cur->dups++; + if ( ((sack.end - cur->end)/tp->t_maxseg) >= + tcprexmtthresh) + cur->dups = tcprexmtthresh; + p = cur; + cur = cur->next; + continue; + } + if (SEQ_LT(cur->start, sack.start) && + SEQ_GT(cur->end, sack.end)) { + /* + * ACKs some data in middle of a hole; need to + * split current hole + */ + temp = (struct sackhole *)malloc(sizeof(*temp), + M_PCB,M_NOWAIT); + if (temp == NULL) + continue; /* ENOBUFS */ +#if defined(TCP_SACK) && defined(TCP_FACK) + if (SEQ_GT(cur->rxmit, sack.end)) + tp->retran_data -= + tcp_seq_subtract(sack.end, + sack.start); + else if (SEQ_GT(cur->rxmit, sack.start)) + tp->retran_data -= + tcp_seq_subtract(cur->rxmit, + sack.start); +#endif /* TCP_FACK */ + temp->next = cur->next; + temp->start = sack.end; + temp->end = cur->end; + temp->dups = cur->dups; + temp->rxmit = max (cur->rxmit, temp->start); + cur->end = sack.start; + cur->rxmit = min (cur->rxmit, cur->end); + cur->dups++; + if ( ((sack.end - cur->end)/tp->t_maxseg) >= + tcprexmtthresh) + cur->dups = tcprexmtthresh; + cur->next = temp; + p = temp; + cur = p->next; + tp->snd_numholes++; + } + } + /* At this point, p points to the last hole on the list */ + if (SEQ_LT(tp->rcv_lastsack, sack.start)) { + /* + * Need to append new hole at end. + * Last hole is p (and it's not NULL). + */ + temp = (struct sackhole *) malloc(sizeof(*temp), + M_PCB, M_NOWAIT); + if (temp == NULL) + continue; /* ENOBUFS */ + temp->start = tp->rcv_lastsack; + temp->end = sack.start; + temp->dups = min(tcprexmtthresh, + ((sack.end - sack.start)/tp->t_maxseg)); + if (temp->dups < 1) + temp->dups = 1; + temp->rxmit = temp->start; + temp->next = 0; + p->next = temp; + tp->rcv_lastsack = sack.end; + tp->snd_numholes++; + } + } +#if defined(TCP_SACK) && defined(TCP_FACK) + /* + * Update retran_data and snd_awnd. Go through the list of + * holes. Increment retran_data by (hole->rxmit - hole->start). + */ + tp->retran_data = 0; + cur = tp->snd_holes; + while (cur) { + tp->retran_data += cur->rxmit - cur->start; + cur = cur->next; + } + tp->snd_awnd = tcp_seq_subtract(tp->snd_nxt, tp->snd_fack) + + tp->retran_data; +#endif /* TCP_FACK */ + + return 0; +} + +/* + * Delete stale (i.e, cumulatively ack'd) holes. Hole is deleted only if + * it is completely acked; otherwise, tcp_sack_option(), called from + * tcp_dooptions(), will fix up the hole. + */ +void +tcp_del_sackholes(tp, th) + struct tcpcb *tp; + struct tcphdr *th; +{ + if (!tp->sack_disable && tp->t_state != TCPS_LISTEN) { + /* max because this could be an older ack just arrived */ + tcp_seq lastack = SEQ_GT(th->th_ack, tp->snd_una) ? + th->th_ack : tp->snd_una; + struct sackhole *cur = tp->snd_holes; + struct sackhole *prev = cur; + while (cur) + if (SEQ_LEQ(cur->end, lastack)) { + cur = cur->next; + free(prev, M_PCB); + prev = cur; + tp->snd_numholes--; + } else if (SEQ_LT(cur->start, lastack)) { + cur->start = lastack; + break; + } else + break; + tp->snd_holes = cur; + } +} + +/* + * Delete all receiver-side SACK information. + */ +void +tcp_clean_sackreport(tp) + struct tcpcb *tp; +{ + int i; + + tp->rcv_numsacks = 0; + for (i = 0; i < MAX_SACK_BLKS; i++) + tp->sackblks[i].start = tp->sackblks[i].end=0; + +} + +/* + * Checks for partial ack. If partial ack arrives, turn off retransmission + * timer, deflate the window, do not clear tp->t_dupacks, and return 1. + * If the ack advances at least to tp->snd_last, return 0. + */ +int +tcp_sack_partialack(tp, th) + struct tcpcb *tp; + struct tcphdr *th; +{ + if (SEQ_LT(th->th_ack, tp->snd_last)) { + /* Turn off retx. timer (will start again next segment) */ + tp->t_timer[TCPT_REXMT] = 0; + tp->t_rtt = 0; +#ifndef TCP_FACK + /* + * Partial window deflation. This statement relies on the + * fact that tp->snd_una has not been updated yet. In FACK + * hold snd_cwnd constant during fast recovery. + */ + tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); +#endif + return 1; + } + return 0; +} +#endif /* TCP_SACK */ + +/* + * Pull out of band byte out of a segment so + * it doesn't appear in the user's data queue. + * It is still reflected in the segment length for + * sequencing purposes. + */ +void +tcp_pulloutofband(so, urgent, m, off) + struct socket *so; + u_int urgent; + register struct mbuf *m; + int off; +{ + int cnt = off + urgent - 1; + + while (cnt >= 0) { + if (m->m_len > cnt) { + char *cp = mtod(m, caddr_t) + cnt; + struct tcpcb *tp = sototcpcb(so); + + tp->t_iobc = *cp; + tp->t_oobflags |= TCPOOB_HAVEDATA; + bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1)); + m->m_len--; + return; + } + cnt -= m->m_len; + m = m->m_next; + if (m == 0) + break; + } + panic("tcp_pulloutofband"); +} + +/* + * Collect new round-trip time estimate + * and update averages and current timeout. + */ +void +tcp_xmit_timer(tp, rtt) + register struct tcpcb *tp; + short rtt; +{ + register short delta; + short rttmin; + + tcpstat.tcps_rttupdated++; + --rtt; + if (tp->t_srtt != 0) { + /* + * srtt is stored as fixed point with 3 bits after the + * binary point (i.e., scaled by 8). The following magic + * is equivalent to the smoothing algorithm in rfc793 with + * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed + * point). Adjust rtt to origin 0. + */ + delta = (rtt << 2) - (tp->t_srtt >> TCP_RTT_SHIFT); + if ((tp->t_srtt += delta) <= 0) + tp->t_srtt = 1; + /* + * We accumulate a smoothed rtt variance (actually, a + * smoothed mean difference), then set the retransmit + * timer to smoothed rtt + 4 times the smoothed variance. + * rttvar is stored as fixed point with 2 bits after the + * binary point (scaled by 4). The following is + * equivalent to rfc793 smoothing with an alpha of .75 + * (rttvar = rttvar*3/4 + |delta| / 4). This replaces + * rfc793's wired-in beta. + */ + if (delta < 0) + delta = -delta; + delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); + if ((tp->t_rttvar += delta) <= 0) + tp->t_rttvar = 1; + } else { + /* + * No rtt measurement yet - use the unsmoothed rtt. + * Set the variance to half the rtt (so our first + * retransmit happens at 3*rtt). + */ + tp->t_srtt = rtt << (TCP_RTT_SHIFT + 2); + tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT + 2 - 1); + } + tp->t_rtt = 0; + tp->t_rxtshift = 0; + + /* + * the retransmit should happen at rtt + 4 * rttvar. + * Because of the way we do the smoothing, srtt and rttvar + * will each average +1/2 tick of bias. When we compute + * the retransmit timer, we want 1/2 tick of rounding and + * 1 extra tick because of +-1/2 tick uncertainty in the + * firing of the timer. The bias will give us exactly the + * 1.5 tick we need. But, because the bias is + * statistical, we have to test that we don't drop below + * the minimum feasible timer (which is 2 ticks). + */ + if (tp->t_rttmin > rtt + 2) + rttmin = tp->t_rttmin; + else + rttmin = rtt + 2; + TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), rttmin, TCPTV_REXMTMAX); + + /* + * We received an ack for a packet that wasn't retransmitted; + * it is probably safe to discard any error indications we've + * received recently. This isn't quite right, but close enough + * for now (a route might have failed after we sent a segment, + * and the return path might not be symmetrical). + */ + tp->t_softerror = 0; +} + +/* + * Determine a reasonable value for maxseg size. + * If the route is known, check route for mtu. + * If none, use an mss that can be handled on the outgoing + * interface without forcing IP to fragment; if bigger than + * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES + * to utilize large mbufs. If no route is found, route has no mtu, + * or the destination isn't local, use a default, hopefully conservative + * size (usually 512 or the default IP max size, but no more than the mtu + * of the interface), as we can't discover anything about intervening + * gateways or networks. We also initialize the congestion/slow start + * window to be a single segment if the destination isn't local. + * While looking at the routing entry, we also initialize other path-dependent + * parameters from pre-set or cached values in the routing entry. + * + * Also take into account the space needed for options that we + * send regularly. Make maxseg shorter by that amount to assure + * that we can send maxseg amount of data even when the options + * are present. Store the upper limit of the length of options plus + * data in maxopd. + */ +int +tcp_mss(tp, offer) + register struct tcpcb *tp; + u_int offer; +{ + struct route *ro; + register struct rtentry *rt; + struct ifnet *ifp; + register int rtt, mss; + u_long bufsize; + struct inpcb *inp; + struct socket *so; + + inp = tp->t_inpcb; + ro = &inp->inp_route; + so = inp->inp_socket; + + if ((rt = ro->ro_rt) == (struct rtentry *)0) { + /* No route yet, so try to acquire one */ +#ifdef INET6 + /* + * Get a new IPv6 route if an IPv6 destination, otherwise, get + * and IPv4 route (including those pesky IPv4-mapped addresses). + */ + bzero(ro,sizeof(struct route_in6)); + if (sotopf(so) == AF_INET6) { + if (IN6_IS_ADDR_V4MAPPED(&inp->inp_faddr6)) { + /* Get an IPv4 route. */ + ro->ro_dst.sa_family = AF_INET; + ro->ro_dst.sa_len = sizeof(ro->ro_dst); + ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = + inp->inp_faddr; + rtalloc(ro); + } else { + ro->ro_dst.sa_family = AF_INET6; + ro->ro_dst.sa_len = sizeof(struct sockaddr_in6); + ((struct sockaddr_in6 *) &ro->ro_dst)->sin6_addr = + inp->inp_faddr6; + rtalloc(ro); + } + } else +#endif /* INET6 */ + if (inp->inp_faddr.s_addr != INADDR_ANY) { + ro->ro_dst.sa_family = AF_INET; + ro->ro_dst.sa_len = sizeof(ro->ro_dst); + satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr; + rtalloc(ro); + } + if ((rt = ro->ro_rt) == (struct rtentry *)0) { + tp->t_maxopd = tp->t_maxseg = tcp_mssdflt; + return (tcp_mssdflt); + } + } + ifp = rt->rt_ifp; + +#ifdef RTV_MTU /* if route characteristics exist ... */ + /* + * While we're here, check if there's an initial rtt + * or rttvar. Convert from the route-table units + * to scaled multiples of the slow timeout timer. + */ + if (tp->t_srtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) { + /* + * XXX the lock bit for MTU indicates that the value + * is also a minimum value; this is subject to time. + */ + if (rt->rt_rmx.rmx_locks & RTV_RTT) + TCPT_RANGESET(tp->t_rttmin, + rtt / (RTM_RTTUNIT / PR_SLOWHZ), + TCPTV_MIN, TCPTV_REXMTMAX); + tp->t_srtt = rtt / (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE)); + if (rt->rt_rmx.rmx_rttvar) + tp->t_rttvar = rt->rt_rmx.rmx_rttvar / + (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE)); + else + /* default variation is +- 1 rtt */ + tp->t_rttvar = + tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE; + TCPT_RANGESET(tp->t_rxtcur, + ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1, + tp->t_rttmin, TCPTV_REXMTMAX); + } + /* + * if there's an mtu associated with the route, use it + */ + if (rt->rt_rmx.rmx_mtu) +#ifdef INET6 + { + /* + * One may wish to lower MSS to take into account options, + * especially security-related options. + */ + if (tp->pf == AF_INET6) + mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpipv6hdr); + else +#endif /* INET6 */ + mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr); +#ifdef INET6 + } +#endif /* INET6 */ + else +#endif /* RTV_MTU */ + { + /* + * ifp may be null and rmx_mtu may be zero in certain + * v6 cases (e.g., if ND wasn't able to resolve the + * destination host. + */ + mss = ifp ? ifp->if_mtu - sizeof(struct tcpiphdr) : 0; +#ifdef INET6 + if (tp->pf == AF_INET) +#endif /* INET6 */ + if (!in_localaddr(inp->inp_faddr)) + mss = min(mss, tcp_mssdflt); + } + /* + * The current mss, t_maxseg, is initialized to the default value. + * If we compute a smaller value, reduce the current mss. + * If we compute a larger value, return it for use in sending + * a max seg size option, but don't store it for use + * unless we received an offer at least that large from peer. + * However, do not accept offers under 32 bytes. + */ + if (offer) + mss = min(mss, offer); + mss = max(mss, 64); /* sanity - at least max opt. space */ + /* + * maxopd stores the maximum length of data AND options + * in a segment; maxseg is the amount of data in a normal + * segment. We need to store this value (maxopd) apart + * from maxseg, because now every segment carries options + * and thus we normally have somewhat less data in segments. + */ + tp->t_maxopd = mss; + + if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && + (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP) + mss -= TCPOLEN_TSTAMP_APPA; + +#if (MCLBYTES & (MCLBYTES - 1)) == 0 + if (mss > MCLBYTES) + mss &= ~(MCLBYTES-1); +#else + if (mss > MCLBYTES) + mss = mss / MCLBYTES * MCLBYTES; +#endif + /* + * If there's a pipesize, change the socket buffer + * to that size. Make the socket buffers an integral + * number of mss units; if the mss is larger than + * the socket buffer, decrease the mss. + */ +#ifdef RTV_SPIPE + if ((bufsize = rt->rt_rmx.rmx_sendpipe) == 0) +#endif + bufsize = so->so_snd.sb_hiwat; + if (bufsize < mss) + mss = bufsize; + else { + bufsize = roundup(bufsize, mss); + if (bufsize > sb_max) + bufsize = sb_max; + (void)sbreserve(&so->so_snd, bufsize); + } + tp->t_maxseg = mss; + +#ifdef RTV_RPIPE + if ((bufsize = rt->rt_rmx.rmx_recvpipe) == 0) +#endif + bufsize = so->so_rcv.sb_hiwat; + if (bufsize > mss) { + bufsize = roundup(bufsize, mss); + if (bufsize > sb_max) + bufsize = sb_max; + (void)sbreserve(&so->so_rcv, bufsize); + } + tp->snd_cwnd = mss; + +#ifdef RTV_SSTHRESH + if (rt->rt_rmx.rmx_ssthresh) { + /* + * There's some sort of gateway or interface + * buffer limit on the path. Use this to set + * the slow start threshhold, but set the + * threshold to no less than 2*mss. + */ + tp->snd_ssthresh = max(2 * mss, rt->rt_rmx.rmx_ssthresh); + } +#endif /* RTV_MTU */ + return (mss); +} +#endif /* TUBA_INCLUDE */ + +#if defined(TCP_NEWRENO) || defined (TCP_SACK) +/* + * Checks for partial ack. If partial ack arrives, force the retransmission + * of the next unacknowledged segment, do not clear tp->t_dupacks, and return + * 1. By setting snd_nxt to ti_ack, this forces retransmission timer to + * be started again. If the ack advances at least to tp->snd_last, return 0. + */ +int +tcp_newreno(tp, th) + struct tcpcb *tp; + struct tcphdr *th; +{ + if (SEQ_LT(th->th_ack, tp->snd_last)) { + /* + * snd_una has not been updated and the socket send buffer + * not yet drained of the acked data, so we have to leave + * snd_una as it was to get the correct data offset in + * tcp_output(). + */ + tcp_seq onxt = tp->snd_nxt; + u_long ocwnd = tp->snd_cwnd; + tp->t_timer[TCPT_REXMT] = 0; + tp->t_rtt = 0; + tp->snd_nxt = th->th_ack; + /* + * Set snd_cwnd to one segment beyond acknowledged offset + * (tp->snd_una not yet updated when this function is called) + */ + tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una); + (void) tcp_output(tp); + tp->snd_cwnd = ocwnd; + if (SEQ_GT(onxt, tp->snd_nxt)) + tp->snd_nxt = onxt; + /* + * Partial window deflation. Relies on fact that tp->snd_una + * not updated yet. + */ + tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); + return 1; + } + return 0; +} +#endif /* TCP_NEWRENO || TCP_SACK */ diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_output.c b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_output.c new file mode 100644 index 0000000..adab0e1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_output.c @@ -0,0 +1,1124 @@ +//========================================================================== +// +// sys/netinet/tcp_output.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_output.c,v 1.27 1999/12/15 16:37:20 provos Exp $ */ +/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_output.c 8.3 (Berkeley) 12/30/93 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/errno.h> +#include <sys/domain.h> + +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#define TCPOUTFLAGS +#include <netinet/tcp_fsm.h> +#include <netinet/tcp_seq.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/tcpip.h> +#include <netinet/tcp_debug.h> + +#ifdef TUBA +#include <netiso/iso.h> +#include <netiso/tuba_table.h> +#endif + +#ifdef INET6 +#include <netinet6/tcpipv6.h> +#endif /* INET6 */ + +#ifdef TCP_SIGNATURE +#include <sys/md5k.h> +#endif /* TCP_SIGNATURE */ + +#ifdef notyet +extern struct mbuf *m_copypack(); +#endif + +#ifdef TCP_SACK +extern int tcprexmtthresh; +#endif + +#ifdef TCP_SACK +#ifdef TCP_SACK_DEBUG +void +tcp_print_holes(tp) +struct tcpcb *tp; +{ + struct sackhole *p = tp->snd_holes; + if (p == 0) + return; + printf("Hole report: start--end dups rxmit\n"); + while (p) { + printf("%x--%x d %d r %x\n", p->start, p->end, p->dups, + p->rxmit); + p = p->next; + } + printf("\n"); +} +#endif /* TCP_SACK_DEBUG */ + +/* + * Returns pointer to a sackhole if there are any pending retransmissions; + * NULL otherwise. + */ +struct sackhole * +tcp_sack_output(tp) +register struct tcpcb *tp; +{ + struct sackhole *p; + if (tp->sack_disable) + return 0; + p = tp->snd_holes; + while (p) { + if (p->dups >= tcprexmtthresh && SEQ_LT(p->rxmit, p->end)) { + if (SEQ_LT(p->rxmit, tp->snd_una)) {/* old SACK hole */ + p = p->next; + continue; + } +#ifdef TCP_SACK_DEBUG + if (p) + tcp_print_holes(tp); +#endif + return p; + } + p = p->next; + } + return 0; +} + +/* + * After a timeout, the SACK list may be rebuilt. This SACK information + * should be used to avoid retransmitting SACKed data. This function + * traverses the SACK list to see if snd_nxt should be moved forward. + */ +void +tcp_sack_adjust(tp) + struct tcpcb *tp; +{ + int i; + + for (i = 0; i < tp->rcv_numsacks; i++) { + if (SEQ_LT(tp->snd_nxt, tp->sackblks[i].start)) + break; + if (SEQ_LEQ(tp->sackblks[i].end, tp->snd_nxt)) + continue; + if (tp->sackblks[i].start == 0 && tp->sackblks[i].end == 0) + continue; + /* snd_nxt must be in middle of block of SACKed data */ + tp->snd_nxt = tp->sackblks[i].end; + break; + } +} +#endif /* TCP_SACK */ + +/* + * Tcp output routine: figure out what should be sent and send it. + */ +int +tcp_output(tp) + register struct tcpcb *tp; +{ + register struct socket *so = tp->t_inpcb->inp_socket; + register long len, win; + int off, flags, error = 0; + register struct mbuf *m; + register struct tcphdr *th; + u_char opt[MAX_TCPOPTLEN]; + unsigned int optlen, hdrlen; + int idle, sendalot; +#ifdef TCP_SACK + int i, sack_rxmit = 0; + struct sackhole *p; +#endif +#if defined(TCP_SACK) || defined(TCP_NEWRENO) + int maxburst = TCP_MAXBURST; +#endif +#ifdef TCP_SIGNATURE + unsigned int sigoff; +#endif /* TCP_SIGNATURE */ + +#if defined(TCP_SACK) && defined(TCP_SIGNATURE) && defined(DIAGNOSTIC) + if (!tp->sack_disable && (tp->t_flags & TF_SIGNATURE)) + return (EINVAL); +#endif /* defined(TCP_SACK) && defined(TCP_SIGNATURE) && defined(DIAGNOSTIC) */ + + /* + * Determine length of data that should be transmitted, + * and flags that will be used. + * If there is some data or critical controls (SYN, RST) + * to send, then transmit; otherwise, investigate further. + */ + idle = (tp->snd_max == tp->snd_una); + if (idle && tp->t_idle >= tp->t_rxtcur) + /* + * We have been idle for "a while" and no acks are + * expected to clock out any data we send -- + * slow start to get ack "clock" running again. + */ + tp->snd_cwnd = tp->t_maxseg; +again: + sendalot = 0; +#ifdef TCP_SACK + /* + * If we've recently taken a timeout, snd_max will be greater than + * snd_nxt. There may be SACK information that allows us to avoid + * resending already delivered data. Adjust snd_nxt accordingly. + */ + if (!tp->sack_disable && SEQ_LT(tp->snd_nxt, tp->snd_max)) + tcp_sack_adjust(tp); +#endif + off = tp->snd_nxt - tp->snd_una; + win = ulmin(tp->snd_wnd, tp->snd_cwnd); + + flags = tcp_outflags[tp->t_state]; + /* + * If in persist timeout with window of 0, send 1 byte. + * Otherwise, if window is small but nonzero + * and timer expired, we will send what we can + * and go to transmit state. + */ + +#ifdef TCP_SACK + /* + * Send any SACK-generated retransmissions. If we're explicitly trying + * to send out new data (when sendalot is 1), bypass this function. + * If we retransmit in fast recovery mode, decrement snd_cwnd, since + * we're replacing a (future) new transmission with a retransmission + * now, and we previously incremented snd_cwnd in tcp_input(). + */ + if (!tp->sack_disable && !sendalot) { + if ((p = tcp_sack_output(tp))) { + off = p->rxmit - tp->snd_una; + sack_rxmit = 1; +#if 0 + /* Coalesce holes into a single retransmission */ +#endif + len = min(tp->t_maxseg, p->end - p->rxmit); +#ifndef TCP_FACK + /* in FACK, hold snd_cwnd constant during recovery */ + if (SEQ_LT(tp->snd_una, tp->snd_last)) + tp->snd_cwnd -= tp->t_maxseg; +#endif + } + } +#endif /* TCP_SACK */ + + if (tp->t_force) { + if (win == 0) { + /* + * If we still have some data to send, then + * clear the FIN bit. Usually this would + * happen below when it realizes that we + * aren't sending all the data. However, + * if we have exactly 1 byte of unset data, + * then it won't clear the FIN bit below, + * and if we are in persist state, we wind + * up sending the packet without recording + * that we sent the FIN bit. + * + * We can't just blindly clear the FIN bit, + * because if we don't have any more data + * to send then the probe will be the FIN + * itself. + */ + if (off < so->so_snd.sb_cc) + flags &= ~TH_FIN; + win = 1; + } else { + tp->t_timer[TCPT_PERSIST] = 0; + tp->t_rxtshift = 0; + } + } + +#ifdef TCP_SACK + if (!sack_rxmit) { +#endif + len = ulmin(so->so_snd.sb_cc, win) - off; + +#if defined(TCP_SACK) && defined(TCP_FACK) + /* + * If we're in fast recovery (SEQ_GT(tp->snd_last, tp->snd_una)), and + * amount of outstanding data (snd_awnd) is >= snd_cwnd, then + * do not send data (like zero window conditions) + */ + if (!tp->sack_disable && len && SEQ_GT(tp->snd_last, tp->snd_una) && + (tp->snd_awnd >= tp->snd_cwnd)) + len = 0; +#endif /* TCP_FACK */ +#ifdef TCP_SACK + } +#endif + + if (len < 0) { + /* + * If FIN has been sent but not acked, + * but we haven't been called to retransmit, + * len will be -1. Otherwise, window shrank + * after we sent into it. If window shrank to 0, + * cancel pending retransmit and pull snd_nxt + * back to (closed) window. We will enter persist + * state below. If the window didn't close completely, + * just wait for an ACK. + */ + len = 0; + if (win == 0) { + tp->t_timer[TCPT_REXMT] = 0; + tp->snd_nxt = tp->snd_una; + } + } + if (len > tp->t_maxseg) { + len = tp->t_maxseg; + sendalot = 1; + } + if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) + flags &= ~TH_FIN; + + win = sbspace(&so->so_rcv); + + /* + * Sender silly window avoidance. If connection is idle + * and can send all data, a maximum segment, + * at least a maximum default-size segment do it, + * or are forced, do it; otherwise don't bother. + * If peer's buffer is tiny, then send + * when window is at least half open. + * If retransmitting (possibly after persist timer forced us + * to send into a small window), then must resend. + */ + if (len) { + if (len == tp->t_maxseg) + goto send; + if ((idle || tp->t_flags & TF_NODELAY) && + len + off >= so->so_snd.sb_cc) + goto send; + if (tp->t_force) + goto send; + if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) + goto send; + if (SEQ_LT(tp->snd_nxt, tp->snd_max)) + goto send; +#ifdef TCP_SACK + if (sack_rxmit) + goto send; +#endif + } + + /* + * Compare available window to amount of window + * known to peer (as advertised window less + * next expected input). If the difference is at least two + * max size segments, or at least 50% of the maximum possible + * window, then want to send a window update to peer. + */ + if (win > 0) { + /* + * "adv" is the amount we can increase the window, + * taking into account that we are limited by + * TCP_MAXWIN << tp->rcv_scale. + */ + long adv = lmin(win, (long)TCP_MAXWIN << tp->rcv_scale) - + (tp->rcv_adv - tp->rcv_nxt); + + if (adv >= (long) (2 * tp->t_maxseg)) + goto send; + if (2 * adv >= (long) so->so_rcv.sb_hiwat) + goto send; + } + + /* + * Send if we owe peer an ACK. + */ + if (tp->t_flags & TF_ACKNOW) + goto send; + if (flags & (TH_SYN|TH_RST)) + goto send; + if (SEQ_GT(tp->snd_up, tp->snd_una)) + goto send; + /* + * If our state indicates that FIN should be sent + * and we have not yet done so, or we're retransmitting the FIN, + * then we need to send. + */ + if (flags & TH_FIN && + ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) + goto send; +#ifdef TCP_SACK + /* + * In SACK, it is possible for tcp_output to fail to send a segment + * after the retransmission timer has been turned off. Make sure + * that the retransmission timer is set. + */ + if (SEQ_GT(tp->snd_max, tp->snd_una) && + tp->t_timer[TCPT_REXMT] == 0 && + tp->t_timer[TCPT_PERSIST] == 0) { + tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; + return (0); + } +#endif /* TCP_SACK */ + + /* + * TCP window updates are not reliable, rather a polling protocol + * using ``persist'' packets is used to insure receipt of window + * updates. The three ``states'' for the output side are: + * idle not doing retransmits or persists + * persisting to move a small or zero window + * (re)transmitting and thereby not persisting + * + * tp->t_timer[TCPT_PERSIST] + * is set when we are in persist state. + * tp->t_force + * is set when we are called to send a persist packet. + * tp->t_timer[TCPT_REXMT] + * is set when we are retransmitting + * The output side is idle when both timers are zero. + * + * If send window is too small, there is data to transmit, and no + * retransmit or persist is pending, then go to persist state. + * If nothing happens soon, send when timer expires: + * if window is nonzero, transmit what we can, + * otherwise force out a byte. + */ + if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && + tp->t_timer[TCPT_PERSIST] == 0) { + tp->t_rxtshift = 0; + tcp_setpersist(tp); + } + + /* + * No reason to send a segment, just return. + */ + return (0); + +send: + /* + * Before ESTABLISHED, force sending of initial options + * unless TCP set not to do any options. + * NOTE: we assume that the IP/TCP header plus TCP options + * always fit in a single mbuf, leaving room for a maximum + * link header, i.e. + * max_linkhdr + sizeof(network header) + sizeof(struct tcphdr + + * optlen <= MHLEN + */ + optlen = 0; + + switch (tp->pf) { + case 0: /*default to PF_INET*/ +#ifdef INET + case PF_INET: + hdrlen = sizeof(struct ip) + sizeof(struct tcphdr); + break; +#endif /* INET */ +#ifdef INET6 + case PF_INET6: + hdrlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); + break; +#endif /* INET6 */ + default: + return (EPFNOSUPPORT); + } + + if (flags & TH_SYN) { + tp->snd_nxt = tp->iss; + if ((tp->t_flags & TF_NOOPT) == 0) { + u_int16_t mss; + + opt[0] = TCPOPT_MAXSEG; + opt[1] = 4; + mss = htons((u_int16_t) tcp_mss(tp, 0)); + bcopy((caddr_t)&mss, (caddr_t)(opt + 2), sizeof(mss)); + optlen = 4; +#ifdef TCP_SACK + /* + * If this is the first SYN of connection (not a SYN + * ACK), include SACK_PERMIT_HDR option. If this is a + * SYN ACK, include SACK_PERMIT_HDR option if peer has + * already done so. + */ + if (!tp->sack_disable && ((flags & TH_ACK) == 0 || + (tp->t_flags & TF_SACK_PERMIT))) { + *((u_int32_t *) (opt + optlen)) = + htonl(TCPOPT_SACK_PERMIT_HDR); + optlen += 4; + } +#endif + + if ((tp->t_flags & TF_REQ_SCALE) && + ((flags & TH_ACK) == 0 || + (tp->t_flags & TF_RCVD_SCALE))) { + *((u_int32_t *) (opt + optlen)) = htonl( + TCPOPT_NOP << 24 | + TCPOPT_WINDOW << 16 | + TCPOLEN_WINDOW << 8 | + tp->request_r_scale); + optlen += 4; + } + } + } + + /* + * Send a timestamp and echo-reply if this is a SYN and our side + * wants to use timestamps (TF_REQ_TSTMP is set) or both our side + * and our peer have sent timestamps in our SYN's. + */ + if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && + (flags & TH_RST) == 0 && + ((flags & (TH_SYN|TH_ACK)) == TH_SYN || + (tp->t_flags & TF_RCVD_TSTMP))) { + u_int32_t *lp = (u_int32_t *)(opt + optlen); + + /* Form timestamp option as shown in appendix A of RFC 1323. */ + *lp++ = htonl(TCPOPT_TSTAMP_HDR); + *lp++ = htonl(tcp_now); + *lp = htonl(tp->ts_recent); + optlen += TCPOLEN_TSTAMP_APPA; + } + +#ifdef TCP_SIGNATURE + if (tp->t_flags & TF_SIGNATURE) { + u_int8_t *bp = (u_int8_t *)(opt + optlen); + + /* Send signature option */ + *(bp++) = TCPOPT_SIGNATURE; + *(bp++) = TCPOLEN_SIGNATURE; + sigoff = optlen + 2; + + { + unsigned int i; + + for (i = 0; i < 16; i++) + *(bp++) = 0; + } + + optlen += TCPOLEN_SIGNATURE; + + /* Pad options list to the next 32 bit boundary and + * terminate it. + */ + *bp++ = TCPOPT_NOP; + *bp++ = TCPOPT_EOL; + optlen += 2; + } +#endif /* TCP_SIGNATURE */ + +#ifdef TCP_SACK + /* + * Send SACKs if necessary. This should be the last option processed. + * Only as many SACKs are sent as are permitted by the maximum options + * size. No more than three SACKs are sent. + */ + if (!tp->sack_disable && tp->t_state == TCPS_ESTABLISHED && + (tp->t_flags & (TF_SACK_PERMIT|TF_NOOPT)) == TF_SACK_PERMIT && + tp->rcv_numsacks) { + u_int32_t *lp = (u_int32_t *)(opt + optlen); + u_int32_t *olp = lp++; + int count = 0; /* actual number of SACKs inserted */ + int maxsack = (MAX_TCPOPTLEN - (optlen + 4))/TCPOLEN_SACK; + + maxsack = min(maxsack, TCP_MAX_SACK); + for (i = 0; (i < tp->rcv_numsacks && count < maxsack); i++) { + struct sackblk sack = tp->sackblks[i]; + if (sack.start == 0 && sack.end == 0) + continue; + *lp++ = htonl(sack.start); + *lp++ = htonl(sack.end); + count++; + } + *olp = htonl(TCPOPT_SACK_HDR|(TCPOLEN_SACK*count+2)); + optlen += TCPOLEN_SACK*count + 4; /* including leading NOPs */ + } +#endif /* TCP_SACK */ + +#ifdef DIAGNOSTIC + if (optlen > MAX_TCPOPTLEN) + panic("tcp_output: options too long"); +#endif /* DIAGNOSTIC */ + + hdrlen += optlen; + + /* + * Adjust data length if insertion of options will + * bump the packet length beyond the t_maxopd length. + */ + if (len > tp->t_maxopd - optlen) { + len = tp->t_maxopd - optlen; + sendalot = 1; + flags &= ~TH_FIN; + } + +#ifdef DIAGNOSTIC + if (max_linkhdr + hdrlen > MCLBYTES) + panic("tcphdr too big"); +#endif + + /* + * Grab a header mbuf, attaching a copy of data to + * be transmitted, and initialize the header from + * the template for sends on this connection. + */ + if (len) { + if (tp->t_force && len == 1) + tcpstat.tcps_sndprobe++; + else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { + tcpstat.tcps_sndrexmitpack++; + tcpstat.tcps_sndrexmitbyte += len; + } else { + tcpstat.tcps_sndpack++; + tcpstat.tcps_sndbyte += len; + } +#ifdef notyet + if ((m = m_copypack(so->so_snd.sb_mb, off, + (int)len, max_linkhdr + hdrlen)) == 0) { + error = ENOBUFS; + goto out; + } + /* + * m_copypack left space for our hdr; use it. + */ + m->m_len += hdrlen; + m->m_data -= hdrlen; +#else + MGETHDR(m, M_DONTWAIT, MT_HEADER); + if (m != NULL) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + m = NULL; + } + } + if (m == NULL) { + error = ENOBUFS; + goto out; + } + m->m_data += max_linkhdr; + m->m_len = hdrlen; + if (len <= MCLBYTES - hdrlen - max_linkhdr) { + m_copydata(so->so_snd.sb_mb, off, (int) len, + mtod(m, caddr_t) + hdrlen); + m->m_len += len; + } else { + m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len); + if (m->m_next == 0) { + (void) m_free(m); + error = ENOBUFS; + goto out; + } + } +#endif + /* + * If we're sending everything we've got, set PUSH. + * (This will keep happy those implementations which only + * give data to the user when a buffer fills or + * a PUSH comes in.) + */ + if (off + len == so->so_snd.sb_cc) + flags |= TH_PUSH; + } else { + if (tp->t_flags & TF_ACKNOW) + tcpstat.tcps_sndacks++; + else if (flags & (TH_SYN|TH_FIN|TH_RST)) + tcpstat.tcps_sndctrl++; + else if (SEQ_GT(tp->snd_up, tp->snd_una)) + tcpstat.tcps_sndurg++; + else + tcpstat.tcps_sndwinup++; + + MGETHDR(m, M_DONTWAIT, MT_HEADER); + if (m != NULL) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + m = NULL; + } + } + if (m == NULL) { + error = ENOBUFS; + goto out; + } + m->m_data += max_linkhdr; + m->m_len = hdrlen; + } + m->m_pkthdr.rcvif = (struct ifnet *)0; + + if (!tp->t_template) + panic("tcp_output"); +#ifdef DIAGNOSTIC + if (tp->t_template->m_len != hdrlen - optlen) + panic("tcp_output: template len != hdrlen - optlen"); +#endif /* DIAGNOSTIC */ + bcopy(mtod(tp->t_template, caddr_t), mtod(m, caddr_t), + tp->t_template->m_len); + th = (struct tcphdr *)(mtod(m, caddr_t) + tp->t_template->m_len - + sizeof(struct tcphdr)); + + /* + * Fill in fields, remembering maximum advertised + * window for use in delaying messages about window sizes. + * If resending a FIN, be sure not to use a new sequence number. + */ + if ((flags & TH_FIN) && (tp->t_flags & TF_SENTFIN) && + (tp->snd_nxt == tp->snd_max)) + tp->snd_nxt--; + /* + * If we are doing retransmissions, then snd_nxt will + * not reflect the first unsent octet. For ACK only + * packets, we do not want the sequence number of the + * retransmitted packet, we want the sequence number + * of the next unsent octet. So, if there is no data + * (and no SYN or FIN), use snd_max instead of snd_nxt + * when filling in ti_seq. But if we are in persist + * state, snd_max might reflect one byte beyond the + * right edge of the window, so use snd_nxt in that + * case, since we know we aren't doing a retransmission. + * (retransmit and persist are mutually exclusive...) + */ + if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST]) + th->th_seq = htonl(tp->snd_nxt); + else + th->th_seq = htonl(tp->snd_max); + +#ifdef TCP_SACK + if (sack_rxmit) { + /* + * If sendalot was turned on (due to option stuffing), turn it + * off. Properly set th_seq field. Advance the ret'x pointer + * by len. + */ + if (sendalot) + sendalot = 0; + th->th_seq = htonl(p->rxmit); + p->rxmit += len; +#if defined(TCP_SACK) && defined(TCP_FACK) + tp->retran_data += len; +#endif /* TCP_FACK */ + } +#endif /* TCP_SACK */ + + th->th_ack = htonl(tp->rcv_nxt); + if (optlen) { + bcopy((caddr_t)opt, (caddr_t)(th + 1), optlen); + th->th_off = (sizeof (struct tcphdr) + optlen) >> 2; + } + th->th_flags = flags; + + /* + * Calculate receive window. Don't shrink window, + * but avoid silly window syndrome. + */ + if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg) + win = 0; + if (win > (long)TCP_MAXWIN << tp->rcv_scale) + win = (long)TCP_MAXWIN << tp->rcv_scale; + if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) + win = (long)(tp->rcv_adv - tp->rcv_nxt); + if (flags & TH_RST) + win = 0; + th->th_win = htons((u_int16_t) (win>>tp->rcv_scale)); + if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { + u_int32_t urp = tp->snd_up - tp->snd_nxt; + if (urp > IP_MAXPACKET) + urp = IP_MAXPACKET; + th->th_urp = htons((u_int16_t)urp); + th->th_flags |= TH_URG; + } else + /* + * If no urgent pointer to send, then we pull + * the urgent pointer to the left edge of the send window + * so that it doesn't drift into the send window on sequence + * number wraparound. + */ + tp->snd_up = tp->snd_una; /* drag it along */ + + /* Put TCP length in pseudo-header */ + switch (tp->pf) { + case 0: /*default to PF_INET*/ +#ifdef INET + case AF_INET: + if (len + optlen) + mtod(m, struct ipovly *)->ih_len = htons((u_int16_t)( + sizeof (struct tcphdr) + optlen + len)); + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + break; +#endif /* INET6 */ + } + +#ifdef TCP_SIGNATURE + if (tp->t_flags & TF_SIGNATURE) { + MD5_CTX ctx; + union sockaddr_union sa; + struct tdb *tdb; + + memset(&sa, 0, sizeof(union sockaddr_union)); + + switch (tp->pf) { + case 0: /*default to PF_INET*/ +#ifdef INET + case AF_INET: + sa.sa.sa_len = sizeof(struct sockaddr_in); + sa.sa.sa_family = AF_INET; + sa.sin.sin_addr = mtod(m, struct ip *)->ip_dst; + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + sa.sa.sa_len = sizeof(struct sockaddr_in6); + sa.sa.sa_family = AF_INET6; + sa.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_dst; + break; +#endif /* INET6 */ + } + + /* XXX gettdb() should really be called at spltdb(). */ + /* XXX this is splsoftnet(), currently they are the same. */ + tdb = gettdb(0, &sa, IPPROTO_TCP); + if (tdb == NULL) + return (EPERM); + + MD5Init(&ctx); + + switch (tp->pf) { + case 0: /*default to PF_INET*/ +#ifdef INET + case AF_INET: + { + struct ippseudo ippseudo; + struct ipovly *ipovly; + + ipovly = mtod(m, struct ipovly *); + + ippseudo.ippseudo_src = ipovly->ih_src; + ippseudo.ippseudo_dst = ipovly->ih_dst; + ippseudo.ippseudo_pad = 0; + ippseudo.ippseudo_p = IPPROTO_TCP; + ippseudo.ippseudo_len = ipovly->ih_len; + MD5Update(&ctx, (char *)&ippseudo, + sizeof(struct ippseudo)); + MD5Update(&ctx, mtod(m, caddr_t) + + sizeof(struct ip), + sizeof(struct tcphdr)); + } + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + { + static int printed = 0; + + if (!printed) { + printf("error: TCP MD5 support for " + "IPv6 not yet implemented.\n"); + printed = 1; + } + } + break; +#endif /* INET6 */ + } + + if (len && m_apply(m, hdrlen, len, tcp_signature_apply, + (caddr_t)&ctx)) + return (EINVAL); + + MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen); + MD5Final(mtod(m, caddr_t) + hdrlen - optlen + sigoff, &ctx); + } +#endif /* TCP_SIGNATURE */ + + /* + * Put TCP length in extended header, and then + * checksum extended header and data. + */ + switch (tp->pf) { + case 0: /*default to PF_INET*/ +#ifdef INET + case AF_INET: + th->th_sum = in_cksum(m, (int)(hdrlen + len)); + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + m->m_pkthdr.len = hdrlen + len; + th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr), + hdrlen - sizeof(struct ip6_hdr) + len); + break; +#endif /* INET6 */ + } + + /* + * In transmit state, time the transmission and arrange for + * the retransmit. In persist state, just set snd_max. + */ + if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { + tcp_seq startseq = tp->snd_nxt; + + /* + * Advance snd_nxt over sequence space of this segment. + */ + if (flags & (TH_SYN|TH_FIN)) { + if (flags & TH_SYN) + tp->snd_nxt++; + if (flags & TH_FIN) { + tp->snd_nxt++; + tp->t_flags |= TF_SENTFIN; + } + } +#ifdef TCP_SACK + if (!tp->sack_disable) { + if (sack_rxmit && (p->rxmit != tp->snd_nxt)) { + goto timer; + } + } +#endif + tp->snd_nxt += len; + if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { + tp->snd_max = tp->snd_nxt; + /* + * Time this transmission if not a retransmission and + * not currently timing anything. + */ + if (tp->t_rtt == 0) { + tp->t_rtt = 1; + tp->t_rtseq = startseq; + tcpstat.tcps_segstimed++; + } + } + + /* + * Set retransmit timer if not currently set, + * and not doing an ack or a keep-alive probe. + * Initial value for retransmit timer is smoothed + * round-trip time + 2 * round-trip time variance. + * Initialize shift counter which is used for backoff + * of retransmit time. + */ +#ifdef TCP_SACK + timer: + if (!tp->sack_disable && sack_rxmit && + tp->t_timer[TCPT_REXMT] == 0 && + tp->snd_nxt != tp->snd_max) { + tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; + if (tp->t_timer[TCPT_PERSIST]) { + tp->t_timer[TCPT_PERSIST] = 0; + tp->t_rxtshift = 0; + } + } +#endif + + if (tp->t_timer[TCPT_REXMT] == 0 && + tp->snd_nxt != tp->snd_una) { + tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; + if (tp->t_timer[TCPT_PERSIST]) { + tp->t_timer[TCPT_PERSIST] = 0; + tp->t_rxtshift = 0; + } + } + } else + if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) + tp->snd_max = tp->snd_nxt + len; + + /* + * Trace. + */ +#ifdef TCPDEBUG + if (so->so_options & SO_DEBUG) + tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, caddr_t), 0, + len); +#endif /* TCPDEBUG */ + + /* + * Fill in IP length and desired time to live and + * send to IP level. There should be a better way + * to handle ttl and tos; we could keep them in + * the template, but need a way to checksum without them. + */ + m->m_pkthdr.len = hdrlen + len; + + switch (tp->pf) { + case 0: /*default to PF_INET*/ +#ifdef INET + case AF_INET: + { + struct ip *ip; + + ip = mtod(m, struct ip *); + ip->ip_len = m->m_pkthdr.len; + ip->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl; + ip->ip_tos = tp->t_inpcb->inp_ip.ip_tos; + } + error = ip_output(m, tp->t_inpcb->inp_options, + &tp->t_inpcb->inp_route, so->so_options & SO_DONTROUTE, + 0, tp->t_inpcb); + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + { + struct ip6_hdr *ipv6; + + ipv6 = mtod(m, struct ip6_hdr *); + ipv6->ip6_plen = m->m_pkthdr.len - + sizeof(struct ip6_hdr); + ipv6->ip6_nxt = IPPROTO_TCP; + ipv6->ip6_hlim = in6_selecthlim(tp->t_inpcb, NULL); + } + error = ip6_output(m, tp->t_inpcb->inp_outputopts6, + &tp->t_inpcb->inp_route6, + (so->so_options & SO_DONTROUTE), NULL, NULL); + break; +#endif /* INET6 */ +#ifdef TUBA + case AF_ISO: + if (tp->t_tuba_pcb) + error = tuba_output(m, tp); + break; +#endif /* TUBA */ + } + +#if defined(TCP_SACK) && defined(TCP_FACK) + /* Update snd_awnd to reflect the new data that was sent. */ + tp->snd_awnd = tcp_seq_subtract(tp->snd_max, tp->snd_fack) + + tp->retran_data; +#endif /* defined(TCP_SACK) && defined(TCP_FACK) */ + + if (error) { +out: + if (error == ENOBUFS) { + tcp_quench(tp->t_inpcb, 0); + return (0); + } + if ((error == EHOSTUNREACH || error == ENETDOWN) + && TCPS_HAVERCVDSYN(tp->t_state)) { + tp->t_softerror = error; + return (0); + } + return (error); + } + tcpstat.tcps_sndtotal++; + + /* + * Data sent (as far as we can tell). + * If this advertises a larger window than any other segment, + * then remember the size of the advertised window. + * Any pending ACK has now been sent. + */ + if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) + tp->rcv_adv = tp->rcv_nxt + win; + tp->last_ack_sent = tp->rcv_nxt; + tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); +#if defined(TCP_SACK) || defined(TCP_NEWRENO) + if (sendalot && --maxburst) +#else + if (sendalot) +#endif + goto again; + return (0); +} + +void +tcp_setpersist(tp) + register struct tcpcb *tp; +{ + register int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; + + if (tp->t_timer[TCPT_REXMT]) + panic("tcp_output REXMT"); + /* + * Start/restart persistance timer. + */ + if (t < tp->t_rttmin) + t = tp->t_rttmin; + TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], + t * tcp_backoff[tp->t_rxtshift], + TCPTV_PERSMIN, TCPTV_PERSMAX); + if (tp->t_rxtshift < TCP_MAXRXTSHIFT) + tp->t_rxtshift++; +} diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_subr.c b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_subr.c new file mode 100644 index 0000000..24937e1 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_subr.c @@ -0,0 +1,899 @@ +//========================================================================== +// +// sys/netinet/tcp_subr.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_subr.c,v 1.21 1999/12/08 06:50:20 itojun Exp $ */ +/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/proc.h> +#include <sys/systm.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/protosw.h> +#include <sys/errno.h> +#ifdef __ECOS +#undef errno +#endif + +#include <net/route.h> +#include <net/if.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/ip_var.h> +#include <netinet/ip_icmp.h> +#include <netinet/tcp.h> +#include <netinet/tcp_fsm.h> +#include <netinet/tcp_seq.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/tcpip.h> +#ifndef __ECOS +#include <dev/rndvar.h> +#endif + +#ifdef INET6 +#include <netinet6/ip6_var.h> +#include <netinet6/tcpipv6.h> +#include <sys/domain.h> +#endif /* INET6 */ + +#ifdef TCP_SIGNATURE +#include <sys/md5k.h> +#endif /* TCP_SIGNATURE */ + +/* patchable/settable parameters for tcp */ +int tcp_mssdflt = TCP_MSS; +int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; + +/* + * Configure kernel with options "TCP_DO_RFC1323=0" to disable RFC1323 stuff. + * This is a good idea over slow SLIP/PPP links, because the timestamp + * pretty well destroys the VJ compression (any packet with a timestamp + * different from the previous one can't be compressed), as well as adding + * more overhead. + * XXX And it should be a settable per route characteristic (with this just + * used as the default). + */ +#ifndef TCP_DO_RFC1323 +#define TCP_DO_RFC1323 1 +#endif +int tcp_do_rfc1323 = TCP_DO_RFC1323; + +#ifndef TCP_DO_SACK +#ifdef TCP_SACK +#define TCP_DO_SACK 0 /* XXX - make this 1 when SACK is fixed */ +#else +#define TCP_DO_SACK 0 +#endif +#endif +int tcp_do_sack = TCP_DO_SACK; /* RFC 2018 selective ACKs */ + +#ifndef TCBHASHSIZE +#define TCBHASHSIZE 128 +#endif +int tcbhashsize = TCBHASHSIZE; + +#ifdef INET6 +extern int ip6_defhlim; +#endif /* INET6 */ + +/* + * Tcp initialization + */ +void +tcp_init() +{ +#ifdef TCP_COMPAT_42 + tcp_iss = 1; /* wrong */ +#else /* TCP_COMPAT_42 */ + tcp_iss = arc4random() + 1; +#endif /* !TCP_COMPAT_42 */ + in_pcbinit(&tcbtable, tcbhashsize); + +#ifdef INET6 + /* + * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we + * do max length checks/computations only on the former. + */ + if (max_protohdr < (sizeof(struct ip6_hdr) + sizeof(struct tcphdr))) + max_protohdr = (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)); + if ((max_linkhdr + sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) > + MHLEN) + panic("tcp_init"); +#endif /* INET6 */ +} + +/* + * Create template to be used to send tcp packets on a connection. + * Call after host entry created, allocates an mbuf and fills + * in a skeletal tcp/ip header, minimizing the amount of work + * necessary when the connection is used. + * + * To support IPv6 in addition to IPv4 and considering that the sizes of + * the IPv4 and IPv6 headers are not the same, we now use a separate pointer + * for the TCP header. Also, we made the former tcpiphdr header pointer + * into just an IP overlay pointer, with casting as appropriate for v6. rja + */ +struct mbuf * +tcp_template(tp) + struct tcpcb *tp; +{ + register struct inpcb *inp = tp->t_inpcb; + register struct mbuf *m; + register struct tcphdr *th = (struct tcphdr *)0; + + if ((m = tp->t_template) == 0) { + m = m_get(M_DONTWAIT, MT_HEADER); + if (m == NULL) + return (0); + + switch (tp->pf) { + case 0: /*default to PF_INET*/ +#ifdef INET + case AF_INET: + m->m_len = sizeof(struct ip); + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + m->m_len = sizeof(struct ip6_hdr); + break; +#endif /* INET6 */ + } + m->m_len += sizeof (struct tcphdr); + + /* + * The link header, network header, TCP header, and TCP options + * all must fit in this mbuf. For now, assume the worst case of + * TCP options size. Eventually, compute this from tp flags. + */ + if (m->m_len + MAX_TCPOPTLEN + max_linkhdr >= MHLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_free(m); + return (0); + } + } + } + + switch(tp->pf) { +#ifdef INET + case AF_INET: + { + struct ipovly *ipovly; + + ipovly = mtod(m, struct ipovly *); + + bzero(ipovly->ih_x1, sizeof ipovly->ih_x1); + ipovly->ih_pr = IPPROTO_TCP; + ipovly->ih_len = htons(sizeof (struct tcpiphdr) - + sizeof (struct ip)); + ipovly->ih_src = inp->inp_laddr; + ipovly->ih_dst = inp->inp_faddr; + + th = (struct tcphdr *)(mtod(m, caddr_t) + + sizeof(struct ip)); + } + break; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + { + struct ip6_hdr *ipv6; + + ipv6 = mtod(m, struct ip6_hdr *); + + ipv6->ip6_src = inp->inp_laddr6; + ipv6->ip6_dst = inp->inp_faddr6; + ipv6->ip6_flow = htonl(0x60000000) | + (inp->inp_ipv6.ip6_flow & htonl(0x0fffffff)); + + + ipv6->ip6_nxt = IPPROTO_TCP; + ipv6->ip6_plen = htons(sizeof(struct tcphdr)); /*XXX*/ + ipv6->ip6_hlim = in6_selecthlim(inp, NULL); /*XXX*/ + + th = (struct tcphdr *)(mtod(m, caddr_t) + + sizeof(struct ip6_hdr)); + } + break; +#endif /* INET6 */ + } + + th->th_sport = inp->inp_lport; + th->th_dport = inp->inp_fport; + th->th_seq = 0; + th->th_ack = 0; + th->th_x2 = 0; + th->th_off = 5; + th->th_flags = 0; + th->th_win = 0; + th->th_sum = 0; + th->th_urp = 0; + return (m); +} + +/* + * Send a single message to the TCP at address specified by + * the given TCP/IP header. If m == 0, then we make a copy + * of the tcpiphdr at ti and send directly to the addressed host. + * This is used to force keep alive messages out using the TCP + * template for a connection tp->t_template. If flags are given + * then we send a message back to the TCP which originated the + * segment ti, and discard the mbuf containing it and any other + * attached mbufs. + * + * In any case the ack and sequence number of the transmitted + * segment are as specified by the parameters. + */ +#ifdef INET6 +/* This function looks hairy, because it was so IPv4-dependent. */ +#endif /* INET6 */ +void +tcp_respond(tp, template, m, ack, seq, flags) + struct tcpcb *tp; + caddr_t template; + register struct mbuf *m; + tcp_seq ack, seq; + int flags; +{ + register int tlen; + int win = 0; + struct route *ro = 0; + register struct tcphdr *th; + register struct tcpiphdr *ti = (struct tcpiphdr *)template; +#ifdef INET6 + int is_ipv6 = 0; /* true iff IPv6 */ +#endif /* INET6 */ + + if (tp) { + win = sbspace(&tp->t_inpcb->inp_socket->so_rcv); +#ifdef INET6 + /* + * If this is called with an unconnected + * socket/tp/pcb (tp->pf is 0), we lose. + */ + is_ipv6 = (tp->pf == PF_INET6); + + /* + * The route/route6 distinction is meaningless + * unless you're allocating space or passing parameters. + */ +#endif /* INET6 */ + ro = &tp->t_inpcb->inp_route; + } +#ifdef INET6 + else + is_ipv6 = (((struct ip *)ti)->ip_v == 6); +#endif /* INET6 */ + if (m == 0) { + m = m_gethdr(M_DONTWAIT, MT_HEADER); + if (m == NULL) + return; +#ifdef TCP_COMPAT_42 + tlen = 1; +#else + tlen = 0; +#endif + m->m_data += max_linkhdr; +#ifdef INET6 + if (is_ipv6) + bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) + + sizeof(struct ip6_hdr)); + else +#endif /* INET6 */ + bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) + + sizeof(struct ip)); + + ti = mtod(m, struct tcpiphdr *); + flags = TH_ACK; + } else { + m_freem(m->m_next); + m->m_next = 0; + m->m_data = (caddr_t)ti; + tlen = 0; +#define xchg(a,b,type) { type t; t=a; a=b; b=t; } +#ifdef INET6 + if (is_ipv6) { + m->m_len = sizeof(struct tcphdr) + sizeof(struct ip6_hdr); + xchg(((struct ip6_hdr *)ti)->ip6_dst,\ + ((struct ip6_hdr *)ti)->ip6_src,\ + struct in6_addr); + th = (void *)ti + sizeof(struct ip6_hdr); + } else +#endif /* INET6 */ + { + m->m_len = sizeof (struct tcpiphdr); + xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t); + th = (void *)((caddr_t)ti + sizeof(struct ip)); + } + xchg(th->th_dport, th->th_sport, u_int16_t); +#undef xchg + } +#ifdef INET6 + if (is_ipv6) { + tlen += sizeof(struct tcphdr) + sizeof(struct ip6_hdr); + th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip6_hdr)); + } else +#endif /* INET6 */ + { + ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) + tlen)); + tlen += sizeof (struct tcpiphdr); + th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip)); + } + + m->m_len = tlen; + m->m_pkthdr.len = tlen; + m->m_pkthdr.rcvif = (struct ifnet *) 0; + th->th_seq = htonl(seq); + th->th_ack = htonl(ack); + th->th_x2 = 0; + th->th_off = sizeof (struct tcphdr) >> 2; + th->th_flags = flags; + if (tp) + th->th_win = htons((u_int16_t) (win >> tp->rcv_scale)); + else + th->th_win = htons((u_int16_t)win); + th->th_urp = 0; + +#ifdef INET6 + if (is_ipv6) { + ((struct ip6_hdr *)ti)->ip6_flow = htonl(0x60000000); + ((struct ip6_hdr *)ti)->ip6_nxt = IPPROTO_TCP; + ((struct ip6_hdr *)ti)->ip6_hlim = + in6_selecthlim(tp ? tp->t_inpcb : NULL, NULL); /*XXX*/ + ((struct ip6_hdr *)ti)->ip6_plen = tlen - sizeof(struct ip6_hdr); + th->th_sum = 0; + th->th_sum = in6_cksum(m, IPPROTO_TCP, + sizeof(struct ip6_hdr), ((struct ip6_hdr *)ti)->ip6_plen); + HTONS(((struct ip6_hdr *)ti)->ip6_plen); + ip6_output(m, tp ? tp->t_inpcb->inp_outputopts6 : NULL, + (struct route_in6 *)ro, 0, NULL, NULL); + } else +#endif /* INET6 */ + { + bzero(ti->ti_x1, sizeof ti->ti_x1); + ti->ti_len = htons((u_short)tlen - sizeof(struct ip)); + th->th_sum = in_cksum(m, tlen); + ((struct ip *)ti)->ip_len = tlen; + ((struct ip *)ti)->ip_ttl = ip_defttl; + ip_output(m, NULL, ro, 0, NULL, tp ? tp->t_inpcb : NULL); + } +} + +/* + * Create a new TCP control block, making an + * empty reassembly queue and hooking it to the argument + * protocol control block. + */ +struct tcpcb * +tcp_newtcpcb(inp) + struct inpcb *inp; +{ + register struct tcpcb *tp; + + tp = malloc(sizeof(*tp), M_PCB, M_NOWAIT); + if (tp == NULL) + return ((struct tcpcb *)0); + bzero((char *) tp, sizeof(struct tcpcb)); + LIST_INIT(&tp->segq); + tp->t_maxseg = tp->t_maxopd = tcp_mssdflt; + +#ifdef TCP_SACK + tp->sack_disable = tcp_do_sack ? 0 : 1; +#endif + tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; + tp->t_inpcb = inp; + /* + * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no + * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives + * reasonable initial retransmit time. + */ + tp->t_srtt = TCPTV_SRTTBASE; + tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << (TCP_RTTVAR_SHIFT + 2 - 1); + tp->t_rttmin = TCPTV_MIN; + TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), + TCPTV_MIN, TCPTV_REXMTMAX); + tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; + tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; +#ifdef INET6 + /* + * If we want to use tp->pf for a quick-n-easy way to determine + * the outbound dgram type, we cannot make this decision + * until a connection is established! Bzero() sets pf to zero, and + * that's the way we want it, unless, of course, it's an AF_INET + * socket... + */ + if ((inp->inp_flags & INP_IPV6) == 0) + tp->pf = PF_INET; /* If AF_INET socket, we can't do v6 from it. */ +#else + tp->pf = PF_INET; +#endif + +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + inp->inp_ipv6.ip6_hlim = ip6_defhlim; + else +#endif /* INET6 */ + inp->inp_ip.ip_ttl = ip_defttl; + + inp->inp_ppcb = (caddr_t)tp; + return (tp); +} + +/* + * Drop a TCP connection, reporting + * the specified error. If connection is synchronized, + * then send a RST to peer. + */ +struct tcpcb * +tcp_drop(tp, errno) + register struct tcpcb *tp; + int errno; +{ + struct socket *so = tp->t_inpcb->inp_socket; + + if (TCPS_HAVERCVDSYN(tp->t_state)) { + tp->t_state = TCPS_CLOSED; + (void) tcp_output(tp); + tcpstat.tcps_drops++; + } else + tcpstat.tcps_conndrops++; + if (errno == ETIMEDOUT && tp->t_softerror) + errno = tp->t_softerror; + so->so_error = errno; + return (tcp_close(tp)); +} + +/* + * Close a TCP control block: + * discard all space held by the tcp + * discard internet protocol block + * wake up any sleepers + */ +struct tcpcb * +tcp_close(tp) + register struct tcpcb *tp; +{ + register struct ipqent *qe; + struct inpcb *inp = tp->t_inpcb; + struct socket *so = inp->inp_socket; +#ifdef TCP_SACK + struct sackhole *p, *q; +#endif +#ifdef RTV_RTT + register struct rtentry *rt; +#ifdef INET6 + register int bound_to_specific = 0; /* I.e. non-default */ + + /* + * This code checks the nature of the route for this connection. + * Normally this is done by two simple checks in the next + * INET/INET6 ifdef block, but because of two possible lower layers, + * that check is done here. + * + * Perhaps should be doing this only for a RTF_HOST route. + */ + rt = inp->inp_route.ro_rt; /* Same for route or route6. */ + if (tp->pf == PF_INET6) { + if (rt) + bound_to_specific = + !(IN6_IS_ADDR_UNSPECIFIED(& + ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr)); + } else { + if (rt) + bound_to_specific = + (((struct sockaddr_in *)rt_key(rt))-> + sin_addr.s_addr != INADDR_ANY); + } +#endif /* INET6 */ + + /* + * If we sent enough data to get some meaningful characteristics, + * save them in the routing entry. 'Enough' is arbitrarily + * defined as the sendpipesize (default 4K) * 16. This would + * give us 16 rtt samples assuming we only get one sample per + * window (the usual case on a long haul net). 16 samples is + * enough for the srtt filter to converge to within 5% of the correct + * value; fewer samples and we could save a very bogus rtt. + * + * Don't update the default route's characteristics and don't + * update anything that the user "locked". + */ +#ifdef INET6 + /* + * Note that rt and bound_to_specific are set above. + */ + if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) && + rt && bound_to_specific) { +#else /* INET6 */ + if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) && + (rt = inp->inp_route.ro_rt) && + satosin(rt_key(rt))->sin_addr.s_addr != INADDR_ANY) { +#endif /* INET6 */ + register u_long i = 0; + + if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) { + i = tp->t_srtt * + (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE)); + if (rt->rt_rmx.rmx_rtt && i) + /* + * filter this update to half the old & half + * the new values, converting scale. + * See route.h and tcp_var.h for a + * description of the scaling constants. + */ + rt->rt_rmx.rmx_rtt = + (rt->rt_rmx.rmx_rtt + i) / 2; + else + rt->rt_rmx.rmx_rtt = i; + } + if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) { + i = tp->t_rttvar * + (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE)); + if (rt->rt_rmx.rmx_rttvar && i) + rt->rt_rmx.rmx_rttvar = + (rt->rt_rmx.rmx_rttvar + i) / 2; + else + rt->rt_rmx.rmx_rttvar = i; + } + /* + * update the pipelimit (ssthresh) if it has been updated + * already or if a pipesize was specified & the threshhold + * got below half the pipesize. I.e., wait for bad news + * before we start updating, then update on both good + * and bad news. + */ + if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 && + (i = tp->snd_ssthresh) && rt->rt_rmx.rmx_ssthresh) || + i < (rt->rt_rmx.rmx_sendpipe / 2)) { + /* + * convert the limit from user data bytes to + * packets then to packet data bytes. + */ + i = (i + tp->t_maxseg / 2) / tp->t_maxseg; + if (i < 2) + i = 2; +#ifdef INET6 + if (tp->pf == PF_INET6) + i *= (u_long)(tp->t_maxseg + sizeof (struct tcphdr) + + sizeof(struct ip6_hdr)); + else +#endif /* INET6 */ + i *= (u_long)(tp->t_maxseg + + sizeof (struct tcpiphdr)); + + if (rt->rt_rmx.rmx_ssthresh) + rt->rt_rmx.rmx_ssthresh = + (rt->rt_rmx.rmx_ssthresh + i) / 2; + else + rt->rt_rmx.rmx_ssthresh = i; + } + } +#endif /* RTV_RTT */ + + /* free the reassembly queue, if any */ +#ifdef INET6 + /* Reassembling TCP segments in v6 might be sufficiently different + * to merit two codepaths to free the reasssembly queue. + * If an undecided TCP socket, then the IPv4 codepath will be used + * because it won't matter much anyway. + */ + if (tp->pf == AF_INET6) { + while ((qe = tp->segq.lh_first) != NULL) { + LIST_REMOVE(qe, ipqe_q); + m_freem(qe->ipqe_m); + FREE(qe, M_IPQ); + } + } else +#endif /* INET6 */ + while ((qe = tp->segq.lh_first) != NULL) { + LIST_REMOVE(qe, ipqe_q); + m_freem(qe->ipqe_m); + FREE(qe, M_IPQ); + } +#ifdef TCP_SACK + /* Free SACK holes. */ + q = p = tp->snd_holes; + while (p != 0) { + q = p->next; + free(p, M_PCB); + p = q; + } +#endif + if (tp->t_template) + (void) m_free(tp->t_template); + free(tp, M_PCB); + inp->inp_ppcb = 0; + soisdisconnected(so); + in_pcbdetach(inp); + tcpstat.tcps_closed++; + return ((struct tcpcb *)0); +} + +void +tcp_drain() +{ + +} + +/* + * Notify a tcp user of an asynchronous error; + * store error as soft error, but wake up user + * (for now, won't do anything until can select for soft error). + */ +void +tcp_notify(inp, error) + struct inpcb *inp; + int error; +{ + register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb; + register struct socket *so = inp->inp_socket; + + /* + * Ignore some errors if we are hooked up. + * If connection hasn't completed, has retransmitted several times, + * and receives a second error, give up now. This is better + * than waiting a long time to establish a connection that + * can never complete. + */ + if (tp->t_state == TCPS_ESTABLISHED && + (error == EHOSTUNREACH || error == ENETUNREACH || + error == EHOSTDOWN)) { + return; + } else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 && + tp->t_rxtshift > 3 && tp->t_softerror) + so->so_error = error; + else + tp->t_softerror = error; + wakeup((caddr_t) &so->so_timeo); + sorwakeup(so); + sowwakeup(so); +} + +#if defined(INET6) && !defined(TCP6) +void +tcp6_ctlinput(cmd, sa, d) + int cmd; + struct sockaddr *sa; + void *d; +{ + (void)tcp_ctlinput(cmd, sa, NULL); /*XXX*/ +} +#endif + +void * +tcp_ctlinput(cmd, sa, v) + int cmd; + struct sockaddr *sa; + register void *v; +{ + register struct ip *ip = v; + register struct tcphdr *th; + extern int inetctlerrmap[]; + void (*notify) __P((struct inpcb *, int)) = tcp_notify; + int errno; + + if ((unsigned)cmd >= PRC_NCMDS) + return NULL; + errno = inetctlerrmap[cmd]; + if (cmd == PRC_QUENCH) + notify = tcp_quench; + else if (PRC_IS_REDIRECT(cmd)) + notify = in_rtchange, ip = 0; + else if (cmd == PRC_HOSTDEAD) + ip = 0; + else if (errno == 0) + return NULL; + +#ifdef INET6 + if (sa->sa_family == AF_INET6) { + if (ip) { + struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip; + + th = (struct tcphdr *)(ipv6 + 1); +#if 0 /*XXX*/ + in6_pcbnotify(&tcbtable, sa, th->th_dport, + &ipv6->ip6_src, th->th_sport, cmd, notify); +#endif + } else { +#if 0 /*XXX*/ + in6_pcbnotify(&tcbtable, sa, 0, + (struct in6_addr *)&in6addr_any, 0, cmd, notify); +#endif + } + } else +#endif /* INET6 */ + { + if (ip) { + th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); + in_pcbnotify(&tcbtable, sa, th->th_dport, ip->ip_src, + th->th_sport, errno, notify); + } else + in_pcbnotifyall(&tcbtable, sa, errno, notify); + } + return NULL; +} + +/* + * When a source quench is received, close congestion window + * to one segment. We will gradually open it again as we proceed. + */ +void +tcp_quench(inp, errno) + struct inpcb *inp; + int errno; +{ + struct tcpcb *tp = intotcpcb(inp); + + if (tp) + tp->snd_cwnd = tp->t_maxseg; +} + +#ifdef TCP_SIGNATURE +int +tcp_signature_tdb_attach() +{ + return (0); +} + +int +tcp_signature_tdb_init(tdbp, xsp, ii) + struct tdb *tdbp; + struct xformsw *xsp; + struct ipsecinit *ii; +{ + char *c; +#define isdigit(c) (((c) >= '0') && ((c) <= '9')) +#define isalpha(c) ( (((c) >= 'A') && ((c) <= 'Z')) || \ + (((c) >= 'a') && ((c) <= 'z')) ) + + if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80)) + return (EINVAL); + + c = (char *)ii->ii_authkey; + + while (c < (char *)ii->ii_authkey + ii->ii_authkeylen - 1) { + if (isdigit(*c)) { + if (*(c + 1) == ' ') + return (EINVAL); + } else { + if (!isalpha(*c)) + return (EINVAL); + } + + c++; + } + + if (!isdigit(*c) && !isalpha(*c)) + return (EINVAL); + + tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_DONTWAIT); + if (tdbp->tdb_amxkey == NULL) + return (ENOMEM); + bcopy(ii->ii_authkey, tdbp->tdb_amxkey, ii->ii_authkeylen); + tdbp->tdb_amxkeylen = ii->ii_authkeylen; + + return (0); +} + +int +tcp_signature_tdb_zeroize(tdbp) + struct tdb *tdbp; +{ + if (tdbp->tdb_amxkey) { + bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen); + free(tdbp->tdb_amxkey, M_XDATA); + tdbp->tdb_amxkey = NULL; + } + + return (0); +} + +struct mbuf * +tcp_signature_tdb_input(m, tdbp) + struct mbuf *m; + struct tdb *tdbp; +{ + return (0); +} + +int +tcp_signature_tdb_output(m, tdbp, mp) + struct mbuf *m; + struct tdb *tdbp; + struct mbuf **mp; +{ + return (EINVAL); +} + +int +tcp_signature_apply(fstate, data, len) + caddr_t fstate; + caddr_t data; + unsigned int len; +{ + MD5Update((MD5_CTX *)fstate, (char *)data, len); + return 0; +} +#endif /* TCP_SIGNATURE */ diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_timer.c b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_timer.c new file mode 100644 index 0000000..514b76b --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_timer.c @@ -0,0 +1,412 @@ +//========================================================================== +// +// sys/netinet/tcp_timer.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_timer.c,v 1.15 1999/11/15 05:50:59 hugh Exp $ */ +/* $NetBSD: tcp_timer.c,v 1.14 1996/02/13 23:44:09 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_timer.c 8.1 (Berkeley) 6/10/93 + */ + +#ifndef TUBA_INCLUDE +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/protosw.h> +#include <sys/errno.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_fsm.h> +#include <netinet/tcp_seq.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/tcpip.h> +#ifndef __ECOS +#include <dev/rndvar.h> +#endif + +int tcp_keepidle = TCPTV_KEEP_IDLE; +int tcp_keepintvl = TCPTV_KEEPINTVL; +int tcp_maxpersistidle = TCPTV_KEEP_IDLE; /* max idle time in persist */ +int tcp_maxidle; +#endif /* TUBA_INCLUDE */ +/* + * Fast timeout routine for processing delayed acks + */ +void +tcp_fasttimo() +{ + register struct inpcb *inp; + register struct tcpcb *tp; + int s; + + s = splsoftnet(); + inp = tcbtable.inpt_queue.cqh_first; + if (inp) /* XXX */ + for (; inp != (struct inpcb *)&tcbtable.inpt_queue; + inp = inp->inp_queue.cqe_next) { + if ((tp = (struct tcpcb *)inp->inp_ppcb) && + (tp->t_flags & TF_DELACK)) { + tp->t_flags &= ~TF_DELACK; + tp->t_flags |= TF_ACKNOW; + tcpstat.tcps_delack++; + (void) tcp_output(tp); + } + } + splx(s); +} + +/* + * Tcp protocol timeout routine called every 500 ms. + * Updates the timers in all active tcb's and + * causes finite state machine actions if timers expire. + */ +void +tcp_slowtimo() +{ + register struct inpcb *ip, *ipnxt; + register struct tcpcb *tp; + int s; + register long i; + + s = splsoftnet(); + tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl; + /* + * Search through tcb's and update active timers. + */ + ip = tcbtable.inpt_queue.cqh_first; + if (ip == (struct inpcb *)0) { /* XXX */ + splx(s); + return; + } + for (; ip != (struct inpcb *)&tcbtable.inpt_queue; ip = ipnxt) { + ipnxt = ip->inp_queue.cqe_next; + tp = intotcpcb(ip); + if (tp == 0 || tp->t_state == TCPS_LISTEN) + continue; + for (i = 0; i < TCPT_NTIMERS; i++) { + if (tp->t_timer[i] && --tp->t_timer[i] == 0) { + (void) tcp_usrreq(tp->t_inpcb->inp_socket, + PRU_SLOWTIMO, (struct mbuf *)0, + (struct mbuf *)i, (struct mbuf *)0); + /* XXX NOT MP SAFE */ + if ((ipnxt == (void *)&tcbtable.inpt_queue && + tcbtable.inpt_queue.cqh_last != ip) || + ipnxt->inp_queue.cqe_prev != ip) + goto tpgone; + } + } + tp->t_idle++; + if (tp->t_rtt) + tp->t_rtt++; +tpgone: + ; + } +#ifdef TCP_COMPAT_42 + tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ + if ((int)tcp_iss < 0) + tcp_iss = 0; /* XXX */ +#else /* TCP_COMPAT_42 */ + tcp_iss += arc4random() % (2 * TCP_ISSINCR / PR_SLOWHZ) + 1; /* increment iss */ +#endif /* !TCP_COMPAT_42 */ + tcp_now++; /* for timestamps */ + splx(s); +} +#ifndef TUBA_INCLUDE + +/* + * Cancel all timers for TCP tp. + */ +void +tcp_canceltimers(tp) + struct tcpcb *tp; +{ + register int i; + + for (i = 0; i < TCPT_NTIMERS; i++) + tp->t_timer[i] = 0; +} + +int tcp_backoff[TCP_MAXRXTSHIFT + 1] = + { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; + +int tcp_totbackoff = 511; /* sum of tcp_backoff[] */ + +/* + * TCP timer processing. + */ +struct tcpcb * +tcp_timers(tp, timer) + register struct tcpcb *tp; + int timer; +{ + short rto; +#ifdef TCP_SACK + struct sackhole *p, *q; + /* + * Free SACK holes for 2MSL and REXMT timers. + */ + if (timer == TCPT_2MSL || timer == TCPT_REXMT) { + q = p = tp->snd_holes; + while (p != 0) { + q = p->next; + free(p, M_PCB); + p = q; + } + tp->snd_holes = 0; +#if defined(TCP_SACK) && defined(TCP_FACK) + tp->snd_fack = tp->snd_una; + tp->retran_data = 0; + tp->snd_awnd = 0; +#endif /* TCP_FACK */ + } +#endif /* TCP_SACK */ + + switch (timer) { + + /* + * 2 MSL timeout in shutdown went off. If we're closed but + * still waiting for peer to close and connection has been idle + * too long, or if 2MSL time is up from TIME_WAIT, delete connection + * control block. Otherwise, check again in a bit. + */ + case TCPT_2MSL: + if (tp->t_state != TCPS_TIME_WAIT && + tp->t_idle <= tcp_maxidle) + tp->t_timer[TCPT_2MSL] = tcp_keepintvl; + else + tp = tcp_close(tp); + break; + + /* + * Retransmission timer went off. Message has not + * been acked within retransmit interval. Back off + * to a longer retransmit interval and retransmit one segment. + */ + case TCPT_REXMT: + if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { + tp->t_rxtshift = TCP_MAXRXTSHIFT; + tcpstat.tcps_timeoutdrop++; + tp = tcp_drop(tp, tp->t_softerror ? + tp->t_softerror : ETIMEDOUT); + break; + } + tcpstat.tcps_rexmttimeo++; + rto = TCP_REXMTVAL(tp); + if (rto < tp->t_rttmin) + rto = tp->t_rttmin; + TCPT_RANGESET(tp->t_rxtcur, + rto * tcp_backoff[tp->t_rxtshift], + tp->t_rttmin, TCPTV_REXMTMAX); + tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; + /* + * If losing, let the lower level know and try for + * a better route. Also, if we backed off this far, + * our srtt estimate is probably bogus. Clobber it + * so we'll take the next rtt measurement as our srtt; + * move the current srtt into rttvar to keep the current + * retransmit times until then. + */ + if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { + in_losing(tp->t_inpcb); + tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); + tp->t_srtt = 0; + } + tp->snd_nxt = tp->snd_una; +#if defined(TCP_SACK) || defined(TCP_NEWRENO) + /* + * Note: We overload snd_last to function also as the + * snd_last variable described in RFC 2582 + */ + tp->snd_last = tp->snd_max; +#endif /* TCP_SACK or TCP_NEWRENO */ + /* + * If timing a segment in this window, stop the timer. + */ + tp->t_rtt = 0; + /* + * Close the congestion window down to one segment + * (we'll open it by one segment for each ack we get). + * Since we probably have a window's worth of unacked + * data accumulated, this "slow start" keeps us from + * dumping all that data as back-to-back packets (which + * might overwhelm an intermediate gateway). + * + * There are two phases to the opening: Initially we + * open by one mss on each ack. This makes the window + * size increase exponentially with time. If the + * window is larger than the path can handle, this + * exponential growth results in dropped packet(s) + * almost immediately. To get more time between + * drops but still "push" the network to take advantage + * of improving conditions, we switch from exponential + * to linear window opening at some threshhold size. + * For a threshhold, we use half the current window + * size, truncated to a multiple of the mss. + * + * (the minimum cwnd that will give us exponential + * growth is 2 mss. We don't allow the threshhold + * to go below this.) + */ + { + u_long win = ulmin(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; + if (win < 2) + win = 2; + tp->snd_cwnd = tp->t_maxseg; + tp->snd_ssthresh = win * tp->t_maxseg; + tp->t_dupacks = 0; + } + (void) tcp_output(tp); + break; + + /* + * Persistance timer into zero window. + * Force a byte to be output, if possible. + */ + case TCPT_PERSIST: + tcpstat.tcps_persisttimeo++; + /* + * Hack: if the peer is dead/unreachable, we do not + * time out if the window is closed. After a full + * backoff, drop the connection if the idle time + * (no responses to probes) reaches the maximum + * backoff that we would use if retransmitting. + */ + rto = TCP_REXMTVAL(tp); + if (rto < tp->t_rttmin) + rto = tp->t_rttmin; + if (tp->t_rxtshift == TCP_MAXRXTSHIFT && + (tp->t_idle >= tcp_maxpersistidle || + tp->t_idle >= rto * tcp_totbackoff)) { + tcpstat.tcps_persistdrop++; + tp = tcp_drop(tp, ETIMEDOUT); + break; + } + tcp_setpersist(tp); + tp->t_force = 1; + (void) tcp_output(tp); + tp->t_force = 0; + break; + + /* + * Keep-alive timer went off; send something + * or drop connection if idle for too long. + */ + case TCPT_KEEP: + tcpstat.tcps_keeptimeo++; + if (TCPS_HAVEESTABLISHED(tp->t_state) == 0) + goto dropit; + if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE && + tp->t_state <= TCPS_CLOSE_WAIT) { + if (tp->t_idle >= tcp_keepidle + tcp_maxidle) + goto dropit; + /* + * Send a packet designed to force a response + * if the peer is up and reachable: + * either an ACK if the connection is still alive, + * or an RST if the peer has closed the connection + * due to timeout or reboot. + * Using sequence number tp->snd_una-1 + * causes the transmitted zero-length segment + * to lie outside the receive window; + * by the protocol spec, this requires the + * correspondent TCP to respond. + */ + tcpstat.tcps_keepprobe++; +#ifdef TCP_COMPAT_42 + /* + * The keepalive packet must have nonzero length + * to get a 4.2 host to respond. + */ + tcp_respond(tp, + mtod(tp->t_template, caddr_t), + (struct mbuf *)NULL, + tp->rcv_nxt - 1, tp->snd_una - 1, 0); +#else + tcp_respond(tp, + mtod(tp->t_template, caddr_t), + (struct mbuf *)NULL, + tp->rcv_nxt, tp->snd_una - 1, 0); +#endif + tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + } else + tp->t_timer[TCPT_KEEP] = tcp_keepidle; + break; + dropit: + tcpstat.tcps_keepdrops++; + tp = tcp_drop(tp, ETIMEDOUT); + break; + } + return (tp); +} +#endif /* TUBA_INCLUDE */ diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_usrreq.c b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_usrreq.c new file mode 100644 index 0000000..5f049a8 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/tcp_usrreq.c @@ -0,0 +1,942 @@ +//========================================================================== +// +// sys/netinet/tcp_usrreq.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: tcp_usrreq.c,v 1.37 1999/12/08 06:50:20 itojun Exp $ */ +/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#ifndef __ECOS +#include <sys/systm.h> +#endif +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/protosw.h> +#include <sys/errno.h> +#ifndef __ECOS +#include <sys/stat.h> +#include <sys/proc.h> +#include <sys/ucred.h> + +#include <vm/vm.h> +#include <sys/sysctl.h> +#endif + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/tcp_fsm.h> +#include <netinet/tcp_seq.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include <netinet/tcpip.h> +#include <netinet/tcp_debug.h> +#ifndef __ECOS +#include <dev/rndvar.h> +#endif + +#ifdef IPSEC +extern int check_ipsec_policy __P((struct inpcb *, u_int32_t)); +#endif + +#ifdef INET6 +#include <sys/domain.h> +#endif /* INET6 */ + +/* + * TCP protocol interface to socket abstraction. + */ +extern char *tcpstates[]; +extern int tcptv_keep_init; + +/* from in_pcb.c */ +extern struct baddynamicports baddynamicports; + +int tcp_ident __P((void *, size_t *, void *, size_t)); + +#if defined(INET6) && !defined(TCP6) +int +tcp6_usrreq(so, req, m, nam, control, p) + struct socket *so; + int req; + struct mbuf *m, *nam, *control; + struct proc *p; +{ + return tcp_usrreq(so, req, m, nam, control); +} +#endif + +/* + * Process a TCP user request for TCP tb. If this is a send request + * then m is the mbuf chain of send data. If this is a timer expiration + * (called from the software clock routine), then timertype tells which timer. + */ +/*ARGSUSED*/ +int +tcp_usrreq(so, req, m, nam, control) + struct socket *so; + int req; + struct mbuf *m, *nam, *control; +{ + struct sockaddr_in *sin; + register struct inpcb *inp; + register struct tcpcb *tp = NULL; + int s; + int error = 0; + int ostate; + + if (req == PRU_CONTROL) { +#ifdef INET6 + if (sotopf(so) == PF_INET6) + return in6_control(so, (u_long)m, (caddr_t)nam, + (struct ifnet *)control, 0); + else +#endif /* INET6 */ + return (in_control(so, (u_long)m, (caddr_t)nam, + (struct ifnet *)control)); + } + if (control && control->m_len) { + m_freem(control); + if (m) + m_freem(m); + return (EINVAL); + } + + s = splsoftnet(); + inp = sotoinpcb(so); + /* + * When a TCP is attached to a socket, then there will be + * a (struct inpcb) pointed at by the socket, and this + * structure will point at a subsidary (struct tcpcb). + */ + if (inp == 0 && req != PRU_ATTACH) { + splx(s); + /* + * The following corrects an mbuf leak under rare + * circumstances + */ + if (m && (req == PRU_SEND || req == PRU_SENDOOB)) + m_freem(m); + return (EINVAL); /* XXX */ + } + if (inp) { + tp = intotcpcb(inp); + /* WHAT IF TP IS 0? */ +#ifdef KPROF + tcp_acounts[tp->t_state][req]++; +#endif + ostate = tp->t_state; + } else + ostate = 0; + switch (req) { + + /* + * TCP attaches to socket via PRU_ATTACH, reserving space, + * and an internet control block. + */ + case PRU_ATTACH: + if (inp) { + error = EISCONN; + break; + } + error = tcp_attach(so); + if (error) + break; + if ((so->so_options & SO_LINGER) && so->so_linger == 0) + so->so_linger = TCP_LINGERTIME; + tp = sototcpcb(so); + break; + + /* + * PRU_DETACH detaches the TCP protocol from the socket. + * If the protocol state is non-embryonic, then can't + * do this directly: have to initiate a PRU_DISCONNECT, + * which may finish later; embryonic TCB's can just + * be discarded here. + */ + case PRU_DETACH: + tp = tcp_disconnect(tp); + break; + + /* + * Give the socket an address. + */ + case PRU_BIND: +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + error = in6_pcbbind(inp, nam); + else +#endif + error = in_pcbbind(inp, nam); + if (error) + break; +#ifdef INET6 + /* + * If we bind to an address, set up the tp->pf accordingly! + */ + if (inp->inp_flags & INP_IPV6) { + /* If a PF_INET6 socket... */ + if (inp->inp_flags & INP_IPV6_MAPPED) + tp->pf = AF_INET; + else if ((inp->inp_flags & INP_IPV6_UNDEC) == 0) + tp->pf = AF_INET6; + /* else tp->pf is still 0. */ + } + /* else socket is PF_INET, and tp->pf is PF_INET. */ +#endif /* INET6 */ + break; + + /* + * Prepare to accept connections. + */ + case PRU_LISTEN: + if (inp->inp_lport == 0) { +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + error = in6_pcbbind(inp, NULL); + else +#endif + error = in_pcbbind(inp, NULL); + } + /* If the in_pcbbind() above is called, the tp->pf + should still be whatever it was before. */ + if (error == 0) + tp->t_state = TCPS_LISTEN; + break; + + /* + * Initiate connection to peer. + * Create a template for use in transmissions on this connection. + * Enter SYN_SENT state, and mark socket as connecting. + * Start keep-alive timer, and seed output sequence space. + * Send initial segment on connection. + */ + case PRU_CONNECT: + sin = mtod(nam, struct sockaddr_in *); + +#ifdef INET6 + if (sin->sin_family == AF_INET6) { + struct in6_addr *in6_addr = &mtod(nam, + struct sockaddr_in6 *)->sin6_addr; + + if (IN6_IS_ADDR_UNSPECIFIED(in6_addr) || + IN6_IS_ADDR_MULTICAST(in6_addr) || + (IN6_IS_ADDR_V4MAPPED(in6_addr) && + ((in6_addr->s6_addr32[3] == INADDR_ANY) || + IN_MULTICAST(in6_addr->s6_addr32[3]) || + in_broadcast(sin->sin_addr, NULL)))) { + error = EINVAL; + break; + } + + if (inp->inp_lport == 0) { + error = in6_pcbbind(inp, NULL); + if (error) + break; + } + error = in6_pcbconnect(inp, nam); + } else if (sin->sin_family == AF_INET) +#endif /* INET6 */ + { + if ((sin->sin_addr.s_addr == INADDR_ANY) || + IN_MULTICAST(sin->sin_addr.s_addr) || + in_broadcast(sin->sin_addr, NULL)) { + error = EINVAL; + break; + } + + /* Trying to connect to some broadcast address */ + if (in_broadcast(sin->sin_addr, NULL)) { + error = EINVAL; + break; + } + + if (inp->inp_lport == 0) { + error = in_pcbbind(inp, NULL); + if (error) + break; + } + error = in_pcbconnect(inp, nam); + } + + if (error) + break; + +#ifdef INET6 + /* + * With a connection, I now know the version of IP + * is in use and hence can set tp->pf with authority. + */ + if (inp->inp_flags & INP_IPV6) { + if (inp->inp_flags & INP_IPV6_MAPPED) + tp->pf = PF_INET; + else + tp->pf = PF_INET6; + } + /* else I'm a PF_INET socket, and hence tp->pf is PF_INET. */ +#endif /* INET6 */ + + tp->t_template = tcp_template(tp); + if (tp->t_template == 0) { + in_pcbdisconnect(inp); + error = ENOBUFS; + break; + } + +#ifdef INET6 + if ((inp->inp_flags & INP_IPV6) && (tp->pf == PF_INET)) { + inp->inp_ip.ip_ttl = ip_defttl; + inp->inp_ip.ip_tos = 0; + } +#endif /* INET6 */ + + so->so_state |= SS_CONNECTOUT; + /* Compute window scaling to request. */ + while (tp->request_r_scale < TCP_MAX_WINSHIFT && + (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) + tp->request_r_scale++; + soisconnecting(so); + tcpstat.tcps_connattempt++; + tp->t_state = TCPS_SYN_SENT; + tp->t_timer[TCPT_KEEP] = tcptv_keep_init; + tp->iss = tcp_iss; +#ifdef TCP_COMPAT_42 + tcp_iss += TCP_ISSINCR/2; +#else /* TCP_COMPAT_42 */ + tcp_iss += arc4random() % TCP_ISSINCR + 1; +#endif /* !TCP_COMPAT_42 */ + tcp_sendseqinit(tp); +#if defined(TCP_SACK) || defined(TCP_NEWRENO) + tp->snd_last = tp->snd_una; +#endif +#if defined(TCP_SACK) && defined(TCP_FACK) + tp->snd_fack = tp->snd_una; + tp->retran_data = 0; + tp->snd_awnd = 0; +#endif + error = tcp_output(tp); + break; + + /* + * Create a TCP connection between two sockets. + */ + case PRU_CONNECT2: + error = EOPNOTSUPP; + break; + + /* + * Initiate disconnect from peer. + * If connection never passed embryonic stage, just drop; + * else if don't need to let data drain, then can just drop anyways, + * else have to begin TCP shutdown process: mark socket disconnecting, + * drain unread data, state switch to reflect user close, and + * send segment (e.g. FIN) to peer. Socket will be really disconnected + * when peer sends FIN and acks ours. + * + * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. + */ + case PRU_DISCONNECT: + tp = tcp_disconnect(tp); + break; + + /* + * Accept a connection. Essentially all the work is + * done at higher levels; just return the address + * of the peer, storing through addr. + */ + case PRU_ACCEPT: +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + in6_setpeeraddr(inp, nam); + else +#endif + in_setpeeraddr(inp, nam); + break; + + /* + * Mark the connection as being incapable of further output. + */ + case PRU_SHUTDOWN: + if (so->so_state & SS_CANTSENDMORE) + break; + socantsendmore(so); + tp = tcp_usrclosed(tp); + if (tp) + error = tcp_output(tp); + break; + + /* + * After a receive, possibly send window update to peer. + */ + case PRU_RCVD: + (void) tcp_output(tp); + break; + + /* + * Do a send by putting data in output queue and updating urgent + * marker if URG set. Possibly send more data. + */ + case PRU_SEND: +#ifdef IPSEC + error = check_ipsec_policy(inp, 0); + if (error) + break; +#endif + sbappend(&so->so_snd, m); + error = tcp_output(tp); + break; + + /* + * Abort the TCP. + */ + case PRU_ABORT: + tp = tcp_drop(tp, ECONNABORTED); + break; + + case PRU_SENSE: +#ifndef __ECOS + ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; +#endif + (void) splx(s); + return (0); + + case PRU_RCVOOB: + if ((so->so_oobmark == 0 && + (so->so_state & SS_RCVATMARK) == 0) || + so->so_options & SO_OOBINLINE || + tp->t_oobflags & TCPOOB_HADDATA) { + error = EINVAL; + break; + } + if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { + error = EWOULDBLOCK; + break; + } + m->m_len = 1; + *mtod(m, caddr_t) = tp->t_iobc; + if (((long)nam & MSG_PEEK) == 0) + tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); + break; + + case PRU_SENDOOB: + if (sbspace(&so->so_snd) < -512) { + m_freem(m); + error = ENOBUFS; + break; + } + /* + * According to RFC961 (Assigned Protocols), + * the urgent pointer points to the last octet + * of urgent data. We continue, however, + * to consider it to indicate the first octet + * of data past the urgent section. + * Otherwise, snd_up should be one lower. + */ + sbappend(&so->so_snd, m); + tp->snd_up = tp->snd_una + so->so_snd.sb_cc; + tp->t_force = 1; + error = tcp_output(tp); + tp->t_force = 0; + break; + + case PRU_SOCKADDR: +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + in6_setsockaddr(inp, nam); + else +#endif + in_setsockaddr(inp, nam); + break; + + case PRU_PEERADDR: +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + in6_setpeeraddr(inp, nam); + else +#endif + in_setpeeraddr(inp, nam); + break; + + /* + * TCP slow timer went off; going through this + * routine for tracing's sake. + */ + case PRU_SLOWTIMO: + tp = tcp_timers(tp, (long)nam); + req |= (long)nam << 8; /* for debug's sake */ + break; + + default: + panic("tcp_usrreq"); + } +#ifdef TCPDEBUG + if (tp && (so->so_options & SO_DEBUG)) + tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0); +#endif /* TCPDEBUG */ + splx(s); + return (error); +} + +int +tcp_ctloutput(op, so, level, optname, mp) + int op; + struct socket *so; + int level, optname; + struct mbuf **mp; +{ + int error = 0, s; + struct inpcb *inp; + register struct tcpcb *tp; + register struct mbuf *m; + register int i; + + s = splsoftnet(); + inp = sotoinpcb(so); + if (inp == NULL) { + splx(s); + if (op == PRCO_SETOPT && *mp) + (void) m_free(*mp); + return (ECONNRESET); + } +#ifdef INET6 + tp = intotcpcb(inp); +#endif /* INET6 */ + if (level != IPPROTO_TCP) { +#ifdef INET6 + /* + * Not sure if this is the best approach. + * It seems to be, but we don't set tp->pf until the connection + * is established, which may lead to confusion in the case of + * AF_INET6 sockets which get SET/GET options for IPv4. + */ + if (tp->pf == PF_INET6) + error = ip6_ctloutput(op, so, level, optname, mp); + else +#endif /* INET6 */ + error = ip_ctloutput(op, so, level, optname, mp); + splx(s); + return (error); + } +#ifndef INET6 + tp = intotcpcb(inp); +#endif /* !INET6 */ + + switch (op) { + + case PRCO_SETOPT: + m = *mp; + switch (optname) { + + case TCP_NODELAY: + if (m == NULL || m->m_len < sizeof (int)) + error = EINVAL; + else if (*mtod(m, int *)) + tp->t_flags |= TF_NODELAY; + else + tp->t_flags &= ~TF_NODELAY; + break; + + case TCP_MAXSEG: + if (m == NULL || m->m_len < sizeof (int)) { + error = EINVAL; + break; + } + + i = *mtod(m, int *); + if (i > 0 && i <= tp->t_maxseg) + tp->t_maxseg = i; + else + error = EINVAL; + break; + +#ifdef TCP_SACK + case TCP_SACK_DISABLE: + if (m == NULL || m->m_len < sizeof (int)) { + error = EINVAL; + break; + } + + if (TCPS_HAVEESTABLISHED(tp->t_state)) { + error = EPERM; + break; + } + + if (tp->t_flags & TF_SIGNATURE) { + error = EPERM; + break; + } + + if (*mtod(m, int *)) + tp->sack_disable = 1; + else + tp->sack_disable = 0; + break; +#endif +#ifdef TCP_SIGNATURE + case TCP_SIGNATURE_ENABLE: + if (m == NULL || m->m_len < sizeof (int)) { + error = EINVAL; + break; + } + + if (TCPS_HAVEESTABLISHED(tp->t_state)) { + error = EPERM; + break; + } + + if (*mtod(m, int *)) { + tp->t_flags |= TF_SIGNATURE; +#ifdef TCP_SACK + tp->sack_disable = 1; +#endif /* TCP_SACK */ + } else + tp->t_flags &= ~TF_SIGNATURE; + break; +#endif /* TCP_SIGNATURE */ + default: + error = ENOPROTOOPT; + break; + } + if (m) + (void) m_free(m); + break; + + case PRCO_GETOPT: + *mp = m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = sizeof(int); + + switch (optname) { + case TCP_NODELAY: + *mtod(m, int *) = tp->t_flags & TF_NODELAY; + break; + case TCP_MAXSEG: + *mtod(m, int *) = tp->t_maxseg; + break; +#ifdef TCP_SACK + case TCP_SACK_DISABLE: + *mtod(m, int *) = tp->sack_disable; + break; +#endif + default: + error = ENOPROTOOPT; + break; + } + break; + } + splx(s); + return (error); +} + +#ifndef TCP_SENDSPACE +#define TCP_SENDSPACE 1024*16; +#endif +u_int tcp_sendspace = TCP_SENDSPACE; +#ifndef TCP_RECVSPACE +#define TCP_RECVSPACE 1024*16; +#endif +u_int tcp_recvspace = TCP_RECVSPACE; + +/* + * Attach TCP protocol to socket, allocating + * internet protocol control block, tcp control block, + * bufer space, and entering LISTEN state if to accept connections. + */ +int +tcp_attach(so) + struct socket *so; +{ + register struct tcpcb *tp; + struct inpcb *inp; + int error; + + if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { + error = soreserve(so, tcp_sendspace, tcp_recvspace); + if (error) + return (error); + } + error = in_pcballoc(so, &tcbtable); + if (error) + return (error); + inp = sotoinpcb(so); + tp = tcp_newtcpcb(inp); + if (tp == NULL) { + int nofd = so->so_state & SS_NOFDREF; /* XXX */ + + so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ + in_pcbdetach(inp); + so->so_state |= nofd; + return (ENOBUFS); + } + tp->t_state = TCPS_CLOSED; + return (0); +} + +/* + * Initiate (or continue) disconnect. + * If embryonic state, just send reset (once). + * If in ``let data drain'' option and linger null, just drop. + * Otherwise (hard), mark socket disconnecting and drop + * current input data; switch states based on user close, and + * send segment to peer (with FIN). + */ +struct tcpcb * +tcp_disconnect(tp) + register struct tcpcb *tp; +{ + struct socket *so = tp->t_inpcb->inp_socket; + + if (TCPS_HAVEESTABLISHED(tp->t_state) == 0) + tp = tcp_close(tp); + else if ((so->so_options & SO_LINGER) && so->so_linger == 0) + tp = tcp_drop(tp, 0); + else { + soisdisconnecting(so); + sbflush(&so->so_rcv); + tp = tcp_usrclosed(tp); + if (tp) + (void) tcp_output(tp); + } + return (tp); +} + +/* + * User issued close, and wish to trail through shutdown states: + * if never received SYN, just forget it. If got a SYN from peer, + * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. + * If already got a FIN from peer, then almost done; go to LAST_ACK + * state. In all other cases, have already sent FIN to peer (e.g. + * after PRU_SHUTDOWN), and just have to play tedious game waiting + * for peer to send FIN or not respond to keep-alives, etc. + * We can let the user exit from the close as soon as the FIN is acked. + */ +struct tcpcb * +tcp_usrclosed(tp) + register struct tcpcb *tp; +{ + + switch (tp->t_state) { + + case TCPS_CLOSED: + case TCPS_LISTEN: + case TCPS_SYN_SENT: + tp->t_state = TCPS_CLOSED; + tp = tcp_close(tp); + break; + + case TCPS_SYN_RECEIVED: + case TCPS_ESTABLISHED: + tp->t_state = TCPS_FIN_WAIT_1; + break; + + case TCPS_CLOSE_WAIT: + tp->t_state = TCPS_LAST_ACK; + break; + } + if (tp && tp->t_state >= TCPS_FIN_WAIT_2) { + soisdisconnected(tp->t_inpcb->inp_socket); + /* + * If we are in FIN_WAIT_2, we arrived here because the + * application did a shutdown of the send side. Like the + * case of a transition from FIN_WAIT_1 to FIN_WAIT_2 after + * a full close, we start a timer to make sure sockets are + * not left in FIN_WAIT_2 forever. + */ + if (tp->t_state == TCPS_FIN_WAIT_2) + tp->t_timer[TCPT_2MSL] = tcp_maxidle; + } + return (tp); +} + +/* + * Look up a socket for ident.. + */ +int +tcp_ident(oldp, oldlenp, newp, newlen) + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; +{ + int error = 0, s; + struct tcp_ident_mapping tir; + struct inpcb *inp; + struct sockaddr_in *fin, *lin; + + if (oldp == NULL || newp != NULL || newlen != 0) + return (EINVAL); + if (*oldlenp < sizeof(tir)) + return (ENOMEM); + if ((error = copyin(oldp, &tir, sizeof (tir))) != 0 ) + return (error); + if (tir.faddr.sa_len != sizeof (struct sockaddr) || + tir.faddr.sa_family != AF_INET) + return (EINVAL); + fin = (struct sockaddr_in *)&tir.faddr; + lin = (struct sockaddr_in *)&tir.laddr; + + s = splsoftnet(); + inp = in_pcbhashlookup(&tcbtable, fin->sin_addr, fin->sin_port, + lin->sin_addr, lin->sin_port); + if (inp == NULL) { + ++tcpstat.tcps_pcbhashmiss; + inp = in_pcblookup(&tcbtable, &fin->sin_addr, fin->sin_port, + &lin->sin_addr, lin->sin_port, 0); + } + if (inp != NULL && (inp->inp_socket->so_state & SS_CONNECTOUT)) { + tir.ruid = inp->inp_socket->so_ruid; + tir.euid = inp->inp_socket->so_euid; + } else { + tir.ruid = -1; + tir.euid = -1; + } + splx(s); + + *oldlenp = sizeof (tir); + error = copyout((void *)&tir, oldp, sizeof (tir)); + return (error); +} + +#ifdef CYGPKG_NET_SYSCTL +/* + * Sysctl for tcp variables. + */ +int +tcp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; +{ + + /* All sysctl names at this level are terminal. */ + if (namelen != 1) + return (ENOTDIR); + + switch (name[0]) { + case TCPCTL_RFC1323: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &tcp_do_rfc1323)); +#ifdef TCP_SACK + case TCPCTL_SACK: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &tcp_do_sack)); +#endif + case TCPCTL_MSSDFLT: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &tcp_mssdflt)); + case TCPCTL_KEEPINITTIME: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &tcptv_keep_init)); + + case TCPCTL_KEEPIDLE: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &tcp_keepidle)); + + case TCPCTL_KEEPINTVL: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &tcp_keepintvl)); + + case TCPCTL_SLOWHZ: + return (sysctl_rdint(oldp, oldlenp, newp, PR_SLOWHZ)); + + case TCPCTL_BADDYNAMIC: + return (sysctl_struct(oldp, oldlenp, newp, newlen, + baddynamicports.tcp, sizeof(baddynamicports.tcp))); + + case TCPCTL_RECVSPACE: + return (sysctl_int(oldp, oldlenp, newp, newlen,&tcp_recvspace)); + + case TCPCTL_SENDSPACE: + return (sysctl_int(oldp, oldlenp, newp, newlen,&tcp_sendspace)); + case TCPCTL_IDENT: + return (tcp_ident(oldp, oldlenp, newp, newlen)); + default: + return (ENOPROTOOPT); + } + /* NOTREACHED */ +} +#endif // CYGPKG_NET_SYSCTL diff --git a/ecos/packages/net/tcpip/current/src/sys/netinet/udp_usrreq.c b/ecos/packages/net/tcpip/current/src/sys/netinet/udp_usrreq.c new file mode 100644 index 0000000..b5549f6 --- /dev/null +++ b/ecos/packages/net/tcpip/current/src/sys/netinet/udp_usrreq.c @@ -0,0 +1,1371 @@ +//========================================================================== +// +// sys/netinet/udp_usrreq.c +// +// +// +//========================================================================== +// ####BSDALTCOPYRIGHTBEGIN#### +// ------------------------------------------- +// Portions of this software may have been derived from OpenBSD +// or other sources, and if so are covered by the appropriate copyright +// and license included herein. +// ------------------------------------------- +// ####BSDALTCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: udp_usrreq.c,v 1.30 1999/12/12 10:59:41 itojun Exp $ */ +/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94 + */ + +/* +%%% portions-copyright-nrl-95 +Portions of this software are Copyright 1995-1998 by Randall Atkinson, +Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights +Reserved. All rights under this copyright have been assigned to the US +Naval Research Laboratory (NRL). The NRL Copyright Notice and License +Agreement Version 1.1 (January 17, 1995) applies to these portions of the +software. +You should have received a copy of the license with this software. If you +didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. +*/ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/errno.h> +#ifdef __ECOS +#undef errno +#endif +#ifndef __ECOS +#include <sys/stat.h> +#include <sys/systm.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <sys/sysctl.h> +#endif + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/ip_var.h> +#include <netinet/ip_icmp.h> +#include <netinet/udp.h> +#include <netinet/udp_var.h> + +#ifdef IPSEC +#include <netinet/ip_ipsp.h> + +extern int check_ipsec_policy __P((struct inpcb *, u_int32_t)); +#endif + +#include <machine/stdarg.h> + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#include <netinet6/ip6.h> +#include <netinet6/in6_var.h> +#include <netinet6/ip6_var.h> +#include <netinet6/icmp6.h> +#include <netinet6/ip6protosw.h> + +#ifndef CREATE_IPV6_MAPPED +#define CREATE_IPV6_MAPPED(a6, a4) \ +do { \ + bzero(&(a6), sizeof(a6)); \ + (a6).s6_addr[10] = (a6).s6_addr[11] = 0xff; \ + *(u_int32_t *)&(a6).s6_addr[12] = (a4); \ +} while (0) +#endif + +extern int ip6_defhlim; + +#endif /* INET6 */ + +/* + * UDP protocol implementation. + * Per RFC 768, August, 1980. + */ +int udpcksum = 1; + + +static void udp_detach __P((struct inpcb *)); +static void udp_notify __P((struct inpcb *, int)); +static struct mbuf *udp_saveopt __P((caddr_t, int, int)); + +#ifndef UDBHASHSIZE +#define UDBHASHSIZE 128 +#endif +int udbhashsize = UDBHASHSIZE; + +/* from in_pcb.c */ +extern struct baddynamicports baddynamicports; + +void +udp_init() +{ + + in_pcbinit(&udbtable, udbhashsize); +} + +#if defined(INET6) && !defined(TCP6) +int +udp6_input(mp, offp, proto) + struct mbuf **mp; + int *offp, proto; +{ + struct mbuf *m = *mp; + +#if defined(NFAITH) && 0 < NFAITH + if (m->m_pkthdr.rcvif) { + if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { + /* XXX send icmp6 host/port unreach? */ + m_freem(m); + return IPPROTO_DONE; + } + } +#endif + + udp_input(m, *offp, proto); + return IPPROTO_DONE; +} +#endif + +void +#if __STDC__ +udp_input(struct mbuf *m, ...) +#else +udp_input(m, va_alist) + struct mbuf *m; + va_dcl +#endif +{ + register struct ip *ip; + register struct udphdr *uh; + register struct inpcb *inp; + struct mbuf *opts = 0; + int len; + struct ip save_ip; + int iphlen; + va_list ap; + u_int16_t savesum; + union { + struct sockaddr sa; + struct sockaddr_in sin; +#ifdef INET6 + struct sockaddr_in6 sin6; +#endif /* INET6 */ + } srcsa, dstsa; +#ifdef INET6 + struct ip6_hdr *ipv6; + struct sockaddr_in6 src_v4mapped; +#endif /* INET6 */ +#ifdef IPSEC + struct tdb *tdb = NULL; +#endif /* IPSEC */ + + va_start(ap, m); + iphlen = va_arg(ap, int); + va_end(ap); + + udpstat.udps_ipackets++; + +#ifdef IPSEC + /* Save the last SA which was used to process the mbuf */ + if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) { + struct tdb_ident *tdbi = m->m_pkthdr.tdbi; + /* XXX gettdb() should really be called at spltdb(). */ + /* XXX this is splsoftnet(), currently they are the same. */ + tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); + free(m->m_pkthdr.tdbi, M_TEMP); + m->m_pkthdr.tdbi = NULL; + } +#endif /* IPSEC */ + + switch (mtod(m, struct ip *)->ip_v) { + case 4: + ip = mtod(m, struct ip *); +#ifdef INET6 + ipv6 = NULL; +#endif /* INET6 */ + srcsa.sa.sa_family = AF_INET; + break; +#ifdef INET6 + case 6: + ip = NULL; + ipv6 = mtod(m, struct ip6_hdr *); + srcsa.sa.sa_family = AF_INET6; + break; +#endif /* INET6 */ + default: +#ifdef __ECOS + diag_printf("udp_input: received unknown IP version %d", + mtod(m, struct ip *)->ip_v); +#else + printf("udp_input: received unknown IP version %d", + mtod(m, struct ip *)->ip_v); +#endif + goto bad; + } + + /* + * Strip IP options, if any; should skip this, + * make available to user, and use on returned packets, + * but we don't yet have a way to check the checksum + * with options still present. + */ + /* + * (contd. from above...) Furthermore, we may want to strip options + * for such things as ICMP errors, where options just get in the way. + */ + if (ip && iphlen > sizeof (struct ip)) { + ip_stripoptions(m, (struct mbuf *)0); + iphlen = sizeof(struct ip); + } + + /* + * Get IP and UDP header together in first mbuf. + */ + if (m->m_len < iphlen + sizeof(struct udphdr)) { + if ((m = m_pullup2(m, iphlen + sizeof(struct udphdr))) == 0) { + udpstat.udps_hdrops++; + return; + } +#ifdef INET6 + if (ipv6) + ipv6 = mtod(m, struct ip6_hdr *); + else +#endif /* INET6 */ + ip = mtod(m, struct ip *); + } + uh = (struct udphdr *)(mtod(m, caddr_t) + iphlen); + + /* + * Make mbuf data length reflect UDP length. + * If not enough data to reflect UDP length, drop. + */ + len = ntohs((u_int16_t)uh->uh_ulen); + if (m->m_pkthdr.len - iphlen != len) { + if (len > (m->m_pkthdr.len - iphlen) || + len < sizeof(struct udphdr)) { + udpstat.udps_badlen++; + goto bad; + } + m_adj(m, len - (m->m_pkthdr.len - iphlen)); + } + /* + * Save a copy of the IP header in case we want restore it + * for sending an ICMP error message in response. + */ + if (ip) + save_ip = *ip; + + /* + * Checksum extended UDP header and data. + * from W.R.Stevens: check incoming udp cksums even if + * udpcksum is not set. + */ + savesum = uh->uh_sum; +#ifdef INET6 + if (ipv6) { + /* + * In IPv6, the UDP checksum is ALWAYS used. + */ + if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len))) { + udpstat.udps_badsum++; + goto bad; + } + } else +#endif /* INET6 */ + if (uh->uh_sum) { + bzero(((struct ipovly *)ip)->ih_x1, + sizeof ((struct ipovly *)ip)->ih_x1); + ((struct ipovly *)ip)->ih_len = uh->uh_ulen; + if ((uh->uh_sum = in_cksum(m, len + sizeof (struct ip))) != 0) { + udpstat.udps_badsum++; + m_freem(m); + return; + } + } else + udpstat.udps_nosum++; + + switch (srcsa.sa.sa_family) { + case AF_INET: + bzero(&srcsa, sizeof(struct sockaddr_in)); + srcsa.sin.sin_len = sizeof(struct sockaddr_in); + srcsa.sin.sin_family = AF_INET; + srcsa.sin.sin_port = uh->uh_sport; + srcsa.sin.sin_addr = ip->ip_src; + +#ifdef INET6 + bzero(&src_v4mapped, sizeof(struct sockaddr_in6)); + src_v4mapped.sin6_len = sizeof(struct sockaddr_in6); + src_v4mapped.sin6_family = AF_INET6; + src_v4mapped.sin6_port = uh->uh_sport; + CREATE_IPV6_MAPPED(src_v4mapped.sin6_addr, ip->ip_src.s_addr); +#endif /* INET6 */ + + bzero(&dstsa, sizeof(struct sockaddr_in)); + dstsa.sin.sin_len = sizeof(struct sockaddr_in); + dstsa.sin.sin_family = AF_INET; + dstsa.sin.sin_port = uh->uh_dport; + dstsa.sin.sin_addr = ip->ip_dst; + break; +#ifdef INET6 + case AF_INET6: + bzero(&srcsa, sizeof(struct sockaddr_in6)); + srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6); + srcsa.sin6.sin6_family = AF_INET6; + srcsa.sin6.sin6_port = uh->uh_sport; + srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ipv6->ip6_flow; + srcsa.sin6.sin6_addr = ipv6->ip6_src; + if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6.sin6_addr)) + srcsa.sin6.sin6_addr.s6_addr16[1] = 0; + if (m->m_pkthdr.rcvif) { + if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6.sin6_addr)) { + srcsa.sin6.sin6_scope_id = + m->m_pkthdr.rcvif->if_index; + } else + srcsa.sin6.sin6_scope_id = 0; + } else + srcsa.sin6.sin6_scope_id = 0; + + bzero(&dstsa, sizeof(struct sockaddr_in6)); + dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6); + dstsa.sin6.sin6_family = AF_INET6; + dstsa.sin6.sin6_port = uh->uh_dport; + dstsa.sin6.sin6_addr = ipv6->ip6_dst; + break; +#endif /* INET6 */ + } + +#ifdef INET6 + if ((ipv6 && IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst)) || + (ip && IN_MULTICAST(ip->ip_dst.s_addr)) || + (ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) { +#else /* INET6 */ + if (IN_MULTICAST(ip->ip_dst.s_addr) || + in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { +#endif /* INET6 */ + struct socket *last; + /* + * Deliver a multicast or broadcast datagram to *all* sockets + * for which the local and remote addresses and ports match + * those of the incoming datagram. This allows more than + * one process to receive multi/broadcasts on the same port. + * (This really ought to be done for unicast datagrams as + * well, but that would cause problems with existing + * applications that open both address-specific sockets and + * a wildcard socket listening to the same port -- they would + * end up receiving duplicates of every unicast datagram. + * Those applications open the multiple sockets to overcome an + * inadequacy of the UDP socket interface, but for backwards + * compatibility we avoid the problem here rather than + * fixing the interface. Maybe 4.5BSD will remedy this?) + */ + + iphlen += sizeof(struct udphdr); + + /* + * Locate pcb(s) for datagram. + * (Algorithm copied from raw_intr().) + */ + last = NULL; + for (inp = udbtable.inpt_queue.cqh_first; + inp != (struct inpcb *)&udbtable.inpt_queue; + inp = inp->inp_queue.cqe_next) { + if (inp->inp_lport != uh->uh_dport) + continue; +#ifdef INET6 + if (ipv6) { + if (!(inp->inp_flags & INP_IPV6)) + continue; + if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) + if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, + &ipv6->ip6_dst)) + continue; + } else +#endif /* INET6 */ + if (inp->inp_laddr.s_addr != INADDR_ANY) { + if (inp->inp_laddr.s_addr != + ip->ip_dst.s_addr) + continue; + } +#ifdef INET6 + if (ipv6) { + if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) + if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, + &ipv6->ip6_src) || + inp->inp_fport != uh->uh_sport) + continue; + } else +#endif /* INET6 */ + if (inp->inp_faddr.s_addr != INADDR_ANY) { + if (inp->inp_faddr.s_addr != + ip->ip_src.s_addr || + inp->inp_fport != uh->uh_sport) + continue; + } + + if (last != NULL) { + struct mbuf *n; + + if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + opts = NULL; +#ifdef INET6 + if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) + ip6_savecontrol(inp, &opts, ipv6, n); +#endif /* INET6 */ + m_adj(n, iphlen); + if (sbappendaddr(&last->so_rcv, +#ifdef INET6 + /* + * This cruft is needed in (the rare) + * case I deliver a {multi,broad}cast + * IPv4 packet to an AF_INET6 socket. + */ + ((((struct inpcb *)last->so_pcb)->inp_flags + & INP_IPV6) && ip) ? + (struct sockaddr *)&src_v4mapped : +#endif /* INET6 */ + &srcsa.sa, n, opts) == 0) { + m_freem(n); + udpstat.udps_fullsock++; + } else + sorwakeup(last); + } + } + last = inp->inp_socket; + /* + * Don't look for additional matches if this one does + * not have either the SO_REUSEPORT or SO_REUSEADDR + * socket options set. This heuristic avoids searching + * through all pcbs in the common case of a non-shared + * port. It * assumes that an application will never + * clear these options after setting them. + */ + if ((last->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0) + break; + } + + if (last == NULL) { + /* + * No matching pcb found; discard datagram. + * (No need to send an ICMP Port Unreachable + * for a broadcast or multicast datgram.) + */ + udpstat.udps_noportbcast++; + goto bad; + } + + opts = NULL; +#ifdef INET6 + if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) + ip6_savecontrol(inp, &opts, ipv6, m); +#endif /* INET6 */ + m_adj(m, iphlen); + if (sbappendaddr(&last->so_rcv, +#ifdef INET6 + /* + * This cruft is needed in (the rare) case I + * deliver a {multi,broad}cast IPv4 packet to + * an AF_INET6 socket. + */ + ((((struct inpcb *)last->so_pcb)->inp_flags & INP_IPV6) && ip) ? + (struct sockaddr *)&src_v4mapped : +#endif /* INET6 */ + &srcsa.sa, m, opts) == 0) { + udpstat.udps_fullsock++; + goto bad; + } + sorwakeup(last); + return; + } + /* + * Locate pcb for datagram. + */ +#ifdef INET6 + if (ipv6) + inp = in6_pcbhashlookup(&udbtable, &ipv6->ip6_src, uh->uh_sport, + &ipv6->ip6_dst, uh->uh_dport); + else +#endif /* INET6 */ + inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport, + ip->ip_dst, uh->uh_dport); + if (inp == 0) { + ++udpstat.udps_pcbhashmiss; +#ifdef INET6 + if (ipv6) { + inp = in_pcblookup(&udbtable, + (struct in_addr *)&(ipv6->ip6_src), + uh->uh_sport, (struct in_addr *)&(ipv6->ip6_dst), + uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); + } else +#endif /* INET6 */ + inp = in_pcblookup(&udbtable, &ip->ip_src, uh->uh_sport, + &ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD); + if (inp == 0) { + udpstat.udps_noport++; + if (m->m_flags & (M_BCAST | M_MCAST)) { + udpstat.udps_noportbcast++; + goto bad; + } +#ifdef INET6 + if (ipv6) { + icmp6_error(m, ICMP6_DST_UNREACH, + ICMP6_DST_UNREACH_NOPORT,0); + } else +#endif /* INET6 */ + { + *ip = save_ip; + HTONS(ip->ip_len); + HTONS(ip->ip_id); + HTONS(ip->ip_off); + uh->uh_sum = savesum; + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, + 0, 0); + } + return; + } + } + +#ifdef IPSEC + /* Check if this socket requires security for incoming packets */ + if ((inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_REQUIRE && + !(m->m_flags & M_AUTH)) || + (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE && + !(m->m_flags & M_CONF))) { +#ifdef notyet +#ifdef INET6 + if (ipv6) + ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0); + else +#endif /* INET6 */ + icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0); + m = NULL; +#endif /* notyet */ + udpstat.udps_nosec++; + goto bad; + } + /* Use tdb_bind_out for this inp's outbound communication */ + if (tdb) + tdb_add_inp(tdb, inp); +#endif /*IPSEC */ + + opts = NULL; +#ifdef INET6 + if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) + ip6_savecontrol(inp, &opts, ipv6, m); +#endif /* INET6 */ + if (ip && (inp->inp_flags & INP_CONTROLOPTS)) { + struct mbuf **mp = &opts; + + if (inp->inp_flags & INP_RECVDSTADDR) { + *mp = udp_saveopt((caddr_t) &ip->ip_dst, + sizeof(struct in_addr), IP_RECVDSTADDR); + if (*mp) + mp = &(*mp)->m_next; + } +#ifdef notyet + /* options were tossed above */ + if (inp->inp_flags & INP_RECVOPTS) { + *mp = udp_saveopt((caddr_t) opts_deleted_above, + sizeof(struct in_addr), IP_RECVOPTS); + if (*mp) + mp = &(*mp)->m_next; + } + /* ip_srcroute doesn't do what we want here, need to fix */ + if (inp->inp_flags & INP_RECVRETOPTS) { + *mp = udp_saveopt((caddr_t) ip_srcroute(), + sizeof(struct in_addr), IP_RECVRETOPTS); + if (*mp) + mp = &(*mp)->m_next; + } +#endif + } + iphlen += sizeof(struct udphdr); + m_adj(m, iphlen); + if (sbappendaddr(&inp->inp_socket->so_rcv, +#ifdef INET6 + /* + * This cruft is needed to deliver a IPv4 packet to + * an AF_INET6 socket. + */ + ((((struct inpcb *)inp->inp_socket->so_pcb)->inp_flags & INP_IPV6) + && ip) ? (struct sockaddr *)&src_v4mapped : +#endif /* INET6 */ + &srcsa.sa, m, opts) == 0) { + udpstat.udps_fullsock++; + goto bad; + } + sorwakeup(inp->inp_socket); + return; +bad: + m_freem(m); + if (opts) + m_freem(opts); +} + +/* + * Create a "control" mbuf containing the specified data + * with the specified type for presentation with a datagram. + */ +struct mbuf * +udp_saveopt(p, size, type) + caddr_t p; + register int size; + int type; +{ + register struct cmsghdr *cp; + struct mbuf *m; + + if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL) + return ((struct mbuf *) NULL); + cp = (struct cmsghdr *) mtod(m, struct cmsghdr *); + bcopy(p, CMSG_DATA(cp), size); + size += sizeof(*cp); + m->m_len = size; + cp->cmsg_len = size; + cp->cmsg_level = IPPROTO_IP; + cp->cmsg_type = type; + return (m); +} + +/* + * Notify a udp user of an asynchronous error; + * just wake up so that he can collect error status. + */ +static void +udp_notify(inp, errno) + register struct inpcb *inp; + int errno; +{ + inp->inp_socket->so_error = errno; + sorwakeup(inp->inp_socket); + sowwakeup(inp->inp_socket); +} + +#if defined(INET6) && !defined(TCP6) +void +udp6_ctlinput(cmd, sa, d) + int cmd; + struct sockaddr *sa; + void *d; +{ + struct sockaddr_in6 sa6; + struct ip6_hdr *ip6; + struct mbuf *m; + int off; + + if (sa == NULL) + return; + if (sa->sa_family != AF_INET6) + return; + + /* decode parameter from icmp6. */ + if (d != NULL) { + struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; + ip6 = ip6cp->ip6c_ip6; + m = ip6cp->ip6c_m; + off = ip6cp->ip6c_off; + } else + return; + + /* translate addresses into internal form */ + sa6 = *(struct sockaddr_in6 *)sa; + if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) && m && m->m_pkthdr.rcvif) + sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); + sa = (struct sockaddr *)&sa6; + + (void)udp_ctlinput(cmd, sa, (void *)ip6); +} +#endif + +void * +udp_ctlinput(cmd, sa, v) + int cmd; + struct sockaddr *sa; + void *v; +{ + register struct ip *ip = v; + register struct udphdr *uh; + extern int inetctlerrmap[]; + void (*notify) __P((struct inpcb *, int)) = udp_notify; + int errno; + + if ((unsigned)cmd >= PRC_NCMDS) + return NULL; + errno = inetctlerrmap[cmd]; + if (PRC_IS_REDIRECT(cmd)) + notify = in_rtchange, ip = 0; + else if (cmd == PRC_HOSTDEAD) + ip = 0; + else if (errno == 0) + return NULL; + if (sa == NULL) + return NULL; +#ifdef INET6 + if (sa->sa_family == AF_INET6) { + if (ip) { + struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip; + + uh = (struct udphdr *)((caddr_t)ipv6 + sizeof(struct ip6_hdr)); +#if 0 /*XXX*/ + in6_pcbnotify(&udbtable, sa, uh->uh_dport, + &(ipv6->ip6_src), uh->uh_sport, cmd, udp_notify); +#endif + } else { +#if 0 /*XXX*/ + in6_pcbnotify(&udbtable, sa, 0, + (struct in6_addr *)&in6addr_any, 0, cmd, udp_notify); +#endif + } + } else +#endif /* INET6 */ + if (ip) { + uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); + in_pcbnotify(&udbtable, sa, uh->uh_dport, ip->ip_src, + uh->uh_sport, errno, notify); + } else + in_pcbnotifyall(&udbtable, sa, errno, notify); + return NULL; +} + +int +#if __STDC__ +udp_output(struct mbuf *m, ...) +#else +udp_output(m, va_alist) + struct mbuf *m; + va_dcl +#endif +{ + register struct inpcb *inp; + struct mbuf *addr, *control; + register struct udpiphdr *ui; + register int len = m->m_pkthdr.len; + struct in_addr laddr; + int s = 0, error = 0; + va_list ap; +#ifdef INET6 + register struct in6_addr laddr6; + int v6packet = 0; + struct sockaddr_in6 *sin6 = NULL; + struct ip6_pktopts opt, *stickyopt = NULL; +#endif /* INET6 */ + int pcbflags = 0; + + va_start(ap, m); + inp = va_arg(ap, struct inpcb *); + addr = va_arg(ap, struct mbuf *); + control = va_arg(ap, struct mbuf *); + va_end(ap); + +#ifdef INET6 + v6packet = ((inp->inp_flags & INP_IPV6) && + !(inp->inp_flags & INP_IPV6_MAPPED)); +#endif + +#ifdef INET6 + stickyopt = inp->inp_outputopts6; + if (control && v6packet) { + error = ip6_setpktoptions(control, &opt, + ((inp->inp_socket->so_state & SS_PRIV) != 0)); + if (error != 0) + goto release; + inp->inp_outputopts6 = &opt; + } +#endif + + if (addr) { +#ifdef INET6 + sin6 = mtod(addr, struct sockaddr_in6 *); +#endif + + /* + * Save current PCB flags because they may change during + * temporary connection, particularly the INP_IPV6_UNDEC + * flag. + */ + pcbflags = inp->inp_flags; + +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + laddr6 = inp->inp_laddr6; + else +#endif /* INET6 */ + laddr = inp->inp_laddr; +#ifdef INET6 + if (((inp->inp_flags & INP_IPV6) && + !IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) || + (inp->inp_faddr.s_addr != INADDR_ANY)) +#else /* INET6 */ + if (inp->inp_faddr.s_addr != INADDR_ANY) +#endif /* INET6 */ + { + error = EISCONN; + goto release; + } + /* + * Must block input while temporarily connected. + */ + s = splsoftnet(); + error = in_pcbconnect(inp, addr); + if (error) { + splx(s); + goto release; + } + } else { +#ifdef INET6 + if (((inp->inp_flags & INP_IPV6) && + IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) || + (inp->inp_faddr.s_addr == INADDR_ANY)) +#else /* INET6 */ + if (inp->inp_faddr.s_addr == INADDR_ANY) +#endif /* INET6 */ + { + error = ENOTCONN; + goto release; + } + } + /* + * Calculate data length and get a mbuf + * for UDP and IP headers. + */ +#ifdef INET6 + /* + * Handles IPv4-mapped IPv6 address because temporary connect sets + * the right flag. + */ + M_PREPEND(m, v6packet ? (sizeof(struct udphdr) + + sizeof(struct ip6_hdr)) : sizeof(struct udpiphdr), M_DONTWAIT); +#else /* INET6 */ + M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); +#endif /* INET6 */ + if (m == 0) { + error = ENOBUFS; + goto bail; + } + + /* + * Compute the packet length of the IP header, and + * punt if the length looks bogus. + */ + if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { + error = EMSGSIZE; + goto release; + } + + /* + * Fill in mbuf with extended UDP header + * and addresses and length put into network format. + */ +#ifdef INET6 + if (v6packet) { + struct ip6_hdr *ipv6 = mtod(m, struct ip6_hdr *); + struct udphdr *uh = (struct udphdr *)(mtod(m, caddr_t) + + sizeof(struct ip6_hdr)); + int payload = sizeof(struct ip6_hdr); + struct in6_addr *faddr; + struct in6_addr *laddr; + struct ifnet *oifp = NULL; + + ipv6->ip6_flow = htonl(0x60000000) | + (inp->inp_ipv6.ip6_flow & htonl(0x0fffffff)); + + ipv6->ip6_nxt = IPPROTO_UDP; + ipv6->ip6_dst = inp->inp_faddr6; + /* + * If the scope of the destination is link-local, + * embed the interface + * index in the address. + * + * XXX advanced-api value overrides sin6_scope_id + */ + faddr = &ipv6->ip6_dst; + if (IN6_IS_ADDR_LINKLOCAL(faddr) || + IN6_IS_ADDR_MC_LINKLOCAL(faddr)) { + struct ip6_pktopts *optp = inp->inp_outputopts6; + struct in6_pktinfo *pi = NULL; + struct ip6_moptions *mopt = NULL; + + /* + * XXX Boundary check is assumed to be already done in + * ip6_setpktoptions(). + */ + if (optp && (pi = optp->ip6po_pktinfo) && + pi->ipi6_ifindex) { + faddr->s6_addr16[1] = htons(pi->ipi6_ifindex); + oifp = ifindex2ifnet[pi->ipi6_ifindex]; + } + else if (IN6_IS_ADDR_MULTICAST(faddr) && + (mopt = inp->inp_moptions6) && + mopt->im6o_multicast_ifp) { + oifp = mopt->im6o_multicast_ifp; + faddr->s6_addr16[1] = oifp->if_index; + } else if (sin6 && sin6->sin6_scope_id) { + /* boundary check */ + if (sin6->sin6_scope_id < 0 + || if_index < sin6->sin6_scope_id) { + error = ENXIO; /* XXX EINVAL? */ + goto release; + } + /* XXX */ + faddr->s6_addr16[1] = + htons(sin6->sin6_scope_id & 0xffff); + } + } + ipv6->ip6_hlim = in6_selecthlim(inp, oifp); + if (sin6) { /*XXX*/ + laddr = in6_selectsrc(sin6, inp->inp_outputopts6, + inp->inp_moptions6, + &inp->inp_route6, + &inp->inp_laddr6, &error); + if (laddr == NULL) { + if (error == 0) + error = EADDRNOTAVAIL; + goto release; + } + } else + laddr = &inp->inp_laddr6; + + ipv6->ip6_src = *laddr; + + ipv6->ip6_plen = (u_short)len + sizeof(struct udphdr); + + uh->uh_sport = inp->inp_lport; + uh->uh_dport = inp->inp_fport; + uh->uh_ulen = htons(ipv6->ip6_plen); + uh->uh_sum = 0; + + /* + * Always calculate udp checksum for IPv6 datagrams + */ + if (!(uh->uh_sum = in6_cksum(m, IPPROTO_UDP, + payload, len + sizeof(struct udphdr)))) + uh->uh_sum = 0xffff; + + error = ip6_output(m, inp->inp_outputopts6, &inp->inp_route6, + inp->inp_socket->so_options & SO_DONTROUTE, + (inp->inp_flags & INP_IPV6_MCAST)?inp->inp_moptions6:NULL, + NULL); + } else +#endif /* INET6 */ + { + ui = mtod(m, struct udpiphdr *); + bzero(ui->ui_x1, sizeof ui->ui_x1); + ui->ui_pr = IPPROTO_UDP; + ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); + ui->ui_src = inp->inp_laddr; + ui->ui_dst = inp->inp_faddr; + ui->ui_sport = inp->inp_lport; + ui->ui_dport = inp->inp_fport; + ui->ui_ulen = ui->ui_len; + + /* + * Stuff checksum and output datagram. + */ + + ui->ui_sum = 0; + if (udpcksum) { + if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + + len)) == 0) + ui->ui_sum = 0xffff; + } + ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; +#ifdef INET6 + /* + * For now, we use the default values for ttl and tos for + * v4 packets sent using a v6 pcb. We probably want to + * later allow v4 setsockopt operations on a v6 socket to + * modify the ttl and tos for v4 packets sent using + * the mapped address format. We really ought to + * save the v4 ttl and v6 hoplimit in separate places + * instead of craming both in the inp_hu union. + */ + if (inp->inp_flags & INP_IPV6) { + ((struct ip *)ui)->ip_ttl = ip_defttl; + ((struct ip *)ui)->ip_tos = 0; + } else +#endif /* INET6 */ + { + ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; + ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; + } + + udpstat.udps_opackets++; +#ifdef INET6 + if (inp->inp_flags & INP_IPV6_MCAST) { + error = ip_output(m, inp->inp_options, &inp->inp_route, + inp->inp_socket->so_options & + (SO_DONTROUTE | SO_BROADCAST), + NULL, NULL, inp->inp_socket); + } else +#endif /* INET6 */ + { + error = ip_output(m, inp->inp_options, &inp->inp_route, + inp->inp_socket->so_options & + (SO_DONTROUTE | SO_BROADCAST), + inp->inp_moptions, inp, NULL); + } + } + +bail: + if (addr) { + in_pcbdisconnect(inp); + inp->inp_flags = pcbflags; +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + inp->inp_laddr6 = laddr6; + else +#endif + inp->inp_laddr = laddr; + splx(s); + } + if (control) { +#ifdef INET6 + if (v6packet) + inp->inp_outputopts6 = stickyopt; +#endif + m_freem(control); + } + return (error); + +release: + m_freem(m); + if (control) { +#ifdef INET6 + if (v6packet) + inp->inp_outputopts6 = stickyopt; +#endif + m_freem(control); + } + return (error); +} + +u_int udp_sendspace = 9216; /* really max datagram size */ +u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); + /* 40 1K datagrams */ + +#if defined(INET6) && !defined(TCP6) +/*ARGSUSED*/ +int +udp6_usrreq(so, req, m, addr, control, p) + struct socket *so; + int req; + struct mbuf *m, *addr, *control; + struct proc *p; +{ + return udp_usrreq(so, req, m, addr, control); +} +#endif + +/*ARGSUSED*/ +int +udp_usrreq(so, req, m, addr, control) + struct socket *so; + int req; + struct mbuf *m, *addr, *control; +{ + struct inpcb *inp = sotoinpcb(so); + int error = 0; + int s; + + if (req == PRU_CONTROL) { +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + return (in6_control(so, (u_long)m, (caddr_t)addr, + (struct ifnet *)control, 0)); + else +#endif /* INET6 */ + return (in_control(so, (u_long)m, (caddr_t)addr, + (struct ifnet *)control)); + } + if (inp == NULL && req != PRU_ATTACH) { + error = EINVAL; + goto release; + } + /* + * Note: need to block udp_input while changing + * the udp pcb queue and/or pcb addresses. + */ + switch (req) { + + case PRU_ATTACH: + if (inp != NULL) { + error = EINVAL; + break; + } + s = splsoftnet(); + error = in_pcballoc(so, &udbtable); + splx(s); + if (error) + break; + error = soreserve(so, udp_sendspace, udp_recvspace); + if (error) + break; +#ifdef INET6 + if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6) + ((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim = + ip6_defhlim; + else +#endif /* INET6 */ + ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl; + break; + + case PRU_DETACH: + udp_detach(inp); + break; + + case PRU_BIND: + s = splsoftnet(); +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + error = in6_pcbbind(inp, addr); + else +#endif + error = in_pcbbind(inp, addr); + splx(s); + break; + + case PRU_LISTEN: + error = EOPNOTSUPP; + break; + + case PRU_CONNECT: +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) { + if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { + error = EISCONN; + break; + } + s = splsoftnet(); + error = in6_pcbconnect(inp, addr); + splx(s); + } else +#endif /* INET6 */ + { + if (inp->inp_faddr.s_addr != INADDR_ANY) { + error = EISCONN; + break; + } + s = splsoftnet(); + error = in_pcbconnect(inp, addr); + splx(s); + } + + if (error == 0) + soisconnected(so); + break; + + case PRU_CONNECT2: + error = EOPNOTSUPP; + break; + + case PRU_ACCEPT: + error = EOPNOTSUPP; + break; + + case PRU_DISCONNECT: +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) { + if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { + error = ENOTCONN; + break; + } + } else +#endif /* INET6 */ + if (inp->inp_faddr.s_addr == INADDR_ANY) { + error = ENOTCONN; + break; + } + + s = splsoftnet(); + in_pcbdisconnect(inp); +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + inp->inp_laddr6 = in6addr_any; + else +#endif /* INET6 */ + inp->inp_laddr.s_addr = INADDR_ANY; + + splx(s); + so->so_state &= ~SS_ISCONNECTED; /* XXX */ + break; + + case PRU_SHUTDOWN: + socantsendmore(so); + break; + + case PRU_SEND: +#ifdef IPSEC + error = check_ipsec_policy(inp,0); + if (error) + return (error); +#endif + return (udp_output(m, inp, addr, control)); + + case PRU_ABORT: + soisdisconnected(so); + udp_detach(inp); + break; + + case PRU_SOCKADDR: +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + in6_setsockaddr(inp, addr); + else +#endif /* INET6 */ + in_setsockaddr(inp, addr); + break; + + case PRU_PEERADDR: +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + in6_setpeeraddr(inp, addr); + else +#endif /* INET6 */ + in_setpeeraddr(inp, addr); + break; + + case PRU_SENSE: + /* + * stat: don't bother with a blocksize. + */ + /* + * Perhaps Path MTU might be returned for a connected + * UDP socket in this case. + */ + return (0); + + case PRU_SENDOOB: + case PRU_FASTTIMO: + case PRU_SLOWTIMO: + case PRU_PROTORCV: + case PRU_PROTOSEND: + error = EOPNOTSUPP; + break; + + case PRU_RCVD: + case PRU_RCVOOB: + return (EOPNOTSUPP); /* do not free mbuf's */ + + default: + panic("udp_usrreq"); + } + +release: + if (control) { +#ifdef __ECOS + diag_printf("udp control data unexpectedly retained\n"); +#else + printf("udp control data unexpectedly retained\n"); +#endif + m_freem(control); + } + if (m) + m_freem(m); + return (error); +} + +static void +udp_detach(inp) + struct inpcb *inp; +{ + int s = splsoftnet(); + + in_pcbdetach(inp); + splx(s); +} + +#ifdef CYGPKG_NET_SYSCTL +/* + * Sysctl for udp variables. + */ +int +udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; +{ + /* All sysctl names at this level are terminal. */ + if (namelen != 1) + return (ENOTDIR); + + switch (name[0]) { + case UDPCTL_CHECKSUM: + return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum)); + case UDPCTL_BADDYNAMIC: + return (sysctl_struct(oldp, oldlenp, newp, newlen, + baddynamicports.udp, sizeof(baddynamicports.udp))); + case UDPCTL_RECVSPACE: + return (sysctl_int(oldp, oldlenp, newp, newlen,&udp_recvspace)); + case UDPCTL_SENDSPACE: + return (sysctl_int(oldp, oldlenp, newp, newlen,&udp_sendspace)); + default: + return (ENOPROTOOPT); + } + /* NOTREACHED */ +} +#endif // CYGPKG_NET_SYSCTL |