[Lguest] rng / netmask / tapdev name patches

Philip Sanderson philip.k.sanderson at gmail.com
Wed Dec 1 23:26:34 EST 2010


Hello,

Here's some random patches for your consideration :-)

First patch allows you to specify the source of the random numbers instead
of /dev/random. Using /dev/urandom is faster and doesn't exhaust hosts
entropy, or you could specify /dev/hwrng for direct access, etc.

--- lguest.c.orig       2010-12-01 19:48:18.212001069 +1100
+++ lguest.c    2010-12-01 19:52:15.325002565 +1100
@@ -1802,13 +1802,13 @@
 /*L:199
  * This creates a "hardware" random number device for the Guest.
  */
-static void setup_rng(void)
+static void setup_rng(char *rng_source)
 {
        struct device *dev;
        struct rng_info *rng_info = malloc(sizeof(*rng_info));

-       /* Our device's privat info simply contains the /dev/random fd. */
-       rng_info->rfd = open_or_die("/dev/random", O_RDONLY);
+       /* Our device's privat info simply contains the rng_source fd. */
+       rng_info->rfd = open_or_die(rng_source, O_RDONLY);

        /* Create the new device. */
        dev = new_device("rng", VIRTIO_ID_RNG);
@@ -1817,7 +1817,7 @@
        /* The device has one virtqueue, where the Guest places inbufs. */
        add_virtqueue(dev, VIRTQUEUE_NUM, rng_input);

-       verbose("device %u: rng\n", devices.device_num++);
+       verbose("device %u: rng from %s\n", devices.device_num++,
rng_source);
 }
 /* That's the end of device setup. */

@@ -1885,6 +1885,7 @@
        { "tunnet", 1, NULL, 't' },
        { "block", 1, NULL, 'b' },
        { "rng", 0, NULL, 'r' },
+       { "rng-source", 1, NULL, 's' },
        { "initrd", 1, NULL, 'i' },
        { "username", 1, NULL, 'u' },
        { "chroot", 1, NULL, 'c' },
@@ -1916,6 +1917,9 @@
        /* Directory to chroot to */
        char *chroot_path = NULL;

+       /* RNG source, defaults to /dev/random */
+       char *rng_source = "/dev/random";
+
        /* Save the args: we "reboot" by execing ourselves again. */
        main_args = argv;

@@ -1966,8 +1970,11 @@
                case 'b':
                        setup_block_file(optarg);
                        break;
+               case 's':
+                       rng_source = optarg;
+                       break;
                case 'r':
-                       setup_rng();
+                       setup_rng(rng_source);
                        break;
                case 'i':
                        initrd_name = optarg;



This patch allows you to specify the tap device name -- useful for iptables
-i interface and long lived rules.



--- lguest.c.rng        2010-12-01 20:24:44.577001373 +1100
+++ lguest.c    2010-12-01 20:22:24.924001823 +1100
@@ -1482,7 +1482,8 @@
         */
        netfd = open_or_die("/dev/net/tun", O_RDWR);
        ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
-       strcpy(ifr.ifr_name, "tap%d");
+       strcpy(ifr.ifr_name, tapif);
        if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
                err(1, "configuring /dev/net/tun");

@@ -1506,7 +1507,7 @@
  * packets into the Host as if they came in from a normal network card.  We
  * just shunt packets between the Guest and the tun device.
  */
