2.4.9: let Net Devices feed Entropy (1/2)
Subsystems (2)
PATCH 1/1 2.4.9: let Net Devices feed Entropy (1/2)
against 2.4.9. 2.4.8-ac7 patches available in previous thread.
the following patch is a rediff of my previous patch, now against 2.4.9. for those who are new, this patch allows user configuration of whether net devices contribute to the entropy pool (/dev/random) by introducing a new flag for request_irq, SA_SAMPLE_NET_RANDOM. this flag is defines to SA_SAMPLE_RANDOM or 0 depending on the value of CONFIG_NET_RANDOM which is configurable from Net Devices.
this is part 1, which is required. part 2 updates a handfull of devices to use the new flag. all net devices (drivers/net/*.c) should be updated.
Documentation/Configure.help +13 -0
@@ -7728,6 +7728,19 @@ If you don't know what to use this for, you don't need it. +Allow Net Devices to contribute to /dev/random +CONFIG_NET_RANDOM + If you say Y here, network device interrupts will contribute to the + kernel entropy pool at /dev/random. Normally, block devices and + some other devices (keyboard, mouse) add to the pool. Some people, + however, feel that network devices should not contribute to /dev/random + because an external attacker could manipulate incoming packets in a + manner to force the pool into a determinable state. Note this is + completely theoretical. + + If you don't mind the risk or are using a headless system and are in + need of more entropy, say Y. + Ethertap network tap (OBSOLETE) CONFIG_ETHERTAP If you say Y here (and have said Y to "Kernel/User network link
drivers/net/Config.in +1 -0
@@ -9,6 +9,7 @@ tristate 'Bonding driver support' CONFIG_BONDING tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER tristate 'Universal TUN/TAP device driver support' CONFIG_TUN +bool 'Allow Net Devices to contribute to /dev/random' CONFIG_NET_RANDOM if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_NETLINK" = "y" ]; then tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP
include/asm-alpha/signal.h +12 -0
@@ -121,8 +121,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x40000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 1/* for blocking signals */ #define SIG_UNBLOCK 2/* for unblocking signals */ #define SIG_SETMASK 3/* for setting the signal mask */
include/asm-arm/signal.h +12 -0
@@ -124,8 +124,20 @@#define SA_SAMPLE_RANDOM 0x10000000#define SA_IRQNOMASK 0x08000000#define SA_SHIRQ 0x04000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 0/* for blocking signals */ #define SIG_UNBLOCK 1/* for unblocking signals */ #define SIG_SETMASK 2/* for setting the signal mask */
include/asm-cris/signal.h +12 -0
@@ -120,8 +120,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 0/* for blocking signals */ #define SIG_UNBLOCK 1/* for unblocking signals */ #define SIG_SETMASK 2/* for setting the signal mask */
include/asm-i386/signal.h +12 -0
@@ -119,8 +119,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 0/* for blocking signals */ #define SIG_UNBLOCK 1/* for unblocking signals */ #define SIG_SETMASK 2/* for setting the signal mask */
include/asm-ia64/signal.h +11 -0
@@ -106,6 +106,17 @@#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0 +#endif +#endif /* __KERNEL__ */ #define SIG_BLOCK 0/* for blocking signals */
include/asm-m68k/signal.h +12 -0
@@ -116,8 +116,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 0/* for blocking signals */ #define SIG_UNBLOCK 1/* for unblocking signals */ #define SIG_SETMASK 2/* for setting the signal mask */
include/asm-mips/signal.h +11 -0
@@ -111,6 +111,17 @@#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x02000000 +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0 +#endif +#endif /* __KERNEL__ */ #define SIG_BLOCK 1/* for blocking signals */
include/asm-mips64/signal.h +11 -0
@@ -112,6 +112,17 @@#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x02000000 +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0 +#endif +#endif /* __KERNEL__ */ #define SIG_BLOCK 1/* for blocking signals */
include/asm-parisc/signal.h +11 -0
@@ -100,6 +100,17 @@#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0 +#endif +#endif /* __KERNEL__ */ #define SIG_BLOCK 0/* for blocking signals */
include/asm-ppc/signal.h +12 -0
@@ -114,8 +114,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 0/* for blocking signals */ #define SIG_UNBLOCK 1/* for unblocking signals */ #define SIG_SETMASK 2/* for setting the signal mask */
include/asm-s390/signal.h +12 -0
@@ -127,8 +127,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 0/* for blocking signals */ #define SIG_UNBLOCK 1/* for unblocking signals */ #define SIG_SETMASK 2/* for setting the signal mask */
include/asm-s390x/signal.h +12 -0
@@ -127,8 +127,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 0/* for blocking signals */ #define SIG_UNBLOCK 1/* for unblocking signals */ #define SIG_SETMASK 2/* for setting the signal mask */
include/asm-sh/signal.h +12 -0
@@ -107,8 +107,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_SHIRQ 0x04000000 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +#define SIG_BLOCK 0/* for blocking signals */ #define SIG_UNBLOCK 1/* for unblocking signals */ #define SIG_SETMASK 2/* for setting the signal mask */
include/asm-sparc/signal.h +12 -0
@@ -176,8 +176,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_STATIC_ALLOC 0x80 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +/* Type of a signal handler. */ #ifdef __KERNEL__typedef void (*__sighandler_t )(int ,int ,struct sigcontext *,char *);
include/asm-sparc64/signal.h +12 -0
@@ -192,8 +192,20 @@#define SA_PROBE SA_ONESHOT#define SA_SAMPLE_RANDOM SA_RESTART#define SA_STATIC_ALLOC 0x80 + +/* +* Net Devices can use SA_SAMPLE_NET_RANDOM and thus only +* contribute to the kernel entropy pool if users want that +* at compile time. +*/ +#ifdef CONFIG_NET_RANDOM +#define SA_SAMPLE_NET_RANDOM SA_SAMPLE_RANDOM +#else +#define SA_SAMPLE_NET_RANDOM 0#endif +#endif /* __KERNEL__ */ +/* Type of a signal handler. */ #ifdef __KERNEL__typedef void (*__sighandler_t )(int ,struct sigcontext *);
Signature · 3 lines
Robert M. Love rml at ufl.edu rml at tech9.net
PATCH 1/1 2.4.9: let Net Devices feed Entropy (2/2)
part 2 of 2, against 2.4.9. see previous email, old thread, or
http://tech9.net/rml/linux for more information.
this patch enables the 3c501, 3c505, 3c509, 3c523, 3c59x, 8139too, cs89x0, eepro, eepro100, eexpress, ibmlana, ne2k-pci, pcnet_cs, xircom_tulic_cb, sk_mca, smc9194, tulic_core, and wavelan drivers to use the new flag. all of the drivers which previously contributed entropy are listed above. None of these drivers will contribute unless you enable the configuration setting
**We need all net drivers to use the new flag. I am accepting patches.
drivers/net/3c501.c +2 -1
@@ -410,7 +410,8 @@if (el_debug >2 )printk ("%s: Doing el_open()..." , dev->name); -if ((retval =request_irq (dev->irq, &el_interrupt,0 , dev->name, dev))) +if ((retval =request_irq (dev->irq, &el_interrupt, +SA_SAMPLE_NET_RANDOM , dev->name, dev)))return retval;spin_lock_irqsave (&lp->lock, flags);
drivers/net/3c505.c +2 -1
@@ -897,7 +897,8 @@/* * install our interrupt service routine */ -if ((retval =request_irq (dev->irq, &elp_interrupt,0 , dev->name, dev))) { +if ((retval =request_irq (dev->irq, &elp_interrupt, +SA_SAMPLE_NET_RANDOM , dev->name, dev))) {printk (KERN_ERR "%s: could not allocate IRQ%d\n" , dev->name, dev->irq);return retval; }
drivers/net/3c509.c +2 -1
@@ -560,7 +560,8 @@outw (RxReset, ioaddr +EL3_CMD );outw (SetStatusEnb |0x00 , ioaddr +EL3_CMD ); - i =request_irq (dev->irq, &el3_interrupt,0 , dev->name, dev); + i =request_irq (dev->irq, &el3_interrupt, +SA_SAMPLE_NET_RANDOM , dev->name, dev);if (i)return i;EL3WINDOW (0 );
drivers/net/3c523.c +1 -1
@@ -280,7 +280,7 @@elmc_id_attn586 ();/* disable interrupts */ - ret =request_irq (dev->irq, &elmc_interrupt,SA_SHIRQ |SA_SAMPLE_RANDOM , + ret =request_irq (dev->irq, &elmc_interrupt,SA_SHIRQ |SA_SAMPLE_NET_RANDOM , dev->name, dev);if (ret) {printk (KERN_ERR "%s: couldn't get irq %d\n" , dev->name, dev->irq);
drivers/net/3c59x.c +1 -1
@@ -1581,7 +1581,7 @@/* Use the now-standard shared IRQ implementation. */ if ((retval =request_irq (dev->irq, vp->full_bus_master_rx ? - &boomerang_interrupt : &vortex_interrupt,SA_SHIRQ , dev->name, dev))) { + &boomerang_interrupt : &vortex_interrupt,SA_SHIRQ |SA_SAMPLE_NET_RANDOM , dev->name, dev))) {printk (KERN_ERR "%s: Could not reserve IRQ %d\n" , dev->name, dev->irq); goto out; }
drivers/net/8139too.c +2 -1
@@ -1289,7 +1289,8 @@DPRINTK ("ENTER\n" ); - retval =request_irq (dev->irq, rtl8139_interrupt,SA_SHIRQ , dev->name, dev); + retval =request_irq (dev->irq, rtl8139_interrupt, +SA_SHIRQ |SA_SAMPLE_NET_RANDOM , dev->name, dev);if (retval) {DPRINTK ("EXIT, returning %d\n" , retval);return retval;
drivers/net/cs89x0.c +1 -1
@@ -1057,7 +1057,7 @@for (i =2 ; i <CS8920_NO_INTS ; i++) {if ((1 << dev->irq) & lp->irq_map) { -if (request_irq (i, net_interrupt,0 , dev->name, dev) ==0 ) { +if (request_irq (i, net_interrupt,SA_SAMPLE_NET_RANDOM , dev->name, dev) ==0 ) { dev->irq = i;write_irq (dev, lp->chip_type, i);/* writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); */
drivers/net/eepro.c +2 -1
@@ -944,7 +944,8 @@return -EAGAIN ; } -if (request_irq (dev->irq , &eepro_interrupt,0 , dev->name, dev)) { +if (request_irq (dev->irq , &eepro_interrupt,SA_SAMPLE_NET_RANDOM , + dev->name, dev)) {printk ("%s: unable to get IRQ %d.\n" , dev->name, dev->irq);return -EAGAIN ; }
drivers/net/eepro100.c +2 -1
@@ -932,7 +932,8 @@ sp->in_interrupt =0 ;/* .. we can safely take handler calls during init. */ - retval =request_irq (dev->irq, &speedo_interrupt,SA_SHIRQ , dev->name, dev); + retval =request_irq (dev->irq, &speedo_interrupt, +SA_SHIRQ |SA_SAMPLE_NET_RANDOM , dev->name, dev);if (retval) {MOD_DEC_USE_COUNT ;return retval;
drivers/net/eexpress.c +2 -1
@@ -433,7 +433,8 @@if (!dev->irq || !irqrmap[dev->irq])return -ENXIO ; - ret =request_irq (dev->irq,&eexp_irq,0 ,dev->name,dev); + ret =request_irq (dev->irq,&eexp_irq,SA_SAMPLE_NET_RANDOM , + dev->name,dev);if (ret)return ret;request_region (ioaddr,EEXP_IO_EXTENT ,"EtherExpress" );
drivers/net/ibmlana.c +1 -1
@@ -856,7 +856,7 @@ result =request_irq (priv->realirq, irq_handler, -SA_SHIRQ |SA_SAMPLE_RANDOM , dev->name, dev); +SA_SHIRQ |SA_SAMPLE_NET_RANDOM , dev->name, dev);if (result !=0 ) {printk ("%s: failed to register irq %d\n" , dev->name, dev->irq);
drivers/net/ne2k-pci.c +2 -1
@@ -387,7 +387,8 @@static int ne2k_pci_open (struct net_device *dev) { -int ret =request_irq (dev->irq, ei_interrupt,SA_SHIRQ , dev->name, dev); +int ret =request_irq (dev->irq, ei_interrupt, +SA_SHIRQ |SA_SAMPLE_NET_RANDOM , dev->name, dev);if (ret)return ret;
drivers/net/pcmcia/pcnet_cs.c +1 -1
@@ -977,7 +977,7 @@MOD_INC_USE_COUNT ;set_misc_reg (dev); -request_irq (dev->irq, ei_irq_wrapper,SA_SHIRQ , dev_info, dev); +request_irq (dev->irq, ei_irq_wrapper,SA_SHIRQ |SA_SAMPLE_NET_RANDOM , dev_info, dev); info->link_status =0x00 ; info->watchdog.function = &ei_watchdog;
drivers/net/pcmcia/xircom_tulip_cb.c +2 -1
@@ -768,7 +768,8 @@ {struct tulip_private *tp = (struct tulip_private *)dev->priv; -if (request_irq (dev->irq, &tulip_interrupt,SA_SHIRQ , dev->name, dev)) +if (request_irq (dev->irq, &tulip_interrupt, +SA_SHIRQ |SA_SAMPLE_NET_RANDOM , dev->name, dev))return -EAGAIN ;tulip_init_ring (dev);
drivers/net/sk_mca.c +1 -1
@@ -861,7 +861,7 @@/* register resources - only necessary for IRQ */ result =request_irq (priv->realirq, irq_handler, -SA_SHIRQ |SA_SAMPLE_RANDOM ,"sk_mca" , dev); +SA_SHIRQ |SA_SAMPLE_NET_RANDOM ,"sk_mca" , dev);if (result !=0 ) {printk ("%s: failed to register irq %d\n" , dev->name, dev->irq);
drivers/net/smc9194.c +1 -1
@@ -1019,7 +1019,7 @@ether_setup (dev);/* Grab the IRQ */ - retval =request_irq (dev->irq, &smc_interrupt,0 , dev->name, dev); + retval =request_irq (dev->irq, &smc_interrupt,SA_SAMPLE_NET_RANDOM , dev->name, dev);if (retval) {printk ("%s: unable to get IRQ %d (irqval=%d).\n" , dev->name, dev->irq, retval);
drivers/net/tulip/tulip_core.c +3 -1
@@ -504,7 +504,9 @@int retval;MOD_INC_USE_COUNT ; -if ((retval =request_irq (dev->irq, &tulip_interrupt,SA_SHIRQ , dev->name, dev))) { +if ((retval =request_irq (dev->irq, &tulip_interrupt, +SA_SHIRQ |SA_SAMPLE_NET_RANDOM , + dev->name, dev))) {MOD_DEC_USE_COUNT ;return retval; }
drivers/net/wavelan.c +2 -1
@@ -3897,7 +3897,8 @@return -ENXIO ; } -if (request_irq (dev->irq, &wavelan_interrupt,0 ,"WaveLAN" , dev) !=0 ) +if (request_irq (dev->irq, &wavelan_interrupt,SA_SAMPLE_NET_RANDOM , +"WaveLAN" , dev) !=0 ) {#ifdef DEBUG_CONFIG_ERROR printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n",
Signature · 3 lines
Robert M. Love rml at ufl.edu rml at tech9.net
Re: [PATCH] 2.4.9: let Net Devices feed Entropy (2/2)
Quoted 11 lines · Robert Love
part 2 of 2, against 2.4.9. see previous email, old thread, or
http://tech9.net/rml/linux for more information.this patch enables the 3c501, 3c505, 3c509, 3c523, 3c59x, 8139too, cs89x0, eepro, eepro100, eexpress, ibmlana, ne2k-pci,
pcnet_cs,xircom_tulic_cb,sk_mca, smc9194,tulic_core, and wavelan drivers to use the new flag. all of the drivers which previously contributed entropy are listed above. None of these drivers will contribute unless you enable the configuration setting**We need all net drivers to use the new flag. I am accepting patches.
I was bored, so...
All I can say is ':wn' ;)
Let me know if there are any problems with it.
Signature · 1 line
Ignacio Vazquez-Abrams <[email protected]>
patch: let net devices feed entropy for 2.2.19
In reply to Robert LoveHi,
In case anyone is interested, I have backported Robert Love's netdev_random patch to the 2.2 kernel. A patch against 2.2.19 can be found at:
ftp://ftp.cm.nu/pub/people/shane/linux-2.2.19-netdev_random.patch.gz
Regards,
Shane
Signature · 5 lines
Shane Wegner: [email protected] http://www.cm.nu/~shane/ PGP: 1024D/FFE3035D A0ED DAC4 77EC D674 5487 5B5C 4F89 9A4E FFE3 035D
Re: patch: let net devices feed entropy for 2.2.19
Quoted 6 lines · Shane Wegner
Hi,
In case anyone is interested, I have backported Robert Love's
netdev_randompatch to the 2.2 kernel. A patch against 2.2.19 can be found at:
ftp://ftp.cm.nu/pub/people/shane/linux-2.2.19-netdev_random.patch.gz
Hey, very good. I will take a look.
If you don't mind, I will put a link to it from my kernel patches list at http://tech9.net/rml/linux
Signature · 3 lines
Robert M. Love rml at ufl.edu rml at tech9.net