diff --git a/Makefile b/Makefile
index 77a85c6..ee82640 100644
--- a/Makefile
+++ b/Makefile
@@ -35,6 +35,11 @@ YACCFLAGS = -d -t -v
 
 LDLIBS += -L../lib -lnetlink -lutil
 
+ifeq ($(shell test -L /usr/local/lib/libnetdevname.so; echo $$?),0)
+LDLIBS +=-lnetdevname
+DEFINES += -DLIBNETDEVNAME_PRESENT
+endif
+
 SUBDIRS=lib ip tc misc netem genl
 
 LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 3a411b1..6fafa2e 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -28,6 +28,10 @@
 #include <linux/if_arp.h>
 #include <linux/sockios.h>
 
+#ifdef LIBNETDEVNAME_PRESENT
+#include <netdevname.h>
+#endif
+
 #include "rt_names.h"
 #include "utils.h"
 #include "ll_map.h"
@@ -712,6 +716,10 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush)
 	char *filter_dev = NULL;
 	int no_link = 0;
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	ipaddr_reset_filter(oneline);
 	filter.showqueue = 1;
 
@@ -787,7 +795,13 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush)
 				usage();
 			if (filter_dev)
 				duparg2("dev", *argv);
+#ifndef LIBNETDEVNAME_PRESENT
 			filter_dev = *argv;
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			filter_dev = kernel_name;
+#endif
 		}
 		argv++; argc--;
 	}
diff --git a/ip/iplink.c b/ip/iplink.c
index cb2c4f5..e9f70e2 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -28,6 +28,10 @@
 #include <sys/ioctl.h>
 #include <linux/sockios.h>
 
+#ifdef LIBNETDEVNAME_PRESENT
+#include <netdevname.h>
+#endif
+
 #include "rt_names.h"
 #include "utils.h"
 #include "ip_common.h"
@@ -703,6 +707,10 @@ static int do_set(int argc, char **argv)
 	char *newname = NULL;
 	int htype, halen;
 
+#ifdef	LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	while (argc > 0) {
 		if (strcmp(*argv, "up") == 0) {
 			mask |= IFF_UP;
@@ -798,7 +806,13 @@ static int do_set(int argc, char **argv)
 				usage();
 			if (dev)
 				duparg2("dev", *argv);
+#ifndef	LIBNETDEVNAME_PRESENT
 			dev = *argv;
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			dev = kernel_name;
+#endif
 		}
 		argc--; argv++;
 	}
diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c
index 44ffdfc..b5c8380 100644
--- a/ip/ipmaddr.c
+++ b/ip/ipmaddr.c
@@ -26,6 +26,10 @@
 #include <linux/if_arp.h>
 #include <linux/sockios.h>
 
+#ifdef LIBNETDEVNAME_PRESENT
+#include <netdevname.h>
+#endif
+
 #include "rt_names.h"
 #include "utils.h"
 
@@ -245,6 +249,9 @@ static int multiaddr_list(int argc, char **argv)
 {
 	struct ma_info *list = NULL;
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
 	if (!filter.family)
 		filter.family = preferred_family;
 
@@ -257,7 +264,13 @@ static int multiaddr_list(int argc, char **argv)
 				usage();
 			if (filter.dev)
 				duparg2("dev", *argv);
+#ifndef LIBNETDEVNAME_PRESENT
 			filter.dev = *argv;
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			filter.dev = kernel_name;
+#endif
 		}
 		argv++; argc--;
 	}
@@ -289,7 +302,12 @@ int multiaddr_modify(int cmd, int argc, char **argv)
 			NEXT_ARG();
 			if (ifr.ifr_name[0])
 				duparg("dev", *argv);
+#ifndef	LIBNETDEVNAME_PRESENT
 			strncpy(ifr.ifr_name, *argv, IFNAMSIZ);
