1 #include <linux/module.h> 2 3 #include <net/sock.h> 4 #include <linux/netlink.h> 5 #include <linux/sock_diag.h> 6 #include <linux/netlink_diag.h> 7 8 #include "af_netlink.h" 9 10 #ifdef CONFIG_NETLINK_MMAP 11 static int sk_diag_put_ring(struct netlink_ring *ring, int nl_type, 12 struct sk_buff *nlskb) 13 { 14 struct netlink_diag_ring ndr; 15 16 ndr.ndr_block_size = ring->pg_vec_pages << PAGE_SHIFT; 17 ndr.ndr_block_nr = ring->pg_vec_len; 18 ndr.ndr_frame_size = ring->frame_size; 19 ndr.ndr_frame_nr = ring->frame_max + 1; 20 21 return nla_put(nlskb, nl_type, sizeof(ndr), &ndr); 22 } 23 24 static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb) 25 { 26 struct netlink_sock *nlk = nlk_sk(sk); 27 int ret; 28 29 mutex_lock(&nlk->pg_vec_lock); 30 ret = sk_diag_put_ring(&nlk->rx_ring, NETLINK_DIAG_RX_RING, nlskb); 31 if (!ret) 32 ret = sk_diag_put_ring(&nlk->tx_ring, NETLINK_DIAG_TX_RING, 33 nlskb); 34 mutex_unlock(&nlk->pg_vec_lock); 35 36 return ret; 37 } 38 #else 39 static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb) 40 { 41 return 0; 42 } 43 #endif 44 45 static int sk_diag_dump_groups(struct sock *sk, struct sk_buff *nlskb) 46 { 47 struct netlink_sock *nlk = nlk_sk(sk); 48 49 if (nlk->groups == NULL) 50 return 0; 51 52 return nla_put(nlskb, NETLINK_DIAG_GROUPS, NLGRPSZ(nlk->ngroups), 53 nlk->groups); 54 } 55 56 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, 57 struct netlink_diag_req *req, 58 u32 portid, u32 seq, u32 flags, int sk_ino) 59 { 60 struct nlmsghdr *nlh; 61 struct netlink_diag_msg *rep; 62 struct netlink_sock *nlk = nlk_sk(sk); 63 64 nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep), 65 flags); 66 if (!nlh) 67 return -EMSGSIZE; 68 69 rep = nlmsg_data(nlh); 70 rep->ndiag_family = AF_NETLINK; 71 rep->ndiag_type = sk->sk_type; 72 rep->ndiag_protocol = sk->sk_protocol; 73 rep->ndiag_state = sk->sk_state; 74 75 rep->ndiag_ino = sk_ino; 76 rep->ndiag_portid = nlk->portid; 77 rep->ndiag_dst_portid = nlk->dst_portid; 78 rep->ndiag_dst_group = nlk->dst_group; 79 sock_diag_save_cookie(sk, rep->ndiag_cookie); 80 81 if ((req->ndiag_show & NDIAG_SHOW_GROUPS) && 82 sk_diag_dump_groups(sk, skb)) 83 goto out_nlmsg_trim; 84 85 if ((req->ndiag_show & NDIAG_SHOW_MEMINFO) && 86 sock_diag_put_meminfo(sk, skb, NETLINK_DIAG_MEMINFO)) 87 goto out_nlmsg_trim; 88 89 if ((req->ndiag_show & NDIAG_SHOW_RING_CFG) && 90 sk_diag_put_rings_cfg(sk, skb)) 91 goto out_nlmsg_trim; 92 93 return nlmsg_end(skb, nlh); 94 95 out_nlmsg_trim: 96 nlmsg_cancel(skb, nlh); 97 return -EMSGSIZE; 98 } 99 100 static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, 101 int protocol, int s_num) 102 { 103 struct netlink_table *tbl = &nl_table[protocol]; 104 struct nl_portid_hash *hash = &tbl->hash; 105 struct net *net = sock_net(skb->sk); 106 struct netlink_diag_req *req; 107 struct sock *sk; 108 int ret = 0, num = 0, i; 109 110 req = nlmsg_data(cb->nlh); 111 112 for (i = 0; i <= hash->mask; i++) { 113 sk_for_each(sk, &hash->table[i]) { 114 if (!net_eq(sock_net(sk), net)) 115 continue; 116 if (num < s_num) { 117 num++; 118 continue; 119 } 120 121 if (sk_diag_fill(sk, skb, req, 122 NETLINK_CB(cb->skb).portid, 123 cb->nlh->nlmsg_seq, 124 NLM_F_MULTI, 125 sock_i_ino(sk)) < 0) { 126 ret = 1; 127 goto done; 128 } 129 130 num++; 131 } 132 } 133 134 sk_for_each_bound(sk, &tbl->mc_list) { 135 if (sk_hashed(sk)) 136 continue; 137 if (!net_eq(sock_net(sk), net)) 138 continue; 139 if (num < s_num) { 140 num++; 141 continue; 142 } 143 144 if (sk_diag_fill(sk, skb, req, 145 NETLINK_CB(cb->skb).portid, 146 cb->nlh->nlmsg_seq, 147 NLM_F_MULTI, 148 sock_i_ino(sk)) < 0) { 149 ret = 1; 150 goto done; 151 } 152 num++; 153 } 154 done: 155 cb->args[0] = num; 156 cb->args[1] = protocol; 157 158 return ret; 159 } 160 161 static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) 162 { 163 struct netlink_diag_req *req; 164 int s_num = cb->args[0]; 165 166 req = nlmsg_data(cb->nlh); 167 168 read_lock(&nl_table_lock); 169 170 if (req->sdiag_protocol == NDIAG_PROTO_ALL) { 171 int i; 172 173 for (i = cb->args[1]; i < MAX_LINKS; i++) { 174 if (__netlink_diag_dump(skb, cb, i, s_num)) 175 break; 176 s_num = 0; 177 } 178 } else { 179 if (req->sdiag_protocol >= MAX_LINKS) { 180 read_unlock(&nl_table_lock); 181 return -ENOENT; 182 } 183 184 __netlink_diag_dump(skb, cb, req->sdiag_protocol, s_num); 185 } 186 187 read_unlock(&nl_table_lock); 188 189 return skb->len; 190 } 191 192 static int netlink_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) 193 { 194 int hdrlen = sizeof(struct netlink_diag_req); 195 struct net *net = sock_net(skb->sk); 196 197 if (nlmsg_len(h) < hdrlen) 198 return -EINVAL; 199 200 if (h->nlmsg_flags & NLM_F_DUMP) { 201 struct netlink_dump_control c = { 202 .dump = netlink_diag_dump, 203 }; 204 return netlink_dump_start(net->diag_nlsk, skb, h, &c); 205 } else 206 return -EOPNOTSUPP; 207 } 208 209 static const struct sock_diag_handler netlink_diag_handler = { 210 .family = AF_NETLINK, 211 .dump = netlink_diag_handler_dump, 212 }; 213 214 static int __init netlink_diag_init(void) 215 { 216 return sock_diag_register(&netlink_diag_handler); 217 } 218 219 static void __exit netlink_diag_exit(void) 220 { 221 sock_diag_unregister(&netlink_diag_handler); 222 } 223 224 module_init(netlink_diag_init); 225 module_exit(netlink_diag_exit); 226 MODULE_LICENSE("GPL"); 227 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 16 /* AF_NETLINK */); 228