1b97bf3fdSPer Liden /* 2b97bf3fdSPer Liden * net/tipc/netlink.c: TIPC configuration handling 3b97bf3fdSPer Liden * 40655f6a8SRichard Alpe * Copyright (c) 2005-2006, 2014, Ericsson AB 559f0c452SAllan Stephens * Copyright (c) 2005-2007, Wind River Systems 6b97bf3fdSPer Liden * All rights reserved. 7b97bf3fdSPer Liden * 8b97bf3fdSPer Liden * Redistribution and use in source and binary forms, with or without 9b97bf3fdSPer Liden * modification, are permitted provided that the following conditions are met: 10b97bf3fdSPer Liden * 119ea1fd3cSPer Liden * 1. Redistributions of source code must retain the above copyright 129ea1fd3cSPer Liden * notice, this list of conditions and the following disclaimer. 139ea1fd3cSPer Liden * 2. Redistributions in binary form must reproduce the above copyright 149ea1fd3cSPer Liden * notice, this list of conditions and the following disclaimer in the 159ea1fd3cSPer Liden * documentation and/or other materials provided with the distribution. 169ea1fd3cSPer Liden * 3. Neither the names of the copyright holders nor the names of its 179ea1fd3cSPer Liden * contributors may be used to endorse or promote products derived from 189ea1fd3cSPer Liden * this software without specific prior written permission. 199ea1fd3cSPer Liden * 209ea1fd3cSPer Liden * Alternatively, this software may be distributed under the terms of the 219ea1fd3cSPer Liden * GNU General Public License ("GPL") version 2 as published by the Free 229ea1fd3cSPer Liden * Software Foundation. 23b97bf3fdSPer Liden * 24b97bf3fdSPer Liden * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25b97bf3fdSPer Liden * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26b97bf3fdSPer Liden * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27b97bf3fdSPer Liden * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 28b97bf3fdSPer Liden * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29b97bf3fdSPer Liden * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30b97bf3fdSPer Liden * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31b97bf3fdSPer Liden * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32b97bf3fdSPer Liden * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33b97bf3fdSPer Liden * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34b97bf3fdSPer Liden * POSSIBILITY OF SUCH DAMAGE. 35b97bf3fdSPer Liden */ 36b97bf3fdSPer Liden 37b97bf3fdSPer Liden #include "core.h" 38b97bf3fdSPer Liden #include "config.h" 3934b78a12SRichard Alpe #include "socket.h" 400655f6a8SRichard Alpe #include "bearer.h" 417be57fc6SRichard Alpe #include "link.h" 42b97bf3fdSPer Liden #include <net/genetlink.h> 43b97bf3fdSPer Liden 44b97bf3fdSPer Liden static int handle_cmd(struct sk_buff *skb, struct genl_info *info) 45b97bf3fdSPer Liden { 46b97bf3fdSPer Liden struct sk_buff *rep_buf; 47b97bf3fdSPer Liden struct nlmsghdr *rep_nlh; 48b97bf3fdSPer Liden struct nlmsghdr *req_nlh = info->nlhdr; 49b97bf3fdSPer Liden struct tipc_genlmsghdr *req_userhdr = info->userhdr; 50573ce260SHong zhi guo int hdr_space = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN); 5159f0c452SAllan Stephens u16 cmd; 52b97bf3fdSPer Liden 5390f62cf3SEric W. Biederman if ((req_userhdr->cmd & 0xC000) && (!netlink_capable(skb, CAP_NET_ADMIN))) 5459f0c452SAllan Stephens cmd = TIPC_CMD_NOT_NET_ADMIN; 55b97bf3fdSPer Liden else 5659f0c452SAllan Stephens cmd = req_userhdr->cmd; 5759f0c452SAllan Stephens 5859f0c452SAllan Stephens rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd, 59573ce260SHong zhi guo nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, 60573ce260SHong zhi guo nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), 61b97bf3fdSPer Liden hdr_space); 62b97bf3fdSPer Liden 63b97bf3fdSPer Liden if (rep_buf) { 64b97bf3fdSPer Liden skb_push(rep_buf, hdr_space); 65b529ccf2SArnaldo Carvalho de Melo rep_nlh = nlmsg_hdr(rep_buf); 66b97bf3fdSPer Liden memcpy(rep_nlh, req_nlh, hdr_space); 67b97bf3fdSPer Liden rep_nlh->nlmsg_len = rep_buf->len; 6815e47304SEric W. Biederman genlmsg_unicast(&init_net, rep_buf, NETLINK_CB(skb).portid); 69b97bf3fdSPer Liden } 70b97bf3fdSPer Liden 71b97bf3fdSPer Liden return 0; 72b97bf3fdSPer Liden } 73b97bf3fdSPer Liden 740655f6a8SRichard Alpe static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = { 750655f6a8SRichard Alpe [TIPC_NLA_UNSPEC] = { .type = NLA_UNSPEC, }, 760655f6a8SRichard Alpe [TIPC_NLA_BEARER] = { .type = NLA_NESTED, }, 7734b78a12SRichard Alpe [TIPC_NLA_SOCK] = { .type = NLA_NESTED, }, 787be57fc6SRichard Alpe [TIPC_NLA_PUBL] = { .type = NLA_NESTED, }, 797be57fc6SRichard Alpe [TIPC_NLA_LINK] = { .type = NLA_NESTED, }, 800655f6a8SRichard Alpe }; 810655f6a8SRichard Alpe 820655f6a8SRichard Alpe /* Legacy ASCII API */ 83acb0a200SMichał Mirosław static struct genl_family tipc_genl_family = { 841dba9743SPer Liden .id = GENL_ID_GENERATE, 85b97bf3fdSPer Liden .name = TIPC_GENL_NAME, 86b97bf3fdSPer Liden .version = TIPC_GENL_VERSION, 87b97bf3fdSPer Liden .hdrsize = TIPC_GENL_HDRLEN, 88b97bf3fdSPer Liden .maxattr = 0, 89b97bf3fdSPer Liden }; 90b97bf3fdSPer Liden 910655f6a8SRichard Alpe /* Legacy ASCII API */ 92c53ed742SJohannes Berg static struct genl_ops tipc_genl_ops[] = { 93c53ed742SJohannes Berg { 94b97bf3fdSPer Liden .cmd = TIPC_GENL_CMD, 95b97bf3fdSPer Liden .doit = handle_cmd, 96c53ed742SJohannes Berg }, 97b97bf3fdSPer Liden }; 98b97bf3fdSPer Liden 990655f6a8SRichard Alpe /* Users of the legacy API (tipc-config) can't handle that we add operations, 1000655f6a8SRichard Alpe * so we have a separate genl handling for the new API. 1010655f6a8SRichard Alpe */ 1020655f6a8SRichard Alpe struct genl_family tipc_genl_v2_family = { 1030655f6a8SRichard Alpe .id = GENL_ID_GENERATE, 1040655f6a8SRichard Alpe .name = TIPC_GENL_V2_NAME, 1050655f6a8SRichard Alpe .version = TIPC_GENL_V2_VERSION, 1060655f6a8SRichard Alpe .hdrsize = 0, 1070655f6a8SRichard Alpe .maxattr = TIPC_NLA_MAX, 1080655f6a8SRichard Alpe }; 1090655f6a8SRichard Alpe 1100655f6a8SRichard Alpe static const struct genl_ops tipc_genl_v2_ops[] = { 1110655f6a8SRichard Alpe { 1120655f6a8SRichard Alpe .cmd = TIPC_NL_BEARER_DISABLE, 1130655f6a8SRichard Alpe .doit = tipc_nl_bearer_disable, 1140655f6a8SRichard Alpe .policy = tipc_nl_policy, 1150655f6a8SRichard Alpe }, 1160655f6a8SRichard Alpe { 1170655f6a8SRichard Alpe .cmd = TIPC_NL_BEARER_ENABLE, 1180655f6a8SRichard Alpe .doit = tipc_nl_bearer_enable, 1190655f6a8SRichard Alpe .policy = tipc_nl_policy, 12035b9dd76SRichard Alpe }, 12135b9dd76SRichard Alpe { 12235b9dd76SRichard Alpe .cmd = TIPC_NL_BEARER_GET, 12335b9dd76SRichard Alpe .doit = tipc_nl_bearer_get, 12435b9dd76SRichard Alpe .dumpit = tipc_nl_bearer_dump, 12535b9dd76SRichard Alpe .policy = tipc_nl_policy, 126315c00bcSRichard Alpe }, 127315c00bcSRichard Alpe { 128315c00bcSRichard Alpe .cmd = TIPC_NL_BEARER_SET, 129315c00bcSRichard Alpe .doit = tipc_nl_bearer_set, 130315c00bcSRichard Alpe .policy = tipc_nl_policy, 13134b78a12SRichard Alpe }, 13234b78a12SRichard Alpe { 13334b78a12SRichard Alpe .cmd = TIPC_NL_SOCK_GET, 13434b78a12SRichard Alpe .dumpit = tipc_nl_sk_dump, 13534b78a12SRichard Alpe .policy = tipc_nl_policy, 1361a1a143dSRichard Alpe }, 1371a1a143dSRichard Alpe { 1381a1a143dSRichard Alpe .cmd = TIPC_NL_PUBL_GET, 1391a1a143dSRichard Alpe .dumpit = tipc_nl_publ_dump, 1401a1a143dSRichard Alpe .policy = tipc_nl_policy, 1417be57fc6SRichard Alpe }, 1427be57fc6SRichard Alpe { 1437be57fc6SRichard Alpe .cmd = TIPC_NL_LINK_GET, 1447be57fc6SRichard Alpe .doit = tipc_nl_link_get, 1457be57fc6SRichard Alpe .dumpit = tipc_nl_link_dump, 1467be57fc6SRichard Alpe .policy = tipc_nl_policy, 147f96ce7a2SRichard Alpe }, 148f96ce7a2SRichard Alpe { 149f96ce7a2SRichard Alpe .cmd = TIPC_NL_LINK_SET, 150f96ce7a2SRichard Alpe .doit = tipc_nl_link_set, 151f96ce7a2SRichard Alpe .policy = tipc_nl_policy, 152*ae36342bSRichard Alpe }, 153*ae36342bSRichard Alpe { 154*ae36342bSRichard Alpe .cmd = TIPC_NL_LINK_RESET_STATS, 155*ae36342bSRichard Alpe .doit = tipc_nl_link_reset_stats, 156*ae36342bSRichard Alpe .policy = tipc_nl_policy, 1570655f6a8SRichard Alpe } 1580655f6a8SRichard Alpe }; 1590655f6a8SRichard Alpe 1601a1a143dSRichard Alpe int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) 1611a1a143dSRichard Alpe { 1621a1a143dSRichard Alpe u32 maxattr = tipc_genl_v2_family.maxattr; 1631a1a143dSRichard Alpe 1641a1a143dSRichard Alpe *attr = tipc_genl_v2_family.attrbuf; 1651a1a143dSRichard Alpe if (!*attr) 1661a1a143dSRichard Alpe return -EOPNOTSUPP; 1671a1a143dSRichard Alpe 1681a1a143dSRichard Alpe return nlmsg_parse(nlh, GENL_HDRLEN, *attr, maxattr, tipc_nl_policy); 1691a1a143dSRichard Alpe } 1701a1a143dSRichard Alpe 1714323add6SPer Liden int tipc_netlink_start(void) 172b97bf3fdSPer Liden { 173acb0a200SMichał Mirosław int res; 174b70e4f45SJon Maloy 175c53ed742SJohannes Berg res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_ops); 176acb0a200SMichał Mirosław if (res) { 1770655f6a8SRichard Alpe pr_err("Failed to register legacy interface\n"); 1780655f6a8SRichard Alpe return res; 1790655f6a8SRichard Alpe } 1800655f6a8SRichard Alpe 1810655f6a8SRichard Alpe res = genl_register_family_with_ops(&tipc_genl_v2_family, 1820655f6a8SRichard Alpe tipc_genl_v2_ops); 1830655f6a8SRichard Alpe if (res) { 1842cf8aa19SErik Hugne pr_err("Failed to register netlink interface\n"); 185acb0a200SMichał Mirosław return res; 186acb0a200SMichał Mirosław } 187acb0a200SMichał Mirosław return 0; 188b97bf3fdSPer Liden } 189b97bf3fdSPer Liden 1904323add6SPer Liden void tipc_netlink_stop(void) 191b97bf3fdSPer Liden { 192acb0a200SMichał Mirosław genl_unregister_family(&tipc_genl_family); 1930655f6a8SRichard Alpe genl_unregister_family(&tipc_genl_v2_family); 194b97bf3fdSPer Liden } 195