Your message dated Sun, 15 Jul 2018 21:37:05 +0000
with message-id <[email protected]>
and subject line Bug#884716: fixed in klibc 2.0.4-12
has caused the Debian Bug report #884716,
regarding klibc-utils: Please support classless static routes (RFC3442)
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
884716: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=884716
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: klibc-utils
Version: 2.0.4-9
Severity: wishlist
Tags: upstream patch

Hi,

ipconfig from klibc-utils does not support classless static routes (as
specified in RFC3442). There is already an Ubuntu bug requesting that
feature and we also want to use it. I went ahead and implemented the
support and tested it. The patch is attached.

-- 
Benjamin Drung
System Developer
Debian & Ubuntu Developer

ProfitBricks GmbH
Greifswalder Str. 207
D - 10405 Berlin

Email: [email protected]
URL: https://www.profitbricks.de

Sitz der Gesellschaft: Berlin
Registergericht: Amtsgericht Charlottenburg, HRB 125506 B
Geschäftsführer: Achim Weiss, Matthias Steinberg
>From 2812cb5cd5f3c48b74e19fe07dde61c93fc8c85a Mon Sep 17 00:00:00 2001
From: Benjamin Drung <[email protected]>
Date: Wed, 13 Dec 2017 23:04:29 +0100
Subject: [PATCH] Implement classless static routes

Implement classless static routes support as specified in RFC3442.

Bug-Ubuntu: https://launchpad.net/bugs/1526956
Signed-off-by: Benjamin Drung <[email protected]>
---
 usr/kinit/ipconfig/bootp_proto.c | 112 +++++++++++++++++++++++++++++++++++++++
 usr/kinit/ipconfig/dhcp_proto.c  |   1 +
 usr/kinit/ipconfig/main.c        |  43 ++++++++++++---
 usr/kinit/ipconfig/netdev.c      |  45 +++++++++++-----
 usr/kinit/ipconfig/netdev.h      |  17 ++++++
 5 files changed, 197 insertions(+), 21 deletions(-)

diff --git a/usr/kinit/ipconfig/bootp_proto.c b/usr/kinit/ipconfig/bootp_proto.c
index 150ebfa7..ae050127 100644
--- a/usr/kinit/ipconfig/bootp_proto.c
+++ b/usr/kinit/ipconfig/bootp_proto.c
@@ -267,6 +267,87 @@ static char *bootp_ext119_decode(const void *ext, int16_t 
ext_size, void *tmp)
        return decoded_str;
 }
 
+/*
+ * DESCRIPTION
+ *  bootp_ext121_decode() decodes Classless Route Option data.
+ *
+ * ARGUMENTS
+ *  const uint8_t *ext
+ *   *ext is a pointer to a DHCP Classless Route Option data.
+ *   For example, if *ext is {16, 192, 168, 192, 168, 42, 1},
+ *   this function returns a pointer to
+ *   {
+ *     subnet = 192.168.0.0;
+ *     netmask_width = 16;
+ *     gateway = 192.168.42.1;
+ *     next = NULL;
+ *   }
+ *
+ *  int16_t ext_size
+ *   ext_size is the memory size of *ext. For example,
+ *   if *ext is {16, 192, 168, 192, 168, 42, 1}, ext_size must be 7.
+ *
+ * RETURN VALUE
+ *  if OK, a pointer to a decoded struct route malloc-ed
+ *  else , NULL
+ *
+ * SEE ALSO RFC3442
+ */
+struct route *bootp_ext121_decode(const uint8_t *ext, int16_t ext_size)
+{
+       int16_t index = 0;
+       uint8_t netmask_width;
+       uint8_t significant_octets;
+       struct route *routes = NULL;
+       struct route *prev_route = NULL;
+
+       while(index < ext_size) {
+               netmask_width = ext[index];
+               index++;
+               if(netmask_width > 32) {
+                       printf("IP-Config: Given Classless Route Option subnet 
mask width '%u' "
+                           "exceeds IPv4 limit of 32. Ignoring remaining 
option.\n",
+                               netmask_width);
+                       return routes;
+               }
+               significant_octets = netmask_width / 8 + (netmask_width % 8 > 
0);
+               if(ext_size - index < significant_octets + 4) {
+                       printf("IP-Config: Given Classless Route Option 
remaining lengths (%u octets) "
+                               "is shorter than the expected %u octets. 
Ignoring remaining options.\n",
+                               ext_size - index, significant_octets + 4);
+                       return routes;
+               }
+
+               struct route *route = malloc(sizeof(struct route));
+               if (route == NULL)
+                       return NULL;
+
+               /* convert only significant octets from array into network byte 
order */
+               route->subnet = 0;
+               memcpy(&route->subnet, &ext[index], significant_octets);
+               index += significant_octets;
+               /* RFC3442 demands: After deriving a subnet number and subnet 
mask from
+                  each destination descriptor, the DHCP client MUST zero any 
bits in
+                  the subnet number where the corresponding bit in the mask is 
zero. */
+               route->subnet &= netdev_genmask(netmask_width);
+
+               /* convert octet array into network byte order */
+               route->gateway = *(uint32_t*)&ext[index];
+               index += 4;
+
+               route->netmask_width = netmask_width;
+               route->next = NULL;
+
+               if (prev_route == NULL) {
+                       routes = route;
+               } else {
+                       prev_route->next = route;
+               }
+               prev_route = route;
+       }
+       return routes;
+}
+
 /*
  * Parse a bootp reply packet
  */
