diff --git a/config.c b/config.c
index d83ea9c..f6a1071 100644
--- a/config.c
+++ b/config.c
@@ -155,6 +155,25 @@ config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype
 	return 0;
 }
 
+/**
+ * config_fixup_interface_device - translate deprecated "ifname" option
+ *
+ * Initially "interface" sections were using "ifname" for specifying device.
+ * That has been replaced by the "device" option. For backward compatibility
+ * translate it.
+ */
+static void config_fixup_interface_device(struct uci_section *s)
+{
+	const char *ifname;
+
+	if (uci_lookup_option(uci_ctx, s, "device"))
+		return;
+
+	ifname = uci_lookup_option_string(uci_ctx, s, "ifname");
+	if (ifname)
+		config_fixup_bridge_var(s, "device", ifname);
+}
+
 static void
 config_parse_interface(struct uci_section *s, bool alias)
 {
@@ -168,6 +187,8 @@ config_parse_interface(struct uci_section *s, bool alias)
 	if (disabled && !strcmp(disabled, "1"))
 		return;
 
+	config_fixup_interface_device(s);
+
 	blob_buf_init(&b, 0);
 
 	if (!alias)
diff --git a/interface.c b/interface.c
index a91246a..c298355 100644
--- a/interface.c
+++ b/interface.c
@@ -30,7 +30,7 @@ struct vlist_tree interfaces;
 static LIST_HEAD(iface_all_users);
 
 enum {
-	IFACE_ATTR_IFNAME,
+	IFACE_ATTR_DEVICE,
 	IFACE_ATTR_PROTO,
 	IFACE_ATTR_AUTO,
 	IFACE_ATTR_JAIL,
@@ -55,8 +55,8 @@ enum {
 };
 
 static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
+	[IFACE_ATTR_DEVICE] = { .name = "device", .type = BLOBMSG_TYPE_STRING },
 	[IFACE_ATTR_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING },
-	[IFACE_ATTR_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
 	[IFACE_ATTR_AUTO] = { .name = "auto", .type = BLOBMSG_TYPE_BOOL },
 	[IFACE_ATTR_JAIL] = { .name = "jail", .type = BLOBMSG_TYPE_STRING },
 	[IFACE_ATTR_JAIL_IFNAME] = { .name = "jail_ifname", .type = BLOBMSG_TYPE_STRING },
@@ -641,9 +641,9 @@ interface_claim_device(struct interface *iface)
 		parent = vlist_find(&interfaces, iface->parent_ifname, parent, node);
 		iface->parent_iface.cb = interface_alias_cb;
 		interface_add_user(&iface->parent_iface, parent);
-	} else if (iface->ifname &&
+	} else if (iface->device &&
 		!(iface->proto_handler->flags & PROTO_FLAG_NODEV)) {
-		dev = device_get(iface->ifname, true);
+		dev = device_get(iface->device, true);
 		interface_set_device_config(iface, dev);
 	} else {
 		dev = iface->ext_dev.dev;
@@ -939,8 +939,8 @@ static bool __interface_add(struct interface *iface, struct blob_attr *config, b
 		if (!iface->parent_ifname)
 			return false;
 	} else {
-		if ((cur = tb[IFACE_ATTR_IFNAME]))
-			iface->ifname = blobmsg_data(cur);
+		if ((cur = tb[IFACE_ATTR_DEVICE]))
+			iface->device = blobmsg_data(cur);
 	}
 
 	if (iface->dynamic) {
@@ -1216,7 +1216,7 @@ interface_start_jail(const char *jail, const pid_t netns_pid)
 		 * list, so we can mess with it :)
 		 */
 		if (iface->jail_ifname)
-			iface->ifname = iface->jail_ifname;
+			iface->device = iface->jail_ifname;
 
 		interface_do_reload(iface);
 		interface_set_up(iface);
@@ -1257,9 +1257,9 @@ interface_stop_jail(const char *jail, const pid_t netns_pid)
 		if (!iface->jail || strcmp(iface->jail, jail))
 			continue;
 
-		orig_ifname = iface->ifname;
+		orig_ifname = iface->device;
 		if (iface->jail_ifname)
-			iface->ifname = iface->jail_ifname;
+			iface->device = iface->jail_ifname;
 
 		interface_do_reload(iface);
 		interface_set_down(iface);
@@ -1352,7 +1352,7 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
 	if (!reload && interface_device_config_changed(if_old, if_new))
 		reload = true;
 
-	if (FIELD_CHANGED_STR(ifname) ||
+	if (FIELD_CHANGED_STR(device) ||
 	    if_old->proto_handler != if_new->proto_handler)
 		reload = true;
 
@@ -1391,7 +1391,7 @@ interface_change_config(struct interface *if_old, struct interface *if_new)
 
 	if_old->jail_ifname = if_new->jail_ifname;
 
-	if_old->ifname = if_new->ifname;
+	if_old->device = if_new->device;
 	if_old->parent_ifname = if_new->parent_ifname;
 	if_old->dynamic = if_new->dynamic;
 	if_old->proto_handler = if_new->proto_handler;
diff --git a/interface.h b/interface.h
index 9c136b6..1767bf1 100644
--- a/interface.h
+++ b/interface.h
@@ -107,7 +107,7 @@ struct interface {
 	enum interface_event hotplug_ev;
 
 	const char *name;
-	const char *ifname;
+	const char *device;
 	char *jail;
 	char *jail_ifname;
 	int netns_fd;
diff --git a/ubus.c b/ubus.c
index be15062..814fd5d 100644
--- a/ubus.c
+++ b/ubus.c
@@ -126,9 +126,12 @@ netifd_add_dynamic(struct ubus_context *ctx, struct ubus_object *obj,
 		      struct ubus_request_data *req, const char *method,
 		      struct blob_attr *msg)
 {
+	static struct blob_buf buf;
 	struct blob_attr *tb[__DI_MAX];
 	struct interface *iface;
 	struct blob_attr *config;
+	struct blob_attr *cur;
+	int rem;
 
 	blobmsg_parse(dynamic_policy, __DI_MAX, tb, blob_data(msg), blob_len(msg));
 
@@ -141,6 +144,17 @@ netifd_add_dynamic(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!iface)
 		return UBUS_STATUS_UNKNOWN_ERROR;
 
+	blob_buf_init(&buf, 0);
+	blob_for_each_attr(cur, msg, rem) {
+		/* Backward compatibility: s/ifname/device/ */
+		if (!strcmp(blobmsg_name(cur), "ifname")) {
+			blobmsg_add_field(&buf, blobmsg_type(cur), "device", blobmsg_data(cur), blobmsg_data_len(cur));
+			continue;
+		}
+		blobmsg_add_blob(&buf, cur);
+	}
+	msg = buf.head;
+
 	config = blob_memdup(msg);
 	if (!config)
 		goto error;
