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