-static void setup_tun_net(char *arg)
+static void setup_tun_net(char *arg, char *tapdev_name)
 {
        struct device *dev;
        struct net_info *net_info = malloc(sizeof(*net_info));
@@ -1516,6 +1517,10 @@
        char tapif[IFNAMSIZ], *p;
        struct virtio_net_config conf;

+       /* Copy over the device name we are going to use */
+       strncpy(tapif, tapdev_name, IFNAMSIZ);
+       tapif[IFNAMSIZ-1] = '\0';
+
        net_info->tunfd = get_tun_device(tapif);

        /* First we create a new network device. */
@@ -1882,6 +1887,7 @@

 static struct option opts[] = {
        { "verbose", 0, NULL, 'v' },
+       { "tap-name", 1, NULL, 'd' },
        { "tunnet", 1, NULL, 't' },
        { "block", 1, NULL, 'b' },
        { "rng", 0, NULL, 'r' },
@@ -1920,6 +1926,9 @@
        /* RNG source, defaults to /dev/random */
        char *rng_source = "/dev/random";

+       /* The device name to set in setup_tun_net */
+       char *tap_name = "tap%d";
+
        /* Save the args: we "reboot" by execing ourselves again. */
        main_args = argv;

@@ -1964,8 +1973,11 @@
                case 'v':
                        verbose = true;
                        break;
+               case 'd':
+                       tap_name = optarg;
+                       break;
                case 't':
-                       setup_tun_net(optarg);
+                       setup_tun_net(optarg, tap_name);
                        break;
                case 'b':
                        setup_block_file(optarg);


This patch allows you to specify the netmask on the command line. Useful if
you don't want to assign the default netmask class to the instance. (ie, /31
or /30's).

--- lguest.c.tapdev     2010-12-01 20:27:13.462001086 +1100
+++ lguest.c    2010-12-01 20:53:24.990000713 +1100
@@ -1447,7 +1447,7 @@
  * it up so packets will flow, the copies the MAC address into the hwaddr
  * pointer.
  */
-static void configure_device(int fd, const char *tapif, u32 ipaddr)
+static void configure_device(int fd, const char *tapif, u32 ipaddr, u32
netmask)
 {
        struct ifreq ifr;
        struct sockaddr_in sin;
@@ -1459,8 +1459,26 @@
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = htonl(ipaddr);
        memcpy(&ifr.ifr_addr, &sin, sizeof(sin));
+
        if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
                err(1, "Setting %s interface address", tapif);
+
+       if(netmask) {
+               sin.sin_addr.s_addr = htonl(netmask);
+               memcpy(&ifr.ifr_netmask, &sin, sizeof(sin));
+
+               if(ioctl(fd, SIOCSIFNETMASK, &ifr) != 0)
+                       err(1, "Setting %s interface netmask", tapif);
+
+               /* Set the broadcast address, otherwise it will be incorrect
:/ */
+               sin.sin_addr.s_addr = htonl(ipaddr | ~(0xffffffff &
netmask));
+               memcpy(&ifr.ifr_broadaddr, &sin, sizeof(sin));
+
+               if(ioctl(fd, SIOCSIFBRDADDR, &ifr) != 0)
+                       err(1, "Setting %s interface broadcast", tapif);
+
+       }
+
        ifr.ifr_flags = IFF_UP;
        if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
                err(1, "Bringing interface %s up", tapif);
@@ -1513,6 +1531,7 @@
        struct net_info *net_info = malloc(sizeof(*net_info));
        int ipfd;
        u32 ip = INADDR_ANY;
+       u32 nm = 0;
        bool bridging = false;
        char tapif[IFNAMSIZ], *p;
        struct virtio_net_config conf;
@@ -1553,14 +1572,25 @@
                *p = '\0';
        }

-       /* arg is now either an IP address or a bridge name */
-       if (bridging)
+       /* arg is now either an IP address(/netmask) or a bridge name */
+       if (bridging) {
                add_to_bridge(ipfd, tapif, arg);
-       else
+       } else {
+               p = strchr(arg, '/');
+               if(p) {
+                       /* Calculate the netmask */
+                       int shift = 0;
+                       shift = atoi(p+1);
+                       nm = ~(0xffffffff >> shift);
+
+                       *p = 0;
+               }
+
                ip = str2ip(arg);
+       }

        /* Set up the tun device. */
-       configure_device(ipfd, tapif, ip);
+       configure_device(ipfd, tapif, ip, nm);

        add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
        /* Expect Guest to handle everything except UFO */


And here's some additional documentation :-)

--- lguest.txt.orig     2010-12-01 20:58:32.555001127 +1100
+++ lguest.txt  2010-12-01 21:05:16.253000679 +1100
@@ -83,7 +83,13 @@
        can also use a standard bzImage.

     --tunnet=192.168.19.1: configures a "tap" device for networking with
this
-       IP address.
+       IP address. You can specify the netmask in CIDR notation as
+       --tunnet=192.168.19.1/30
+
+       If you require the ability to specify the tap device name, the
option
+       --tap-name example0 can be specified before --tunnet. This can be
+       useful if you are running multiple lguest's, and are using
+       iptables.

     --block=rootfile: a file or block device which becomes /dev/vda
        inside the guest.
@@ -114,10 +120,15 @@
   See http://linux-net.osdl.org/index.php/Bridge for general information
   on how to get bridging working.

-- Random number generation. Using the --rng option will provide a
-  /dev/hwrng in the guest that will read from the host's /dev/random.
-  Use this option in conjunction with rng-tools (see ../hw_random.txt)
-  to provide entropy to the guest kernel's /dev/random.
+- Random number generation. Using the --rng option will provide a
/dev/hwrng
+  in the guest that will read from the host's /dev/random.  Use this option
in
+  conjunction with rng-tools (see ../hw_random.txt) to provide entropy to
the
+  guest kernel's /dev/random. You may specify --rng-source before --rng to
+  change the source of the random numbers.  Specifying /dev/urandom has the
+  advantage of being faster and does not allow malicious guests to exhaust
the
+  hosts entropy pool, however the quality of the randomness may be reduced.
+  Another use of this option is to allow direct access to the hardware
random
+  number generator on the host.

 There is a helpful mailing list at
http://ozlabs.org/mailman/listinfo/lguest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/lguest/attachments/20101201/f337b2d2/attachment.html>


More information about the Lguest mailing list