linux/net/ax25/ax25_dev.c
<<
>>
Prefs
   1/*
   2 * This program is free software; you can redistribute it and/or modify
   3 * it under the terms of the GNU General Public License as published by
   4 * the Free Software Foundation; either version 2 of the License, or
   5 * (at your option) any later version.
   6 *
   7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   8 */
   9#include <linux/errno.h>
  10#include <linux/types.h>
  11#include <linux/socket.h>
  12#include <linux/in.h>
  13#include <linux/kernel.h>
  14#include <linux/timer.h>
  15#include <linux/string.h>
  16#include <linux/sockios.h>
  17#include <linux/net.h>
  18#include <linux/spinlock.h>
  19#include <net/ax25.h>
  20#include <linux/inet.h>
  21#include <linux/netdevice.h>
  22#include <linux/if_arp.h>
  23#include <linux/skbuff.h>
  24#include <net/sock.h>
  25#include <asm/uaccess.h>
  26#include <asm/system.h>
  27#include <linux/fcntl.h>
  28#include <linux/mm.h>
  29#include <linux/interrupt.h>
  30#include <linux/init.h>
  31
  32ax25_dev *ax25_dev_list;
  33DEFINE_SPINLOCK(ax25_dev_lock);
  34
  35ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
  36{
  37        ax25_dev *ax25_dev, *res = NULL;
  38
  39        spin_lock_bh(&ax25_dev_lock);
  40        for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
  41                if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) {
  42                        res = ax25_dev;
  43                }
  44        spin_unlock_bh(&ax25_dev_lock);
  45
  46        return res;
  47}
  48
  49/*
  50 *      This is called when an interface is brought up. These are
  51 *      reasonable defaults.
  52 */
  53void ax25_dev_device_up(struct net_device *dev)
  54{
  55        ax25_dev *ax25_dev;
  56
  57        if ((ax25_dev = kzalloc(sizeof(*ax25_dev), GFP_ATOMIC)) == NULL) {
  58                printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");
  59                return;
  60        }
  61
  62        ax25_unregister_sysctl();
  63
  64        dev->ax25_ptr     = ax25_dev;
  65        ax25_dev->dev     = dev;
  66        dev_hold(dev);
  67        ax25_dev->forward = NULL;
  68
  69        ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;
  70        ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;
  71        ax25_dev->values[AX25_VALUES_BACKOFF]   = AX25_DEF_BACKOFF;
  72        ax25_dev->values[AX25_VALUES_CONMODE]   = AX25_DEF_CONMODE;
  73        ax25_dev->values[AX25_VALUES_WINDOW]    = AX25_DEF_WINDOW;
  74        ax25_dev->values[AX25_VALUES_EWINDOW]   = AX25_DEF_EWINDOW;
  75        ax25_dev->values[AX25_VALUES_T1]        = AX25_DEF_T1;
  76        ax25_dev->values[AX25_VALUES_T2]        = AX25_DEF_T2;
  77        ax25_dev->values[AX25_VALUES_T3]        = AX25_DEF_T3;
  78        ax25_dev->values[AX25_VALUES_IDLE]      = AX25_DEF_IDLE;
  79        ax25_dev->values[AX25_VALUES_N2]        = AX25_DEF_N2;
  80        ax25_dev->values[AX25_VALUES_PACLEN]    = AX25_DEF_PACLEN;
  81        ax25_dev->values[AX25_VALUES_PROTOCOL]  = AX25_DEF_PROTOCOL;
  82        ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
  83
  84#if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
  85        ax25_ds_setup_timer(ax25_dev);
  86#endif
  87
  88        spin_lock_bh(&ax25_dev_lock);
  89        ax25_dev->next = ax25_dev_list;
  90        ax25_dev_list  = ax25_dev;
  91        spin_unlock_bh(&ax25_dev_lock);
  92
  93        ax25_register_sysctl();
  94}
  95
  96void ax25_dev_device_down(struct net_device *dev)
  97{
  98        ax25_dev *s, *ax25_dev;
  99
 100        if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
 101                return;
 102
 103        ax25_unregister_sysctl();
 104
 105        spin_lock_bh(&ax25_dev_lock);
 106
 107#ifdef CONFIG_AX25_DAMA_SLAVE
 108        ax25_ds_del_timer(ax25_dev);
 109#endif
 110
 111        /*
 112         *      Remove any packet forwarding that points to this device.
 113         */
 114        for (s = ax25_dev_list; s != NULL; s = s->next)
 115                if (s->forward == dev)
 116                        s->forward = NULL;
 117
 118        if ((s = ax25_dev_list) == ax25_dev) {
 119                ax25_dev_list = s->next;
 120                spin_unlock_bh(&ax25_dev_lock);
 121                dev_put(dev);
 122                kfree(ax25_dev);
 123                ax25_register_sysctl();
 124                return;
 125        }
 126
 127        while (s != NULL && s->next != NULL) {
 128                if (s->next == ax25_dev) {
 129                        s->next = ax25_dev->next;
 130                        spin_unlock_bh(&ax25_dev_lock);
 131                        dev_put(dev);
 132                        kfree(ax25_dev);
 133                        ax25_register_sysctl();
 134                        return;
 135                }
 136
 137                s = s->next;
 138        }
 139        spin_unlock_bh(&ax25_dev_lock);
 140        dev->ax25_ptr = NULL;
 141
 142        ax25_register_sysctl();
 143}
 144
 145int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
 146{
 147        ax25_dev *ax25_dev, *fwd_dev;
 148
 149        if ((ax25_dev = ax25_addr_ax25dev(&fwd->port_from)) == NULL)
 150                return -EINVAL;
 151
 152        switch (cmd) {
 153        case SIOCAX25ADDFWD:
 154                if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL)
 155                        return -EINVAL;
 156                if (ax25_dev->forward != NULL)
 157                        return -EINVAL;
 158                ax25_dev->forward = fwd_dev->dev;
 159                break;
 160
 161        case SIOCAX25DELFWD:
 162                if (ax25_dev->forward == NULL)
 163                        return -EINVAL;
 164                ax25_dev->forward = NULL;
 165                break;
 166
 167        default:
 168                return -EINVAL;
 169        }
 170
 171        return 0;
 172}
 173
 174struct net_device *ax25_fwd_dev(struct net_device *dev)
 175{
 176        ax25_dev *ax25_dev;
 177
 178        if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
 179                return dev;
 180
 181        if (ax25_dev->forward == NULL)
 182                return dev;
 183
 184        return ax25_dev->forward;
 185}
 186
 187/*
 188 *      Free all memory associated with device structures.
 189 */
 190void __exit ax25_dev_free(void)
 191{
 192        ax25_dev *s, *ax25_dev;
 193
 194        spin_lock_bh(&ax25_dev_lock);
 195        ax25_dev = ax25_dev_list;
 196        while (ax25_dev != NULL) {
 197                s        = ax25_dev;
 198                dev_put(ax25_dev->dev);
 199                ax25_dev = ax25_dev->next;
 200                kfree(s);
 201        }
 202        ax25_dev_list = NULL;
 203        spin_unlock_bh(&ax25_dev_lock);
 204}
 205
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.