linux/net/ipv4/inet_diag.c
<<
>>
Prefs
   1/*
   2 * inet_diag.c  Module for monitoring INET transport protocols sockets.
   3 *
   4 * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
   5 *
   6 *      This program is free software; you can redistribute it and/or
   7 *      modify it under the terms of the GNU General Public License
   8 *      as published by the Free Software Foundation; either version
   9 *      2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/types.h>
  15#include <linux/fcntl.h>
  16#include <linux/random.h>
  17#include <linux/slab.h>
  18#include <linux/cache.h>
  19#include <linux/init.h>
  20#include <linux/time.h>
  21
  22#include <net/icmp.h>
  23#include <net/tcp.h>
  24#include <net/ipv6.h>
  25#include <net/inet_common.h>
  26#include <net/inet_connection_sock.h>
  27#include <net/inet_hashtables.h>
  28#include <net/inet_timewait_sock.h>
  29#include <net/inet6_hashtables.h>
  30#include <net/netlink.h>
  31
  32#include <linux/inet.h>
  33#include <linux/stddef.h>
  34
  35#include <linux/inet_diag.h>
  36#include <linux/sock_diag.h>
  37
  38static const struct inet_diag_handler **inet_diag_table;
  39
  40struct inet_diag_entry {
  41        __be32 *saddr;
  42        __be32 *daddr;
  43        u16 sport;
  44        u16 dport;
  45        u16 family;
  46        u16 userlocks;
  47};
  48
  49static DEFINE_MUTEX(inet_diag_table_mutex);
  50
  51static const struct inet_diag_handler *inet_diag_lock_handler(int proto)
  52{
  53        if (!inet_diag_table[proto])
  54                request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK,
  55                               NETLINK_SOCK_DIAG, AF_INET, proto);
  56
  57        mutex_lock(&inet_diag_table_mutex);
  58        if (!inet_diag_table[proto])
  59                return ERR_PTR(-ENOENT);
  60
  61        return inet_diag_table[proto];
  62}
  63
  64static inline void inet_diag_unlock_handler(
  65        const struct inet_diag_handler *handler)
  66{
  67        mutex_unlock(&inet_diag_table_mutex);
  68}
  69
  70int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
  71                              struct sk_buff *skb, struct inet_diag_req_v2 *req,
  72                              u32 pid, u32 seq, u16 nlmsg_flags,
  73                              const struct nlmsghdr *unlh)
  74{
  75        const struct inet_sock *inet = inet_sk(sk);
  76        struct inet_diag_msg *r;
  77        struct nlmsghdr  *nlh;
  78        struct nlattr *attr;
  79        void *info = NULL;
  80        const struct inet_diag_handler *handler;
  81        int ext = req->idiag_ext;
  82
  83        handler = inet_diag_table[req->sdiag_protocol];
  84        BUG_ON(handler == NULL);
  85
  86        nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r),
  87                        nlmsg_flags);
  88        if (!nlh)
  89                return -EMSGSIZE;
  90
  91        r = nlmsg_data(nlh);
  92        BUG_ON(sk->sk_state == TCP_TIME_WAIT);
  93
  94        r->idiag_family = sk->sk_family;
  95        r->idiag_state = sk->sk_state;
  96        r->idiag_timer = 0;
  97        r->idiag_retrans = 0;
  98
  99        r->id.idiag_if = sk->sk_bound_dev_if;
 100        sock_diag_save_cookie(sk, r->id.idiag_cookie);
 101
 102        r->id.idiag_sport = inet->inet_sport;
 103        r->id.idiag_dport = inet->inet_dport;
 104        r->id.idiag_src[0] = inet->inet_rcv_saddr;
 105        r->id.idiag_dst[0] = inet->inet_daddr;
 106
 107        /* IPv6 dual-stack sockets use inet->tos for IPv4 connections,
 108         * hence this needs to be included regardless of socket family.
 109         */
 110        if (ext & (1 << (INET_DIAG_TOS - 1)))
 111                if (nla_put_u8(skb, INET_DIAG_TOS, inet->tos) < 0)
 112                        goto errout;
 113
 114#if IS_ENABLED(CONFIG_IPV6)
 115        if (r->idiag_family == AF_INET6) {
 116                const struct ipv6_pinfo *np = inet6_sk(sk);
 117
 118                *(struct in6_addr *)r->id.idiag_src = np->rcv_saddr;
 119                *(struct in6_addr *)r->id.idiag_dst = np->daddr;
 120
 121                if (ext & (1 << (INET_DIAG_TCLASS - 1)))
 122                        if (nla_put_u8(skb, INET_DIAG_TCLASS, np->tclass) < 0)
 123                                goto errout;
 124        }
 125#endif
 126
 127        r->idiag_uid = sock_i_uid(sk);
 128        r->idiag_inode = sock_i_ino(sk);
 129
 130        if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
 131                struct inet_diag_meminfo minfo = {
 132                        .idiag_rmem = sk_rmem_alloc_get(sk),
 133                        .idiag_wmem = sk->sk_wmem_queued,
 134                        .idiag_fmem = sk->sk_forward_alloc,
 135                        .idiag_tmem = sk_wmem_alloc_get(sk),
 136                };
 137
 138                if (nla_put(skb, INET_DIAG_MEMINFO, sizeof(minfo), &minfo) < 0)
 139                        goto errout;
 140        }
 141
 142        if (ext & (1 << (INET_DIAG_SKMEMINFO - 1)))
 143                if (sock_diag_put_meminfo(sk, skb, INET_DIAG_SKMEMINFO))
 144                        goto errout;
 145
 146        if (icsk == NULL) {
 147                handler->idiag_get_info(sk, r, NULL);
 148                goto out;
 149        }
 150
 151#define EXPIRES_IN_MS(tmo)  DIV_ROUND_UP((tmo - jiffies) * 1000, HZ)
 152
 153        if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
 154                r->idiag_timer = 1;
 155                r->idiag_retrans = icsk->icsk_retransmits;
 156                r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);
 157        } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
 158                r->idiag_timer = 4;
 159                r->idiag_retrans = icsk->icsk_probes_out;
 160                r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);
 161        } else if (timer_pending(&sk->sk_timer)) {
 162                r->idiag_timer = 2;
 163                r->idiag_retrans = icsk->icsk_probes_out;
 164                r->idiag_expires = EXPIRES_IN_MS(sk->sk_timer.expires);
 165        } else {
 166                r->idiag_timer = 0;
 167                r->idiag_expires = 0;
 168        }
 169#undef EXPIRES_IN_MS
 170
 171        if (ext & (1 << (INET_DIAG_INFO - 1))) {
 172                attr = nla_reserve(skb, INET_DIAG_INFO,
 173                                   sizeof(struct tcp_info));
 174                if (!attr)
 175                        goto errout;
 176
 177                info = nla_data(attr);
 178        }
 179
 180        if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops)
 181                if (nla_put_string(skb, INET_DIAG_CONG,
 182                                   icsk->icsk_ca_ops->name) < 0)
 183                        goto errout;
 184
 185        handler->idiag_get_info(sk, r, info);
 186
 187        if (sk->sk_state < TCP_TIME_WAIT &&
 188            icsk->icsk_ca_ops && icsk->icsk_ca_ops->get_info)
 189                icsk->icsk_ca_ops->get_info(sk, ext, skb);
 190
 191out:
 192        return nlmsg_end(skb, nlh);
 193
 194errout:
 195        nlmsg_cancel(skb, nlh);
 196        return -EMSGSIZE;
 197}
 198EXPORT_SYMBOL_GPL(inet_sk_diag_fill);
 199
 200static int inet_csk_diag_fill(struct sock *sk,
 201                              struct sk_buff *skb, struct inet_diag_req_v2 *req,
 202                              u32 pid, u32 seq, u16 nlmsg_flags,
 203                              const struct nlmsghdr *unlh)
 204{
 205        return inet_sk_diag_fill(sk, inet_csk(sk),
 206                        skb, req, pid, seq, nlmsg_flags, unlh);
 207}
 208
 209static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 210                               struct sk_buff *skb, struct inet_diag_req_v2 *req,
 211                               u32 pid, u32 seq, u16 nlmsg_flags,
 212                               const struct nlmsghdr *unlh)
 213{
 214        long tmo;
 215        struct inet_diag_msg *r;
 216        struct nlmsghdr *nlh;
 217
 218        nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r),
 219                        nlmsg_flags);
 220        if (!nlh)
 221                return -EMSGSIZE;
 222
 223        r = nlmsg_data(nlh);
 224        BUG_ON(tw->tw_state != TCP_TIME_WAIT);
 225
 226        tmo = tw->tw_ttd - jiffies;
 227        if (tmo < 0)
 228                tmo = 0;
 229
 230        r->idiag_family       = tw->tw_family;
 231        r->idiag_retrans      = 0;
 232        r->id.idiag_if        = tw->tw_bound_dev_if;
 233        sock_diag_save_cookie(tw, r->id.idiag_cookie);
 234        r->id.idiag_sport     = tw->tw_sport;
 235        r->id.idiag_dport     = tw->tw_dport;
 236        r->id.idiag_src[0]    = tw->tw_rcv_saddr;
 237        r->id.idiag_dst[0]    = tw->tw_daddr;
 238        r->idiag_state        = tw->tw_substate;
 239        r->idiag_timer        = 3;
 240        r->idiag_expires      = DIV_ROUND_UP(tmo * 1000, HZ);
 241        r->idiag_rqueue       = 0;
 242        r->idiag_wqueue       = 0;
 243        r->idiag_uid          = 0;
 244        r->idiag_inode        = 0;
 245#if IS_ENABLED(CONFIG_IPV6)
 246        if (tw->tw_family == AF_INET6) {
 247                const struct inet6_timewait_sock *tw6 =
 248                                                inet6_twsk((struct sock *)tw);
 249
 250                *(struct in6_addr *)r->id.idiag_src = tw6->tw_v6_rcv_saddr;
 251                *(struct in6_addr *)r->id.idiag_dst = tw6->tw_v6_daddr;
 252        }
 253#endif
 254
 255        return nlmsg_end(skb, nlh);
 256}
 257
 258static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
 259                        struct inet_diag_req_v2 *r, u32 pid, u32 seq, u16 nlmsg_flags,
 260                        const struct nlmsghdr *unlh)
 261{
 262        if (sk->sk_state == TCP_TIME_WAIT)
 263                return inet_twsk_diag_fill((struct inet_timewait_sock *)sk,
 264                                           skb, r, pid, seq, nlmsg_flags,
 265                                           unlh);
 266        return inet_csk_diag_fill(sk, skb, r, pid, seq, nlmsg_flags, unlh);
 267}
 268
 269int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb,
 270                const struct nlmsghdr *nlh, struct inet_diag_req_v2 *req)
 271{
 272        int err;
 273        struct sock *sk;
 274        struct sk_buff *rep;
 275        struct net *net = sock_net(in_skb->sk);
 276
 277        err = -EINVAL;
 278        if (req->sdiag_family == AF_INET) {
 279                sk = inet_lookup(net, hashinfo, req->id.idiag_dst[0],
 280                                 req->id.idiag_dport, req->id.idiag_src[0],
 281                                 req->id.idiag_sport, req->id.idiag_if);
 282        }
 283#if IS_ENABLED(CONFIG_IPV6)
 284        else if (req->sdiag_family == AF_INET6) {
 285                sk = inet6_lookup(net, hashinfo,
 286                                  (struct in6_addr *)req->id.idiag_dst,
 287                                  req->id.idiag_dport,
 288                                  (struct in6_addr *)req->id.idiag_src,
 289                                  req->id.idiag_sport,
 290                                  req->id.idiag_if);
 291        }
 292#endif
 293        else {
 294                goto out_nosk;
 295        }
 296
 297        err = -ENOENT;
 298        if (sk == NULL)
 299                goto out_nosk;
 300
 301        err = sock_diag_check_cookie(sk, req->id.idiag_cookie);
 302        if (err)
 303                goto out;
 304
 305        rep = nlmsg_new(sizeof(struct inet_diag_msg) +
 306                        sizeof(struct inet_diag_meminfo) +
 307                        sizeof(struct tcp_info) + 64, GFP_KERNEL);
 308        if (!rep) {
 309                err = -ENOMEM;
 310                goto out;
 311        }
 312
 313        err = sk_diag_fill(sk, rep, req,
 314                           NETLINK_CB(in_skb).pid,
 315                           nlh->nlmsg_seq, 0, nlh);
 316        if (err < 0) {
 317                WARN_ON(err == -EMSGSIZE);
 318                nlmsg_free(rep);
 319                goto out;
 320        }
 321        err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
 322                              MSG_DONTWAIT);
 323        if (err > 0)
 324                err = 0;
 325
 326out:
 327        if (sk) {
 328                if (sk->sk_state == TCP_TIME_WAIT)
 329                        inet_twsk_put((struct inet_timewait_sock *)sk);
 330                else
 331                        sock_put(sk);
 332        }
 333out_nosk:
 334        return err;
 335}
 336EXPORT_SYMBOL_GPL(inet_diag_dump_one_icsk);
 337
 338static int inet_diag_get_exact(struct sk_buff *in_skb,
 339                               const struct nlmsghdr *nlh,
 340                               struct inet_diag_req_v2 *req)
 341{
 342        const struct inet_diag_handler *handler;
 343        int err;
 344
 345        handler = inet_diag_lock_handler(req->sdiag_protocol);
 346        if (IS_ERR(handler))
 347                err = PTR_ERR(handler);
 348        else
 349                err = handler->dump_one(in_skb, nlh, req);
 350        inet_diag_unlock_handler(handler);
 351
 352        return err;
 353}
 354
 355static int bitstring_match(const __be32 *a1, const __be32 *a2, int bits)
 356{
 357        int words = bits >> 5;
 358
 359        bits &= 0x1f;
 360
 361        if (words) {
 362                if (memcmp(a1, a2, words << 2))
 363                        return 0;
 364        }
 365        if (bits) {
 366                __be32 w1, w2;
 367                __be32 mask;
 368
 369                w1 = a1[words];
 370                w2 = a2[words];
 371
 372                mask = htonl((0xffffffff) << (32 - bits));
 373
 374                if ((w1 ^ w2) & mask)
 375                        return 0;
 376        }
 377
 378        return 1;
 379}
 380
 381
 382static int inet_diag_bc_run(const struct nlattr *_bc,
 383                const struct inet_diag_entry *entry)
 384{
 385        const void *bc = nla_data(_bc);
 386        int len = nla_len(_bc);
 387
 388        while (len > 0) {
 389                int yes = 1;
 390                const struct inet_diag_bc_op *op = bc;
 391
 392                switch (op->code) {
 393                case INET_DIAG_BC_NOP:
 394                        break;
 395                case INET_DIAG_BC_JMP:
 396                        yes = 0;
 397                        break;
 398                case INET_DIAG_BC_S_GE:
 399                        yes = entry->sport >= op[1].no;
 400                        break;
 401                case INET_DIAG_BC_S_LE:
 402                        yes = entry->sport <= op[1].no;
 403                        break;
 404                case INET_DIAG_BC_D_GE:
 405                        yes = entry->dport >= op[1].no;
 406                        break;
 407                case INET_DIAG_BC_D_LE:
 408                        yes = entry->dport <= op[1].no;
 409                        break;
 410                case INET_DIAG_BC_AUTO:
 411                        yes = !(entry->userlocks & SOCK_BINDPORT_LOCK);
 412                        break;
 413                case INET_DIAG_BC_S_COND:
 414                case INET_DIAG_BC_D_COND: {
 415                        struct inet_diag_hostcond *cond;
 416                        __be32 *addr;
 417
 418                        cond = (struct inet_diag_hostcond *)(op + 1);
 419                        if (cond->port != -1 &&
 420                            cond->port != (op->code == INET_DIAG_BC_S_COND ?
 421                                             entry->sport : entry->dport)) {
 422                                yes = 0;
 423                                break;
 424                        }
 425
 426                        if (cond->prefix_len == 0)
 427                                break;
 428
 429                        if (op->code == INET_DIAG_BC_S_COND)
 430                                addr = entry->saddr;
 431                        else
 432                                addr = entry->daddr;
 433
 434                        if (bitstring_match(addr, cond->addr,
 435                                            cond->prefix_len))
 436                                break;
 437                        if (entry->family == AF_INET6 &&
 438                            cond->family == AF_INET) {
 439                                if (addr[0] == 0 && addr[1] == 0 &&
 440                                    addr[2] == htonl(0xffff) &&
 441                                    bitstring_match(addr + 3, cond->addr,
 442                                                    cond->prefix_len))
 443                                        break;
 444                        }
 445                        yes = 0;
 446                        break;
 447                }
 448                }
 449
 450                if (yes) {
 451                        len -= op->yes;
 452                        bc += op->yes;
 453                } else {
 454                        len -= op->no;
 455                        bc += op->no;
 456                }
 457        }
 458        return len == 0;
 459}
 460
 461int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
 462{
 463        struct inet_diag_entry entry;
 464        struct inet_sock *inet = inet_sk(sk);
 465
 466        if (bc == NULL)
 467                return 1;
 468
 469        entry.family = sk->sk_family;
 470#if IS_ENABLED(CONFIG_IPV6)
 471        if (entry.family == AF_INET6) {
 472                struct ipv6_pinfo *np = inet6_sk(sk);
 473
 474                entry.saddr = np->rcv_saddr.s6_addr32;
 475                entry.daddr = np->daddr.s6_addr32;
 476        } else
 477#endif
 478        {
 479                entry.saddr = &inet->inet_rcv_saddr;
 480                entry.daddr = &inet->inet_daddr;
 481        }
 482        entry.sport = inet->inet_num;
 483        entry.dport = ntohs(inet->inet_dport);
 484        entry.userlocks = sk->sk_userlocks;
 485
 486        return inet_diag_bc_run(bc, &entry);
 487}
 488EXPORT_SYMBOL_GPL(inet_diag_bc_sk);
 489
 490static int valid_cc(const void *bc, int len, int cc)
 491{
 492        while (len >= 0) {
 493                const struct inet_diag_bc_op *op = bc;
 494
 495                if (cc > len)
 496                        return 0;
 497                if (cc == len)
 498                        return 1;
 499                if (op->yes < 4 || op->yes & 3)
 500                        return 0;
 501                len -= op->yes;
 502                bc  += op->yes;
 503        }
 504        return 0;
 505}
 506
 507static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
 508{
 509        const void *bc = bytecode;
 510        int  len = bytecode_len;
 511
 512        while (len > 0) {
 513                const struct inet_diag_bc_op *op = bc;
 514
 515//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
 516                switch (op->code) {
 517                case INET_DIAG_BC_AUTO:
 518                case INET_DIAG_BC_S_COND:
 519                case INET_DIAG_BC_D_COND:
 520                case INET_DIAG_BC_S_GE:
 521                case INET_DIAG_BC_S_LE:
 522                case INET_DIAG_BC_D_GE:
 523                case INET_DIAG_BC_D_LE:
 524                case INET_DIAG_BC_JMP:
 525                        if (op->no < 4 || op->no > len + 4 || op->no & 3)
 526                                return -EINVAL;
 527                        if (op->no < len &&
 528                            !valid_cc(bytecode, bytecode_len, len - op->no))
 529                                return -EINVAL;
 530                        break;
 531                case INET_DIAG_BC_NOP:
 532                        break;
 533                default:
 534                        return -EINVAL;
 535                }
 536                if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
 537                        return -EINVAL;
 538                bc  += op->yes;
 539                len -= op->yes;
 540        }
 541        return len == 0 ? 0 : -EINVAL;
 542}
 543
 544static int inet_csk_diag_dump(struct sock *sk,
 545                              struct sk_buff *skb,
 546                              struct netlink_callback *cb,
 547                              struct inet_diag_req_v2 *r,
 548                              const struct nlattr *bc)
 549{
 550        if (!inet_diag_bc_sk(bc, sk))
 551                return 0;
 552
 553        return inet_csk_diag_fill(sk, skb, r,
 554                                  NETLINK_CB(cb->skb).pid,
 555                                  cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
 556}
 557
 558static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
 559                               struct sk_buff *skb,
 560                               struct netlink_callback *cb,
 561                               struct inet_diag_req_v2 *r,
 562                               const struct nlattr *bc)
 563{
 564        if (bc != NULL) {
 565                struct inet_diag_entry entry;
 566
 567                entry.family = tw->tw_family;
 568#if IS_ENABLED(CONFIG_IPV6)
 569                if (tw->tw_family == AF_INET6) {
 570                        struct inet6_timewait_sock *tw6 =
 571                                                inet6_twsk((struct sock *)tw);
 572                        entry.saddr = tw6->tw_v6_rcv_saddr.s6_addr32;
 573                        entry.daddr = tw6->tw_v6_daddr.s6_addr32;
 574                } else
 575#endif
 576                {
 577                        entry.saddr = &tw->tw_rcv_saddr;
 578                        entry.daddr = &tw->tw_daddr;
 579                }
 580                entry.sport = tw->tw_num;
 581                entry.dport = ntohs(tw->tw_dport);
 582                entry.userlocks = 0;
 583
 584                if (!inet_diag_bc_run(bc, &entry))
 585                        return 0;
 586        }
 587
 588        return inet_twsk_diag_fill(tw, skb, r,
 589                                   NETLINK_CB(cb->skb).pid,
 590                                   cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
 591}
 592
 593static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
 594                              struct request_sock *req, u32 pid, u32 seq,
 595                              const struct nlmsghdr *unlh)
 596{
 597        const struct inet_request_sock *ireq = inet_rsk(req);
 598        struct inet_sock *inet = inet_sk(sk);
 599        struct inet_diag_msg *r;
 600        struct nlmsghdr *nlh;
 601        long tmo;
 602
 603        nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r),
 604                        NLM_F_MULTI);
 605        if (!nlh)
 606                return -EMSGSIZE;
 607
 608        r = nlmsg_data(nlh);
 609        r->idiag_family = sk->sk_family;
 610        r->idiag_state = TCP_SYN_RECV;
 611        r->idiag_timer = 1;
 612        r->idiag_retrans = req->retrans;
 613
 614        r->id.idiag_if = sk->sk_bound_dev_if;
 615        sock_diag_save_cookie(req, r->id.idiag_cookie);
 616
 617        tmo = req->expires - jiffies;
 618        if (tmo < 0)
 619                tmo = 0;
 620
 621        r->id.idiag_sport = inet->inet_sport;
 622        r->id.idiag_dport = ireq->rmt_port;
 623        r->id.idiag_src[0] = ireq->loc_addr;
 624        r->id.idiag_dst[0] = ireq->rmt_addr;
 625        r->idiag_expires = jiffies_to_msecs(tmo);
 626        r->idiag_rqueue = 0;
 627        r->idiag_wqueue = 0;
 628        r->idiag_uid = sock_i_uid(sk);
 629        r->idiag_inode = 0;
 630#if IS_ENABLED(CONFIG_IPV6)
 631        if (r->idiag_family == AF_INET6) {
 632                *(struct in6_addr *)r->id.idiag_src = inet6_rsk(req)->loc_addr;
 633                *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr;
 634        }
 635#endif
 636
 637        return nlmsg_end(skb, nlh);
 638}
 639
 640static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
 641                               struct netlink_callback *cb,
 642                               struct inet_diag_req_v2 *r,
 643                               const struct nlattr *bc)
 644{
 645        struct inet_diag_entry entry;
 646        struct inet_connection_sock *icsk = inet_csk(sk);
 647        struct listen_sock *lopt;
 648        struct inet_sock *inet = inet_sk(sk);
 649        int j, s_j;
 650        int reqnum, s_reqnum;
 651        int err = 0;
 652
 653        s_j = cb->args[3];
 654        s_reqnum = cb->args[4];
 655
 656        if (s_j > 0)
 657                s_j--;
 658
 659        entry.family = sk->sk_family;
 660
 661        read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
 662
 663        lopt = icsk->icsk_accept_queue.listen_opt;
 664        if (!lopt || !lopt->qlen)
 665                goto out;
 666
 667        if (bc != NULL) {
 668                entry.sport = inet->inet_num;
 669                entry.userlocks = sk->sk_userlocks;
 670        }
 671
 672        for (j = s_j; j < lopt->nr_table_entries; j++) {
 673                struct request_sock *req, *head = lopt->syn_table[j];
 674
 675                reqnum = 0;
 676                for (req = head; req; reqnum++, req = req->dl_next) {
 677                        struct inet_request_sock *ireq = inet_rsk(req);
 678
 679                        if (reqnum < s_reqnum)
 680                                continue;
 681                        if (r->id.idiag_dport != ireq->rmt_port &&
 682                            r->id.idiag_dport)
 683                                continue;
 684
 685                        if (bc) {
 686                                entry.saddr =
 687#if IS_ENABLED(CONFIG_IPV6)
 688                                        (entry.family == AF_INET6) ?
 689                                        inet6_rsk(req)->loc_addr.s6_addr32 :
 690#endif
 691                                        &ireq->loc_addr;
 692                                entry.daddr =
 693#if IS_ENABLED(CONFIG_IPV6)
 694                                        (entry.family == AF_INET6) ?
 695                                        inet6_rsk(req)->rmt_addr.s6_addr32 :
 696#endif
 697                                        &ireq->rmt_addr;
 698                                entry.dport = ntohs(ireq->rmt_port);
 699
 700                                if (!inet_diag_bc_run(bc, &entry))
 701                                        continue;
 702                        }
 703
 704                        err = inet_diag_fill_req(skb, sk, req,
 705                                               NETLINK_CB(cb->skb).pid,
 706                                               cb->nlh->nlmsg_seq, cb->nlh);
 707                        if (err < 0) {
 708                                cb->args[3] = j + 1;
 709                                cb->args[4] = reqnum;
 710                                goto out;
 711                        }
 712                }
 713
 714                s_reqnum = 0;
 715        }
 716
 717out:
 718        read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
 719
 720        return err;
 721}
 722
 723void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 724                struct netlink_callback *cb, struct inet_diag_req_v2 *r, struct nlattr *bc)
 725{
 726        int i, num;
 727        int s_i, s_num;
 728        struct net *net = sock_net(skb->sk);
 729
 730        s_i = cb->args[1];
 731        s_num = num = cb->args[2];
 732
 733        if (cb->args[0] == 0) {
 734                if (!(r->idiag_states & (TCPF_LISTEN | TCPF_SYN_RECV)))
 735                        goto skip_listen_ht;
 736
 737                for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
 738                        struct sock *sk;
 739                        struct hlist_nulls_node *node;
 740                        struct inet_listen_hashbucket *ilb;
 741
 742                        num = 0;
 743                        ilb = &hashinfo->listening_hash[i];
 744                        spin_lock_bh(&ilb->lock);
 745                        sk_nulls_for_each(sk, node, &ilb->head) {
 746                                struct inet_sock *inet = inet_sk(sk);
 747
 748                                if (!net_eq(sock_net(sk), net))
 749                                        continue;
 750
 751                                if (num < s_num) {
 752                                        num++;
 753                                        continue;
 754                                }
 755
 756                                if (r->sdiag_family != AF_UNSPEC &&
 757                                                sk->sk_family != r->sdiag_family)
 758                                        goto next_listen;
 759
 760                                if (r->id.idiag_sport != inet->inet_sport &&
 761                                    r->id.idiag_sport)
 762                                        goto next_listen;
 763
 764                                if (!(r->idiag_states & TCPF_LISTEN) ||
 765                                    r->id.idiag_dport ||
 766                                    cb->args[3] > 0)
 767                                        goto syn_recv;
 768
 769                                if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) {
 770                                        spin_unlock_bh(&ilb->lock);
 771                                        goto done;
 772                                }
 773
 774syn_recv:
 775                                if (!(r->idiag_states & TCPF_SYN_RECV))
 776                                        goto next_listen;
 777
 778                                if (inet_diag_dump_reqs(skb, sk, cb, r, bc) < 0) {
 779                                        spin_unlock_bh(&ilb->lock);
 780                                        goto done;
 781                                }
 782
 783next_listen:
 784                                cb->args[3] = 0;
 785                                cb->args[4] = 0;
 786                                ++num;
 787                        }
 788                        spin_unlock_bh(&ilb->lock);
 789
 790                        s_num = 0;
 791                        cb->args[3] = 0;
 792                        cb->args[4] = 0;
 793                }
 794skip_listen_ht:
 795                cb->args[0] = 1;
 796                s_i = num = s_num = 0;
 797        }
 798
 799        if (!(r->idiag_states & ~(TCPF_LISTEN | TCPF_SYN_RECV)))
 800                goto out;
 801
 802        for (i = s_i; i <= hashinfo->ehash_mask; i++) {
 803                struct inet_ehash_bucket *head = &hashinfo->ehash[i];
 804                spinlock_t *lock = inet_ehash_lockp(hashinfo, i);
 805                struct sock *sk;
 806                struct hlist_nulls_node *node;
 807
 808                num = 0;
 809
 810                if (hlist_nulls_empty(&head->chain) &&
 811                        hlist_nulls_empty(&head->twchain))
 812                        continue;
 813
 814                if (i > s_i)
 815                        s_num = 0;
 816
 817                spin_lock_bh(lock);
 818                sk_nulls_for_each(sk, node, &head->chain) {
 819                        struct inet_sock *inet = inet_sk(sk);
 820
 821                        if (!net_eq(sock_net(sk), net))
 822                                continue;
 823                        if (num < s_num)
 824                                goto next_normal;
 825                        if (!(r->idiag_states & (1 << sk->sk_state)))
 826                                goto next_normal;
 827                        if (r->sdiag_family != AF_UNSPEC &&
 828                                        sk->sk_family != r->sdiag_family)
 829                                goto next_normal;
 830                        if (r->id.idiag_sport != inet->inet_sport &&
 831                            r->id.idiag_sport)
 832                                goto next_normal;
 833                        if (r->id.idiag_dport != inet->inet_dport &&
 834                            r->id.idiag_dport)
 835                                goto next_normal;
 836                        if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) {
 837                                spin_unlock_bh(lock);
 838                                goto done;
 839                        }
 840next_normal:
 841                        ++num;
 842                }
 843
 844                if (r->idiag_states & TCPF_TIME_WAIT) {
 845                        struct inet_timewait_sock *tw;
 846
 847                        inet_twsk_for_each(tw, node,
 848                                    &head->twchain) {
 849                                if (!net_eq(twsk_net(tw), net))
 850                                        continue;
 851
 852                                if (num < s_num)
 853                                        goto next_dying;
 854                                if (r->sdiag_family != AF_UNSPEC &&
 855                                                tw->tw_family != r->sdiag_family)
 856                                        goto next_dying;
 857                                if (r->id.idiag_sport != tw->tw_sport &&
 858                                    r->id.idiag_sport)
 859                                        goto next_dying;
 860                                if (r->id.idiag_dport != tw->tw_dport &&
 861                                    r->id.idiag_dport)
 862                                        goto next_dying;
 863                                if (inet_twsk_diag_dump(tw, skb, cb, r, bc) < 0) {
 864                                        spin_unlock_bh(lock);
 865                                        goto done;
 866                                }
 867next_dying:
 868                                ++num;
 869                        }
 870                }
 871                spin_unlock_bh(lock);
 872        }
 873
 874done:
 875        cb->args[1] = i;
 876        cb->args[2] = num;
 877out:
 878        ;
 879}
 880EXPORT_SYMBOL_GPL(inet_diag_dump_icsk);
 881
 882static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
 883                struct inet_diag_req_v2 *r, struct nlattr *bc)
 884{
 885        const struct inet_diag_handler *handler;
 886        int err = 0;
 887
 888        handler = inet_diag_lock_handler(r->sdiag_protocol);
 889        if (!IS_ERR(handler))
 890                handler->dump(skb, cb, r, bc);
 891        else
 892                err = PTR_ERR(handler);
 893        inet_diag_unlock_handler(handler);
 894
 895        return err ? : skb->len;
 896}
 897
 898static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
 899{
 900        struct nlattr *bc = NULL;
 901        int hdrlen = sizeof(struct inet_diag_req_v2);
 902
 903        if (nlmsg_attrlen(cb->nlh, hdrlen))
 904                bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE);
 905
 906        return __inet_diag_dump(skb, cb, nlmsg_data(cb->nlh), bc);
 907}
 908
 909static inline int inet_diag_type2proto(int type)
 910{
 911        switch (type) {
 912        case TCPDIAG_GETSOCK:
 913                return IPPROTO_TCP;
 914        case DCCPDIAG_GETSOCK:
 915                return IPPROTO_DCCP;
 916        default:
 917                return 0;
 918        }
 919}
 920
 921static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *cb)
 922{
 923        struct inet_diag_req *rc = nlmsg_data(cb->nlh);
 924        struct inet_diag_req_v2 req;
 925        struct nlattr *bc = NULL;
 926        int hdrlen = sizeof(struct inet_diag_req);
 927
 928        req.sdiag_family = AF_UNSPEC; /* compatibility */
 929        req.sdiag_protocol = inet_diag_type2proto(cb->nlh->nlmsg_type);
 930        req.idiag_ext = rc->idiag_ext;
 931        req.idiag_states = rc->idiag_states;
 932        req.id = rc->id;
 933
 934        if (nlmsg_attrlen(cb->nlh, hdrlen))
 935                bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE);
 936
 937        return __inet_diag_dump(skb, cb, &req, bc);
 938}
 939
 940static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
 941                               const struct nlmsghdr *nlh)
 942{
 943        struct inet_diag_req *rc = nlmsg_data(nlh);
 944        struct inet_diag_req_v2 req;
 945
 946        req.sdiag_family = rc->idiag_family;
 947        req.sdiag_protocol = inet_diag_type2proto(nlh->nlmsg_type);
 948        req.idiag_ext = rc->idiag_ext;
 949        req.idiag_states = rc->idiag_states;
 950        req.id = rc->id;
 951
 952        return inet_diag_get_exact(in_skb, nlh, &req);
 953}
 954
 955static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
 956{
 957        int hdrlen = sizeof(struct inet_diag_req);
 958        struct net *net = sock_net(skb->sk);
 959
 960        if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX ||
 961            nlmsg_len(nlh) < hdrlen)
 962                return -EINVAL;
 963
 964        if (nlh->nlmsg_flags & NLM_F_DUMP) {
 965                if (nlmsg_attrlen(nlh, hdrlen)) {
 966                        struct nlattr *attr;
 967
 968                        attr = nlmsg_find_attr(nlh, hdrlen,
 969                                               INET_DIAG_REQ_BYTECODE);
 970                        if (attr == NULL ||
 971                            nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
 972                            inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
 973                                return -EINVAL;
 974                }
 975                {
 976                        struct netlink_dump_control c = {
 977                                .dump = inet_diag_dump_compat,
 978                        };
 979                        return netlink_dump_start(net->diag_nlsk, skb, nlh, &c);
 980                }
 981        }
 982
 983        return inet_diag_get_exact_compat(skb, nlh);
 984}
 985
 986static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 987{
 988        int hdrlen = sizeof(struct inet_diag_req_v2);
 989        struct net *net = sock_net(skb->sk);
 990
 991        if (nlmsg_len(h) < hdrlen)
 992                return -EINVAL;
 993
 994        if (h->nlmsg_flags & NLM_F_DUMP) {
 995                if (nlmsg_attrlen(h, hdrlen)) {
 996                        struct nlattr *attr;
 997                        attr = nlmsg_find_attr(h, hdrlen,
 998                                               INET_DIAG_REQ_BYTECODE);
 999                        if (attr == NULL ||
1000                            nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
1001                            inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
1002                                return -EINVAL;
1003                }
1004                {
1005                        struct netlink_dump_control c = {
1006                                .dump = inet_diag_dump,
1007                        };
1008                        return netlink_dump_start(net->diag_nlsk, skb, h, &c);
1009                }
1010        }
1011
1012        return inet_diag_get_exact(skb, h, nlmsg_data(h));
1013}
1014
1015static const struct sock_diag_handler inet_diag_handler = {
1016        .family = AF_INET,
1017        .dump = inet_diag_handler_dump,
1018};
1019
1020static const struct sock_diag_handler inet6_diag_handler = {
1021        .family = AF_INET6,
1022        .dump = inet_diag_handler_dump,
1023};
1024
1025int inet_diag_register(const struct inet_diag_handler *h)
1026{
1027        const __u16 type = h->idiag_type;
1028        int err = -EINVAL;
1029
1030        if (type >= IPPROTO_MAX)
1031                goto out;
1032
1033        mutex_lock(&inet_diag_table_mutex);
1034        err = -EEXIST;
1035        if (inet_diag_table[type] == NULL) {
1036                inet_diag_table[type] = h;
1037                err = 0;
1038        }
1039        mutex_unlock(&inet_diag_table_mutex);
1040out:
1041        return err;
1042}
1043EXPORT_SYMBOL_GPL(inet_diag_register);
1044
1045void inet_diag_unregister(const struct inet_diag_handler *h)
1046{
1047        const __u16 type = h->idiag_type;
1048
1049        if (type >= IPPROTO_MAX)
1050                return;
1051
1052        mutex_lock(&inet_diag_table_mutex);
1053        inet_diag_table[type] = NULL;
1054        mutex_unlock(&inet_diag_table_mutex);
1055}
1056EXPORT_SYMBOL_GPL(inet_diag_unregister);
1057
1058static int __init inet_diag_init(void)
1059{
1060        const int inet_diag_table_size = (IPPROTO_MAX *
1061                                          sizeof(struct inet_diag_handler *));
1062        int err = -ENOMEM;
1063
1064        inet_diag_table = kzalloc(inet_diag_table_size, GFP_KERNEL);
1065        if (!inet_diag_table)
1066                goto out;
1067
1068        err = sock_diag_register(&inet_diag_handler);
1069        if (err)
1070                goto out_free_nl;
1071
1072        err = sock_diag_register(&inet6_diag_handler);
1073        if (err)
1074                goto out_free_inet;
1075
1076        sock_diag_register_inet_compat(inet_diag_rcv_msg_compat);
1077out:
1078        return err;
1079
1080out_free_inet:
1081        sock_diag_unregister(&inet_diag_handler);
1082out_free_nl:
1083        kfree(inet_diag_table);
1084        goto out;
1085}
1086
1087static void __exit inet_diag_exit(void)
1088{
1089        sock_diag_unregister(&inet6_diag_handler);
1090        sock_diag_unregister(&inet_diag_handler);
1091        sock_diag_unregister_inet_compat(inet_diag_rcv_msg_compat);
1092        kfree(inet_diag_table);
1093}
1094
1095module_init(inet_diag_init);
1096module_exit(inet_diag_exit);
1097MODULE_LICENSE("GPL");
1098MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2 /* AF_INET */);
1099MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10 /* AF_INET6 */);
1100
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.