@@ -275,6 +356,8 @@ int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr,
 {
        uint8_t ext119_buf[BOOTP_EXTS_SIZE];
        int16_t ext119_len = 0;
+       uint8_t ext121_buf[BOOTP_EXTS_SIZE];
+       int16_t ext121_len = 0;
 
        dev->bootp.gateway      = hdr->giaddr;
        dev->ip_addr            = hdr->yiaddr;
@@ -367,6 +450,16 @@ int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr,
                                } else
                                        ext119_len = -1;
 
+                               break;
+                       case 121:       /* Classless Static Route Option 
(RFC3442) */
+                               if (ext121_len >= 0 &&
+                                   ext121_len + len <= sizeof(ext121_buf)) {
+                                       memcpy(ext121_buf + ext121_len,
+                                              ext, len);
+                                       ext121_len += len;
+                               } else
+                                       ext121_len = -1;
+
                                break;
                        }
 
@@ -385,6 +478,25 @@ int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr,
                }
        }
 
+       if (ext121_len > 0) {
+               struct route *ret;
+
+               ret = bootp_ext121_decode(ext121_buf, ext121_len);
+               if (ret != NULL) {
+                       if (dev->routes != NULL) {
+                               struct route *cur = dev->routes;
+                               struct route *next;
+                               while(cur->next != NULL) {
+                                       next = cur->next;
+                                       free(cur);
+                                       cur = next;
+                               }
+                               free(cur);
+                       }
+                       dev->routes = ret;
+               }
+       }
+
        /*
         * Got packet.
         */
