From 499f60b10b6c85bc7d196723c8d310ed5994d076 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Sat, 2 Feb 2013 11:54:00 +0000 Subject: [PATCH] ng_ether: track interface renaming Also sanitize interface names that can potentially contain characters that are prohibited in netgraph names. PR: kern/154850 (sanitizing of names) Discussed with: eri, melifaro Submitted by: Nikolay Denev (sanitizing code) Reviewed by: eri, glebius MFC after: 17 days --- sys/netgraph/ng_ether.c | 60 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c index 05d2e6e5e953..6266f40534eb 100644 --- a/sys/netgraph/ng_ether.c +++ b/sys/netgraph/ng_ether.c @@ -117,6 +117,8 @@ static ng_rcvdata_t ng_ether_rcvdata; static ng_disconnect_t ng_ether_disconnect; static int ng_ether_mod_event(module_t mod, int event, void *data); +static eventhandler_tag ng_ether_ifnet_arrival_cookie; + /* List of commands and how to convert arguments to/from ASCII */ static const struct ng_cmdlist ng_ether_cmdlist[] = { { @@ -213,6 +215,24 @@ static struct ng_type ng_ether_typestruct = { }; NETGRAPH_INIT(ether, &ng_ether_typestruct); +/****************************************************************** + UTILITY FUNCTIONS +******************************************************************/ +static void +ng_ether_sanitize_ifname(const char *ifname, char *name) +{ + int i; + + for (i = 0; i < IFNAMSIZ; i++) { + if (ifname[i] == '.' || ifname[i] == ':') + name[i] = '_'; + else + name[i] = ifname[i]; + if (name[i] == '\0') + break; + } +} + /****************************************************************** ETHERNET FUNCTION HOOKS ******************************************************************/ @@ -282,6 +302,7 @@ ng_ether_output(struct ifnet *ifp, struct mbuf **mp) static void ng_ether_attach(struct ifnet *ifp) { + char name[IFNAMSIZ]; priv_p priv; node_p node; @@ -319,10 +340,9 @@ ng_ether_attach(struct ifnet *ifp) priv->hwassist = ifp->if_hwassist; /* Try to give the node the same name as the interface */ - if (ng_name_node(node, ifp->if_xname) != 0) { - log(LOG_WARNING, "%s: can't name node %s\n", - __func__, ifp->if_xname); - } + ng_ether_sanitize_ifname(ifp->if_xname, name); + if (ng_name_node(node, name) != 0) + log(LOG_WARNING, "%s: can't name node %s\n", __func__, name); } /* @@ -378,6 +398,32 @@ ng_ether_link_state(struct ifnet *ifp, int state) } } +/* + * Interface arrival notification handler. + * The notification is produced in two cases: + * o a new interface arrives + * o an existing interface got renamed + * Currently the first case is handled by ng_ether_attach via special + * hook ng_ether_attach_p. + */ +static void +ng_ether_ifnet_arrival_event(void *arg __unused, struct ifnet *ifp) +{ + char name[IFNAMSIZ]; + node_p node = IFP2NG(ifp); + + /* + * Just return if it's a new interface without an ng_ether companion. + */ + if (node == NULL) + return; + + /* Try to give the node the same name as the new interface name */ + ng_ether_sanitize_ifname(ifp->if_xname, name); + if (ng_name_node(node, name) != 0) + log(LOG_WARNING, "%s: can't re-name node %s\n", __func__, name); +} + /****************************************************************** NETGRAPH NODE METHODS ******************************************************************/ @@ -771,6 +817,9 @@ ng_ether_mod_event(module_t mod, int event, void *data) ng_ether_input_orphan_p = ng_ether_input_orphan; ng_ether_link_state_p = ng_ether_link_state; + ng_ether_ifnet_arrival_cookie = + EVENTHANDLER_REGISTER(ifnet_arrival_event, + ng_ether_ifnet_arrival_event, NULL, EVENTHANDLER_PRI_ANY); break; case MOD_UNLOAD: @@ -783,6 +832,9 @@ ng_ether_mod_event(module_t mod, int event, void *data) * is MOD_UNLOAD, so there's no need to detach any nodes. */ + EVENTHANDLER_DEREGISTER(ifnet_arrival_event, + ng_ether_ifnet_arrival_cookie); + /* Unregister function hooks */ ng_ether_attach_p = NULL; ng_ether_detach_p = NULL;