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 __user *buffer,
  53                                size_t *lenp, loff_t *ppos)
  54{
  55        int ret;
  56        int range[2] = {local_port_range[0], local_port_range[1]};
  57        struct ctl_table tmp = {
  58                .data = &range,
  59                .maxlen = sizeof(range),
  60                .mode = table->mode,
  61                .extra1 = &local_port_range_min,
  62                .extra2 = &local_port_range_max,
  63        };
  64
  65        ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
  66
  67        if (write && ret == 0) {
  68                if (range[1] < range[0])
  69                        ret = -EINVAL;
  70                else
  71                        set_local_port_range(range);
  72        }
  73
  74        return ret;
  75}
  76
  77static struct ctl_table phonet_table[] = {
  78        {
  79                .procname       = "local_port_range",
  80                .data           = &local_port_range,
  81                .maxlen         = sizeof(local_port_range),
  82                .mode           = 0644,
  83                .proc_handler   = proc_local_port_range,
  84        },
  85        { }
  86};
  87
  88int __init phonet_sysctl_init(void)
  89{
  90        phonet_table_hrd = register_net_sysctl(&init_net, "net/phonet", phonet_table);
  91        return phonet_table_hrd == NULL ? -ENOMEM : 0;
  92}
  93
  94void phonet_sysctl_exit(void)
  95{
  96        unregister_net_sysctl_table(phonet_table_hrd);
  97}
  98