ed359a3b7b
Pull networking fixes from David Miller: 1) Provide device string properly for USB i2400m wimax devices, also don't OOPS when providing firmware string. From Phil Sutter. 2) Add support for sh_eth SH7734 chips, from Nobuhiro Iwamatsu. 3) Add another device ID to USB zaurus driver, from Guan Xin. 4) Loop index start in pool vector iterator is wrong causing MAC to not get configured in bnx2x driver, fix from Dmitry Kravkov. 5) EQL driver assumes HZ=100, fix from Eric Dumazet. 6) Now that skb_add_rx_frag() can specify the truesize increment separately, do so in f_phonet and cdc_phonet, also from Eric Dumazet. 7) virtio_net accidently uses net_ratelimit() not only on the kernel warning but also the statistic bump, fix from Rick Jones. 8) ip_route_input_mc() uses fixed init_net namespace, oops, use dev_net(dev) instead. Fix from Benjamin LaHaise. 9) dev_forward_skb() needs to clear the incoming interface index of the SKB so that it looks like a new incoming packet, also from Benjamin LaHaise. 10) iwlwifi mistakenly initializes a channel entry as 2GHZ instead of 5GHZ, fix from Stanislav Yakovlev. 11) Missing kmalloc() return value checks in orinoco, from Santosh Nayak. 12) ath9k doesn't check for HT capabilities in the right way, it is checking ht_supported instead of the ATH9K_HW_CAP_HT flag. Fix from Sujith Manoharan. 13) Fix x86 BPF JIT emission of 16-bit immediate field of AND instructions, from Feiran Zhuang. 14) Avoid infinite loop in GARP code when registering sysfs entries. From David Ward. 15) rose protocol uses memcpy instead of memcmp in a device address comparison, oops. Fix from Daniel Borkmann. 16) Fix build of lpc_eth due to dev_hw_addr_rancom() interface being renamed to eth_hw_addr_random(). From Roland Stigge. 17) Make ipv6 RTM_GETROUTE interpret RTA_IIF attribute the same way that ipv4 does. Fix from Shmulik Ladkani. 18) via-rhine has an inverted bit test, causing suspend/resume regressions. Fix from Andreas Mohr. 19) RIONET assumes 4K page size, fix from Akinobu Mita. 20) Initialization of imask register in sky2 is buggy, because bits are "or'd" into an uninitialized local variable. Fix from Lino Sanfilippo. 21) Fix FCOE checksum offload handling, from Yi Zou. 22) Fix VLAN processing regression in e1000, from Jiri Pirko. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (52 commits) sky2: dont overwrite settings for PHY Quick link tg3: Fix 5717 serdes powerdown problem net: usb: cdc_eem: fix mtu net: sh_eth: fix endian check for architecture independent usb/rtl8150 : Remove duplicated definitions rionet: fix page allocation order of rionet_active via-rhine: fix wait-bit inversion. ipv6: Fix RTM_GETROUTE's interpretation of RTA_IIF to be consistent with ipv4 net: lpc_eth: Fix rename of dev_hw_addr_random net/netfilter/nfnetlink_acct.c: use linux/atomic.h rose_dev: fix memcpy-bug in rose_set_mac_address Fix non TBI PHY access; a bad merge undid bug fix in a previous commit. net/garp: avoid infinite loop if attribute already exists x86 bpf_jit: fix a bug in emitting the 16-bit immediate operand of AND bonding: emit event when bonding changes MAC mac80211: fix oper channel timestamp updation ath9k: Use HW HT capabilites properly MAINTAINERS: adding maintainer for ipw2x00 net: orinoco: add error handling for failed kmalloc(). net/wireless: ipw2x00: fix a typo in wiphy struct initilization ...
172 lines
3.6 KiB
C
172 lines
3.6 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/types.h>
|
|
#include <linux/sysctl.h>
|
|
#include <linux/string.h>
|
|
#include <linux/socket.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/fcntl.h>
|
|
#include <linux/in.h>
|
|
#include <linux/if_ether.h>
|
|
#include <linux/slab.h>
|
|
|
|
#include <asm/io.h>
|
|
|
|
#include <linux/inet.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/etherdevice.h>
|
|
#include <linux/if_arp.h>
|
|
#include <linux/skbuff.h>
|
|
|
|
#include <net/ip.h>
|
|
#include <net/arp.h>
|
|
|
|
#include <net/ax25.h>
|
|
#include <net/rose.h>
|
|
|
|
static int rose_header(struct sk_buff *skb, struct net_device *dev,
|
|
unsigned short type,
|
|
const void *daddr, const void *saddr, unsigned len)
|
|
{
|
|
unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2);
|
|
|
|
*buff++ = ROSE_GFI | ROSE_Q_BIT;
|
|
*buff++ = 0x00;
|
|
*buff++ = ROSE_DATA;
|
|
*buff++ = 0x7F;
|
|
*buff++ = AX25_P_IP;
|
|
|
|
if (daddr != NULL)
|
|
return 37;
|
|
|
|
return -37;
|
|
}
|
|
|
|
static int rose_rebuild_header(struct sk_buff *skb)
|
|
{
|
|
#ifdef CONFIG_INET
|
|
struct net_device *dev = skb->dev;
|
|
struct net_device_stats *stats = &dev->stats;
|
|
unsigned char *bp = (unsigned char *)skb->data;
|
|
struct sk_buff *skbn;
|
|
unsigned int len;
|
|
|
|
if (arp_find(bp + 7, skb)) {
|
|
return 1;
|
|
}
|
|
|
|
if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
|
|
kfree_skb(skb);
|
|
return 1;
|
|
}
|
|
|
|
if (skb->sk != NULL)
|
|
skb_set_owner_w(skbn, skb->sk);
|
|
|
|
kfree_skb(skb);
|
|
|
|
len = skbn->len;
|
|
|
|
if (!rose_route_frame(skbn, NULL)) {
|
|
kfree_skb(skbn);
|
|
stats->tx_errors++;
|
|
return 1;
|
|
}
|
|
|
|
stats->tx_packets++;
|
|
stats->tx_bytes += len;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
static int rose_set_mac_address(struct net_device *dev, void *addr)
|
|
{
|
|
struct sockaddr *sa = addr;
|
|
int err;
|
|
|
|
if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))
|
|
return 0;
|
|
|
|
if (dev->flags & IFF_UP) {
|
|
err = rose_add_loopback_node((rose_address *)sa->sa_data);
|
|
if (err)
|
|
return err;
|
|
|
|
rose_del_loopback_node((rose_address *)dev->dev_addr);
|
|
}
|
|
|
|
memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int rose_open(struct net_device *dev)
|
|
{
|
|
int err;
|
|
|
|
err = rose_add_loopback_node((rose_address *)dev->dev_addr);
|
|
if (err)
|
|
return err;
|
|
|
|
netif_start_queue(dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int rose_close(struct net_device *dev)
|
|
{
|
|
netif_stop_queue(dev);
|
|
rose_del_loopback_node((rose_address *)dev->dev_addr);
|
|
return 0;
|
|
}
|
|
|
|
static netdev_tx_t rose_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
{
|
|
struct net_device_stats *stats = &dev->stats;
|
|
|
|
if (!netif_running(dev)) {
|
|
printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
|
|
return NETDEV_TX_BUSY;
|
|
}
|
|
dev_kfree_skb(skb);
|
|
stats->tx_errors++;
|
|
return NETDEV_TX_OK;
|
|
}
|
|
|
|
static const struct header_ops rose_header_ops = {
|
|
.create = rose_header,
|
|
.rebuild= rose_rebuild_header,
|
|
};
|
|
|
|
static const struct net_device_ops rose_netdev_ops = {
|
|
.ndo_open = rose_open,
|
|
.ndo_stop = rose_close,
|
|
.ndo_start_xmit = rose_xmit,
|
|
.ndo_set_mac_address = rose_set_mac_address,
|
|
};
|
|
|
|
void rose_setup(struct net_device *dev)
|
|
{
|
|
dev->mtu = ROSE_MAX_PACKET_SIZE - 2;
|
|
dev->netdev_ops = &rose_netdev_ops;
|
|
|
|
dev->header_ops = &rose_header_ops;
|
|
dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN;
|
|
dev->addr_len = ROSE_ADDR_LEN;
|
|
dev->type = ARPHRD_ROSE;
|
|
|
|
/* New-style flags. */
|
|
dev->flags = IFF_NOARP;
|
|
}
|