Index: sys/conf/files =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/conf/files,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/conf/files 6 Jun 2005 21:55:52 -0000 1.1.1.1 +++ sys/conf/files 7 Jun 2005 00:05:55 -0000 1.2 @@ -1509,6 +1509,11 @@ netinet/ip_input.c optional inet netinet/ip_mroute.c optional mrouting netinet/ip_output.c optional inet +netinet/datarouting.c optional inet +netinet/tlv.c optional inet +netinet/regexp.c optional inet +netinet/regsub.c optional inet +netinet/regerror.c optional inet netinet/raw_ip.c optional inet netinet/tcp_debug.c optional tcpdebug netinet/tcp_hostcache.c optional inet Index: sys/conf/options =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/conf/options,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/conf/options 6 Jun 2005 21:55:52 -0000 1.1.1.1 +++ sys/conf/options 7 Jun 2005 00:05:55 -0000 1.2 @@ -376,6 +376,9 @@ TCP_DROP_SYNFIN opt_tcp_input.h XBONEHACK +#enable data routing +DATA_ROUTING opt_datarouting.h + # Netgraph(4). Use option NETGRAPH to enable the base netgraph code. # Each netgraph node type can be either be compiled into the kernel # or loaded dynamically. To get the former, include the corresponding Index: sys/i386/conf/DR-KERNEL =================================================================== RCS file: sys/i386/conf/DR-KERNEL diff -N sys/i386/conf/DR-KERNEL --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/i386/conf/DR-KERNEL 7 Jun 2005 00:43:12 -0000 @@ -0,0 +1,260 @@ +# +# GENERIC -- Generic kernel configuration file for FreeBSD/i386 +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD: src/sys/i386/conf/GENERIC,v 1.369.2.2 2002/12/31 05:35:45 scottl Exp $ + +machine i386 +cpu I486_CPU +cpu I586_CPU +cpu I686_CPU +ident GENERIC +maxusers 0 + +#To statically compile in device wiring instead of /boot/device.hints +#hints "GENERIC.hints" #Default places to look for devices. + +#makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols + +options SCHED_4BSD #4BSD scheduler +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options FFS #Berkeley Fast Filesystem +options SOFTUPDATES #Enable FFS soft updates support +options UFS_ACL #Support for access control lists +options UFS_DIRHASH #Improve performance on big directories +options MD_ROOT #MD is a potential root device +options NFSCLIENT #Network Filesystem Client +options NFSSERVER #Network Filesystem Server +options NFS_ROOT #NFS usable as root device, requires NFSCLIENT +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options PROCFS #Process filesystem (requires PSEUDOFS) +options PSEUDOFS #Pseudo-filesystem framework +options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] +options COMPAT_FREEBSD4 #Compatible with FreeBSD4 +options SCSI_DELAY=15000 #Delay (in ms) before probing SCSI +options KTRACE #ktrace(1) support +options SYSVSHM #SYSV-style shared memory +options SYSVMSG #SYSV-style message queues +options SYSVSEM #SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options AHC_REG_PRETTY_PRINT # Print register bitfields in debug + # output. Adds ~128k to driver. +options AHD_REG_PRETTY_PRINT # Print register bitfields in debug + # output. Adds ~215k to driver. + +# Debugging for use in -current +#options DDB #Enable the kernel debugger +#options INVARIANTS #Enable calls of extra sanity checking +options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS #Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed + +# To make an SMP kernel, the next two are needed +#options SMP # Symmetric MultiProcessor Kernel +#options APIC_IO # Symmetric (APIC) I/O + +device isa +device eisa +device pci + +# Floppy drives +device fdc + +# ATA and ATAPI devices +device ata +device atadisk # ATA disk drives +device atapicd # ATAPI CDROM drives +device atapifd # ATAPI floppy drives +device atapist # ATAPI tape drives +options ATA_STATIC_ID #Static device numbering + +# SCSI Controllers +device ahb # EISA AHA1742 family +device ahc # AHA2940 and onboard AIC7xxx devices +device ahd # AHA39320/29320 and onboard AIC79xx devices +device amd # AMD 53C974 (Tekram DC-390(T)) +device isp # Qlogic family +device mpt # LSI-Logic MPT-Fusion +#device ncr # NCR/Symbios Logic +device sym # NCR/Symbios Logic (newer chipsets + those of `ncr') + +device adv # Advansys SCSI adapters +device adw # Advansys wide SCSI adapters +device aha # Adaptec 154x SCSI adapters +device aic # Adaptec 15[012]x SCSI adapters, AIC-6[23]60. +device bt # Buslogic/Mylex MultiMaster SCSI adapters + +device ncv # NCR 53C500 +device nsp # Workbit Ninja SCSI-3 +device stg # TMC 18C30/18C50 + +# RAID controllers interfaced to the SCSI subsystem +device asr # DPT SmartRAID V, VI and Adaptec SCSI RAID +device ciss # Compaq Smart RAID 5* +device dpt # DPT Smartcache III, IV - See NOTES for options! +device iir # Intel Integrated RAID +device mly # Mylex AcceleRAID/eXtremeRAID + +# SCSI peripherals +device scbus # SCSI bus (required) +device ch # SCSI media changers +device da # Direct Access (disks) +device sa # Sequential Access (tape etc) +device cd # CD +device pass # Passthrough device (direct SCSI access) +device ses # SCSI Environmental Services (and SAF-TE) + +# RAID controllers +device aac # Adaptec FSA RAID +device aacp # SCSI passthrough for aac (requires CAM) +device amr # AMI MegaRAID +device ida # Compaq Smart RAID +device mlx # Mylex DAC960 family +device pst # Promise Supertrak SX6000 +device twe # 3ware ATA RAID + +# atkbdc0 controls both the keyboard and the PS/2 mouse +device atkbdc # AT keyboard controller +device atkbd # AT keyboard +device psm # PS/2 mouse + +device vga # VGA video card driver + +device splash # Splash screen and screen saver support + +# syscons is the default console driver, resembling an SCO console +device sc + +# Enable this for the pcvt (VT220 compatible) console driver +#device vt +#options XSERVER # support for X server on a vt console +#options FAT_CURSOR # start with block cursor + +device agp # support several AGP chipsets + +# Floating point support - do not disable. +device npx + +# Power management support (see NOTES for more options) +#device apm +# Add suspend/resume support for the i8254. +device pmtimer + +# PCCARD (PCMCIA) support +# Pcmcia and cardbus bridge support +device cbb # cardbus (yenta) bridge +#device pcic # ExCA ISA and PCI bridges +device pccard # PC Card (16-bit) bus +device cardbus # CardBus (32-bit) bus + +# Serial (COM) ports +device sio # 8250, 16[45]50 based serial ports + +# Parallel port +device ppc +device ppbus # Parallel port bus (required) +device lpt # Printer +device plip # TCP/IP over parallel +device ppi # Parallel port interface device +#device vpo # Requires scbus and da + + +# PCI Ethernet NICs. +device de # DEC/Intel DC21x4x (``Tulip'') +device em # Intel PRO/1000 adapter Gigabit Ethernet Card +device txp # 3Com 3cR990 (``Typhoon'') +device vx # 3Com 3c590, 3c595 (``Vortex'') + +options DEVICE_POLLING +options HZ=1000 +options DATA_ROUTING + +# PCI Ethernet NICs that use the common MII bus controller code. +# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs! +device miibus # MII bus support +device dc # DEC/Intel 21143 and various workalikes +device fxp # Intel EtherExpress PRO/100B (82557, 82558) +device pcn # AMD Am79C97x PCI 10/100 (precedence over 'lnc') +device rl # RealTek 8129/8139 +device sf # Adaptec AIC-6915 (``Starfire'') +device sis # Silicon Integrated Systems SiS 900/SiS 7016 +device ste # Sundance ST201 (D-Link DFE-550TX) +device tl # Texas Instruments ThunderLAN +device tx # SMC EtherPower II (83c170 ``EPIC'') +device vr # VIA Rhine, Rhine II +device wb # Winbond W89C840F +device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'') +device bge # Broadcom BCM570xx Gigabit Ethernet + +# ISA Ethernet NICs. pccard nics included. +device cs # Crystal Semiconductor CS89x0 NIC +# 'device ed' requires 'device miibus' +device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards +device ex # Intel EtherExpress Pro/10 and Pro/10+ +device ep # Etherlink III based cards +device fe # Fujitsu MB8696x based cards +device lnc # NE2100, NE32-VL Lance Ethernet cards +device sn # SMC's 9000 series of ethernet chips +device xe # Xircom pccard ethernet + +# ISA devices that use the old ISA shims +#device le + +# Wireless NIC cards +#device an # Aironet 4500/4800 802.11 wireless NICs. +#device awi # BayStack 660 and others +#device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs. +#device wl # Older non 802.11 Wavelan wireless NIC. + +# Pseudo devices - the number indicates how many units to allocate. +device random # Entropy device +device loop # Network loopback +device ether # Ethernet support +device sl # Kernel SLIP +device ppp # Kernel PPP +device tun # Packet tunnel. +device pty # Pseudo-ttys (telnet etc) +device md # Memory "disks" +device gif # IPv6 and IPv4 tunneling +device faith # IPv6-to-IPv4 relaying (translation) + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +device bpf # Berkeley packet filter + +# USB support +device uhci # UHCI PCI->USB interface +device ohci # OHCI PCI->USB interface +device usb # USB Bus (required) +#device udbp # USB Double Bulk Pipe devices +device ugen # Generic +device uhid # "Human Interface Devices" +device ukbd # Keyboard +device ulpt # Printer +device umass # Disks/Mass storage - Requires scbus and da +device ums # Mouse +device urio # Diamond Rio 500 MP3 player +device uscanner # Scanners +# USB Ethernet, requires mii +device aue # ADMtek USB ethernet +device cue # CATC USB ethernet +device kue # Kawasaki LSI USB ethernet + + Index: sys/i386/conf/KERNEL-wo-DR =================================================================== RCS file: sys/i386/conf/KERNEL-wo-DR diff -N sys/i386/conf/KERNEL-wo-DR --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/i386/conf/KERNEL-wo-DR 7 Jun 2005 00:05:58 -0000 1.1 @@ -0,0 +1,261 @@ +# +# GENERIC -- Generic kernel configuration file for FreeBSD/i386 +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD: src/sys/i386/conf/GENERIC,v 1.369.2.2 2002/12/31 05:35:45 scottl Exp $ + +machine i386 +cpu I486_CPU +cpu I586_CPU +cpu I686_CPU +ident GENERIC +maxusers 0 + +#To statically compile in device wiring instead of /boot/device.hints +#hints "GENERIC.hints" #Default places to look for devices. + +#makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols + +#options SCHED_4BSD #4BSD scheduler +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options FFS #Berkeley Fast Filesystem +options SOFTUPDATES #Enable FFS soft updates support +options UFS_ACL #Support for access control lists +options UFS_DIRHASH #Improve performance on big directories +options MD_ROOT #MD is a potential root device +options NFSCLIENT #Network Filesystem Client +options NFSSERVER #Network Filesystem Server +options NFS_ROOT #NFS usable as root device, requires NFSCLIENT +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options PROCFS #Process filesystem (requires PSEUDOFS) +options PSEUDOFS #Pseudo-filesystem framework +options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] +options COMPAT_FREEBSD4 #Compatible with FreeBSD4 +options SCSI_DELAY=15000 #Delay (in ms) before probing SCSI +options KTRACE #ktrace(1) support +options SYSVSHM #SYSV-style shared memory +options SYSVMSG #SYSV-style message queues +options SYSVSEM #SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options AHC_REG_PRETTY_PRINT # Print register bitfields in debug + # output. Adds ~128k to driver. +options AHD_REG_PRETTY_PRINT # Print register bitfields in debug + # output. Adds ~215k to driver. + +# Debugging for use in -current +#options DDB #Enable the kernel debugger +#options INVARIANTS #Enable calls of extra sanity checking +options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS #Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed + +# To make an SMP kernel, the next two are needed +#options SMP # Symmetric MultiProcessor Kernel +#options APIC_IO # Symmetric (APIC) I/O + +device isa +device eisa +device pci + +# Floppy drives +device fdc + +# ATA and ATAPI devices +device ata +device atadisk # ATA disk drives +device atapicd # ATAPI CDROM drives +device atapifd # ATAPI floppy drives +device atapist # ATAPI tape drives +options ATA_STATIC_ID #Static device numbering + +# SCSI Controllers +device ahb # EISA AHA1742 family +device ahc # AHA2940 and onboard AIC7xxx devices +device ahd # AHA39320/29320 and onboard AIC79xx devices +device amd # AMD 53C974 (Tekram DC-390(T)) +device isp # Qlogic family +device mpt # LSI-Logic MPT-Fusion +#device ncr # NCR/Symbios Logic +device sym # NCR/Symbios Logic (newer chipsets + those of `ncr') + +device adv # Advansys SCSI adapters +device adw # Advansys wide SCSI adapters +device aha # Adaptec 154x SCSI adapters +device aic # Adaptec 15[012]x SCSI adapters, AIC-6[23]60. +device bt # Buslogic/Mylex MultiMaster SCSI adapters + +device ncv # NCR 53C500 +device nsp # Workbit Ninja SCSI-3 +device stg # TMC 18C30/18C50 + +# RAID controllers interfaced to the SCSI subsystem +device asr # DPT SmartRAID V, VI and Adaptec SCSI RAID +device ciss # Compaq Smart RAID 5* +device dpt # DPT Smartcache III, IV - See NOTES for options! +device iir # Intel Integrated RAID +device mly # Mylex AcceleRAID/eXtremeRAID + +# SCSI peripherals +device scbus # SCSI bus (required) +device ch # SCSI media changers +device da # Direct Access (disks) +device sa # Sequential Access (tape etc) +device cd # CD +device pass # Passthrough device (direct SCSI access) +device ses # SCSI Environmental Services (and SAF-TE) + +# RAID controllers +device aac # Adaptec FSA RAID +device aacp # SCSI passthrough for aac (requires CAM) +device amr # AMI MegaRAID +device ida # Compaq Smart RAID +device mlx # Mylex DAC960 family +device pst # Promise Supertrak SX6000 +device twe # 3ware ATA RAID + +# atkbdc0 controls both the keyboard and the PS/2 mouse +device atkbdc # AT keyboard controller +device atkbd # AT keyboard +device psm # PS/2 mouse + +device vga # VGA video card driver + +device splash # Splash screen and screen saver support + +# syscons is the default console driver, resembling an SCO console +device sc + +# Enable this for the pcvt (VT220 compatible) console driver +#device vt +#options XSERVER # support for X server on a vt console +#options FAT_CURSOR # start with block cursor + +device agp # support several AGP chipsets + +# Floating point support - do not disable. +device npx + +# Power management support (see NOTES for more options) +#device apm +# Add suspend/resume support for the i8254. +device pmtimer + +# PCCARD (PCMCIA) support +# Pcmcia and cardbus bridge support +device cbb # cardbus (yenta) bridge +#device pcic # ExCA ISA and PCI bridges +device pccard # PC Card (16-bit) bus +device cardbus # CardBus (32-bit) bus + +# Serial (COM) ports +device sio # 8250, 16[45]50 based serial ports + +# Parallel port +device ppc +device ppbus # Parallel port bus (required) +device lpt # Printer +device plip # TCP/IP over parallel +device ppi # Parallel port interface device +#device vpo # Requires scbus and da + + +# PCI Ethernet NICs. +device de # DEC/Intel DC21x4x (``Tulip'') +device em # Intel PRO/1000 adapter Gigabit Ethernet Card +device txp # 3Com 3cR990 (``Typhoon'') +device vx # 3Com 3c590, 3c595 (``Vortex'') + +# VENKATA +options DEVICE_POLLING +options HZ=10000 +#options DATA_ROUTING + +# PCI Ethernet NICs that use the common MII bus controller code. +# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs! +device miibus # MII bus support +device dc # DEC/Intel 21143 and various workalikes +device fxp # Intel EtherExpress PRO/100B (82557, 82558) +device pcn # AMD Am79C97x PCI 10/100 (precedence over 'lnc') +device rl # RealTek 8129/8139 +device sf # Adaptec AIC-6915 (``Starfire'') +device sis # Silicon Integrated Systems SiS 900/SiS 7016 +device ste # Sundance ST201 (D-Link DFE-550TX) +device tl # Texas Instruments ThunderLAN +device tx # SMC EtherPower II (83c170 ``EPIC'') +device vr # VIA Rhine, Rhine II +device wb # Winbond W89C840F +device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'') +device bge # Broadcom BCM570xx Gigabit Ethernet + +# ISA Ethernet NICs. pccard nics included. +device cs # Crystal Semiconductor CS89x0 NIC +# 'device ed' requires 'device miibus' +device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards +device ex # Intel EtherExpress Pro/10 and Pro/10+ +device ep # Etherlink III based cards +device fe # Fujitsu MB8696x based cards +device lnc # NE2100, NE32-VL Lance Ethernet cards +device sn # SMC's 9000 series of ethernet chips +device xe # Xircom pccard ethernet + +# ISA devices that use the old ISA shims +#device le + +# Wireless NIC cards +#device an # Aironet 4500/4800 802.11 wireless NICs. +#device awi # BayStack 660 and others +#device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs. +#device wl # Older non 802.11 Wavelan wireless NIC. + +# Pseudo devices - the number indicates how many units to allocate. +device random # Entropy device +device loop # Network loopback +device ether # Ethernet support +device sl # Kernel SLIP +device ppp # Kernel PPP +device tun # Packet tunnel. +device pty # Pseudo-ttys (telnet etc) +device md # Memory "disks" +device gif # IPv6 and IPv4 tunneling +device faith # IPv6-to-IPv4 relaying (translation) + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +device bpf # Berkeley packet filter + +# USB support +device uhci # UHCI PCI->USB interface +device ohci # OHCI PCI->USB interface +device usb # USB Bus (required) +#device udbp # USB Double Bulk Pipe devices +device ugen # Generic +device uhid # "Human Interface Devices" +device ukbd # Keyboard +device ulpt # Printer +device umass # Disks/Mass storage - Requires scbus and da +device ums # Mouse +device urio # Diamond Rio 500 MP3 player +device uscanner # Scanners +# USB Ethernet, requires mii +device aue # ADMtek USB ethernet +device cue # CATC USB ethernet +device kue # Kawasaki LSI USB ethernet + + Index: sys/netinet/datarouting.c =================================================================== RCS file: sys/netinet/datarouting.c diff -N sys/netinet/datarouting.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/datarouting.c 7 Jun 2005 00:40:18 -0000 1.2 @@ -0,0 +1,500 @@ + +/* + * Notes: + * This is the primary datarouting processing file. Here a tag is presented + * and a nexthop is expected to be returned. The tag type is looked at + * and the appropriate table is processed. In the first version, there is + * only one unified table. Later versions will have multiple tables. + * + * XXX: The next generation of the datarouting table will have to + * (1) take a replacement array i.e., a single tag can be replaced + * by a tag array. + * (2) there should be multiple nexthops to support multicast. + * - the droute command should be extended accordingly. + * (3) should we do away with tlvs? - i think they are ok because + * you can then define templates for the table entries. + * (4) make this table template based. have a new command that + * creates a table and naming it before adding new entries + * for the same. + * (5) all these functions should be function pointers instead + * of functions to be able to reuse existing library of + * implementations. + * (6) there would be default brute-force search function + * that will always be supported. any optimizations can + * loaded later on. + * + */ +#include "opt_datarouting.h" + +#ifdef DATA_ROUTING + +#include +#include +#include +#include +#include + +#ifdef _KERNEL +#undef PRINT2 +#define PRINT2(x, y) log(LOG_INFO, x, y) +#endif + +extern int alloc_count; +drt_stats mystats = {0, 0, 0}; + +/* TODO: convert this into a several tables indexed by the class and +using different kinds of matchings -- exact, longest matching prefix, +substring? */ + +/* + ======================================================================== + Manipulate the routing table + ======================================================================== +*/ + +uint32_t drcurrent = 0; +drtable_t drtable[MAX_TABLE_ENTRIES]; + +/* + * Initialize the datarouting table. Right now we can store about 1024 + * entries. + * + * XXX: Only allocate a meta array or tables. Tables will be instantiated + * and destroyed using a command + */ +void data_route_init( void) { + + PRINT2("data_route_init %d \n", 0); + drcurrent = 0; + memset(drtable, '\0', sizeof(drtable)); + +} + +/* + * This is a generic add entry function. It takes in a tlv as index. It + * also supports a replacement tag. + * + */ + +uint32_t add_entry_drtable(tlv *in, uint32_t next_hop, tlv *replacement){ + + uint32_t i, is_update = 0; + int len = 0; + + if (drcurrent < 0) return ENXIO; + if (drcurrent > MAX_TABLE_ENTRIES) return ENOSPC; + if ( !in) return EINVAL; + + /* replacement could be null */ + + /* check for duplicate entries */ + for (i = 0; i < drcurrent; i++) { + if (tlv_match(in, drtable[i].id, DRT_MATCH_EXACT, &len)) { + /* exact or overlap will be chosen by the */ + drtable[i].next_hop = next_hop; + if (drtable[i].replacement) { + TLVFREE(drtable[i].replacement, ALLOC_LONGTERM); + } + drtable[i].replacement = replacement; + is_update = 1; + break; + } + }; + + if (!is_update){ + /* doesnt exist */ + drtable[drcurrent].id = in; + drtable[drcurrent].next_hop = next_hop; + drtable[drcurrent].replacement = replacement; + drcurrent++; + } else { + if (drtable[drcurrent].id) + TLVFREE(in, ALLOC_LONGTERM); + } + + /*print_drtable(); */ + return 0; +} + +/* + * Look at the add entry function. The same will have to be applied + * here too. + */ +uint32_t delete_entry_drtable(tlv *in){ + uint32_t i; + int len = 0; + + if (0) PRINT2("delete_entry_drtable %d \n", 0); + if (drcurrent <= 0 || drcurrent > MAX_TABLE_ENTRIES) + return EINVAL; + + /* check for duplicate entries */ + for (i = 0; i < drcurrent; i++) { + if (tlv_match(in, drtable[i].id, DRT_MATCH_EXACT, &len)){ + int to = i, from = i+1; + + TLVFREE(drtable[i].id, ALLOC_LONGTERM); + if (drtable[i].replacement) + TLVFREE(drtable[i].replacement, ALLOC_LONGTERM); + + for (; from < drcurrent; from++, to++){ + drtable[to].id = drtable[from].id; + drtable[to].next_hop = drtable[from].next_hop; + drtable[to].replacement = drtable[from].replacement; + } + drcurrent--; + } + } + + /*print_drtable();*/ + + /* couldnt find the entry i was looking for */ + return 0; +} + +uint32_t lookup_drtable(tlv *id, uint32_t *nexthop, tlv **replacement){ + int i; + int len; + + mystats.lookups++; + + if (drcurrent < 0 || drcurrent > MAX_TABLE_ENTRIES || !id || !nexthop) + return 0; + + /* no check for replacement here */ + + if (id->base.match == DRT_MATCH_EXACT || id->base.match == DRT_MATCH_RANGE){ + + for (i = 0; i < drcurrent; i++) { + if (1) { + log(LOG_INFO, "Looking at index %d id = ", i); + tlv_print(drtable[i].id); + log(LOG_INFO, "\n"); + } + if (tlv_match(id, drtable[i].id, id->base.match, &len)){ + struct in_addr nh; + nh.s_addr = drtable[i].next_hop; + if (1) { + log(LOG_INFO, "data_routing: FOUND nexthop for " ); + tlv_print(id); + PRINT2("%s\n", inet_ntoa(nh)); + } + + mystats.succ_lookups++; + *nexthop = drtable[i].next_hop; + if (replacement){ + *replacement = NULL; + if (drtable[i].replacement) { + if (drtable[i].replacement->base.returnflag == DRT_RETURNFLAG_MATCH){ + *replacement = drtable[i].replacement; + } else if (drtable[i].replacement->base.returnflag == DRT_RETURNFLAG_INPUT){ + *replacement = id; + } + } + } /* if replacement exists */ + return 1; /* success */ + } /* if tlv_match...*/ + } /* for i = ...*/ + + } else if (id->base.match == DRT_MATCH_LONGEST){ + + uint32_t score = 0, temp = 0, index =0 ; + for (i = 0; i < drcurrent; i++) { + tlv_match(id, drtable[i].id, DRT_MATCH_LONGEST, &temp); + if (0) { + log(LOG_INFO,"score of " ); + tlv_print(drtable[i].id); + log(LOG_INFO,"is %d \n", temp); + } + if (temp > 0 && temp > score){ + score = temp; + index = i; + } + } + + if (score > 0) { + struct in_addr nh; + nh.s_addr = drtable[index].next_hop; + + if (1){ + PRINT2("data_routing: FOUND nexthop for %d ", 1); + tlv_print(id); + PRINT2("%s\n", inet_ntoa(nh)); + } + + mystats.succ_lookups++; + *nexthop = drtable[index].next_hop; + if (replacement){ + if (drtable[index].replacement) { + *replacement = NULL; + if (drtable[index].replacement->base.returnflag == DRT_RETURNFLAG_MATCH){ + *replacement = drtable[index].replacement; + } else if (drtable[index].replacement->base.returnflag == DRT_RETURNFLAG_INPUT){ + *replacement = id; + }; + } /* replacement exists */ + } /* if replacement is needed */ + return 1; /* success */ + } + } + + if (1) { + PRINT2("data_routing: NOT FOUND nexthop for %d ", 1); + tlv_print(id); + } + return 0; +} + +void print_drtable(){ + uint32_t i; + struct in_addr dummy; + + log(LOG_INFO, " ****** DATA ROUTING TABLE ******* \n"); + for (i = 0; i < drcurrent; i++) { + PRINT2("[%d\t", i); + tlv_print(drtable[i].id); + + dummy.s_addr = drtable[i].next_hop; + PRINT2("\t%s ", inet_ntoa(dummy)); + tlv_print(drtable[i].replacement); + PRINT2("]%s\n",""); + } +} + +uint32_t dump(struct sysctl_req *req){ + uint32_t i, *p = 0, bytes; + char *buf; + + log(LOG_INFO, "dump: drtable = %x drcurrent = %d req = %x \n", + (uint32_t)drtable, (uint32_t) drcurrent, (uint32_t)req ); + if (!drtable) return EINVAL; + print_drtable(); + + for (i = 0; i < drcurrent; i++) { + int size = 8 ; + + log(LOG_INFO, "%d id = %x replacement = %x \n", + i, (uint32_t)drtable[i].id, (uint32_t)drtable[i].replacement); + + if ( !drtable[i].id) return EINVAL; + size += tlv_serialized_size(drtable[i].id); + + if (drtable[i].replacement) + size += tlv_serialized_size(drtable[i].replacement); + + buf = (char *)malloc(size, M_RTABLE, M_NOWAIT); + if (!buf) return ENOMEM; + + memset(buf, '\0', size); + p = (uint32_t *)buf; + *p++ = htonl(size); + *p++ = drtable[i].next_hop; + bytes = tlv_serialize(drtable[i].id, (char *)p, (size - 8)); + p += (bytes >> 2); + + if (drtable[i].replacement) { + bytes = tlv_serialize(drtable[i].replacement, + (char *)p, + (size - (8 + bytes))); + } + log(LOG_INFO, "called sysctl_out size = %d \n", size); + SYSCTL_OUT(req, buf, size); + } + + return 0; +} + +uint32_t flush(){ + int i; + for (i = 0; i < drcurrent; i++) { + free(drtable[i].id, M_RTABLE); + if (drtable[i].replacement) + free(drtable[i].replacement, M_RTABLE); + } + memset(drtable, '\0', sizeof(drtable)); + drcurrent = 0; + return 0; +} + +/* + ======================================================================== + User Interface + ======================================================================== +*/ + +/* + * This is the user interface. The route add, delete, dump etc. come + * in the form of sysctls from the user space. Entries will have + * to start looking like + */ + +static int +sysctl_drt(SYSCTL_HANDLER_ARGS) +{ + int *name = (int *)arg1; + u_int namelen = arg2; + int error = 0; + int s; + drt_msghdr drtm; + static char buf[1024]; + uint32_t *p, bytes, size; + + name ++; + namelen--; + if (namelen != 3) + return (EINVAL); + + s = splnet(); + switch (name[1]) { + case NET_DRT_UPDATE: + case NET_DRT_ADD: + + /* this is peeking into the request structure. FIX ME */ + size = req->newlen - req->newidx; + if (0) + log(LOG_INFO, "req->newlen = %d req->newidx = %d len = %d \n", + req->newlen, req->newidx, 1024 ); + + error = SYSCTL_IN(req, buf, size); + if (error > 0) { + log(LOG_INFO, "could not read in data"); + return EINVAL; + } + + p = (uint32_t *)buf; + drtm.drtm_len = ntohl(*p++); + drtm.drtm_nexthop = *p++; + drtm.drtm_match = drtm.drtm_replacement = 0; + + bytes = tlv_unserialize((tlv **)&drtm.drtm_match, + buf + 8, + (drtm.drtm_len - 8), + ALLOC_LONGTERM); + + if ( drtm.drtm_len > (8 + bytes)){ + /* replacement has been specified */ + bytes = tlv_unserialize((tlv **)&drtm.drtm_replacement, + buf + 8 + bytes, + (drtm.drtm_len - (8 + bytes)), + ALLOC_LONGTERM); + } + + if (0){ + log(LOG_INFO, + " from sysctl_drt len = %d nexthost = %x", + drtm.drtm_len, drtm.drtm_nexthop ); + tlv_print(drtm.drtm_match); + tlv_print(drtm.drtm_replacement); + } + error = + add_entry_drtable(drtm.drtm_match, + drtm.drtm_nexthop, + drtm.drtm_replacement); + + if (error){ + TLVFREE(drtm.drtm_match, ALLOC_LONGTERM); + if (drtm.drtm_replacement) + TLVFREE(drtm.drtm_replacement, ALLOC_LONGTERM); + } + break; + + case NET_DRT_DUMP: + error = dump(req); + break; + case NET_DRT_FLUSH: + error = flush(); + break; + case NET_DRT_DEL: + size = req->newlen - req->newidx; + SYSCTL_IN(req, buf, size); + p = (uint32_t *)buf; + drtm.drtm_len = ntohl(*p++); + drtm.drtm_nexthop = *p++; + + bytes = tlv_unserialize((tlv **)&drtm.drtm_match, + buf + 8, + drtm.drtm_len - 8, + ALLOC_SHORTTERM); + + error = delete_entry_drtable(drtm.drtm_match); + TLVFREE(drtm.drtm_match, ALLOC_SHORTTERM); + break; + + default: + error = EOPNOTSUPP; + break; + } + splx(s); + return (error); +} + +SYSCTL_NODE(_net, PF_DATAROUTE, dataroutetable, CTLFLAG_RW, sysctl_drt, + "Data Routing Table"); + +int enable_modified_tcb = 0; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, enable_modified_tcb, CTLFLAG_RW, + &enable_modified_tcb , 0, "Enable Modified TCB for Data Routing"); + + +int enable_route_stats = 0; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, enable_route_stats, CTLFLAG_RW, + &enable_route_stats , 0, "Enable collection of statistics"); + + +/* + ======================================================================== + Statistics + ======================================================================== +*/ + +/* + * The following two functions will be called when it is detected + * that datarouter packet is observed/processed. + */ +void drt_note_begin(){ +} + +void drt_note_end(){ + mystats.numpkts++; + return; +} + +/* + * Gather and return the stats. Right now we support only simple stats. + */ + +static int +sysctl_route_stats(SYSCTL_HANDLER_ARGS) +{ + + int size = 16; + char *buf; + uint32_t *p; + + if (0) log(LOG_INFO, "Printing route stats"); + + buf = (char *)malloc(size, M_RTABLE, M_NOWAIT); + if (!buf) return ENOMEM; + memset(buf, '\0', size); + p = (uint32_t *)buf; + *p++ = htonl(mystats.numpkts); + *p++ = htonl(mystats.lookups); + *p++ = htonl(mystats.succ_lookups); + *p++ = htonl(alloc_count); + SYSCTL_OUT(req, buf, size); + + free(buf, M_RTABLE); + + return 0; +} + + +/* + * Show some useful stats through the printstats. May be it should be + * called dstats + */ + +SYSCTL_NODE(_net_inet_tcp, OID_AUTO, routestats, CTLFLAG_RD, + sysctl_route_stats,"Routing Statistics"); + +#endif Index: sys/netinet/datarouting.h =================================================================== RCS file: sys/netinet/datarouting.h diff -N sys/netinet/datarouting.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/datarouting.h 7 Jun 2005 00:06:02 -0000 1.1 @@ -0,0 +1,134 @@ +#ifdef _KERNEL +#include "opt_datarouting.h" +#endif + +#ifdef DATA_ROUTING +#ifdef _KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#endif + +#include + +#include + +/* how is the ditribution of the various field members? */ +/* this needs fixing because class should be 1 byte, match should be 1 + byte and there should be a TLV covering the hash */ +/* + + DSRR Option + =========== + + +--------------+--------------+ + | NOP | DSRR | optlen| off | + +--------------+--------------+ + : : + : TAG : + : : + +-----------------------------+ + : : + : TAG : + : : + +-----------------------------+ + : : + + + +--------------+--------------+ + | HASH | MATCH | LEN | 0 | + +--------------+--------------+ + | hash-val | + +-----------------------------+ + + + +--------------+--------------+ + | DOMAIN| MATCH| LEN | 0 | + +--------------+--------------+ + : : + : string : + +-----------------------------+ + +*/ + +#define DR_OFFSET_MATCH 0 +#define DR_OFFSET_RET 2 +#define DR_OFFSET_CLASS 4 +#define DR_OFFSET_LEN 6 +#define DR_OFFSET_HASH 8 + + +/* + DSRR option type: Length + ================================= + NOP 1 byte + OP 1 byte + OLEN 1 byte + OFFSET 1 byte + FIRST HOP IP ADDRESS 4 byte + CLASS 2 bytes? + MATCH 2 bytes? + TLV +*/ + +#ifdef _KERNEL + +uint32_t lookup_drtable(tlv *tomatch, uint32_t *nexthop, tlv **replacement); +uint32_t add_entry_drtable(tlv *match, uint32_t next_hop, tlv *replacement); +uint32_t delete_entry_drtable(tlv *in); +void print_drtable(void); +uint32_t dump(struct sysctl_req *req); +uint32_t flush(void); +void data_route_init( void); +extern + int enable_modified_tcb; +#endif + +typedef struct { + uint32_t drtm_len; + uint32_t drtm_nexthop; + tlv *drtm_match; + tlv *drtm_replacement; +} drt_msghdr; + +typedef struct { + uint32_t numpkts; + uint32_t lookups; + uint32_t succ_lookups; +} drt_stats; + +extern int enable_route_stats; +void drt_note_begin(void); +void drt_note_end(void); + +/* table of entries */ +typedef struct { + tlv *id; + uint32_t next_hop; + tlv *replacement; +} drtable_t; + +#define MAX_TABLE_ENTRIES 1024 +#define MAX_REGEX_LEN 20 + +#endif + Index: sys/netinet/in.h =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/in.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/in.h 6 Jun 2005 21:58:15 -0000 1.1.1.1 +++ sys/netinet/in.h 7 Jun 2005 00:06:02 -0000 1.2 @@ -533,7 +533,10 @@ #define IPCTL_FASTFORWARDING 14 /* use fast IP forwarding code */ #define IPCTL_KEEPFAITH 15 /* FAITH IPv4->IPv6 translater ctl */ #define IPCTL_GIF_TTL 16 /* default TTL for gif encap packet */ -#define IPCTL_MAXID 17 +/* #define IPCTL_MAXID 17*/ +#define IPCTL_DATAROUTE 17 +#define IPCTL_ACCEPTDATAROUTE 18 +#define IPCTL_MAXID 19 #define IPCTL_NAMES { \ { 0, 0 }, \ @@ -551,6 +554,10 @@ { "stats", CTLTYPE_STRUCT }, \ { "accept_sourceroute", CTLTYPE_INT }, \ { "fastforwarding", CTLTYPE_INT }, \ + { "keep_faith", CTLTYPE_INT }, \ + { "gif_ttl", CTLTYPE_INT }, \ + { "dataroute", CTLTYPE_INT }, \ + { "acceptdataroute", CTLTYPE_INT }, \ } #endif /* __BSD_VISIBLE */ Index: sys/netinet/in_pcb.c =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/in_pcb.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/in_pcb.c 6 Jun 2005 21:58:15 -0000 1.1.1.1 +++ sys/netinet/in_pcb.c 7 Jun 2005 00:06:02 -0000 1.2 @@ -33,6 +33,7 @@ #include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_mac.h" +#include "opt_datarouting.h" #include #include @@ -54,6 +55,7 @@ #include #include +#include #include #include #include @@ -71,6 +73,7 @@ #include #endif /* IPSEC */ + #ifdef FAST_IPSEC #if defined(IPSEC) || defined(IPSEC_ESP) #error "Bad idea: don't compile with both IPSEC and FAST_IPSEC!" @@ -236,6 +239,7 @@ INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo); INP_LOCK_ASSERT(inp); + if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY) return (EINVAL); anonport = inp->inp_lport == 0 && (nam == NULL || @@ -251,6 +255,7 @@ } if (anonport) inp->inp_flags |= INP_ANONPORT; + return (0); } @@ -470,6 +475,7 @@ return (EINVAL); *laddrp = laddr.s_addr; *lportp = lport; + return (0); } @@ -494,6 +500,7 @@ lport = inp->inp_lport; laddr = inp->inp_laddr.s_addr; + anonport = (lport == 0); error = in_pcbconnect_setup(inp, nam, &laddr, &lport, &faddr, &fport, NULL, cred); @@ -679,6 +686,7 @@ *lportp = lport; *faddrp = faddr.s_addr; *fportp = fport; + return (0); } @@ -781,6 +789,7 @@ splx(s); *nam = in_sockaddr(port, &addr); + return 0; } @@ -1128,6 +1137,7 @@ inp->inp_phd = phd; LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist); LIST_INSERT_HEAD(pcbhash, inp, inp_hash); + return (0); } @@ -1159,6 +1169,7 @@ LIST_REMOVE(inp, inp_hash); LIST_INSERT_HEAD(head, inp, inp_hash); + } /* Index: sys/netinet/ip.h =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/ip.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/ip.h 6 Jun 2005 21:58:15 -0000 1.1.1.1 +++ sys/netinet/ip.h 7 Jun 2005 00:06:02 -0000 1.2 @@ -131,6 +131,7 @@ #define IPOPT_CIPSO 134 /* commerical security */ #define IPOPT_SATID 136 /* satnet id */ #define IPOPT_SSRR 137 /* strict source route */ +#define IPOPT_DSRR 138 /* data source route */ #define IPOPT_RA 148 /* router alert */ /* Index: sys/netinet/ip_input.c =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/ip_input.c,v retrieving revision 1.1.1.1 retrieving revision 1.6 diff -u -r1.1.1.1 -r1.6 --- sys/netinet/ip_input.c 6 Jun 2005 21:58:15 -0000 1.1.1.1 +++ sys/netinet/ip_input.c 7 Jun 2005 00:38:46 -0000 1.6 @@ -36,6 +36,7 @@ #include "opt_ipsec.h" #include "opt_mac.h" #include "opt_carp.h" +#include "opt_datarouting.h" #include #include @@ -77,6 +78,13 @@ #include #include +#ifdef DATA_ROUTING +/* #define PRINT2(x, y) log(LOG_INFO, x, y) */ +#define PRINT2(x, y) +#include +#endif + + #ifdef IPSEC #include #include @@ -140,6 +148,18 @@ &ip_do_randomid, 0, "Assign random ip_id values"); +#ifdef DATA_ROUTING +static int ip_dodataroute = 0; +SYSCTL_INT(_net_inet_ip, IPCTL_DATAROUTE, dataroute, CTLFLAG_RW, + &ip_dodataroute, 0, "Enable forwarding data routed IP packets"); + +static int ip_acceptdataroute = 0; +SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTDATAROUTE, accept_dataroute, + CTLFLAG_RW, &ip_acceptdataroute, 0, + "Enable accepting data routed IP packets"); + +#endif + /* * XXX - Setting ip_checkinterface mostly implements the receive side of * the Strong ES model described in RFC 1122, but since the routing table @@ -325,8 +345,17 @@ int s, error; #endif /* FAST_IPSEC */ +#ifdef DATA_ROUTING + int drpacket = 0; +#endif + M_ASSERTPKTHDR(m); - + +#ifdef DATA_ROUTING + if (enable_route_stats) + drt_note_begin(); +#endif + if (m->m_flags & M_FASTFWD_OURS) { /* * Firewall or NAT changed destination to local. @@ -369,6 +398,11 @@ ip = mtod(m, struct ip *); } +#ifdef DATA_ROUTING + if (hlen > sizeof (struct ip) ){ + drpacket = 1; + } +#endif /* 127/8 must not appear on wire - RFC1122 */ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { @@ -398,6 +432,11 @@ return; #endif +#ifdef DATA_ROUTING + if (drpacket){ + printf("Came here 1 \n"); + } +#endif /* * Convert fields to host representation. */ @@ -512,6 +551,11 @@ (m->m_flags & (M_MCAST|M_BCAST)) == 0) goto ours; +#ifdef DATA_ROUTING + if (drpacket){ + printf("Came here 2 \n"); + } +#endif /* * Enable a consistency check between the destination address * and the arrival interface for a unicast packet (the RFC 1122 @@ -768,6 +812,7 @@ } #endif /* FAST_IPSEC */ + /* * Switch out to protocol's input routine. */ @@ -776,6 +821,11 @@ (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); return; bad: +#ifdef DATA_ROUTING + if (drpacket){ + printf("dropping packet \n"); + } +#endif m_freem(m); } @@ -1199,11 +1249,17 @@ struct ip *ip = mtod(m, struct ip *); u_char *cp; struct in_ifaddr *ia; - int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; + int opt, optlen = 0, cnt, off, code =0, type = ICMP_PARAMPROB, forward = 0; struct in_addr *sin, dst; n_time ntime; struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; +#ifdef DATA_ROUTING + u_char dr_opt_length = 0; + u_char dr_replacement_length = 0; + tlv *replacement = NULL; +#endif + /* ignore or reject packets with IP options */ if (ip_doopts == 0) return 0; @@ -1247,8 +1303,22 @@ * component. If strictly routed make sure next * address is on directly accessible net. */ +#ifdef DATA_ROUTING + case IPOPT_DSRR: +#endif case IPOPT_LSRR: case IPOPT_SSRR: +#ifdef DATA_ROUTING + if (1){ + int i = 0, pktlen = cp[IPOPT_OLEN]; + printf("\"pktlen = %d \"\n ", pktlen); + for (i= 0; i< pktlen; i++) { + log( LOG_INFO, "%x:", cp[i]); + } + printf("\"dst = %s\"\n ", inet_ntoa(ip->ip_dst)); + } + +#endif #ifdef IPSTEALTH if (ipstealth && pass > 0) break; @@ -1278,6 +1348,36 @@ */ break; } +#ifdef DATA_ROUTING + if (opt == IPOPT_DSRR) { + /* look at the datarouting.h for the + structure of the option. the tricky part is + figuring out when to end a data source + route -- check if the packet must be + received + */ + + /* accept if we have exceeded the length of the + * source route + */ + off--; + if (off > optlen - 8 /* min DR tag size*/){ + if (!ip_acceptdataroute) + goto nosourcerouting; + /* convert the flag to a source route */ + if (1) + log(LOG_INFO, "%s%s", + "accepting data route.", + "saving the option\n"); + cp[IPOPT_OPTVAL] = IPOPT_LSRR; + save_rte(m, cp, ip->ip_src); + break; + } + } else { /* opt == DSRR */ + /* have already saved the rte -- so dont bother. */ + /* source route - non-DSRR */ + +#endif off--; /* 0 origin */ if (off > optlen - (int)sizeof(struct in_addr)) { /* @@ -1288,6 +1388,10 @@ save_rte(m, cp, ip->ip_src); break; } +#ifdef DATA_ROUTING + } /* end opt == DSRR */ +#endif + #ifdef IPSTEALTH if (ipstealth) goto dropit; @@ -1300,9 +1404,9 @@ */ nosourcerouting: strcpy(buf, inet_ntoa(ip->ip_dst)); - log(LOG_WARNING, - "attempted source route from %s to %s\n", - inet_ntoa(ip->ip_src), buf); + /*log(LOG_WARNING, + "attempted source route from %s to %s\n", + inet_ntoa(ip->ip_src), buf);*/ type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; @@ -1319,11 +1423,67 @@ } } +#ifdef DATA_ROUTING + + /* before you forward update the next hop to + value returned by datarouter lookup */ + + if (opt == IPOPT_DSRR) { + + /* compute the next hop */ + u_char *loc; + uint32_t nexthop; + tlv *in = NULL; + + /* cp = base_addr + 1 + total length = cp[IPOPT_OFFSET + 1 + off = cp[IPOPT_OFFSET] - 1 + */ + loc = cp + off; + if ((uint32_t)loc & 0x3) + goto bad; + + tlv_unserialize((tlv **)&in, + /* unserialize from here */ + loc, + /* off has already been dec by 1 + 3b header + 4b match/ret */ + optlen - off, + ALLOC_SHORTTERM); + if (!in) { goto bad; } + + if (! lookup_drtable(in, &nexthop, &replacement) || + ! nexthop){ + TLVFREE(in, ALLOC_SHORTTERM); + type = ICMP_UNREACH; + code = ICMP_UNREACH_SRCFAIL; + goto bad; + } else { + TLVFREE(in, ALLOC_SHORTTERM); + } + + dr_opt_length = tlv_serialized_size(in); + dr_replacement_length = + tlv_serialized_size(replacement); + + /* next hop cannot be zero because if it were + it would have already got delivered by now */ + (void)memcpy(&ipaddr.sin_addr, &nexthop, + sizeof(ipaddr.sin_addr)); + + + } else { +#endif /* * locate outgoing interface */ (void)memcpy(&ipaddr.sin_addr, cp + off, sizeof(ipaddr.sin_addr)); +#ifdef DATA_ROUTING + } /* finished replacing next hop by value returned + by Data Router table lookup. + */ +#endif if (opt == IPOPT_SSRR) { #define INA struct in_ifaddr * @@ -1338,9 +1498,152 @@ goto bad; } ip->ip_dst = ipaddr.sin_addr; + (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), - sizeof(struct in_addr)); + sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); + + +#ifdef DATA_ROUTING + if (opt == IPOPT_DSRR){ + + + + /* there are two possibilities here - the + length of the ip address of this node + + the length of the replacement */ + + if ( (4 /* ip address */ + dr_replacement_length) + <= dr_opt_length){ + + /* + dr_opt_len optlen + |-------------|-----------| + off + |----|-----|------------| + IP replacement optlen-decrease + (dr_replacement_length) + */ + + u_int decrease = + dr_opt_length - (dr_replacement_length + 4); + + /* The option now has an ip address at off + * datarouter now has to do some surgery + * because data router option may be + * longer than 4 bytes + */ + + if (replacement) { + tlv_serialize(replacement, + cp + off + 4, + dr_opt_length /* this is + the max*/ + ); + } + + + if ( decrease > 0) { + /* reduce the size only if necessary */ + memcpy(cp + off + 4 + dr_replacement_length, + /* dst - beginning of the option + * 4 bytes IP address + */ + cp + off + dr_opt_length, + /* src - beginning of the + next option */ + optlen - (off + dr_opt_length) + /* how many left?*/ + ); + + } + + /* set the last few bits to 1 */ + memset((cp + optlen - decrease), '\1', decrease); + cp[IPOPT_OLEN] -= (dr_opt_length - 4); + + /* remove from the header len */ + /* ip->ip_hl -= (decrease >> 2); */ + /* m->m_len -= decrease; */ + /* we are not decreasing the length because we + are filling the space with nops */ + + } else { /* increase or decrease? */ + + int i; + struct mbuf *n; + u_int increase = + dr_replacement_length + 4 - dr_opt_length; + + if (optlen + increase > 40) { + /* need to write something here */ + /* we cannot support this */ + goto bad; + } + + /* create space in the middle of the mbuf + to add the replacement tag + */ + n = m_split(m, (ip->ip_hl << 2), M_DONTWAIT); + if (n == NULL) { /* m is retained by m_split */ + goto bad; + } + + /* make n writable so that you can separate it + from m - much like copy on write */ + if (!M_WRITABLE(n) + && (n = m_pullup(n, 1)) == NULL) + return (ENOBUFS); + + /* create space in the first mbuf */ + m->m_len += increase; + m->m_pkthdr.len += increase; + ip->ip_hl += (increase >> 2); + + /* + dr_opt_len optlen + |-------------|-----------| + off + |----|---------------|----------| + IP replacement optlen+increase + + */ + + for (i=optlen ; i > (off + dr_opt_length); i--){ + cp[i+increase] = cp[i]; + } + + tlv_serialize + (replacement, cp + off + 4, dr_replacement_length); + + cp[IPOPT_OLEN] += increase; + + /* m_cat does not update m_pkthdr.len */ + m_cat(m, n); + m_fixhdr(m); + m = m_pullup(m, m->m_pkthdr.len); + + } /* increase/decrease the tag based on the rules */ + + + if (1){ + /* printouts to capture the result option + processing */ + log(LOG_INFO, "ip_dooptions: after everythingn\n"); + if (1){ + int i = 0, pktlen = cp[IPOPT_OLEN]; + printf("\"pktlen = %d \"\n ", pktlen); + for (i= 0; i< pktlen; i++) { + log( LOG_INFO, "%x:", cp[i]); + } + log(LOG_INFO, "\"dst = %s\"\n", inet_ntoa(ip->ip_dst)); + } + } /* debug message */ + } /* DSRR */ + + +#endif + /* * Let ip_intr's mcast routing check handle mcast pkts */ @@ -1513,6 +1816,10 @@ if (ipprintfs) printf("save_rte: olen %d\n", olen); #endif +#ifdef DATA_ROUTING + printf("save_rte: olen = %d ipsrcrt size = %d dest = %x \n", + olen, sizeof(opts->ip_srcrt), dst.s_addr); +#endif if (olen > sizeof(opts->ip_srcrt) - (1 + sizeof(dst))) return; bcopy(option, opts->ip_srcrt.srcopt, olen); @@ -1543,7 +1850,10 @@ m = m_get(M_DONTWAIT, MT_HEADER); if (m == NULL) return (NULL); - +#ifdef DATA_ROUTING + if ((unsigned char) opts->ip_srcrt.srcopt[IPOPT_OPTVAL] != + IPOPT_DSRR) { +#endif #define OPTSIZ (sizeof(opts->ip_srcrt.nop) + sizeof(opts->ip_srcrt.srcopt)) /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */ @@ -1554,6 +1864,9 @@ printf("ip_srcroute: nhops %d mlen %d", opts->ip_nhops, m->m_len); #endif + if (0) + printf("VENK ip_srcroute: nhops %d mlen %d", opts->ip_nhops, m->m_len); + /* * First save first hop for return route */ @@ -1563,6 +1876,8 @@ if (ipprintfs) printf(" hops %lx", (u_long)ntohl(mtod(m, struct in_addr *)->s_addr)); #endif + if (0) + printf("VENK hops %lx \n", (u_long)ntohl(mtod(m, struct in_addr *)->s_addr)); /* * Copy option fields and padding (nop) to mbuf. @@ -1593,6 +1908,29 @@ if (ipprintfs) printf(" %lx\n", (u_long)ntohl(q->s_addr)); #endif +#ifdef DATA_ROUTING + + /* basically ignore the complete portion above which has + to do with address sequence manipulation. */ + } else { + + /* data source route option */ + /* length is (nhops+1)*sizeof(addr) + + sizeof(nop + srcrt header) */ + unsigned char *data; + m->m_len = sizeof(struct in_addr) + sizeof(opts->ip_srcrt.nop) + + opts->ip_srcrt.srcopt[IPOPT_OLEN]; + *(mtod(m, struct in_addr *)) = opts->ip_srcrt.dst; + data = (unsigned char *)mtod(m, unsigned char *) + + sizeof(struct in_addr); + opts->ip_srcrt.nop = IPOPT_NOP; + opts->ip_srcrt.srcopt[IPOPT_OPTVAL] = IPOPT_LSRR; + opts->ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; + bcopy((unsigned char *)&opts->ip_srcrt.nop, data, + (sizeof(opts->ip_srcrt.nop) + opts->ip_srcrt.srcopt[IPOPT_OLEN])); + + } +#endif m_tag_delete(m0, (struct m_tag *)opts); return (m); } @@ -1616,6 +1954,16 @@ olen = (ip->ip_hl << 2) - sizeof (struct ip); opts = (caddr_t)(ip + 1); +#ifdef DATA_ROUTING + if (mopt){ + /* copy the minimum of the option length and the space + available*/ + caddr_t dest; + dest = mtod(mopt, caddr_t); + bcopy(opts, dest, olen); + mopt->m_len = olen; + } +#endif i = m->m_len - (sizeof (struct ip) + olen); bcopy(opts + olen, opts, (unsigned)i); m->m_len -= olen; @@ -1778,6 +2126,12 @@ } error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); +#ifdef DATA_ROUTING + if (!error && enable_route_stats) { + /* forwarded message */ + drt_note_end(); + } +#endif if (error) ipstat.ips_cantforward++; else { @@ -1975,6 +2329,25 @@ mp = &(*mp)->m_next; } #endif + +#ifdef DATA_ROUTING +/* enabled copying of source route...*/ + /* ip_srcroute doesn't do what we want here, need to fix */ + if (inp->inp_flags & INP_RECVRETOPTS) { + struct mbuf *msrc; + msrc = ip_srcroute(m); + + if (msrc) { + *mp = sbcreatecontrol((caddr_t)mtod(msrc, caddr_t), + msrc->m_len, + IP_RECVRETOPTS, IPPROTO_IP); + + if (*mp) + mp = &(*mp)->m_next; + } /* msrc exists */ + } +#endif + if (inp->inp_flags & INP_RECVIF) { struct ifnet *ifp; struct sdlbuf { Index: sys/netinet/ip_output.c =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/ip_output.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/ip_output.c 6 Jun 2005 21:58:16 -0000 1.1.1.1 +++ sys/netinet/ip_output.c 7 Jun 2005 00:06:03 -0000 1.2 @@ -60,6 +60,13 @@ #include +#ifdef DATA_ROUTING +#include +#define PRINT2(x, y) log(LOG_INFO, x, y) +/* #define PRINT2(x, y) */ +#include +#endif + static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options"); #ifdef IPSEC @@ -808,10 +815,10 @@ if (ia != NULL) { ia->ia_ifa.if_opackets++; ia->ia_ifa.if_obytes += m->m_pkthdr.len; - } - + } error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); + } else m_freem(m); } @@ -1488,6 +1495,10 @@ default: break; +#ifdef DATA_ROUTING + case IPOPT_DSRR: + /* fall through */ +#endif case IPOPT_LSRR: case IPOPT_SSRR: /* Index: sys/netinet/regerror.c =================================================================== RCS file: sys/netinet/regerror.c diff -N sys/netinet/regerror.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/regerror.c 7 Jun 2005 00:06:03 -0000 1.1 @@ -0,0 +1,11 @@ +/* #include */ + +#include +#include +#include +#include + +void regerror(char *s) +{ + log(LOG_INFO,"regexp: %s", s); +} Index: sys/netinet/regexp.c =================================================================== RCS file: sys/netinet/regexp.c diff -N sys/netinet/regexp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/regexp.c 7 Jun 2005 00:06:03 -0000 1.1 @@ -0,0 +1,1179 @@ +/* + * regcomp and regexec -- regsub and regerror are elsewhere + * @(#)regexp.c 1.3 of 18 April 87 + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * Beware that some of this code is subtly aware of the way operator + * precedence is structured in regular expressions. Serious changes in + * regular-expression syntax might require a total rethink. + */ +#include +#include +#include +#include + +#ifndef NULL +#define NULL 0 +#endif + +/* + * The "internal use only" fields in regexp.h are present to pass info from + * compile to execute that permits the execute phase to run lots faster on + * simple cases. They are: + * + * regstart char that must begin a match; '\0' if none obvious + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL + * regmlen length of regmust string + * + * Regstart and reganch permit very fast decisions on suitable starting points + * for a match, cutting down the work a lot. Regmust permits fast rejection + * of lines that cannot possibly match. The regmust tests are costly enough + * that regcomp() supplies a regmust only if the r.e. contains something + * potentially expensive (at present, the only such thing detected is * or + + * at the start of the r.e., which can involve a lot of backup). Regmlen is + * supplied because the test in regexec() needs it and regcomp() is computing + * it anyway. + */ + +/* + * Structure for regexp "program". This is essentially a linear encoding + * of a nondeterministic finite-state machine (aka syntax charts or + * "railroad normal form" in parsing technology). Each node is an opcode + * plus a "next" pointer, possibly plus an operand. "Next" pointers of + * all nodes except BRANCH implement concatenation; a "next" pointer with + * a BRANCH on both ends of it is connecting two alternatives. (Here we + * have one of the subtle syntax dependencies: an individual BRANCH (as + * opposed to a collection of them) is never concatenated with anything + * because of operator precedence.) The operand of some types of node is + * a literal string; for others, it is a node leading into a sub-FSM. In + * particular, the operand of a BRANCH node is the first node of the branch. + * (NB this is *not* a tree structure: the tail of the branch connects + * to the thing following the set of BRANCHes.) The opcodes are: + */ + +/* definition number opnd? meaning */ +#define END 0 /* no End of program. */ +#define BOL 1 /* no Match "" at beginning of line. */ +#define EOL 2 /* no Match "" at end of line. */ +#define ANY 3 /* no Match any one character. */ +#define ANYOF 4 /* str Match any character in this string. */ +#define ANYBUT 5 /* str Match any character not in this string. */ +#define BRANCH 6 /* node Match this alternative, or the next... */ +#define BACK 7 /* no Match "", "next" ptr points backward. */ +#define EXACTLY 8 /* str Match this string. */ +#define NOTHING 9 /* no Match empty string. */ +#define STAR 10 /* node Match this (simple) thing 0 or more times. */ +#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ +#define OPEN 20 /* no Mark this point in input as start of #n. */ + /* OPEN+1 is number 1, etc. */ +#define CLOSE 30 /* no Analogous to OPEN. */ + +/* + * Opcode notes: + * + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. + * + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. + * + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. + * + * OPEN,CLOSE ...are numbered at compile time. + */ + +/* + * A node is one char of opcode followed by two chars of "next" pointer. + * "Next" pointers are stored as two 8-bit pieces, high order first. The + * value is a positive offset from the opcode of the node containing it. + * An operand, if any, simply follows the node. (Note that much of the + * code generation knows about this implicit relationship.) + * + * Using two bytes for the "next" pointer is vast overkill for most things, + * but allows patterns to get big without disasters. + */ +#define OP(p) (*(p)) +#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) +#define OPERAND(p) ((p) + 3) + +/* + * See regmagic.h for one further detail of program structure. + */ + + +/* + * Utility definitions. + */ +#ifndef CHARBITS +#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#else +#define UCHARAT(p) ((int)*(p)&CHARBITS) +#endif + +#define FAIL(m) { regerror(m); return(NULL); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') +#define META "^$.[()|?+*\\" + +/* + * Flags to be passed up and down. + */ +#define HASWIDTH 01 /* Known never to match null string. */ +#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +#define SPSTART 04 /* Starts with * or +. */ +#define WORST 0 /* Worst case. */ + +/* + * Global work variables for regcomp(). + */ +static char *regparse; /* Input-scan pointer. */ +int regnpar; /* () count. */ +static char regdummy; +static char *regcode; /* Code-emit pointer; ®dummy = don't. */ +static long regsize; /* Code size. */ + +/* + * Forward declarations for regcomp()'s friends. + */ +#ifndef STATIC +#define STATIC static +#endif +STATIC char * reg( int paren, int *flagp); +STATIC char * regbranch(int *flagp); +STATIC char * regpiece( int *flagp); +STATIC char * regatom(int *flagp); +STATIC char * regnode(char op); +STATIC char * regnext(register char *p); +STATIC void regc(char b); +STATIC void reginsert(char op, char *opnd); +STATIC void regtail(char *p, char *val); +STATIC void regoptail(char *p, char *val); +STATIC int regtry(regexp *prog, char *string); +STATIC int regmatch(char *prog); +STATIC int regrepeat(char *p); + +#define STRCSPN +#ifdef STRCSPN +STATIC int strcspn(char *s1, char *s2); +#endif + +/* + - regcomp - compile a regular expression into internal code + * + * We can't allocate space until we know how big the compiled form will be, + * but we can't compile it (and thus know how big it is) until we've got a + * place to put the code. So we cheat: we compile it twice, once with code + * generation turned off and size counting turned on, and once "for real". + * This also means that we don't allocate space until we are sure that the + * thing really will compile successfully, and we never have to move the + * code and thus invalidate pointers into it. (Note that it has to be in + * one piece because free() must be able to free it all.) + * + * Beware that the optimization-preparation code in here knows about some + * of the structure of the compiled regexp. + */ + +regexp * +regcomp(char *exp, char *regbuf_in, int buflen_in) +{ + register regexp *r; + register char *scan; + register char *longest; + register int len; + int flags; + + if (exp == NULL) + FAIL("NULL argument"); + + /* First pass: determine size, legality. */ + regparse = exp; + regnpar = 1; + regsize = 0L; + regcode = ®dummy; + regc(MAGIC); + if (reg(0, &flags) == NULL) + return(NULL); + + /* Small enough for pointer-storage convention? */ + if (regsize >= 32767L) /* Probably could be 65535L. */ + FAIL("regexp too big"); + + /* Allocate space. */ + if ((sizeof(regexp) + (unsigned)regsize) < buflen_in) + r = (regexp *)regbuf_in; + else + r = NULL; + if (r == NULL) + FAIL("out of space"); + + /* Second pass: emit code. */ + regparse = exp; + regnpar = 1; + regcode = r->program; + regc(MAGIC); + if (reg(0, &flags) == NULL) + return(NULL); + + /* Dig out information for optimizations. */ + r->regstart = '\0'; /* Worst-case defaults. */ + r->reganch = 0; + r->regmust = NULL; + r->regmlen = 0; + scan = r->program+1; /* First BRANCH. */ + if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ + scan = OPERAND(scan); + + /* Starting-point info. */ + if (OP(scan) == EXACTLY) + r->regstart = *OPERAND(scan); + else if (OP(scan) == BOL) + r->reganch++; + + /* + * If there's something expensive in the r.e., find the + * longest literal string that must appear and make it the + * regmust. Resolve ties in favor of later strings, since + * the regstart check works with the beginning of the r.e. + * and avoiding duplication strengthens checking. Not a + * strong reason, but sufficient in the absence of others. + */ + if (flags&SPSTART) { + longest = NULL; + len = 0; + for (; scan != NULL; scan = regnext(scan)) + if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { + longest = OPERAND(scan); + len = strlen(OPERAND(scan)); + } + r->regmust = longest; + r->regmlen = len; + } + } + + return(r); +} + +/* + - reg - regular expression, i.e. main body or parenthesized thing + * + * Caller must absorb opening parenthesis. + * + * Combining parenthesis handling with the base level of regular expression + * is a trifle forced, but the need to tie the tails of the branches to what + * follows makes it hard to avoid. + */ +static char * reg( int paren, int *flagp) +{ + register char *ret; + register char *br; + register char *ender; + register int parno = 0; + int flags; + + *flagp = HASWIDTH; /* Tentatively. */ + + /* Make an OPEN node, if parenthesized. */ + if (paren) { + if (regnpar >= NSUBEXP) + FAIL("too many ()"); + parno = regnpar; + regnpar++; + ret = regnode(OPEN+parno); + } else + ret = NULL; + + /* Pick up the branches, linking them together. */ + br = regbranch(&flags); + if (br == NULL) + return(NULL); + if (ret != NULL) + regtail(ret, br); /* OPEN -> first. */ + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*regparse == '|') { + regparse++; + br = regbranch(&flags); + if (br == NULL) + return(NULL); + regtail(ret, br); /* BRANCH -> BRANCH. */ + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } + + /* Make a closing node, and hook it on the end. */ + ender = regnode((paren) ? CLOSE+parno : END); + regtail(ret, ender); + + /* Hook the tails of the branches to the closing node. */ + for (br = ret; br != NULL; br = regnext(br)) + regoptail(br, ender); + + /* Check for proper termination. */ + if (paren && *regparse++ != ')') { + FAIL("unmatched ()"); + } else if (!paren && *regparse != '\0') { + if (*regparse == ')') { + FAIL("unmatched ()"); + } else + FAIL("junk on end"); /* "Can't happen". */ + /* NOTREACHED */ + } + + return(ret); +} + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +static char * regbranch(int *flagp) +{ + register char *ret; + register char *chain; + register char *latest; + int flags; + + *flagp = WORST; /* Tentatively. */ + + ret = regnode(BRANCH); + chain = NULL; + while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { + latest = regpiece(&flags); + if (latest == NULL) + return(NULL); + *flagp |= flags&HASWIDTH; + if (chain == NULL) /* First piece. */ + *flagp |= flags&SPSTART; + else + regtail(chain, latest); + chain = latest; + } + if (chain == NULL) /* Loop ran zero times. */ + (void) regnode(NOTHING); + + return(ret); +} + +/* + - regpiece - something followed by possible [*+?] + * + * Note that the branching code sequences used for ? and the general cases + * of * and + are somewhat optimized: they use the same NOTHING node as + * both the endmarker for their branch list and the body of the last branch. + * It might seem that this node could be dispensed with entirely, but the + * endmarker role is not redundant. + */ +static char * regpiece( int *flagp) +{ + register char *ret; + register char op; + register char *next; + int flags; + + ret = regatom(&flags); + if (ret == NULL) + return(NULL); + + op = *regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } + + if (!(flags&HASWIDTH) && op != '?') + FAIL("*+ operand could be empty"); + *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); + + if (op == '*' && (flags&SIMPLE)) + reginsert(STAR, ret); + else if (op == '*') { + /* Emit x* as (x&|), where & means "self". */ + reginsert(BRANCH, ret); /* Either x */ + regoptail(ret, regnode(BACK)); /* and loop */ + regoptail(ret, ret); /* back */ + regtail(ret, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '+' && (flags&SIMPLE)) + reginsert(PLUS, ret); + else if (op == '+') { + /* Emit x+ as x(&|), where & means "self". */ + next = regnode(BRANCH); /* Either */ + regtail(ret, next); + regtail(regnode(BACK), ret); /* loop back */ + regtail(next, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '?') { + /* Emit x? as (x|) */ + reginsert(BRANCH, ret); /* Either x */ + regtail(ret, regnode(BRANCH)); /* or */ + next = regnode(NOTHING); /* null. */ + regtail(ret, next); + regoptail(ret, next); + } + regparse++; + if (ISMULT(*regparse)) + FAIL("nested *?+"); + + return(ret); +} + +/* + - regatom - the lowest level + * + * Optimization: gobbles an entire sequence of ordinary characters so that + * it can turn them into a single node, which is smaller to store and + * faster to run. Backslashed characters are exceptions, each becoming a + * separate node; the code is simpler that way and it's not worth fixing. + */ +static char * regatom(int *flagp) +{ + register char *ret; + int flags; + + *flagp = WORST; /* Tentatively. */ + + switch (*regparse++) { + case '^': + ret = regnode(BOL); + break; + case '$': + ret = regnode(EOL); + break; + case '.': + ret = regnode(ANY); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + register int class; + register int classend; + + if (*regparse == '^') { /* Complement of range. */ + ret = regnode(ANYBUT); + regparse++; + } else + ret = regnode(ANYOF); + if (*regparse == ']' || *regparse == '-') + regc(*regparse++); + while (*regparse != '\0' && *regparse != ']') { + if (*regparse == '-') { + regparse++; + if (*regparse == ']' || *regparse == '\0') + regc('-'); + else { + class = UCHARAT(regparse-2)+1; + classend = UCHARAT(regparse); + if (class > classend+1) + FAIL("invalid [] range"); + for (; class <= classend; class++) + regc(class); + regparse++; + } + } else + regc(*regparse++); + } + regc('\0'); + if (*regparse != ']') + FAIL("unmatched []"); + regparse++; + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(1, &flags); + if (ret == NULL) + return(NULL); + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case ')': + FAIL("internal urp"); /* Supposed to be caught earlier. */ + break; + case '?': + case '+': + case '*': + FAIL("?+* follows nothing"); + break; + case '\\': + if (*regparse == '\0') + FAIL("trailing \\"); + ret = regnode(EXACTLY); + regc(*regparse++); + regc('\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + default: { + register int len; + register char ender; + + regparse--; + len = strcspn(regparse, META); + if (len <= 0) + FAIL("internal disaster"); + ender = *(regparse+len); + if (len > 1 && ISMULT(ender)) + len--; /* Back off clear of ?+* operand. */ + *flagp |= HASWIDTH; + if (len == 1) + *flagp |= SIMPLE; + ret = regnode(EXACTLY); + while (len > 0) { + regc(*regparse++); + len--; + } + regc('\0'); + } + break; + } + + return(ret); +} + +/* + - regnode - emit a node + */ +static char * regnode(char op) +{ + register char *ret; + register char *ptr; + + ret = regcode; + if (ret == ®dummy) { + regsize += 3; + return(ret); + } + + ptr = ret; + *ptr++ = op; + *ptr++ = '\0'; /* Null "next" pointer. */ + *ptr++ = '\0'; + regcode = ptr; + + return(ret); +} + +/* + - regc - emit (if appropriate) a byte of code + */ +static void regc(char b) +{ + if (regcode != ®dummy) + *regcode++ = b; + else + regsize++; +} + +/* + - reginsert - insert an operator in front of already-emitted operand + * + * Means relocating the operand. + */ +static void reginsert(char op, char *opnd) +{ + register char *src; + register char *dst; + register char *place; + + if (regcode == ®dummy) { + regsize += 3; + return; + } + + src = regcode; + regcode += 3; + dst = regcode; + while (src > opnd) + *--dst = *--src; + + place = opnd; /* Op node, where operand used to be. */ + *place++ = op; + *place++ = '\0'; + *place++ = '\0'; +} + +/* + - regtail - set the next-pointer at the end of a node chain + */ +static void regtail(char *p, char *val) +{ + register char *scan; + register char *temp; + register int offset; + + if (p == ®dummy) + return; + + /* Find last node. */ + scan = p; + for (;;) { + temp = regnext(scan); + if (temp == NULL) + break; + scan = temp; + } + + if (OP(scan) == BACK) + offset = scan - val; + else + offset = val - scan; + *(scan+1) = (offset>>8)&0377; + *(scan+2) = offset&0377; +} + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ +static void regoptail(char *p, char *val) +{ + /* "Operandless" and "op != BRANCH" are synonymous in practice. */ + if (p == NULL || p == ®dummy || OP(p) != BRANCH) + return; + regtail(OPERAND(p), val); +} + +/* + * regexec and friends + */ + +/* + * Global work variables for regexec(). + */ +static char *reginput; /* String-input pointer. */ +static char *regbol; /* Beginning of input, for ^ check. */ +static char **regstartp; /* Pointer to startp array. */ +static char **regendp; /* Ditto for endp. */ + +#ifdef DEBUG +int regnarrate = 0; +void regdump(); +STATIC char *regprop(); +#endif + +/* + - regexec - match a regexp against a string + */ +int regexec( register regexp *prog, register char *string) +{ + register char *s; + + /* Be paranoid... */ + if (prog == NULL || string == NULL) { + regerror("NULL parameter"); + return(0); + } + + /* Check validity of program. */ + if (UCHARAT(prog->program) != MAGIC) { + regerror("corrupted program"); + return(0); + } + + /* If there is a "must appear" string, look for it. */ + if (prog->regmust != NULL) { + s = string; + while ((s = index(s, prog->regmust[0])) != NULL) { + if (strncmp(s, prog->regmust, prog->regmlen) == 0) + break; /* Found it. */ + s++; + } + if (s == NULL) /* Not present. */ + return(0); + } + + /* Mark beginning of line for ^ . */ + regbol = string; + + /* Simplest case: anchored match need be tried only once. */ + if (prog->reganch) + return(regtry(prog, string)); + + /* Messy cases: unanchored match. */ + s = string; + if (prog->regstart != '\0') + /* We know what char it must start with. */ + while ((s = index(s, prog->regstart)) != NULL) { + if (regtry(prog, s)) + return(1); + s++; + } + else + /* We don't -- general case. */ + do { + if (regtry(prog, s)) + return(1); + } while (*s++ != '\0'); + + /* Failure. */ + return(0); +} + +/* + - regtry - try match at specific point + */ +static int /* 0 failure, 1 success */ +regtry(regexp *prog, char *string) +{ + register int i; + register char **sp; + register char **ep; + + reginput = string; + regstartp = prog->startp; + regendp = prog->endp; + + sp = prog->startp; + ep = prog->endp; + for (i = NSUBEXP; i > 0; i--) { + *sp++ = NULL; + *ep++ = NULL; + } + if (regmatch(prog->program + 1)) { + prog->startp[0] = string; + prog->endp[0] = reginput; + return(1); + } else + return(0); +} + +/* + - regmatch - main matching routine + * + * Conceptually the strategy is simple: check to see whether the current + * node matches, call self recursively to see whether the rest matches, + * and then act accordingly. In practice we make some effort to avoid + * recursion, in particular by going through "ordinary" nodes (that don't + * need to know whether the rest of the match failed) by a loop instead of + * by recursion. + */ +static int /* 0 failure, 1 success */ +regmatch(char *prog) +{ + register char *scan; /* Current node. */ + char *next; /* Next node. */ + + scan = prog; +#ifdef DEBUG + if (scan != NULL && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); +#endif + while (scan != NULL) { +#ifdef DEBUG + if (regnarrate) + fprintf(stderr, "%s...\n", regprop(scan)); +#endif + next = regnext(scan); + + switch (OP(scan)) { + case BOL: + if (reginput != regbol) + return(0); + break; + case EOL: + if (*reginput != '\0') + return(0); + break; + case ANY: + if (*reginput == '\0') + return(0); + reginput++; + break; + case EXACTLY: { + register int len; + register char *opnd; + + opnd = OPERAND(scan); + /* Inline the first character, for speed. */ + if (*opnd != *reginput) + return(0); + len = strlen(opnd); + if (len > 1 && strncmp(opnd, reginput, len) != 0) + return(0); + reginput += len; + } + break; + case ANYOF: + if (*reginput == '\0' || index(OPERAND(scan), *reginput) == NULL) + return(0); + reginput++; + break; + case ANYBUT: + if (*reginput == '\0' || index(OPERAND(scan), *reginput) != NULL) + return(0); + reginput++; + break; + case NOTHING: + break; + case BACK: + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: { + register int no; + register char *save; + + no = OP(scan) - OPEN; + save = reginput; + + if (regmatch(next)) { + /* + * Don't set startp if some later + * invocation of the same parentheses + * already has. + */ + if (regstartp[no] == NULL) + regstartp[no] = save; + return(1); + } else + return(0); + } + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: { + register int no; + register char *save; + + no = OP(scan) - CLOSE; + save = reginput; + + if (regmatch(next)) { + /* + * Don't set endp if some later + * invocation of the same parentheses + * already has. + */ + if (regendp[no] == NULL) + regendp[no] = save; + return(1); + } else + return(0); + } + break; + case BRANCH: { + register char *save; + + if (OP(next) != BRANCH) /* No choice. */ + next = OPERAND(scan); /* Avoid recursion. */ + else { + do { + save = reginput; + if (regmatch(OPERAND(scan))) + return(1); + reginput = save; + scan = regnext(scan); + } while (scan != NULL && OP(scan) == BRANCH); + return(0); + /* NOTREACHED */ + } + } + break; + case STAR: + case PLUS: { + register char nextch; + register int no; + register char *save; + register int min; + + /* + * Lookahead to avoid useless match attempts + * when we know what character comes next. + */ + nextch = '\0'; + if (OP(next) == EXACTLY) + nextch = *OPERAND(next); + min = (OP(scan) == STAR) ? 0 : 1; + save = reginput; + no = regrepeat(OPERAND(scan)); + while (no >= min) { + /* If it could work, try it. */ + if (nextch == '\0' || *reginput == nextch) + if (regmatch(next)) + return(1); + /* Couldn't or didn't -- back up. */ + no--; + reginput = save + no; + } + return(0); + } + break; + case END: + return(1); /* Success! */ + break; + default: + regerror("memory corruption"); + return(0); + break; + } + + scan = next; + } + + /* + * We get here only if there's trouble -- normally "case END" is + * the terminating point. + */ + regerror("corrupted pointers"); + return(0); +} + +/* + - regrepeat - repeatedly match something simple, report how many + */ +static int regrepeat(char *p) +{ + register int count = 0; + register char *scan; + register char *opnd; + + scan = reginput; + opnd = OPERAND(p); + switch (OP(p)) { + case ANY: + count = strlen(scan); + scan += count; + break; + case EXACTLY: + while (*opnd == *scan) { + count++; + scan++; + } + break; + case ANYOF: + while (*scan != '\0' && index(opnd, *scan) != NULL) { + count++; + scan++; + } + break; + case ANYBUT: + while (*scan != '\0' && index(opnd, *scan) == NULL) { + count++; + scan++; + } + break; + default: /* Oh dear. Called inappropriately. */ + regerror("internal foulup"); + count = 0; /* Best compromise. */ + break; + } + reginput = scan; + + return(count); +} + +/* + - regnext - dig the "next" pointer out of a node + */ +static char * regnext(register char *p) +{ + register int offset; + + if (p == ®dummy) + return(NULL); + + offset = NEXT(p); + if (offset == 0) + return(NULL); + + if (OP(p) == BACK) + return(p-offset); + else + return(p+offset); +} + +#ifdef DEBUG + +STATIC char *regprop(); + +/* + - regdump - dump a regexp onto stdout in vaguely comprehensible form + */ +void +regdump( regexp *r) +{ + register char *s; + register char op = EXACTLY; /* Arbitrary non-END op. */ + register char *next; + + + s = r->program + 1; + while (op != END) { /* While that wasn't END last time... */ + op = OP(s); + printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ + next = regnext(s); + if (next == NULL) /* Next ptr. */ + printf("(0)"); + else + printf("(%d)", (s-r->program)+(next-s)); + s += 3; + if (op == ANYOF || op == ANYBUT || op == EXACTLY) { + /* Literal string, where present. */ + while (*s != '\0') { + putchar(*s); + s++; + } + s++; + } + putchar('\n'); + } + + /* Header fields of interest. */ + if (r->regstart != '\0') + printf("start `%c' ", r->regstart); + if (r->reganch) + printf("anchored "); + if (r->regmust != NULL) + printf("must have \"%s\"", r->regmust); + printf("\n"); +} + +/* + - regprop - printable representation of opcode + */ +static char * regprop(char *op) +{ + register char *p; + static char buf[50]; + + (void) strcpy(buf, ":"); + + switch (OP(op)) { + case BOL: + p = "BOL"; + break; + case EOL: + p = "EOL"; + break; + case ANY: + p = "ANY"; + break; + case ANYOF: + p = "ANYOF"; + break; + case ANYBUT: + p = "ANYBUT"; + break; + case BRANCH: + p = "BRANCH"; + break; + case EXACTLY: + p = "EXACTLY"; + break; + case NOTHING: + p = "NOTHING"; + break; + case BACK: + p = "BACK"; + break; + case END: + p = "END"; + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: + sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); + p = NULL; + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: + sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); + p = NULL; + break; + case STAR: + p = "STAR"; + break; + case PLUS: + p = "PLUS"; + break; + default: + regerror("corrupted opcode"); + break; + } + if (p != NULL) + (void) strcat(buf, p); + return(buf); +} +#endif + +/* + * The following is provided for those people who do not have strcspn() in + * their C libraries. They should get off their butts and do something + * about it; at least one public-domain implementation of those (highly + * useful) string routines has been published on Usenet. + */ +#ifdef STRCSPN +/* + * strcspn - find length of initial segment of s1 consisting entirely + * of characters not from s2 + */ + +static int +strcspn(char *s1, char *s2) +{ + register char *scan1; + register char *scan2; + register int count; + + count = 0; + for (scan1 = s1; *scan1 != '\0'; scan1++) { + for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ + if (*scan1 == *scan2++) + return(count); + count++; + } + return(count); +} +#endif Index: sys/netinet/regexp.h =================================================================== RCS file: sys/netinet/regexp.h diff -N sys/netinet/regexp.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/regexp.h 7 Jun 2005 00:06:03 -0000 1.1 @@ -0,0 +1,21 @@ +/* + * Definitions etc. for regexp(3) routines. + * + * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], + * not the System V one. + */ +#define NSUBEXP 10 +typedef struct regexp { + char *startp[NSUBEXP]; + char *endp[NSUBEXP]; + char regstart; /* Internal use only. */ + char reganch; /* Internal use only. */ + char *regmust; /* Internal use only. */ + int regmlen; /* Internal use only. */ + char program[1]; /* Unwarranted chumminess with compiler. */ +} regexp; + +extern regexp * regcomp(char *exp, char *buf, int len); +extern int regexec( register regexp *prog, register char *string); +extern void regsub( regexp *prog, char *source, char *dest); +extern void regerror(char *s); Index: sys/netinet/regmagic.h =================================================================== RCS file: sys/netinet/regmagic.h diff -N sys/netinet/regmagic.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/regmagic.h 7 Jun 2005 00:06:03 -0000 1.1 @@ -0,0 +1,5 @@ +/* + * The first byte of the regexp internal "program" is actually this magic + * number; the start node begins in the second byte. + */ +#define MAGIC 0234 Index: sys/netinet/regsub.c =================================================================== RCS file: sys/netinet/regsub.c diff -N sys/netinet/regsub.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/regsub.c 7 Jun 2005 00:06:03 -0000 1.1 @@ -0,0 +1,79 @@ +/* + * regsub + * @(#)regsub.c 1.3 of 2 April 86 + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + */ +/* #include */ +#include +#include +#include +#include + +#ifndef CHARBITS +#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#else +#define UCHARAT(p) ((int)*(p)&CHARBITS) +#endif + +/* + - regsub - perform substitutions after a regexp match + */ +void regsub( regexp *prog, char *source, char *dest) +{ + register char *src; + register char *dst; + register char c; + register int no; + register int len; + + if (prog == NULL || source == NULL || dest == NULL) { + regerror("NULL parm to regsub"); + return; + } + if (UCHARAT(prog->program) != MAGIC) { + regerror("damaged regexp fed to regsub"); + return; + } + + src = source; + dst = dest; + while ((c = *src++) != '\0') { + if (c == '&') + no = 0; + else if (c == '\\' && '0' <= *src && *src <= '9') + no = *src++ - '0'; + else + no = -1; + + if (no < 0) { /* Ordinary character. */ + if (c == '\\' && (*src == '\\' || *src == '&')) + c = *src++; + *dst++ = c; + } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { + len = prog->endp[no] - prog->startp[no]; + (void) strncpy(dst, prog->startp[no], len); + dst += len; + if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */ + regerror("damaged match string"); + return; + } + } + } + *dst++ = '\0'; +} Index: sys/netinet/tcp_input.c =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/tcp_input.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/tcp_input.c 6 Jun 2005 21:58:16 -0000 1.1.1.1 +++ sys/netinet/tcp_input.c 7 Jun 2005 00:06:03 -0000 1.2 @@ -38,6 +38,7 @@ #include "opt_tcpdebug.h" #include "opt_tcp_input.h" #include "opt_tcp_sack.h" +#include "opt_datarouting.h" #include #include Index: sys/netinet/tcp_output.c =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/tcp_output.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/tcp_output.c 6 Jun 2005 21:58:16 -0000 1.1.1.1 +++ sys/netinet/tcp_output.c 7 Jun 2005 00:06:03 -0000 1.2 @@ -36,6 +36,7 @@ #include "opt_mac.h" #include "opt_tcpdebug.h" #include "opt_tcp_sack.h" +#include "opt_datarouting.h" #include #include @@ -187,6 +188,7 @@ sendwin = min(tp->snd_wnd, tp->snd_cwnd); sendwin = min(sendwin, tp->snd_bwnd); + flags = tcp_outflags[tp->t_state]; /* * Send any SACK-generated retransmissions. If we're explicitly trying @@ -727,10 +729,10 @@ ipoptlen = ip6_optlen(tp->t_inpcb); else #endif - if (tp->t_inpcb->inp_options) - ipoptlen = tp->t_inpcb->inp_options->m_len - - offsetof(struct ipoption, ipopt_list); - else + if (tp->t_inpcb->inp_options) { + ipoptlen = tp->t_inpcb->inp_options->m_len - + offsetof(struct ipoption, ipopt_list); + } else ipoptlen = 0; #ifdef IPSEC ipoptlen += ipsec_hdrsiz_tcp(tp); @@ -962,6 +964,8 @@ * Put TCP length in extended header, and then * checksum extended header and data. */ + + m->m_pkthdr.len = hdrlen + len; /* in6_cksum() need this */ #ifdef INET6 if (isipv6) Index: sys/netinet/tcp_subr.c =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/tcp_subr.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/tcp_subr.c 6 Jun 2005 21:58:16 -0000 1.1.1.1 +++ sys/netinet/tcp_subr.c 7 Jun 2005 00:06:04 -0000 1.2 @@ -37,6 +37,7 @@ #include "opt_mac.h" #include "opt_tcpdebug.h" #include "opt_tcp_sack.h" +#include "opt_datarouting.h" #include #include @@ -108,6 +109,8 @@ #define IPSEC #endif /*FAST_IPSEC*/ +#include + #include #include Index: sys/netinet/tcp_usrreq.c =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/tcp_usrreq.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/tcp_usrreq.c 6 Jun 2005 21:58:16 -0000 1.1.1.1 +++ sys/netinet/tcp_usrreq.c 7 Jun 2005 00:06:04 -0000 1.2 @@ -34,6 +34,7 @@ #include "opt_inet.h" #include "opt_inet6.h" #include "opt_tcpdebug.h" +#include "opt_datarouting.h" #include #include @@ -836,6 +837,7 @@ bzero(&tao, sizeof(tao)); + error = 0; if (inp->inp_lport == 0) { error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred); if (error) Index: sys/netinet/tlv.c =================================================================== RCS file: sys/netinet/tlv.c diff -N sys/netinet/tlv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/tlv.c 7 Jun 2005 00:06:04 -0000 1.1 @@ -0,0 +1,784 @@ + +/* + * Generic TLV (type, length and value) settings and manipulation + * functions. This is getting a little messy because the user + * level code also needs this. hence the clumsiness of the + * PRINT2. Yuck! + */ + +/* users of this must define their own TLVMALLOC, PRINT2 + used as PRINT1("...") + used as PRINT2("...", x) +*/ + + +#include +#include +#include + +#ifndef PRINT2 +#ifdef _KERNEL +#include +#define PRINT2(x, y) log(LOG_INFO, x , y) +#else +#define PRINT2(x, y) printf(x , y) +#endif +#endif + +int refcount = 0; +int alloc_count = 0; + +char mallocbuf[1024]; +char mallocbuf1[1024]; + +void *TLVMALLOC(int x, int term) { + + void *retval = NULL; ; + switch(term){ + case ALLOC_SHORTTERM: + if (x > 1024) break; + + refcount++; + alloc_count++; + if (refcount > 1) { + memset(mallocbuf1, '\0', x); + retval = &mallocbuf1[0]; + } else { + memset(mallocbuf, '\0', x); + retval = &mallocbuf[0]; + } + + break; + case ALLOC_LONGTERM: +#ifdef _KERNEL + retval = malloc(x, M_RTABLE, M_NOWAIT); +#else + retval = malloc(x); +#endif + break; + default: + break; + } + + return retval; + +} + +void TLVFREE(void *x, int term) { + + switch(term){ + case ALLOC_SHORTTERM: + if (refcount > 0){ + refcount--; + } else { + } + break; + case ALLOC_LONGTERM: +#ifdef _KERNEL + free(x, M_RTABLE); +#else + free(x); +#endif + break; + default: + break; + } + + return; +} + + +/********************** +All functions that deal with rangees or simple numbers that are used to +route data. +***********************/ + +/* + 00 32 + +---------+-----------+--------+---------+ + | type | match | size | 0 | + +---------+-----------+--------+---------+ + | Min | + | Max | + +---------+-----------+--------+---------+ +*/ + +uint32_t range_serialized_size(tlv_range *in){ + return (in? 12 : 0); +} + +uint32_t range_serialize(tlv_range *in, char *data, int len) { + u_char *p; + uint32_t *pp; + + if (len < 12 || !in + || in->type != DRT_CLASS_RANGE + || (in->min > in->max) + ) { + return 0; + }; + + p = (u_char *) data; + *p++ = DRT_CLASS_RANGE; + *p++ = DRT_MATCH_RANGE; + *p++ = 8; /* just the length of the body = 2 integers */ + *p++ = DRT_RETURNFLAG_INPUT; + pp = (uint32_t *) data; + pp++; + *pp = htonl(in->min); + pp++; + *pp = htonl(in->max); + return 12; +} + +uint32_t range_unserialize(tlv **in, char *data, int len, int term) { + u_char *p; + uint32_t *pp; + tlv_range *ret; + + if (!data || len < 12) return 0; + + p = (u_char *) data; + if (p[0] != DRT_CLASS_RANGE) return 0; + if (p[2] != 8) return 0; + + ret = (tlv_range *)TLVMALLOC(sizeof(tlv_range), term); + if (! ret) return 0; + + ret->type = *p++; + ret->match = *p++; + ret->len = *p++; /* length of the range */ + ret->returnflag = *p++; + + pp = (uint32_t *) data; + pp++; + ret->min = ntohl(*pp); + pp++; + ret->max = ntohl(*pp); + *in = (tlv *)ret; + + return 12; /* the number of bytes in data advanced */ +} + +/* all rangees return 0 if no match and a non-zero score if there is a + match substring is little more complex but there also a higher + score => better match */ +uint32_t range_match(tlv *in1, tlv_range *in2, int preferred_match, int *match_len){ + + if (!in1 || + !in2 || + ((in1->base.type != DRT_CLASS_HASH) && + (in1->base.type != DRT_CLASS_RANGE)) || + /* (in1->match != DRT_MATCH_RANGE) || */ + (in2->type != DRT_CLASS_RANGE)|| + (in2->match != DRT_MATCH_RANGE) || + !match_len + ) + return -1; + + /* there is only one kind of match here. so ignore the preferred + match */ + if (in1->base.type == DRT_CLASS_HASH) { + tlv_hash *in1_hash; + + in1_hash = (tlv_hash *)in1; + if (in1_hash->hash >= in2->min && in1_hash->hash <= in2->max) { + *match_len = 4; + return 1; + } else { + return 0; + } + } else if (in1->base.type == DRT_CLASS_RANGE) { + tlv_range *in1_range; + + in1_range = (tlv_range *)in1; + if ((in1_range->max < in2->min) || + (in1_range->min > in2->max)){ + /* ranges are non-overlapping*/ + return 0; + } else { + *match_len = 8; + return 1; + } + } else { + return -1; + }; /* range */ +} /* range_match */ + +void range_print(tlv_range *in) { + if ( !in || + in->type != DRT_CLASS_RANGE){ + PRINT2("range_print: Invalid input %d \n", 0); + return; + } + + PRINT2("[%s, RANGE,", + (in->returnflag == DRT_RETURNFLAG_MATCH)? + "MATCH":"INPUT"); + PRINT2("%u <-> ", in->min); + PRINT2("%u]", in->max); + + return; +} + +/********************** +All functions that deal with hashes or simple numbers that are used to +route data. +***********************/ + +/* + 00 32 + +---------+-----------+--------+---------+ + | type | match | size | 0 | + +---------+-----------+--------+---------+ + | Hash Value | + +---------+-----------+--------+---------+ +*/ + +uint32_t hash_serialized_size(tlv_hash *in){ + return (in? 8 : 0); +} + +uint32_t hash_serialize(tlv_hash *in, char *data, int len) { + u_char *p; + uint32_t *pp; + + + if (len < 8 || !in || in->type != DRT_CLASS_HASH) return 0; + + p = (u_char *) data; + *p++ = in->type; + *p++ = in->match; + *p++ = 4; /* just the length of the body = 4 bytes*/ + *p++ = in->returnflag; + pp = (uint32_t *) data; + pp++; + *pp = htonl(in->hash); + return 8; +} + +uint32_t hash_unserialize(tlv **in, char *data, int len, int term) { + u_char *p; + uint32_t *pp; + tlv_hash *ret; + + if (!data || len < 8) return 0; + p = (u_char *) data; + if (p[0] != DRT_CLASS_HASH) return 0; + if (p[2] != 4) return 0; + + ret = (tlv_hash *)TLVMALLOC(sizeof(tlv_hash), term); + if (! ret) return 0; + + ret->type = *p++; + ret->match = *p++; + ret->len = *p++; /* length of the hash */ + ret->returnflag = *p++; + + pp = (uint32_t *) data; + pp++; + ret->hash = ntohl(*pp); + *in = (tlv *)ret; + + return 8; /* the number of bytes in data advanced */ +} + +/* all hashes return 0 if no match and a non-zero score if there is a + match substring is little more complex but there also a higher + score => better match */ +uint32_t hash_match(tlv_hash *in1, tlv_hash *in2, int preferred_match, int *match_len){ + + if (!in1 || + !in2 || + in1->type != DRT_CLASS_HASH || + in1->type != DRT_CLASS_HASH|| + in1->match != DRT_MATCH_EXACT || + in1->match != DRT_MATCH_EXACT || + !match_len + ) + return -1; + + /* there is only one kind of match here. so ignore the preferred + match */ + + if (in1->hash == in2->hash) { + *match_len = 4; + return 1; + } else { + return 0; + } +} + +void hash_print(tlv_hash *in) { + if ( !in || + in->type != DRT_CLASS_HASH){ + PRINT2("hash_print: Invalid input %d \n", 0); + return; + } + + PRINT2("[%s, HASH, EXACT, ", + (in->returnflag == DRT_RETURNFLAG_MATCH)? + "MATCH":"INPUT"); + PRINT2("%u]", in->hash); + return; +} + + +/********************** +All functions that deal with a string as being the data routing +tag. may be it is URL or domain name. it has to be in general a linear +structure. +***********************/ + +/* + 00 32 + +---------+-----------+--------+---------+ + | type | match | size | 0 | + +---------+-----------+--------+---------+ + | Data.... | + : : + | Data.... | + +---------+-----------+--------+---------+ +*/ + +uint32_t domain_serialized_size(tlv_domain *in){ + if ( !in + || ( in->type != DRT_CLASS_DOMAIN_STD + && in->type != DRT_CLASS_DOMAIN_REGEX ) + || !in->str) + return 0; + + return ROUNDUP(4 + in->len); +} + +uint32_t domain_serialize(tlv_domain *in, char *data, int len) { + u_char *p; + uint32_t size; + + if ( !in + || (in->type != DRT_CLASS_DOMAIN_STD && + in->type != DRT_CLASS_DOMAIN_REGEX) + || !in->str ) + return 0; + + size = domain_serialized_size(in); + if (len < size) + return 0; + + p = (u_char *) data; + *p++ = in->type; + *p++ = DRT_MATCH_LONGEST; + *p++ = in->len; + *p++ = in->returnflag; + memcpy(p, in->str, in->len); + + return size; /* this is already serialized. so nothing to do */ +} + +uint32_t domain_unserialize(tlv **in, char *data, int len, int term) { + u_char *p; + tlv_domain *ret; + uint32_t size; + + if (!in || !data || len < 4) return 0; + + p = (u_char *) data; + + if (p[0] != DRT_CLASS_DOMAIN_STD && p[0] != DRT_CLASS_DOMAIN_REGEX ) + return 0; + + if (len < (ROUNDUP(p[2]) + 4)){ + return 0; + } /* we need 4 extra bytes to + accomodate the char *str */ + + /* the in-memory structure has an additional overhead of 4 bytes */ + size = ROUNDUP(p[2]) + 8; /* match and type */ + ret = (tlv_domain *)TLVMALLOC(size, term); + if (!ret) return 0; + + ret->type = p[0]; + ret->match = p[1]; + ret->len = p[2]; /* length of the string */ + ret->returnflag = p[3]; /* this will likely be ignored */ + ret->str = (char *)(ret + 1); + memcpy(ret->str, (char *)&p[4], ret->len); + + *in = (tlv *)ret; + return ROUNDUP(p[2] + 4); /* we have consumed so many bytes */ + +} + + +/* all hashes return 0 if no match and a non-zero score if there is a + match substring is little more complex but there also a higher + score => better match */ +uint32_t domain_match(tlv_domain *in1, tlv_domain *in2, + int preferred_match, int *match_len_ret){ + + int match_len, lim, match; + char *p, *q; + + if ( !in1 + || !in2 + || (in1->type != DRT_CLASS_DOMAIN_REGEX && + in1->type != DRT_CLASS_DOMAIN_STD) + || (in2->type != DRT_CLASS_DOMAIN_REGEX && + in2->type != DRT_CLASS_DOMAIN_STD) + || (in1->match != DRT_MATCH_EXACT && + in1->match != DRT_MATCH_LONGEST) + || (in2->match != DRT_MATCH_EXACT && + in2->match != DRT_MATCH_LONGEST) + || (in1->match != in2->match ) + || ! in1->str + || ! in2->str + || ! match_len_ret ) + return 0; + + *match_len_ret = 0; + + if (preferred_match != 0){ + if ((preferred_match != DRT_MATCH_EXACT) && + (preferred_match != DRT_MATCH_SUBSTRING) && + (preferred_match != DRT_MATCH_LONGEST)){ + return 0; + } + match = preferred_match; + } else { + /* which one to choose? the left one is assumed to come from + * the packet. the search method must be specified in the packet + * and the + */ + match = in1->match; + } + + /* + * Several possible combinations here + * + * class match + * + * DRT_CLASS_DOMAIN_STD DRT_MATCH_EXACT + * DRT_CLASS_DOMAIN_REGEX DRT_MATCH_SUBSTRING + * DRT_MATCH_LONGEST + * + */ + + /* 2/4 combinations */ + if (match == DRT_MATCH_EXACT || + (in1->type == DRT_CLASS_DOMAIN_STD && + in2->type == DRT_CLASS_DOMAIN_STD) || + (in1->type == DRT_CLASS_DOMAIN_REGEX && + in2->type == DRT_CLASS_DOMAIN_REGEX)) { + + /* how to match two regular expressions? We do a string compare. + this case should probably not be supported + */ + lim = (in1->len > in2->len) ? in2->len : in1->len; + p = in1->str; + q = in2->str; + for (match_len = 0; match_len < lim; match_len++) + if (p[match_len] != q[match_len]) + break; + + if (match == DRT_MATCH_EXACT) { + /* the match len is useless in case of an exact match */ + if (in1->len != in2->len) + return 0; + if (match_len == in1->len) { + *match_len_ret = match_len; + return 1; + } + return 0; + } else if (match == DRT_MATCH_LONGEST) { + *match_len_ret = match_len; + return 1; + } else { + /* MATCH_SUBSTRING - not supported as yet.*/ + return 0; + } + } + + /* We maintain a cache of two regexs that are compiled. + another 2/4 combinations - one is a regular expression and + another is not - length here is always the length of the + fixed string that matched the regular expression */ + /* are the match operations being ignored? */ + if (1){ + /* the second entry is a regular exp then */ + int reti; + static char inputstr[1024]; + static char regexpbuf[1024]; + int regexp_len = 0; + static int which_one = 0; + static char prev_regexpbuf[2][1024]; + static int prev_regexp_len[2] = {0, 0}; + static regexp *reg[2] = {0, 0}; + static regexp *correctreg = 0; + + #ifdef COMMENT + if (in1->type == DRT_CLASS_DOMAIN_STD) { + memcpy(inputstr, in1->str, in1->len); + inputstr[in1->len] = '\0'; + memcpy(regexpbuf, in2->str, in2->len); + inputstr[in2->len] = '\0'; + regexp_len = in2->len; + } else { + memcpy(inputstr, in2->str, in2->len); + inputstr[in2->len] = '\0'; + memcpy(regexpbuf, in1->str, in1->len); + inputstr[in1->len] = '\0'; + regexp_len = in1->len; + } + + if (reg[0] && regexp_len == prev_regexp_len[0] && + (memcmp(regexpbuf, prev_regexpbuf[0], regexp_len ) == 0)) + correctreg = reg[0]; + else + if (reg[1] && regexp_len == prev_regexp_len[1] && + (memcmp(regexpbuf, prev_regexpbuf[1], regexp_len ) == 0)) + correctreg = reg[1]; + else { + correctreg = reg[which_one] = + regcomp(regexpbuf, prev_regexpbuf[which_one], 1024); + memcpy(prev_regexpbuf[which_one], regexpbuf, regexp_len); + prev_regexp_len[which_one] = regexp_len; + which_one = (which_one + 1) & 0x1; + } +#else + + /* this is optimized code which assumes that the + regular expression is specified in the router + and the packet specifies the string */ + + /* change the order to in1 being the string, in2 the regex*/ + if (in1->type == DRT_CLASS_DOMAIN_REGEX) { + tlv_domain *temp = in1; + in1 = in2; + in2 = temp; + } + + /* in1 has string, in2 regex */ + + if (reg[0] && in2->len == prev_regexp_len[0] && + (memcmp(in2->str, prev_regexpbuf[0], in2->len) == 0)) + correctreg = reg[0]; + else if (reg[1] && in2->len == prev_regexp_len[1] && + (memcmp(in2->str, prev_regexpbuf[1], in2->len ) == 0)) + correctreg = reg[1]; + else { + memcpy(regexpbuf, in2->str, in2->len); + regexpbuf[in2->len] = '\0'; + correctreg = reg[which_one] = + regcomp(regexpbuf, prev_regexpbuf[which_one], 1024); + memcpy(prev_regexpbuf[which_one], regexpbuf, regexp_len); + prev_regexp_len[which_one] = regexp_len; + which_one = (which_one + 1) & 0x1; + } + + memcpy(inputstr, in1->str, in1->len); + inputstr[in1->len] = '\0'; + +#endif + + if (!correctreg){ + PRINT2("Error in parsing regular expression %d \n", 1); + } + /* DONT HAVE TO FREE SINCE A POINTER TO INTERNAL BUFFER + IS BEING RETURNED */ + reti = regexec(correctreg, inputstr); + if (reti) { + *match_len_ret = in1->len; + return 1; + } else { + *match_len_ret = 0; + return 0; + } + } + + /* should never come here */ + return 0; +} + +void domain_print(tlv_domain *in) { + char *s; + if ( !in + || (in->type != DRT_CLASS_DOMAIN_STD + && in->type != DRT_CLASS_DOMAIN_REGEX) + || !in->str ) + return; + + s = (char *)TLVMALLOC(in->len + 1, ALLOC_SHORTTERM); + memcpy(s, in->str, in->len); + s[in->len] = '\0'; + if (in->type == DRT_CLASS_DOMAIN_REGEX){ + PRINT2("[%s, DOMAIN_REGEX, ", + (in->returnflag == DRT_RETURNFLAG_MATCH)? + "MATCH":"INPUT"); + PRINT2("%d,", in->len); + PRINT2("%s]", s); + } else { + PRINT2("[%s, DOMAIN_STD, ", + (in->returnflag == DRT_RETURNFLAG_MATCH)? + "MATCH":"INPUT"); + PRINT2("%d,", in->len); + PRINT2("%s]", s); + } + TLVFREE(s, ALLOC_SHORTTERM); + + return; +} + +/****************** +generic top level functions +*******************/ + +uint32_t tlv_serialized_size(tlv *in) { + uint32_t size; + + if (!in) return 0; + + switch(in->base.type) { + case DRT_CLASS_HASH: + size = hash_serialized_size((tlv_hash *)in); + break; + case DRT_CLASS_RANGE: + size = range_serialized_size((tlv_range *)in); + break; + case DRT_CLASS_DOMAIN_STD: + case DRT_CLASS_DOMAIN_REGEX: + size = domain_serialized_size((tlv_domain *)in); + break; + default: + size = 0; + break; + } + + return size; +} + +uint32_t tlv_serialize(tlv *in, char *data, int len){ + uint32_t size = 0; + + if (!in) return 0; + + switch(((tlv_base *)in)->type){ + case DRT_CLASS_HASH: + if (hash_serialized_size((tlv_hash *)in) > len) + size = 0; + else + size = hash_serialize((tlv_hash *)in, data, len); + break; + case DRT_CLASS_RANGE: + if (range_serialized_size((tlv_range *)in) > len) + size = 0; + else + size = range_serialize((tlv_range *)in, data, len); + break; + case DRT_CLASS_DOMAIN_STD: + case DRT_CLASS_DOMAIN_REGEX: + if (domain_serialized_size((tlv_domain *)in) > len) + size = 0; + else + size = domain_serialize((tlv_domain *)in, data, len); + break; + default: + size = 0; + break; + } + + return size; +} + +uint32_t tlv_unserialize(tlv **in, char *data, int len, int term){ + uint32_t size = 0; + u_char *p = (u_char *)(data); + + if (!in) return 0; + *in = NULL; + + + switch(p[0]){ + case DRT_CLASS_HASH: + size = hash_unserialize(in, data, len, term); + break; + case DRT_CLASS_RANGE: + size = range_unserialize(in, data, len, term); + break; + case DRT_CLASS_DOMAIN_STD: + case DRT_CLASS_DOMAIN_REGEX: + size = domain_unserialize(in, data, len, term); + break; + default: + PRINT2("Unsupported TLV type %d", p[0]); + break; + } + + return size; +} + +uint32_t tlv_match(tlv *in1, tlv *in2, int preferred_match, int *match_len) { + uint32_t res = 0; + + if (!in1 || !in2 || !match_len) + return 0; + + if (preferred_match != 0){ + if ( + (preferred_match != DRT_MATCH_EXACT) && + (preferred_match != DRT_MATCH_SUBSTRING) && + (preferred_match != DRT_MATCH_LONGEST) && + (preferred_match != DRT_MATCH_RANGE) + ){ + return 0; + } + } + + switch(in1->base.type) { + case DRT_CLASS_HASH: + if (in2->base.type == DRT_CLASS_HASH){ + res = hash_match((tlv_hash *)in1, (tlv_hash *)in2, + preferred_match, match_len); + } else if (in2->base.type == DRT_CLASS_RANGE){ + res = range_match(in1, (tlv_range *)in2, + preferred_match, match_len); + } + break; + case DRT_CLASS_RANGE: + /* you cant match a range against a hash value. + so directly go to the range_match. */ + res = range_match(in1, (tlv_range *)in2, + preferred_match, match_len); + break; + case DRT_CLASS_DOMAIN_STD: + case DRT_CLASS_DOMAIN_REGEX: + res = domain_match((tlv_domain *)in1, (tlv_domain *)in2, + preferred_match, match_len); + break; + default: + break; + } + + return res; +} + +void tlv_print(tlv *in) { + if (!in) return; + + switch(in->base.type) { + case DRT_CLASS_HASH: + hash_print((tlv_hash *)in); + break; + case DRT_CLASS_RANGE: + range_print((tlv_range *)in); + break; + case DRT_CLASS_DOMAIN_STD: + case DRT_CLASS_DOMAIN_REGEX: + domain_print((tlv_domain *)in); + break; + default: + PRINT2("Unsupported TLV type %d", in->base.type); + break; + } + + return; +} Index: sys/netinet/tlv.h =================================================================== RCS file: sys/netinet/tlv.h diff -N sys/netinet/tlv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/netinet/tlv.h 7 Jun 2005 00:06:04 -0000 1.1 @@ -0,0 +1,139 @@ +#ifndef _TLB_H__ +#define _TLB_H__ +/* users of this must define their own TLVMALLOC, PRINT2 + used as PRINT1("...") + used as PRINT2("...", x) +*/ + +#ifdef _KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#else +#include +#include +#endif + +/* +#ifndef PRINT2 +#define PRINT2(x, y) printf(x, y) +#endif +*/ + +extern int refcount; +extern char mallocbuf[1024]; + +#define ALLOC_SHORTTERM 1 +#define ALLOC_LONGTERM 2 +void *TLVMALLOC(int x, int term); +void TLVFREE(void *x, int term) ; + +#define ROUNDUP(x) ((x % 4)? (((x) + 4) & ~0x3): (x)) + +#define DRT_CLASS_NONE 0 +#define DRT_CLASS_HASH 1 +#define DRT_CLASS_DOMAIN_STD 2 /* this is just a string */ +#define DRT_CLASS_DOMAIN_REGEX 3 /* this is a regular expression */ +#define DRT_CLASS_RANGE 4 /* this could be but it is not + necessary to be used with the + search */ + +#define DRT_MATCH_EXACT 1 +#define DRT_MATCH_SUBSTRING 2 +#define DRT_MATCH_LONGEST 3 +#define DRT_MATCH_RANGE 4 + +/* upon lookup match, what should be returned? */ +#define DRT_RETURNFLAG_MATCH 0 +#define DRT_RETURNFLAG_INPUT 1 + + +typedef struct { + u_char type; + u_char match; + u_char len; + u_char returnflag; /* meaningful only at the host. */ +} tlv_base; + +typedef struct { + u_char type; + u_char match; + u_char len; + u_char returnflag; /* meaningful only at the host. */ + uint32_t hash; +} tlv_hash; + +typedef struct { + u_char type; + u_char match; + u_char len; + u_char returnflag; /* meaningful only at the host. */ + uint32_t min; + uint32_t max; +} tlv_range; + +typedef struct { + u_char type; + u_char match; + u_char len; + u_char returnflag; /* meaningful only at the host. */ + char *str; +} tlv_domain; + +typedef union { + tlv_base base; + tlv_hash hash; + tlv_range range; + tlv_domain domain; +} tlv; + + +uint32_t range_serialized_size(tlv_range *in); +uint32_t range_serialize(tlv_range *in, char *data, int len) ; +uint32_t range_unserialize(tlv **in, char *data, int len, int term) ; +uint32_t range_match(tlv *in1, tlv_range *in2, + int preferred_match, int *match_len); +void range_print(tlv_range *in) ; + +uint32_t hash_serialized_size(tlv_hash *in); +uint32_t hash_serialize(tlv_hash *in, char *data, int len) ; +uint32_t hash_unserialize(tlv **in, char *data, int len, int term) ; +uint32_t hash_match(tlv_hash *in1, tlv_hash *in2, + int preferred_match, int *match_len); +void hash_print(tlv_hash *in) ; + +uint32_t domain_serialized_size(tlv_domain *in); +uint32_t domain_serialize(tlv_domain *in, char *data, int len) ; +uint32_t domain_unserialize(tlv **in, char *data, int len, int term) ; +uint32_t domain_match(tlv_domain *in1, tlv_domain *in2, + int preferred_match, int *match_len); +void domain_print(tlv_domain *in) ; + +uint32_t tlv_serialized_size(tlv *in) ; +uint32_t tlv_serialize(tlv *in, char *data, int len); +uint32_t tlv_unserialize(tlv **in, char *data, int len, int term); +uint32_t tlv_match(tlv *in1, tlv *in2, + int preferred_match, int *match_len); + +void tlv_print(tlv *in); + +#endif Index: sys/netinet/udp_usrreq.c =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/netinet/udp_usrreq.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/netinet/udp_usrreq.c 6 Jun 2005 21:58:17 -0000 1.1.1.1 +++ sys/netinet/udp_usrreq.c 7 Jun 2005 00:06:04 -0000 1.2 @@ -33,6 +33,7 @@ #include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_mac.h" +#include "opt_datarouting.h" #include #include @@ -202,6 +203,7 @@ len = ntohs((u_short)uh->uh_ulen); if (ip->ip_len != len) { if (len > ip->ip_len || len < sizeof(struct udphdr)) { + if (0) log(LOG_INFO, "length mismatch len %d ip_len = %d \n", len, ip->ip_len); udpstat.udps_badlen++; goto badunlocked; } @@ -236,6 +238,7 @@ bcopy(b, ((struct ipovly *)ip)->ih_x1, 9); } if (uh->uh_sum) { + if (0) log(LOG_INFO, "bad checksum\n"); udpstat.udps_badsum++; m_freem(m); return; @@ -996,6 +999,7 @@ return EINVAL; } INP_LOCK(inp); + if (inp->inp_faddr.s_addr != INADDR_ANY) { INP_UNLOCK(inp); INP_INFO_WUNLOCK(&udbinfo); Index: sys/sys/socket.h =================================================================== RCS file: /home/xbone/CVSROOT/data-router/kernel-5.4/sys/sys/socket.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sys/sys/socket.h 6 Jun 2005 21:58:40 -0000 1.1.1.1 +++ sys/sys/socket.h 7 Jun 2005 00:06:05 -0000 1.2 @@ -205,7 +205,8 @@ #define AF_SCLUSTER 34 /* Sitara cluster protocol */ #define AF_ARP 35 #define AF_BLUETOOTH 36 /* Bluetooth sockets */ -#define AF_MAX 37 +#define AF_DATAROUTE 37 /* Data Router options */ +#define AF_MAX 38 #endif /* @@ -291,6 +292,8 @@ #define PF_ARP AF_ARP #define PF_BLUETOOTH AF_BLUETOOTH +#define PF_DATAROUTE AF_DATAROUTE + #define PF_MAX AF_MAX /* @@ -339,6 +342,7 @@ { "netgraph", CTLTYPE_NODE }, \ { "snp", CTLTYPE_NODE }, \ { "scp", CTLTYPE_NODE }, \ + { "dataroute", CTLTYPE_NODE } \ } /* @@ -364,6 +368,24 @@ } #endif /* __BSD_VISIBLE */ +#ifdef DATA_ROUTING +#define NET_DRT_ADD 1 +#define NET_DRT_DUMP 2 +#define NET_DRT_DEL 3 +#define NET_DRT_UPDATE 4 +#define NET_DRT_FLUSH 5 + +#define CTL_NET_DRT_NAMES { \ + { 0, 0 }, \ + { "add", CTLTYPE_STRUCT }, \ + { "dump", CTLTYPE_STRUCT }, \ + { "del", CTLTYPE_STRUCT }, \ + { "update", CTLTYPE_STRUCT }, \ + { "flush", CTLTYPE_STRUCT } \ +} + +#endif + /* * Maximum queue length specifiable by listen. */