linux/net/rose/rose_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/module.h>
  10#include <linux/proc_fs.h>
  11#include <linux/kernel.h>
  12#include <linux/interrupt.h>
  13#include <linux/fs.h>
  14#include <linux/types.h>
  15#include <linux/sysctl.h>
  16#include <linux/string.h>
  17#include <linux/socket.h>
  18#include <linux/errno.h>
  19#include <linux/fcntl.h>
  20#include <linux/in.h>
  21#include <linux/if_ether.h>
  22#include <linux/slab.h>
  23
  24#include <asm/system.h>
  25#include <asm/io.h>
  26
  27#include <linux/inet.h>
  28#include <linux/netdevice.h>
  29#include <linux/etherdevice.h>
  30#include <linux/if_arp.h>
  31#include <linux/skbuff.h>
  32
  33#include <net/ip.h>
  34#include <net/arp.h>
  35
  36#include <net/ax25.h>
  37#include <net/rose.h>
  38
  39static int rose_header(struct sk_buff *skb, struct net_device *dev,
  40                       unsigned short type,
  41                       const void *daddr, const void *saddr, unsigned len)
  42{
  43        unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2);
  44
  45        *buff++ = ROSE_GFI | ROSE_Q_BIT;
  46        *buff++ = 0x00;
  47        *buff++ = ROSE_DATA;
  48        *buff++ = 0x7F;
  49        *buff++ = AX25_P_IP;
  50
  51        if (daddr != NULL)
  52                return 37;
  53
  54        return -37;
  55}
  56
  57static int rose_rebuild_header(struct sk_buff *skb)
  58{
  59#ifdef CONFIG_INET
  60        struct net_device *dev = skb->dev;
  61        struct net_device_stats *stats = &dev->stats;
  62        unsigned char *bp = (unsigned char *)skb->data;
  63        struct sk_buff *skbn;
  64        unsigned int len;
  65
  66        if (arp_find(bp + 7, skb)) {
  67                return 1;
  68        }
  69
  70        if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
  71                kfree_skb(skb);
  72                return 1;
  73        }
  74
  75        if (skb->sk != NULL)
  76                skb_set_owner_w(skbn, skb->sk);
  77
  78        kfree_skb(skb);
  79
  80        len = skbn->len;
  81
  82        if (!rose_route_frame(skbn, NULL)) {
  83                kfree_skb(skbn);
  84                stats->tx_errors++;
  85                return 1;
  86        }
  87
  88        stats->tx_packets++;
  89        stats->tx_bytes += len;
  90#endif
  91        return 1;
  92}
  93
  94static int rose_set_mac_address(struct net_device *dev, void *addr)
  95{
  96        struct sockaddr *sa = addr;
  97        int err;
  98
  99        if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len))
 100                return 0;
 101
 102        if (dev->flags & IFF_UP) {
 103                err = rose_add_loopback_node((rose_address *)dev->dev_addr);
 104                if (err)
 105                        return err;
 106
 107                rose_del_loopback_node((rose_address *)dev->dev_addr);
 108        }
 109
 110        memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
 111
 112        return 0;
 113}
 114
 115static int rose_open(struct net_device *dev)
 116{
 117        int err;
 118
 119        err = rose_add_loopback_node((rose_address *)dev->dev_addr);
 120        if (err)
 121                return err;
 122
 123        netif_start_queue(dev);
 124
 125        return 0;
 126}
 127
 128static int rose_close(struct net_device *dev)
 129{
 130        netif_stop_queue(dev);
 131        rose_del_loopback_node((rose_address *)dev->dev_addr);
 132        return 0;
 133}
 134
 135static netdev_tx_t rose_xmit(struct sk_buff *skb, struct net_device *dev)
 136{
 137        struct net_device_stats *stats = &dev->stats;
 138
 139        if (!netif_running(dev)) {
 140                printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
 141                return NETDEV_TX_BUSY;
 142        }
 143        dev_kfree_skb(skb);
 144        stats->tx_errors++;
 145        return NETDEV_TX_OK;
 146}
 147
 148static const struct header_ops rose_header_ops = {
 149        .create = rose_header,
 150        .rebuild= rose_rebuild_header,
 151};
 152
 153static const struct net_device_ops rose_netdev_ops = {
 154        .ndo_open               = rose_open,
 155        .ndo_stop               = rose_close,
 156        .ndo_start_xmit         = rose_xmit,
 157        .ndo_set_mac_address    = rose_set_mac_address,
 158};
 159
 160void rose_setup(struct net_device *dev)
 161{
 162        dev->mtu                = ROSE_MAX_PACKET_SIZE - 2;
 163        dev->netdev_ops         = &rose_netdev_ops;
 164
 165        dev->header_ops         = &rose_header_ops;
 166        dev->hard_header_len    = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN;
 167        dev->addr_len           = ROSE_ADDR_LEN;
 168        dev->type               = ARPHRD_ROSE;
 169
 170        /* New-style flags. */
 171        dev->flags              = IFF_NOARP;
 172}
 173