linux/net/phonet/sysctl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * File: sysctl.c
   4 *
   5 * Phonet /proc/sys/net/phonet interface implementation
   6 *
   7 * Copyright (C) 2008 Nokia Corporation.
   8 *
   9 * Author: RĂ©mi Denis-Courmont
  10 */
  11
  12#include <linux/seqlock.h>
  13#include <linux/sysctl.h>
  14#include <linux/errno.h>
  15#include <linux/init.h>
  16
  17#include <net/sock.h>
  18#include <linux/phonet.h>
  19#include <net/phonet/phonet.h>
  20
  21#define DYNAMIC_PORT_MIN        0x40
  22#define DYNAMIC_PORT_MAX        0x7f
  23
  24static DEFINE_SEQLOCK(local_port_range_lock);
  25static int local_port_range_min[2] = {0, 0};
  26static int local_port_range_max[2] = {1023, 1023};
  27static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX};
  28static struct ctl_table_header *phonet_table_hrd;
  29
  30static void set_local_port_range(int range[2])
  31{
  32        write_seqlock(&local_port_range_lock);
  33        local_port_range[0] = range[0];
  34        local_port_range[1] = range[1];
  35        write_sequnlock(&local_port_range_lock);
  36}
  37
  38void phonet_get_local_port_range(int *min, int *max)
  39{
  40        unsigned int seq;
  41
  42        do {
  43                seq = read_seqbegin(&local_port_range_lock);
  44                if (min)
  45                        *min = local_port_range[0];
  46                if (max)
  47                        *max = local_port_range[1];
  48        } while (read_seqretry(&local_port_range_lock, seq));
  49}
  50
  51static int proc_local_port_range(struct ctl_table *table, int write,
  52                                 void *buffer, size_t *lenp, loff_t *ppos)
  53{
  54        int ret;
  55        int range[2] = {local_port_range[0], local_port_range[1]};
  56        struct ctl_table tmp = {
  57                .data = &range,
  58                .maxlen = sizeof(range),
  59                .mode = table->mode,
  60                .extra1 = &local_port_range_min,
  61                .extra2 = &local_port_range_max,
  62        };
  63
  64        ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
  65
  66        if (write && ret == 0) {
  67                if (range[1] < range[0])
  68                        ret = -EINVAL;
  69                else
  70                        set_local_port_range(range);
  71        }
  72
  73        return ret;
  74}
  75
  76static struct ctl_table phonet_table[] = {
  77        {
  78                .procname       = "local_port_range",
  79                .data           = &local_port_range,
  80                .maxlen         = sizeof(local_port_range),
  81                .mode           = 0644,
  82                .proc_handler   = proc_local_port_range,
  83        },
  84        { }
  85};
  86
  87int __init phonet_sysctl_init(void)
  88{
  89        phonet_table_hrd = register_net_sysctl(&init_net, "net/phonet", phonet_table);
  90        return phonet_table_hrd == NULL ? -ENOMEM : 0;
  91}
  92
  93void phonet_sysctl_exit(void)
  94{
  95        unregister_net_sysctl_table(phonet_table_hrd);
  96}
  97