+#else
+			if (netdev_alias_to_kernelname(*argv, ifr.ifr_name) < 0)
+				show_firmware_alias_usage(*argv);
+#endif
 		} else {
 			if (matches(*argv, "address") == 0) {
 				NEXT_ARG();
diff --git a/lib/ll_map.c b/lib/ll_map.c
index b8b49aa..1476255 100644
--- a/lib/ll_map.c
+++ b/lib/ll_map.c
@@ -19,9 +19,15 @@
 #include <netinet/in.h>
 #include <string.h>
 
+#ifdef LIBNETDEVNAME_PRESENT
+#include <netdevname.h>
+#include <linux/if.h>
+#endif
+
 #include "libnetlink.h"
 #include "ll_map.h"
 
+
 extern unsigned int if_nametoindex (const char *);
 
 struct idxmap
@@ -163,8 +169,18 @@ unsigned ll_name_to_index(const char *name)
 	int i;
 	unsigned idx;
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
 	if (name == NULL)
 		return 0;
+
+#ifdef LIBNETDEVNAME_PRESENT
+	if (netdev_alias_to_kernelname(name, kernel_name) < 0)
+		show_firmware_alias_usage(name);
+	strncpy(name, kernel_name, IFNAMSIZ);
+#endif
+
 	if (icache && strcmp(name, ncache) == 0)
 		return icache;
 	for (i=0; i<16; i++) {
diff --git a/tc/f_fw.c b/tc/f_fw.c
index 219b404..244bc8a 100644
--- a/tc/f_fw.c
+++ b/tc/f_fw.c
@@ -20,6 +20,11 @@
 #include <arpa/inet.h>
 #include <string.h>
 #include <linux/if.h> /* IFNAMSIZ */
+
+#ifdef LIBNETDEVNAME_PRESENT
+#include <netdevname.h>
+#endif
+
 #include "utils.h"
 #include "tc_util.h"
 
@@ -39,6 +44,10 @@ static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **a
 	__u32 mask = 0;
 	int mask_set = 0;
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	memset(&tp, 0, sizeof(tp));
 
 	if (handle) {
@@ -100,7 +109,13 @@ static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **a
 				fprintf(stderr, "Illegal indev\n");
 				return -1;
 			}
+#ifndef LIBNETDEVNAME_PRESENT
 			strncpy(d, *argv, sizeof (d) - 1);
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			strncpy(d, kernel_name, sizeof (d) - 1);
+#endif
 			addattr_l(n, MAX_MSG, TCA_FW_INDEV, d, strlen(d) + 1);
 		} else if (strcmp(*argv, "help") == 0) {
 			explain();
diff --git a/tc/tc_class.c b/tc/tc_class.c
index 9d4eea5..bff90f8 100644
--- a/tc/tc_class.c
+++ b/tc/tc_class.c
@@ -21,6 +21,11 @@
 #include <string.h>
 #include <math.h>
 
+#ifdef LIBNETDEVNAME_PRESENT
+#include <netdevname.h>
+#include <linux/if.h>
+#endif
+
 #include "utils.h"
 #include "tc_util.h"
 #include "tc_common.h"
@@ -52,6 +57,10 @@ int tc_class_modify(int cmd, unsigned flags, int argc, char **argv)
 	char  d[16];
 	char  k[16];
 
+#ifdef	LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	memset(&req, 0, sizeof(req));
 	memset(&est, 0, sizeof(est));
 	memset(d, 0, sizeof(d));
@@ -67,7 +76,13 @@ int tc_class_modify(int cmd, unsigned flags, int argc, char **argv)
 			NEXT_ARG();
 			if (d[0])
 				duparg("dev", *argv);
+#ifndef LIBNETDEVNAME_PRESENT
 			strncpy(d, *argv, sizeof(d)-1);
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			strncpy(d, kernel_name, sizeof (d) - 1);
+#endif
 		} else if (strcmp(*argv, "classid") == 0) {
 			__u32 handle;
 			NEXT_ARG();
@@ -237,6 +252,10 @@ int tc_class_list(int argc, char **argv)
 	struct tcmsg t;
 	char d[16];
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	memset(&t, 0, sizeof(t));
 	t.tcm_family = AF_UNSPEC;
 	memset(d, 0, sizeof(d));
@@ -246,7 +265,13 @@ int tc_class_list(int argc, char **argv)
 			NEXT_ARG();
 			if (d[0])
 				duparg("dev", *argv);
+#ifndef LIBNETDEVNAME_PRESENT
 			strncpy(d, *argv, sizeof(d)-1);
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			strncpy(d, kernel_name, sizeof (d) - 1);
+#endif
 		} else if (strcmp(*argv, "qdisc") == 0) {
 			NEXT_ARG();
 			if (filter_qdisc)
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index 919c57c..e144f9d 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -21,6 +21,11 @@
 #include <string.h>
 #include <linux/if_ether.h>
 
+#ifdef LIBNETDEVNAME_PRESENT
+#include <netdevname.h>
+#include <linux/if.h>
+#endif
+
 #include "rt_names.h"
 #include "utils.h"
 #include "tc_util.h"
@@ -61,6 +66,10 @@ int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv)
 	char  k[16];
 	struct tc_estimator est;
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	memset(&req, 0, sizeof(req));
 	memset(&est, 0, sizeof(est));
 	memset(d, 0, sizeof(d));
@@ -80,7 +89,13 @@ int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv)
 			NEXT_ARG();
 			if (d[0])
 				duparg("dev", *argv);
+#ifndef LIBNETDEVNAME_PRESENT
 			strncpy(d, *argv, sizeof(d)-1);
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			strncpy(d, kernel_name, sizeof (d) - 1);
+#endif
 		} else if (strcmp(*argv, "root") == 0) {
 			if (req.t.tcm_parent) {
 				fprintf(stderr, "Error: \"root\" is duplicate parent ID\n");
@@ -268,6 +283,10 @@ int tc_filter_list(int argc, char **argv)
 	__u32 protocol = 0;
 	char *fhandle = NULL;
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	memset(&t, 0, sizeof(t));
 	t.tcm_family = AF_UNSPEC;
 	memset(d, 0, sizeof(d));
@@ -277,7 +296,13 @@ int tc_filter_list(int argc, char **argv)
 			NEXT_ARG();
 			if (d[0])
 				duparg("dev", *argv);
+#ifndef LIBNETDEVNAME_PRESENT
 			strncpy(d, *argv, sizeof(d)-1);
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			strncpy(d, kernel_name, sizeof (d) - 1);
+#endif
 		} else if (strcmp(*argv, "root") == 0) {
 			if (t.tcm_parent) {
 				fprintf(stderr, "Error: \"root\" is duplicate parent ID\n");
diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c
index c7f2988..3a9b05c 100644
--- a/tc/tc_qdisc.c
+++ b/tc/tc_qdisc.c
@@ -21,6 +21,10 @@
 #include <string.h>
 #include <math.h>
 #include <malloc.h>
+#ifdef LIBNETDEVNAME_PRESENT
+#include <netdevname.h>
+#include <linux/if.h>
+#endif
 
 #include "utils.h"
 #include "tc_util.h"
@@ -60,6 +64,10 @@ int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
 		char   			buf[TCA_BUF_MAX];
 	} req;
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	memset(&req, 0, sizeof(req));
 	memset(&stab, 0, sizeof(stab));
 	memset(&est, 0, sizeof(est));
@@ -76,7 +84,13 @@ int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
 			NEXT_ARG();
 			if (d[0])
 				duparg("dev", *argv);
+#ifndef LIBNETDEVNAME_PRESENT
 			strncpy(d, *argv, sizeof(d)-1);
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			strncpy(d, kernel_name, sizeof (d) - 1);
+#endif
 		} else if (strcmp(*argv, "handle") == 0) {
 			__u32 handle;
 			if (req.t.tcm_handle)
@@ -282,6 +296,10 @@ int tc_qdisc_list(int argc, char **argv)
 	struct tcmsg t;
 	char d[16];
 
+#ifdef LIBNETDEVNAME_PRESENT
+	char kernel_name[IFNAMSIZ];
+#endif
+
 	memset(&t, 0, sizeof(t));
 	t.tcm_family = AF_UNSPEC;
 	memset(&d, 0, sizeof(d));
@@ -289,7 +307,13 @@ int tc_qdisc_list(int argc, char **argv)
 	while (argc > 0) {
 		if (strcmp(*argv, "dev") == 0) {
 			NEXT_ARG();
+#ifndef LIBNETDEVNAME_PRESENT
 			strncpy(d, *argv, sizeof(d)-1);
+#else
+			if (netdev_alias_to_kernelname(*argv, kernel_name) < 0)
+				show_firmware_alias_usage(*argv);
+			strncpy(d, kernel_name, sizeof (d) - 1);
+#endif
 #ifdef TC_H_INGRESS
                 } else if (strcmp(*argv, "ingress") == 0) {
                              if (t.tcm_parent) {
