rtnetlink replacement for SIOCSIFHWADDR

rtnetlink replacement for SIOCSIFHWADDR

Post by Roland Dreie » Thu, 05 Dec 2002 20:40:11



Hi, since you are the architects of the rtnetlink facility, I am
writing to you to ask your opinion on how to add some functionality.

I'm exploring what changes are needed in the kernel to support devices
with large addr_len.  My motivation is to get the infrastructure for
IP-over-InfiniBand, which has addr_len 20, into the kernel, and I am
trying to produce a patch that can be accepted into mainline 2.5.

With a few a minor fixes to avoid overrunning array bounds, almost
everything just works.  The RTM_NEWNEIGH and RTM_DELNEIGH messages
seem to provide what is needed to manage ARP entries with large L2
addresses (replacing the SIOCSARP and SIOCDARP ioctls).

The one major piece that is missing is a replacement for SIOCSIFHWADDR
(which can only set L2 addresses up to 14 bytes long, because of the
size of sa_data in struct sockaddr).  I can see two ways one might set
an interface's L2 address through rtnetlink:

  We could extend the RTM_NEWLINK message (possibly using the change
  mask) to include changing just the L2 address, and add support in
  the kernel for receiving these messages from userspace.

  Or, we could add a new RTM_SETLINK message that userspace can send
  to the kernel to modify an interface's properties.

Of course I am open to other suggestions for how to replace
SIOCSIFHWADDR.  I would very much appreciate your thoughts on how to
proceed.

Thanks,

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

rtnetlink replacement for SIOCSIFHWADDR

Post by Andi Klee » Thu, 05 Dec 2002 22:20:11


Quote:>   Or, we could add a new RTM_SETLINK message that userspace can send
>   to the kernel to modify an interface's properties.

Defining a RTM_SETLINK would seem to be cleanest to me.

-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

rtnetlink replacement for SIOCSIFHWADDR

Post by Roland Dreie » Thu, 02 Jan 2003 01:20:05


The patch included below is intended to increase MAX_ADDR_LEN to 32,
which will make adding IP-over-InfiniBand support much simpler.

I included the rtnetlink-based support for big hardware adresses that
we discussed earlier.  Specifically, the patch:

  1. Adds ARPHRD_INFINIBAND to if_arp.h.  This is extremely minor, but
     will make an IP-over-InfiniBand driver cleaner.

  2. Increases MAX_ADDR_LEN to 32 (from 8).

  3. Makes some small changes to net/core/dev.c to prevent the
     increased MAX_ADDR_LEN from overflowing when the SIOCGIFHWADDR
     and SIOCSIFHWADDR ioctls are used on interfaces with addr_len >
     14 (the size of sa_data in struct sockaddr).

  4. Adds RTM_SETLINK to <linux/rtnetlink.h> and adds a function
     do_setlink() to net/core/rtnetlink.c to handle this message from
     userspace.  This lets userspace set the hardware address and
     broadcast address for interfaces with addr_len > 14.

  5. Cleans up the initializer for link_rtnetlink_table[] so that it
     is much easier to read and change.

There is some suspicious-looking use of MAX_ADDR_LEN in
drivers/net/sungem.c and drivers/s390/net/lcs.c but I did not touch
those files in this patch.

This patch was created and tested with UML on kernel 2.5.47, but
applies cleanly to Linus's current 2.5.53-BK (with a few offsets).

Please apply this patch or let me know what needs to change for it to
be applied.

Thanks,
  Roland <rol...@topspin.com>

diff -Naur linux-2.5.47/include/linux/if_arp.h linux-2.5.47-max-addr/include/linux/if_arp.h
--- linux-2.5.47/include/linux/if_arp.h Sun Nov 10 19:28:29 2002
+++ linux-2.5.47-max-addr/include/linux/if_arp.h        Mon Dec 30 13:50:07 2002
@@ -40,6 +40,7 @@
 #define ARPHRD_METRICOM        23              /* Metricom STRIP (new IANA id) */
 #define        ARPHRD_IEEE1394 24              /* IEEE 1394 IPv4 - RFC 2734    */
 #define ARPHRD_EUI64   27              /* EUI-64                       */
+#define ARPHRD_INFINIBAND 32           /* InfiniBand                   */

 /* Dummy types for non ARP hardware */
 #define ARPHRD_SLIP    256
diff -Naur linux-2.5.47/include/linux/netdevice.h linux-2.5.47-max-addr/include/linux/netdevice.h
--- linux-2.5.47/include/linux/netdevice.h      Sun Nov 10 19:28:31 2002
+++ linux-2.5.47-max-addr/include/linux/netdevice.h     Mon Dec 30 12:05:42 2002
@@ -65,7 +65,7 @@

 #endif