diff --git a/usr/kinit/ipconfig/dhcp_proto.c b/usr/kinit/ipconfig/dhcp_proto.c
index ebf79cc0..ab7bdadc 100644
--- a/usr/kinit/ipconfig/dhcp_proto.c
+++ b/usr/kinit/ipconfig/dhcp_proto.c
@@ -26,6 +26,7 @@ static uint8_t dhcp_params[] = {
        28,                     /* broadcast addr */
        40,                     /* NIS domain name (why?) */
        119,                    /* Domain Search Option */
+       121,                    /* Classless Static Route Option (RFC3442) */
 };
 
 static uint8_t dhcp_discover_hdr[] = {
diff --git a/usr/kinit/ipconfig/main.c b/usr/kinit/ipconfig/main.c
index 7be2a1fc..0e12db4d 100644
--- a/usr/kinit/ipconfig/main.c
+++ b/usr/kinit/ipconfig/main.c
@@ -79,9 +79,22 @@ static void print_device_config(struct netdev *dev)
        printf(":\n address: %-16s ", my_inet_ntoa(dev->ip_addr));
        printf("broadcast: %-16s ", my_inet_ntoa(dev->ip_broadcast));
        printf("netmask: %-16s\n", my_inet_ntoa(dev->ip_netmask));
-       printf(" gateway: %-16s ", my_inet_ntoa(dev->ip_gateway));
-       printf("dns0     : %-16s ", my_inet_ntoa(dev->ip_nameserver[0]));
-       printf("dns1   : %-16s\n", my_inet_ntoa(dev->ip_nameserver[1]));
+       if (dev->routes != NULL) {
+               struct route *cur;
+               char *delim = "";
+               printf(" routes :");
+               for (cur = dev->routes; cur != NULL; cur = cur->next) {
+                       printf("%s %s/%u", delim, my_inet_ntoa(cur->subnet), 
cur->netmask_width);
+                       printf(" via %s", my_inet_ntoa(cur->gateway));
+                       delim = ",";
+               }
+               printf("\n dns0   : %-16s ", 
my_inet_ntoa(dev->ip_nameserver[0]));
+               printf("dns1     : %-16s\n", 
my_inet_ntoa(dev->ip_nameserver[1]));
+       } else {
+               printf(" gateway: %-16s ", my_inet_ntoa(dev->ip_gateway));
+               printf("dns0     : %-16s ", 
my_inet_ntoa(dev->ip_nameserver[0]));
+               printf("dns1   : %-16s\n", my_inet_ntoa(dev->ip_nameserver[1]));
+       }
        if (dev->hostname[0])
                printf(" host   : %-64s\n", dev->hostname);
        if (dev->dnsdomainname[0])
@@ -105,8 +118,8 @@ static void configure_device(struct netdev *dev)
        if (netdev_setaddress(dev))
                printf("IP-Config: failed to set addresses on %s\n",
                       dev->name);
-       if (netdev_setdefaultroute(dev))
-               printf("IP-Config: failed to set default route on %s\n",
+       if (netdev_setroutes(dev))
+               printf("IP-Config: failed to set routes on %s\n",
                       dev->name);
        if (dev->hostname[0] &&
                        sethostname(dev->hostname, strlen(dev->hostname)))
@@ -160,8 +173,24 @@ static void dump_device_config(struct netdev *dev)
                                my_inet_ntoa(dev->ip_broadcast));
                write_option(f, "IPV4NETMASK",
                                my_inet_ntoa(dev->ip_netmask));
-               write_option(f, "IPV4GATEWAY",
-                               my_inet_ntoa(dev->ip_gateway));
+               if (dev->routes != NULL) {
+                       /* Use 6 digits to encode the index */
+                       char key[23];
+                       char value[19];
+                       int i = 0;
+                       struct route *cur;
+                       for (cur = dev->routes; cur != NULL; cur = cur->next) {
+                               snprintf(key, sizeof(key), "IPV4ROUTE%iSUBNET", 
i);
+                               snprintf(value, sizeof(value), "%s/%u", 
my_inet_ntoa(cur->subnet), cur->netmask_width);
+                               write_option(f, key, value);
+                               snprintf(key, sizeof(key), 
"IPV4ROUTE%iGATEWAY", i);
+                               write_option(f, key, 
my_inet_ntoa(cur->gateway));
+                               i++;
+                       }
+               } else {
+                       write_option(f, "IPV4GATEWAY",
+                                       my_inet_ntoa(dev->ip_gateway));
+               }
                write_option(f, "IPV4DNS0",
                                my_inet_ntoa(dev->ip_nameserver[0]));
                write_option(f, "IPV4DNS1",
diff --git a/usr/kinit/ipconfig/netdev.c b/usr/kinit/ipconfig/netdev.c
index e203d0c6..446b4d87 100644
--- a/usr/kinit/ipconfig/netdev.c
+++ b/usr/kinit/ipconfig/netdev.c
@@ -88,23 +88,40 @@ static void set_s_addr(struct sockaddr *saddr, uint32_t 
ipaddr)
        memcpy(saddr, &sin, sizeof sin);
 }
 
-int netdev_setdefaultroute(struct netdev *dev)
+int netdev_setroutes(struct netdev *dev)
 {
        struct rtentry r;
 
-       if (dev->ip_gateway == INADDR_ANY)
-               return 0;
-
-       memset(&r, 0, sizeof(r));
-
-       set_s_addr(&r.rt_dst, INADDR_ANY);
-       set_s_addr(&r.rt_gateway, dev->ip_gateway);
-       set_s_addr(&r.rt_genmask, INADDR_ANY);
-       r.rt_flags = RTF_UP | RTF_GATEWAY;
-
-       if (ioctl(cfd, SIOCADDRT, &r) == -1 && errno != EEXIST) {
-               perror("SIOCADDRT");
-               return -1;
+       /* RFC3442 demands:
+          If the DHCP server returns both a Classless Static Routes option and
+          a Router option, the DHCP client MUST ignore the Router option. */
+       if (dev->routes != NULL) {
+               struct route *cur;
+               for (cur = dev->routes; cur != NULL; cur = cur->next) {
+                       memset(&r, 0, sizeof(r));
+
+                       set_s_addr(&r.rt_dst, cur->subnet);
+                       set_s_addr(&r.rt_gateway, cur->gateway);
+                       set_s_addr(&r.rt_genmask, 
netdev_genmask(cur->netmask_width));
+                       r.rt_flags = RTF_UP | RTF_GATEWAY;
+
+                       if (ioctl(cfd, SIOCADDRT, &r) == -1 && errno != EEXIST) 
{
+                               perror("SIOCADDRT");
+                               return -1;
+                       }
+               }
+       } else if (dev->ip_gateway != INADDR_ANY) {
+               memset(&r, 0, sizeof(r));
+
+               set_s_addr(&r.rt_dst, INADDR_ANY);
+               set_s_addr(&r.rt_gateway, dev->ip_gateway);
+               set_s_addr(&r.rt_genmask, INADDR_ANY);
+               r.rt_flags = RTF_UP | RTF_GATEWAY;
+
+               if (ioctl(cfd, SIOCADDRT, &r) == -1 && errno != EEXIST) {
+                       perror("SIOCADDRT");
+                       return -1;
+               }
        }
        return 0;
 }
diff --git a/usr/kinit/ipconfig/netdev.h b/usr/kinit/ipconfig/netdev.h
index cd853b6c..e909ef22 100644
--- a/usr/kinit/ipconfig/netdev.h
+++ b/usr/kinit/ipconfig/netdev.h
@@ -1,12 +1,20 @@
 #ifndef IPCONFIG_NETDEV_H
 #define IPCONFIG_NETDEV_H
 
+#include <arpa/inet.h>
 #include <sys/utsname.h>
 #include <net/if.h>
 
 #define BPLEN          256
 #define FNLEN          128                     /* from DHCP  RFC 2131 */
 
+struct route {
+       uint32_t subnet;                        /* subnet            */
+       uint32_t netmask_width; /* subnet mask width */
+       uint32_t gateway;               /* gateway           */
+       struct route *next;
+};
+
 struct netdev {
        const char *name;       /* Device name          */
        unsigned int ifindex;   /* interface index      */
@@ -44,6 +52,7 @@ struct netdev {
        char bootpath[BPLEN];   /* boot path            */
        char filename[FNLEN];   /* filename             */
        char *domainsearch;     /* decoded, NULL or malloc-ed  */
+       struct route *routes;   /* decoded, NULL or malloc-ed list */
        long uptime;            /* when complete configuration */
        struct netdev *next;    /* next configured i/f  */
 };
@@ -70,6 +79,7 @@ extern struct netdev *ifaces;
 int netdev_getflags(struct netdev *dev, short *flags);
 int netdev_setaddress(struct netdev *dev);
 int netdev_setdefaultroute(struct netdev *dev);
+int netdev_setroutes(struct netdev *dev);
 int netdev_up(struct netdev *dev);
 int netdev_down(struct netdev *dev);
 int netdev_init_if(struct netdev *dev);
@@ -83,4 +93,11 @@ static inline int netdev_running(struct netdev *dev)
        return ret ? 0 : !!(flags & IFF_RUNNING);
 }
 
+static inline uint32_t netdev_genmask(uint32_t netmask_width)
+{
+       /* Map netmask width to network mask in network byte order.
+          Example: 24 -> "255.255.255.0" -> htonl(0xFFFFFF00) */
+       return htonl(~((1u << (32 - netmask_width)) - 1));
+}
+
 #endif /* IPCONFIG_NETDEV_H */
-- 
2.14.1


--- End Message ---
--- Begin Message ---
Source: klibc
Source-Version: 2.0.4-12

We believe that the bug you reported is fixed in the latest version of
klibc, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Ben Hutchings <[email protected]> (supplier of updated klibc package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Sun, 15 Jul 2018 22:22:07 +0100
Source: klibc
Binary: libklibc-dev libklibc klibc-utils
Architecture: source
Version: 2.0.4-12
Distribution: unstable
Urgency: medium
Maintainer: maximilian attems <[email protected]>
Changed-By: Ben Hutchings <[email protected]>
Description:
 klibc-utils - small utilities built with klibc for early boot
 libklibc   - minimal libc subset for use with initramfs
 libklibc-dev - kernel headers used during the build of klibc
Closes: 863761 884716 886939 891924 903849
Changes:
 klibc (2.0.4-12) unstable; urgency=medium
 .
   [ Ben Hutchings ]
   * debian/control: Point Vcs URLs to Salsa
   * debian/klibc-utils.postinst: Remove diversion of initramfs-tools hook
     script (Closes: #886939)
   * [klibc] mips64: compile with -mno-abicalls, thanks to James Cowgill
     (Closes: #891924)
   * reboot: Add support for reboot syscall argument, thanks to Alfonso
     Sanchez-Beato (Closes: #863761, LP: #1692494)
   * [klibc] x86_64: Reduce ld max-page-size option again (Closes: #903849)
   * Never clean files in quilt status directory
 .
   [ Frank Scheiner ]
   * [klibc] ia64: Build static tools (again)
 .
   [ Benjamin Drung ]
   * ipconfig: Implement classless static routes (Closes: #884716, LP: #1526956)
   * mount_main: Fix empty string check
Checksums-Sha1:
 fa6f64a531a165ff4bdb91ca1837937665ff5481 2031 klibc_2.0.4-12.dsc
 fb18065967c348abf6d7f244cca72d5fa3ebe167 37588 klibc_2.0.4-12.debian.tar.xz
 66dda1bc3a2c3ca5182ab589c7ff47c8b00fba8e 5944 klibc_2.0.4-12_source.buildinfo
Checksums-Sha256:
 de8078b3b7e13a2242b470cf54ffed8b94ea8251ee9754125e46cbd1c49c01eb 2031 
klibc_2.0.4-12.dsc
 626471808ca50fc7812c05b91dc21c9ee170dd0908052707c6dedd3f0a0dd77f 37588 
klibc_2.0.4-12.debian.tar.xz
 8cb10acbaa2dab9f60ca5fa35902d01e0921ce86677a68b8ccdfc436f6ee907a 5944 
klibc_2.0.4-12_source.buildinfo
Files:
 ff65d734e012b8015ed2453ff772b1d2 2031 libs optional klibc_2.0.4-12.dsc
 fb8b4a2c57822aadd1992723d9f01df6 37588 libs optional 
klibc_2.0.4-12.debian.tar.xz
 ca06e9bc2786acf8ee7e7e895579d999 5944 libs optional 
klibc_2.0.4-12_source.buildinfo

-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEErCspvTSmr92z9o8157/I7JWGEQkFAltLuyQACgkQ57/I7JWG
EQlfpw//dX5zfuZPaKnVDfyCXM9Usx6mhLCeI6DI/b85IlPGcMQGfftRfIMXSfsW
mp1SEHaNuforocIleoTAOWiDIITaFhbX8BxnZF20VesEYjzjxbZBS1tF8wOm/mbO
giFkjIzko2RCqlso0/RL0RZj+n4ISHZlo/IsFUNngR5520DnC3S7ARQockGRxyus
3GUzfv7CxXgQPOjChTE9NskK10vC749vOwlsmfkW4adSOVn6Ney0bBhvNViurRmj
Yc1EVWSSolmVcivLIKFosRhcvO3Sv7XbvZ8yZ1k/QCAOlEpfHF929ztfSwnkQqaZ
+kCWnNEgqD+22jvM+JPrsWr9RBc0daPepCUaXxkZsu6NS3K/bInhiUt2z70vnw4d
O7CqBbb2BYl4irwAMaVYftZ/cb6yBfgk22EvhGHBenAxg0V7m8CBBBlhIJYM/YNF
GKoiyCZQPhw7l1c/kPiJJf/b3feIu259vhAvBcylrZUOPxMefq0z39TRY0p/1Ab6
mqGy198uq5FPhLT9KkwFf5znYWWeFnTP0UtW/Lbbc+0JMM+dUUyfN1B9tU6cWHX4
jr5XsY7f6d07fXxWokj8hKyFhF+kUDil+myhjtnLgejAzB5CK3aFt9RZjzpVf0wY
XIX5whitfo1jtESwYUwQ1OS3IGJqbo570E8dpD8XfbYvTru9o5Y=
=ubk2
-----END PGP SIGNATURE-----

--- End Message ---

Reply via email to