|  | /* | 
|  | * net/tipc/diag.c: TIPC socket diag | 
|  | * | 
|  | * Copyright (c) 2018, Ericsson AB | 
|  | * All rights reserved. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions are met: | 
|  | * | 
|  | * 1. Redistributions of source code must retain the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer. | 
|  | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer in the | 
|  | *    documentation and/or other materials provided with the distribution. | 
|  | * 3. Neither the names of the copyright holders nor the names of its | 
|  | *    contributors may be used to endorse or promote products derived from | 
|  | *    this software without specific prior written permission. | 
|  | * | 
|  | * Alternatively, this software may be distributed under the terms of the | 
|  | * GNU General Public License ("GPL") version 2 as published by the Free | 
|  | * Software Foundation. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "ASIS" | 
|  | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | 
|  | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
|  | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 
|  | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
|  | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
|  | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|  | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 
|  | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
|  | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
|  | * POSSIBILITY OF SUCH DAMAGE. | 
|  | */ | 
|  |  | 
|  | #include "core.h" | 
|  | #include "socket.h" | 
|  | #include <linux/sock_diag.h> | 
|  | #include <linux/tipc_sockets_diag.h> | 
|  |  | 
|  | static u64 __tipc_diag_gen_cookie(struct sock *sk) | 
|  | { | 
|  | u32 res[2]; | 
|  |  | 
|  | sock_diag_save_cookie(sk, res); | 
|  | return *((u64 *)res); | 
|  | } | 
|  |  | 
|  | static int __tipc_add_sock_diag(struct sk_buff *skb, | 
|  | struct netlink_callback *cb, | 
|  | struct tipc_sock *tsk) | 
|  | { | 
|  | struct tipc_sock_diag_req *req = nlmsg_data(cb->nlh); | 
|  | struct nlmsghdr *nlh; | 
|  | int err; | 
|  |  | 
|  | nlh = nlmsg_put_answer(skb, cb, SOCK_DIAG_BY_FAMILY, 0, | 
|  | NLM_F_MULTI); | 
|  | if (!nlh) | 
|  | return -EMSGSIZE; | 
|  |  | 
|  | err = tipc_sk_fill_sock_diag(skb, cb, tsk, req->tidiag_states, | 
|  | __tipc_diag_gen_cookie); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | nlmsg_end(skb, nlh); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int tipc_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | 
|  | { | 
|  | return tipc_nl_sk_walk(skb, cb, __tipc_add_sock_diag); | 
|  | } | 
|  |  | 
|  | static int tipc_sock_diag_handler_dump(struct sk_buff *skb, | 
|  | struct nlmsghdr *h) | 
|  | { | 
|  | int hdrlen = sizeof(struct tipc_sock_diag_req); | 
|  | struct net *net = sock_net(skb->sk); | 
|  |  | 
|  | if (nlmsg_len(h) < hdrlen) | 
|  | return -EINVAL; | 
|  |  | 
|  | if (h->nlmsg_flags & NLM_F_DUMP) { | 
|  | struct netlink_dump_control c = { | 
|  | .start = tipc_dump_start, | 
|  | .dump = tipc_diag_dump, | 
|  | .done = tipc_dump_done, | 
|  | }; | 
|  | netlink_dump_start(net->diag_nlsk, skb, h, &c); | 
|  | return 0; | 
|  | } | 
|  | return -EOPNOTSUPP; | 
|  | } | 
|  |  | 
|  | static const struct sock_diag_handler tipc_sock_diag_handler = { | 
|  | .owner = THIS_MODULE, | 
|  | .family = AF_TIPC, | 
|  | .dump = tipc_sock_diag_handler_dump, | 
|  | }; | 
|  |  | 
|  | static int __init tipc_diag_init(void) | 
|  | { | 
|  | return sock_diag_register(&tipc_sock_diag_handler); | 
|  | } | 
|  |  | 
|  | static void __exit tipc_diag_exit(void) | 
|  | { | 
|  | sock_diag_unregister(&tipc_sock_diag_handler); | 
|  | } | 
|  |  | 
|  | module_init(tipc_diag_init); | 
|  | module_exit(tipc_diag_exit); | 
|  |  | 
|  | MODULE_LICENSE("Dual BSD/GPL"); | 
|  | MODULE_DESCRIPTION("TIPC socket monitoring via SOCK_DIAG"); | 
|  | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, AF_TIPC); |