-#define MAX_ADDR_LEN   8               /* Largest hardware address length */
+#define MAX_ADDR_LEN   32              /* Largest hardware address length */

 /*
  *     Compute the worst case header length according to the protocols
diff -Naur linux-2.5.47/include/linux/rtnetlink.h linux-2.5.47-max-addr/include/linux/rtnetlink.h
--- linux-2.5.47/include/linux/rtnetlink.h      Sun Nov 10 19:28:29 2002
+++ linux-2.5.47-max-addr/include/linux/rtnetlink.h     Tue Dec 31 14:38:13 2002
@@ -17,6 +17,7 @@
 #define        RTM_NEWLINK     (RTM_BASE+0)
 #define        RTM_DELLINK     (RTM_BASE+1)
 #define        RTM_GETLINK     (RTM_BASE+2)
+#define        RTM_SETLINK     (RTM_BASE+3)

 #define        RTM_NEWADDR     (RTM_BASE+4)
 #define        RTM_DELADDR     (RTM_BASE+5)
diff -Naur linux-2.5.47/net/core/dev.c linux-2.5.47-max-addr/net/core/dev.c
--- linux-2.5.47/net/core/dev.c Sun Nov 10 19:28:16 2002
+++ linux-2.5.47-max-addr/net/core/dev.c        Mon Dec 30 12:06:06 2002
@@ -2062,7 +2062,7 @@

                case SIOCGIFHWADDR:
                        memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr,
-                              MAX_ADDR_LEN);
+                              min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
                        ifr->ifr_hwaddr.sa_family = dev->type;
                        return 0;

@@ -2083,7 +2083,7 @@
                        if (ifr->ifr_hwaddr.sa_family != dev->type)
                                return -EINVAL;
                        memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
-                              MAX_ADDR_LEN);
+                              min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
                        notifier_call_chain(&netdev_chain,
                                            NETDEV_CHANGEADDR, dev);
                        return 0;
diff -Naur linux-2.5.47/net/core/rtnetlink.c linux-2.5.47-max-addr/net/core/rtnetlink.c
--- linux-2.5.47/net/core/rtnetlink.c   Sun Nov 10 19:28:33 2002
+++ linux-2.5.47-max-addr/net/core/rtnetlink.c  Tue Dec 31 14:38:50 2002
@@ -220,6 +220,40 @@
        return skb->len;
 }

+static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) {
+       struct ifinfomsg  *ifm = NLMSG_DATA(nlh);
+       struct rtattr    **ida = arg;
+       struct net_device *dev;
+       int err;
+
+       dev = dev_get_by_index(ifm->ifi_index);
+       if (!dev) {
+               return -ENODEV;
+       }
+
+       err = -EINVAL;
+
+       if (ida[IFLA_ADDRESS - 1]) {
+               if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) {
+                       goto out;
+               }
+               memcpy(dev->dev_addr, RTA_DATA(ida[IFLA_ADDRESS - 1]), dev->addr_len);
+       }
+
+       if (ida[IFLA_BROADCAST - 1]) {
+               if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len)) {
+                       goto out;
+               }
+               memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]), dev->addr_len);
+       }
+
+       err = 0;
+
+out:
+       dev_put(dev);
+       return err;
+}
+
 int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 {
        int idx;
@@ -457,32 +491,14 @@

 static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
 {
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 rtnetlink_dump_ifinfo,  },
-       { NULL,                 NULL,                   },
-
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 rtnetlink_dump_all,     },
-       { NULL,                 NULL,                   },
-
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 rtnetlink_dump_all,     },
-       { NULL,                 NULL,                   },
-
-       { neigh_add,            NULL,                   },
-       { neigh_delete,         NULL,                   },
-       { NULL,                 neigh_dump_info,        },
-       { NULL,                 NULL,                   },
-
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
+       [RTM_GETLINK  - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
+       [RTM_SETLINK  - RTM_BASE] = { .doit   = do_setlink            },
+       [RTM_GETADDR  - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
+       [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
+       [RTM_NEWNEIGH - RTM_BASE] = { .doit   = neigh_add             },
+       [RTM_DELNEIGH - RTM_BASE] = { .doit   = neigh_delete          },
+       [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info       }
 };
-

 static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

rtnetlink replacement for SIOCSIFHWADDR

Post by Roland Dreie » Tue, 07 Jan 2003 18:00:18


Hi, I think this got lost in your inbox over New Year's (I send it
December 31), so I'm resending.

The patch included below is intended to increase MAX_ADDR_LEN to 32,
which will make adding IP-over-InfiniBand support much simpler.

I included the rtnetlink-based support for big hardware adresses that
we discussed earlier.  Specifically, the patch:

  1. Adds ARPHRD_INFINIBAND to if_arp.h.  This is extremely minor, but
     will make an IP-over-InfiniBand driver cleaner.

  2. Increases MAX_ADDR_LEN to 32 (from 8).

  3. Makes some small changes to net/core/dev.c to prevent the
     increased MAX_ADDR_LEN from overflowing when the SIOCGIFHWADDR
     and SIOCSIFHWADDR ioctls are used on interfaces with addr_len >
     14 (the size of sa_data in struct sockaddr).

  4. Adds RTM_SETLINK to <linux/rtnetlink.h> and adds a function
     do_setlink() to net/core/rtnetlink.c to handle this message from
     userspace.  This lets userspace set the hardware address and
     broadcast address for interfaces with addr_len > 14.

  5. Cleans up the initializer for link_rtnetlink_table[] so that it
     is much easier to read and change.

There is some suspicious-looking use of MAX_ADDR_LEN in
drivers/net/sungem.c and drivers/s390/net/lcs.c but I did not touch
those files in this patch.

This patch was created and tested with UML on kernel 2.5.47, but
applies cleanly to Linus's current 2.5.53-BK (with a few offsets).

Please apply this patch or let me know what needs to change for it to
be applied.

Thanks,
  Roland <rol...@topspin.com>

diff -Naur linux-2.5.47/include/linux/if_arp.h linux-2.5.47-max-addr/include/linux/if_arp.h
--- linux-2.5.47/include/linux/if_arp.h Sun Nov 10 19:28:29 2002
+++ linux-2.5.47-max-addr/include/linux/if_arp.h        Mon Dec 30 13:50:07 2002
@@ -40,6 +40,7 @@
 #define ARPHRD_METRICOM        23              /* Metricom STRIP (new IANA id) */
 #define        ARPHRD_IEEE1394 24              /* IEEE 1394 IPv4 - RFC 2734    */
 #define ARPHRD_EUI64   27              /* EUI-64                       */
