linux/net/sctp/sysctl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* SCTP kernel implementation
   3 * (C) Copyright IBM Corp. 2002, 2004
   4 * Copyright (c) 2002 Intel Corp.
   5 *
   6 * This file is part of the SCTP kernel implementation
   7 *
   8 * Sysctl related interfaces for SCTP.
   9 *
  10 * Please send any bug reports or fixes you make to the
  11 * email address(es):
  12 *    lksctp developers <linux-sctp@vger.kernel.org>
  13 *
  14 * Written or modified by:
  15 *    Mingqin Liu           <liuming@us.ibm.com>
  16 *    Jon Grimm             <jgrimm@us.ibm.com>
  17 *    Ardelle Fan           <ardelle.fan@intel.com>
  18 *    Ryan Layer            <rmlayer@us.ibm.com>
  19 *    Sridhar Samudrala     <sri@us.ibm.com>
  20 */
  21
  22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  23
  24#include <net/sctp/structs.h>
  25#include <net/sctp/sctp.h>
  26#include <linux/sysctl.h>
  27
  28static int zero = 0;
  29static int one = 1;
  30static int timer_max = 86400000; /* ms in one day */
  31static int int_max = INT_MAX;
  32static int sack_timer_min = 1;
  33static int sack_timer_max = 500;
  34static int addr_scope_max = SCTP_SCOPE_POLICY_MAX;
  35static int rwnd_scale_max = 16;
  36static int rto_alpha_min = 0;
  37static int rto_beta_min = 0;
  38static int rto_alpha_max = 1000;
  39static int rto_beta_max = 1000;
  40
  41static unsigned long max_autoclose_min = 0;
  42static unsigned long max_autoclose_max =
  43        (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX)
  44        ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ;
  45
  46static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
  47                                void __user *buffer, size_t *lenp,
  48                                loff_t *ppos);
  49static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
  50                                void __user *buffer, size_t *lenp,
  51                                loff_t *ppos);
  52static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
  53                                void __user *buffer, size_t *lenp,
  54                                loff_t *ppos);
  55static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
  56                                   void __user *buffer, size_t *lenp,
  57                                   loff_t *ppos);
  58static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
  59                             void __user *buffer, size_t *lenp,
  60                             loff_t *ppos);
  61
  62static struct ctl_table sctp_table[] = {
  63        {
  64                .procname       = "sctp_mem",
  65                .data           = &sysctl_sctp_mem,
  66                .maxlen         = sizeof(sysctl_sctp_mem),
  67                .mode           = 0644,
  68                .proc_handler   = proc_doulongvec_minmax
  69        },
  70        {
  71                .procname       = "sctp_rmem",
  72                .data           = &sysctl_sctp_rmem,
  73                .maxlen         = sizeof(sysctl_sctp_rmem),
  74                .mode           = 0644,
  75                .proc_handler   = proc_dointvec,
  76        },
  77        {
  78                .procname       = "sctp_wmem",
  79                .data           = &sysctl_sctp_wmem,
  80                .maxlen         = sizeof(sysctl_sctp_wmem),
  81                .mode           = 0644,
  82                .proc_handler   = proc_dointvec,
  83        },
  84
  85        { /* sentinel */ }
  86};
  87
  88static struct ctl_table sctp_net_table[] = {
  89        {
  90                .procname       = "rto_initial",
  91                .data           = &init_net.sctp.rto_initial,
  92                .maxlen         = sizeof(unsigned int),
  93                .mode           = 0644,
  94                .proc_handler   = proc_dointvec_minmax,
  95                .extra1         = &one,
  96                .extra2         = &timer_max
  97        },
  98        {
  99                .procname       = "rto_min",
 100                .data           = &init_net.sctp.rto_min,
 101                .maxlen         = sizeof(unsigned int),
 102                .mode           = 0644,
 103                .proc_handler   = proc_sctp_do_rto_min,
 104                .extra1         = &one,
 105                .extra2         = &init_net.sctp.rto_max
 106        },
 107        {
 108                .procname       = "rto_max",
 109                .data           = &init_net.sctp.rto_max,
 110                .maxlen         = sizeof(unsigned int),
 111                .mode           = 0644,
 112                .proc_handler   = proc_sctp_do_rto_max,
 113                .extra1         = &init_net.sctp.rto_min,
 114                .extra2         = &timer_max
 115        },
 116        {
 117                .procname       = "rto_alpha_exp_divisor",
 118                .data           = &init_net.sctp.rto_alpha,
 119                .maxlen         = sizeof(int),
 120                .mode           = 0644,
 121                .proc_handler   = proc_sctp_do_alpha_beta,
 122                .extra1         = &rto_alpha_min,
 123                .extra2         = &rto_alpha_max,
 124        },
 125        {
 126                .procname       = "rto_beta_exp_divisor",
 127                .data           = &init_net.sctp.rto_beta,
 128                .maxlen         = sizeof(int),
 129                .mode           = 0644,
 130                .proc_handler   = proc_sctp_do_alpha_beta,
 131                .extra1         = &rto_beta_min,
 132                .extra2         = &rto_beta_max,
 133        },
 134        {
 135                .procname       = "max_burst",
 136                .data           = &init_net.sctp.max_burst,
 137                .maxlen         = sizeof(int),
 138                .mode           = 0644,
 139                .proc_handler   = proc_dointvec_minmax,
 140                .extra1         = &zero,
 141                .extra2         = &int_max
 142        },
 143        {
 144                .procname       = "cookie_preserve_enable",
 145                .data           = &init_net.sctp.cookie_preserve_enable,
 146                .maxlen         = sizeof(int),
 147                .mode           = 0644,
 148                .proc_handler   = proc_dointvec,
 149        },
 150        {
 151                .procname       = "cookie_hmac_alg",
 152                .data           = &init_net.sctp.sctp_hmac_alg,
 153                .maxlen         = 8,
 154                .mode           = 0644,
 155                .proc_handler   = proc_sctp_do_hmac_alg,
 156        },
 157        {
 158                .procname       = "valid_cookie_life",
 159                .data           = &init_net.sctp.valid_cookie_life,
 160                .maxlen         = sizeof(unsigned int),
 161                .mode           = 0644,
 162                .proc_handler   = proc_dointvec_minmax,
 163                .extra1         = &one,
 164                .extra2         = &timer_max
 165        },
 166        {
 167                .procname       = "sack_timeout",
 168                .data           = &init_net.sctp.sack_timeout,
 169                .maxlen         = sizeof(int),
 170                .mode           = 0644,
 171                .proc_handler   = proc_dointvec_minmax,
 172                .extra1         = &sack_timer_min,
 173                .extra2         = &sack_timer_max,
 174        },
 175        {
 176                .procname       = "hb_interval",
 177                .data           = &init_net.sctp.hb_interval,
 178                .maxlen         = sizeof(unsigned int),
 179                .mode           = 0644,
 180                .proc_handler   = proc_dointvec_minmax,
 181                .extra1         = &one,
 182                .extra2         = &timer_max
 183        },
 184        {
 185                .procname       = "association_max_retrans",
 186                .data           = &init_net.sctp.max_retrans_association,
 187                .maxlen         = sizeof(int),
 188                .mode           = 0644,
 189                .proc_handler   = proc_dointvec_minmax,
 190                .extra1         = &one,
 191                .extra2         = &int_max
 192        },
 193        {
 194                .procname       = "path_max_retrans",
 195                .data           = &init_net.sctp.max_retrans_path,
 196                .maxlen         = sizeof(int),
 197                .mode           = 0644,
 198                .proc_handler   = proc_dointvec_minmax,
 199                .extra1         = &one,
 200                .extra2         = &int_max
 201        },
 202        {
 203                .procname       = "max_init_retransmits",
 204                .data           = &init_net.sctp.max_retrans_init,
 205                .maxlen         = sizeof(int),
 206                .mode           = 0644,
 207                .proc_handler   = proc_dointvec_minmax,
 208                .extra1         = &one,
 209                .extra2         = &int_max
 210        },
 211        {
 212                .procname       = "pf_retrans",
 213                .data           = &init_net.sctp.pf_retrans,
 214                .maxlen         = sizeof(int),
 215                .mode           = 0644,
 216                .proc_handler   = proc_dointvec_minmax,
 217                .extra1         = &zero,
 218                .extra2         = &int_max
 219        },
 220        {
 221                .procname       = "sndbuf_policy",
 222                .data           = &init_net.sctp.sndbuf_policy,
 223                .maxlen         = sizeof(int),
 224                .mode           = 0644,
 225                .proc_handler   = proc_dointvec,
 226        },
 227        {
 228                .procname       = "rcvbuf_policy",
 229                .data           = &init_net.sctp.rcvbuf_policy,
 230                .maxlen         = sizeof(int),
 231                .mode           = 0644,
 232                .proc_handler   = proc_dointvec,
 233        },
 234        {
 235                .procname       = "default_auto_asconf",
 236                .data           = &init_net.sctp.default_auto_asconf,
 237                .maxlen         = sizeof(int),
 238                .mode           = 0644,
 239                .proc_handler   = proc_dointvec,
 240        },
 241        {
 242                .procname       = "addip_enable",
 243                .data           = &init_net.sctp.addip_enable,
 244                .maxlen         = sizeof(int),
 245                .mode           = 0644,
 246                .proc_handler   = proc_dointvec,
 247        },
 248        {
 249                .procname       = "addip_noauth_enable",
 250                .data           = &init_net.sctp.addip_noauth,
 251                .maxlen         = sizeof(int),
 252                .mode           = 0644,
 253                .proc_handler   = proc_dointvec,
 254        },
 255        {
 256                .procname       = "prsctp_enable",
 257                .data           = &init_net.sctp.prsctp_enable,
 258                .maxlen         = sizeof(int),
 259                .mode           = 0644,
 260                .proc_handler   = proc_dointvec,
 261        },
 262        {
 263                .procname       = "reconf_enable",
 264                .data           = &init_net.sctp.reconf_enable,
 265                .maxlen         = sizeof(int),
 266                .mode           = 0644,
 267                .proc_handler   = proc_dointvec,
 268        },
 269        {
 270                .procname       = "auth_enable",
 271                .data           = &init_net.sctp.auth_enable,
 272                .maxlen         = sizeof(int),
 273                .mode           = 0644,
 274                .proc_handler   = proc_sctp_do_auth,
 275        },
 276        {
 277                .procname       = "intl_enable",
 278                .data           = &init_net.sctp.intl_enable,
 279                .maxlen         = sizeof(int),
 280                .mode           = 0644,
 281                .proc_handler   = proc_dointvec,
 282        },
 283        {
 284                .procname       = "addr_scope_policy",
 285                .data           = &init_net.sctp.scope_policy,
 286                .maxlen         = sizeof(int),
 287                .mode           = 0644,
 288                .proc_handler   = proc_dointvec_minmax,
 289                .extra1         = &zero,
 290                .extra2         = &addr_scope_max,
 291        },
 292        {
 293                .procname       = "rwnd_update_shift",
 294                .data           = &init_net.sctp.rwnd_upd_shift,
 295                .maxlen         = sizeof(int),
 296                .mode           = 0644,
 297                .proc_handler   = &proc_dointvec_minmax,
 298                .extra1         = &one,
 299                .extra2         = &rwnd_scale_max,
 300        },
 301        {
 302                .procname       = "max_autoclose",
 303                .data           = &init_net.sctp.max_autoclose,
 304                .maxlen         = sizeof(unsigned long),
 305                .mode           = 0644,
 306                .proc_handler   = &proc_doulongvec_minmax,
 307                .extra1         = &max_autoclose_min,
 308                .extra2         = &max_autoclose_max,
 309        },
 310        {
 311                .procname       = "pf_enable",
 312                .data           = &init_net.sctp.pf_enable,
 313                .maxlen         = sizeof(int),
 314                .mode           = 0644,
 315                .proc_handler   = proc_dointvec,
 316        },
 317
 318        { /* sentinel */ }
 319};
 320
 321static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
 322                                void __user *buffer, size_t *lenp,
 323                                loff_t *ppos)
 324{
 325        struct net *net = current->nsproxy->net_ns;
 326        struct ctl_table tbl;
 327        bool changed = false;
 328        char *none = "none";
 329        char tmp[8] = {0};
 330        int ret;
 331
 332        memset(&tbl, 0, sizeof(struct ctl_table));
 333
 334        if (write) {
 335                tbl.data = tmp;
 336                tbl.maxlen = sizeof(tmp);
 337        } else {
 338                tbl.data = net->sctp.sctp_hmac_alg ? : none;
 339                tbl.maxlen = strlen(tbl.data);
 340        }
 341
 342        ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
 343        if (write && ret == 0) {
 344#ifdef CONFIG_CRYPTO_MD5
 345                if (!strncmp(tmp, "md5", 3)) {
 346                        net->sctp.sctp_hmac_alg = "md5";
 347                        changed = true;
 348                }
 349#endif
 350#ifdef CONFIG_CRYPTO_SHA1
 351                if (!strncmp(tmp, "sha1", 4)) {
 352                        net->sctp.sctp_hmac_alg = "sha1";
 353                        changed = true;
 354                }
 355#endif
 356                if (!strncmp(tmp, "none", 4)) {
 357                        net->sctp.sctp_hmac_alg = NULL;
 358                        changed = true;
 359                }
 360                if (!changed)
 361                        ret = -EINVAL;
 362        }
 363
 364        return ret;
 365}
 366
 367static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
 368                                void __user *buffer, size_t *lenp,
 369                                loff_t *ppos)
 370{
 371        struct net *net = current->nsproxy->net_ns;
 372        unsigned int min = *(unsigned int *) ctl->extra1;
 373        unsigned int max = *(unsigned int *) ctl->extra2;
 374        struct ctl_table tbl;
 375        int ret, new_value;
 376
 377        memset(&tbl, 0, sizeof(struct ctl_table));
 378        tbl.maxlen = sizeof(unsigned int);
 379
 380        if (write)
 381                tbl.data = &new_value;
 382        else
 383                tbl.data = &net->sctp.rto_min;
 384
 385        ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
 386        if (write && ret == 0) {
 387                if (new_value > max || new_value < min)
 388                        return -EINVAL;
 389
 390                net->sctp.rto_min = new_value;
 391        }
 392
 393        return ret;
 394}
 395
 396static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
 397                                void __user *buffer, size_t *lenp,
 398                                loff_t *ppos)
 399{
 400        struct net *net = current->nsproxy->net_ns;
 401        unsigned int min = *(unsigned int *) ctl->extra1;
 402        unsigned int max = *(unsigned int *) ctl->extra2;
 403        struct ctl_table tbl;
 404        int ret, new_value;
 405
 406        memset(&tbl, 0, sizeof(struct ctl_table));
 407        tbl.maxlen = sizeof(unsigned int);
 408
 409        if (write)
 410                tbl.data = &new_value;
 411        else
 412                tbl.data = &net->sctp.rto_max;
 413
 414        ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
 415        if (write && ret == 0) {
 416                if (new_value > max || new_value < min)
 417                        return -EINVAL;
 418
 419                net->sctp.rto_max = new_value;
 420        }
 421
 422        return ret;
 423}
 424
 425static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
 426                                   void __user *buffer, size_t *lenp,
 427                                   loff_t *ppos)
 428{
 429        if (write)
 430                pr_warn_once("Changing rto_alpha or rto_beta may lead to "
 431                             "suboptimal rtt/srtt estimations!\n");
 432
 433        return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
 434}
 435
 436static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
 437                             void __user *buffer, size_t *lenp,
 438                             loff_t *ppos)
 439{
 440        struct net *net = current->nsproxy->net_ns;
 441        struct ctl_table tbl;
 442        int new_value, ret;
 443
 444        memset(&tbl, 0, sizeof(struct ctl_table));
 445        tbl.maxlen = sizeof(unsigned int);
 446
 447        if (write)
 448                tbl.data = &new_value;
 449        else
 450                tbl.data = &net->sctp.auth_enable;
 451
 452        ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
 453        if (write && ret == 0) {
 454                struct sock *sk = net->sctp.ctl_sock;
 455
 456                net->sctp.auth_enable = new_value;
 457                /* Update the value in the control socket */
 458                lock_sock(sk);
 459                sctp_sk(sk)->ep->auth_enable = new_value;
 460                release_sock(sk);
 461        }
 462
 463        return ret;
 464}
 465
 466int sctp_sysctl_net_register(struct net *net)
 467{
 468        struct ctl_table *table;
 469        int i;
 470
 471        table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
 472        if (!table)
 473                return -ENOMEM;
 474
 475        for (i = 0; table[i].data; i++)
 476                table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
 477
 478        net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
 479        if (net->sctp.sysctl_header == NULL) {
 480                kfree(table);
 481                return -ENOMEM;
 482        }
 483        return 0;
 484}
 485
 486void sctp_sysctl_net_unregister(struct net *net)
 487{
 488        struct ctl_table *table;
 489
 490        table = net->sctp.sysctl_header->ctl_table_arg;
 491        unregister_net_sysctl_table(net->sctp.sysctl_header);
 492        kfree(table);
 493}
 494
 495static struct ctl_table_header *sctp_sysctl_header;
 496
 497/* Sysctl registration.  */
 498void sctp_sysctl_register(void)
 499{
 500        sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table);
 501}
 502
 503/* Sysctl deregistration.  */
 504void sctp_sysctl_unregister(void)
 505{
 506        unregister_net_sysctl_table(sctp_sysctl_header);
 507}
 508