+#define ARPHRD_INFINIBAND 32           /* InfiniBand                   */

 /* Dummy types for non ARP hardware */
 #define ARPHRD_SLIP    256
diff -Naur linux-2.5.47/include/linux/netdevice.h linux-2.5.47-max-addr/include/linux/netdevice.h
--- linux-2.5.47/include/linux/netdevice.h      Sun Nov 10 19:28:31 2002
+++ linux-2.5.47-max-addr/include/linux/netdevice.h     Mon Dec 30 12:05:42 2002
@@ -65,7 +65,7 @@

 #endif

-#define MAX_ADDR_LEN   8               /* Largest hardware address length */
+#define MAX_ADDR_LEN   32              /* Largest hardware address length */

 /*
  *     Compute the worst case header length according to the protocols
diff -Naur linux-2.5.47/include/linux/rtnetlink.h linux-2.5.47-max-addr/include/linux/rtnetlink.h
--- linux-2.5.47/include/linux/rtnetlink.h      Sun Nov 10 19:28:29 2002
+++ linux-2.5.47-max-addr/include/linux/rtnetlink.h     Tue Dec 31 14:38:13 2002
@@ -17,6 +17,7 @@
 #define        RTM_NEWLINK     (RTM_BASE+0)
 #define        RTM_DELLINK     (RTM_BASE+1)
 #define        RTM_GETLINK     (RTM_BASE+2)
+#define        RTM_SETLINK     (RTM_BASE+3)

 #define        RTM_NEWADDR     (RTM_BASE+4)
 #define        RTM_DELADDR     (RTM_BASE+5)
diff -Naur linux-2.5.47/net/core/dev.c linux-2.5.47-max-addr/net/core/dev.c
--- linux-2.5.47/net/core/dev.c Sun Nov 10 19:28:16 2002
+++ linux-2.5.47-max-addr/net/core/dev.c        Mon Dec 30 12:06:06 2002
@@ -2062,7 +2062,7 @@

                case SIOCGIFHWADDR:
                        memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr,
-                              MAX_ADDR_LEN);
+                              min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
                        ifr->ifr_hwaddr.sa_family = dev->type;
                        return 0;

@@ -2083,7 +2083,7 @@
                        if (ifr->ifr_hwaddr.sa_family != dev->type)
                                return -EINVAL;
                        memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
-                              MAX_ADDR_LEN);
+                              min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
                        notifier_call_chain(&netdev_chain,
                                            NETDEV_CHANGEADDR, dev);
                        return 0;
diff -Naur linux-2.5.47/net/core/rtnetlink.c linux-2.5.47-max-addr/net/core/rtnetlink.c
--- linux-2.5.47/net/core/rtnetlink.c   Sun Nov 10 19:28:33 2002
+++ linux-2.5.47-max-addr/net/core/rtnetlink.c  Tue Dec 31 14:38:50 2002
@@ -220,6 +220,40 @@
        return skb->len;
 }

+static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) {
+       struct ifinfomsg  *ifm = NLMSG_DATA(nlh);
+       struct rtattr    **ida = arg;
+       struct net_device *dev;
+       int err;
+
+       dev = dev_get_by_index(ifm->ifi_index);
+       if (!dev) {
+               return -ENODEV;
+       }
+
+       err = -EINVAL;
+
+       if (ida[IFLA_ADDRESS - 1]) {
+               if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) {
+                       goto out;
+               }
+               memcpy(dev->dev_addr, RTA_DATA(ida[IFLA_ADDRESS - 1]), dev->addr_len);
+       }
+
+       if (ida[IFLA_BROADCAST - 1]) {
+               if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len)) {
+                       goto out;
+               }
+               memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]), dev->addr_len);
+       }
+
+       err = 0;
+
+out:
+       dev_put(dev);
+       return err;
+}
+
 int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 {
        int idx;
@@ -457,32 +491,14 @@

 static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
 {
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 rtnetlink_dump_ifinfo,  },
-       { NULL,                 NULL,                   },
-
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 rtnetlink_dump_all,     },
-       { NULL,                 NULL,                   },
-
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 rtnetlink_dump_all,     },
-       { NULL,                 NULL,                   },
-
-       { neigh_add,            NULL,                   },
-       { neigh_delete,         NULL,                   },
-       { NULL,                 neigh_dump_info,        },
-       { NULL,                 NULL,                   },
-
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
-       { NULL,                 NULL,                   },
+       [RTM_GETLINK  - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
+       [RTM_SETLINK  - RTM_BASE] = { .doit   = do_setlink            },
+       [RTM_GETADDR  - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
+       [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
+       [RTM_NEWNEIGH - RTM_BASE] = { .doit   = neigh_add             },
+       [RTM_DELNEIGH - RTM_BASE] = { .doit   = neigh_delete          },
+       [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info       }
 };
-

 static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

rtnetlink replacement for SIOCSIFHWADDR

Post by David S. Mille » Wed, 08 Jan 2003 01:40:20



   Date: 06 Jan 2003 07:52:57 -0800

   Hi, I think this got lost in your inbox over New Year's (I send it
   December 31), so I'm resending.

Not lost, I'm just still working on my backlog.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

rtnetlink replacement for SIOCSIFHWADDR

Post by David S. Mille » Wed, 08 Jan 2003 11:20:04



   Date: 31 Dec 2002 15:11:31 -0800

   There is some suspicious-looking use of MAX_ADDR_LEN in
   drivers/net/sungem.c and drivers/s390/net/lcs.c but I did not touch
   those files in this patch.
 ...  
   Please apply this patch or let me know what needs to change for it to
   be applied.

I applied the patch and added a #warning to the powerpc bits of
sungem.c that look suspicious.

Thanks.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

1. Routing and rtnetlink

I'm using Red Hat 6.2 with the 2.2.14 kernel.

Is there a way to dump the entire routing table (displayed when you type
"ip route") to an application using rtnetlink?  I've looked at the man
pages for it, and didn't see anything that looked like it would work.

Any help is greatly appreciated.

Thanks,
Dave

Sent via Deja.com
http://www.deja.com/

2. Question on Makefile

3. rtnetlink: network unreachable for Routing for multiple uplinks using ip route add

4. Q: Internet connection

5. using rtnetlink to modify routing table

6. DHCPD and Hardware Proxy Server

7. rtnetlink, setting gateway on eth1 fails

8. FreeBSD 4.0 and PAM and AMANDA

9. IP Route RTNETLINK Error: File Exists

10. IPv6-over-IPv4: "RTNETLINK answers: No route to host"-Error

11. NETLINK/RTNETLINK tutorial

12. rtnetlink interface state monitoring problems.

13. Setting up QDisc and classes without using RTNetlink sockets