summaryrefslogtreecommitdiff
path: root/pfinet.old/linux-src/net/core
diff options
context:
space:
mode:
authorZheng Da <zhengda1936@gmail.com>2010-05-04 16:08:14 +0200
committerZheng Da <zhengda1936@gmail.com>2010-05-04 16:08:14 +0200
commita03e2da13bfbed30eedd589977595a5f3398a478 (patch)
treee17d290e2ded14b5abbd51cdf8ddc8430e365fd8 /pfinet.old/linux-src/net/core
parent045fb6a578e0e4d97f0e581bbf514654686a86c1 (diff)
remove all temporary files created by vim.
Diffstat (limited to 'pfinet.old/linux-src/net/core')
-rw-r--r--pfinet.old/linux-src/net/core/dev.c~2092
1 files changed, 0 insertions, 2092 deletions
diff --git a/pfinet.old/linux-src/net/core/dev.c~ b/pfinet.old/linux-src/net/core/dev.c~
deleted file mode 100644
index 7d0658c5..00000000
--- a/pfinet.old/linux-src/net/core/dev.c~
+++ /dev/null
@@ -1,2092 +0,0 @@
-/*
- * NET3 Protocol independent device support routines.
- *
- * 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.
- *
- * Derived from the non IP parts of dev.c 1.0.19
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Mark Evans, <evansmp@uhura.aston.ac.uk>
- *
- * Additional Authors:
- * Florian la Roche <rzsfl@rz.uni-sb.de>
- * Alan Cox <gw4pts@gw4pts.ampr.org>
- * David Hinds <dhinds@allegro.stanford.edu>
- * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
- * Adam Sulmicki <adam@cfar.umd.edu>
- *
- * Changes:
- * Marcelo Tosatti <marcelo@conectiva.com.br> : dont accept mtu 0 or <
- * Alan Cox : device private ioctl copies fields back.
- * Alan Cox : Transmit queue code does relevant stunts to
- * keep the queue safe.
- * Alan Cox : Fixed double lock.
- * Alan Cox : Fixed promisc NULL pointer trap
- * ???????? : Support the full private ioctl range
- * Alan Cox : Moved ioctl permission check into drivers
- * Tim Kordas : SIOCADDMULTI/SIOCDELMULTI
- * Alan Cox : 100 backlog just doesn't cut it when
- * you start doing multicast video 8)
- * Alan Cox : Rewrote net_bh and list manager.
- * Alan Cox : Fix ETH_P_ALL echoback lengths.
- * Alan Cox : Took out transmit every packet pass
- * Saved a few bytes in the ioctl handler
- * Alan Cox : Network driver sets packet type before calling netif_rx. Saves
- * a function call a packet.
- * Alan Cox : Hashed net_bh()
- * Richard Kooijman: Timestamp fixes.
- * Alan Cox : Wrong field in SIOCGIFDSTADDR
- * Alan Cox : Device lock protection.
- * Alan Cox : Fixed nasty side effect of device close changes.
- * Rudi Cilibrasi : Pass the right thing to set_mac_address()
- * Dave Miller : 32bit quantity for the device lock to make it work out
- * on a Sparc.
- * Bjorn Ekwall : Added KERNELD hack.
- * Alan Cox : Cleaned up the backlog initialise.
- * Craig Metz : SIOCGIFCONF fix if space for under
- * 1 device.
- * Thomas Bogendoerfer : Return ENODEV for dev_open, if there
- * is no device open function.
- * Andi Kleen : Fix error reporting for SIOCGIFCONF
- * Michael Chastain : Fix signed/unsigned for SIOCGIFCONF
- * Cyrus Durgin : Cleaned for KMOD
- * Adam Sulmicki : Bug Fix : Network Device Unload
- * A network device unload needs to purge
- * the backlog queue.
- * Paul Rusty Russel : SIOCSIFNAME
- * Andrea Arcangeli : dev_clear_backlog() needs the
- * skb_queue_lock held.
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <linux/rtnetlink.h>
-#include <net/slhc.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <net/br.h>
-#include <net/dst.h>
-#include <net/pkt_sched.h>
-#include <net/profile.h>
-#include <linux/init.h>
-#include <linux/kmod.h>
-#ifdef CONFIG_NET_RADIO
-#include <linux/wireless.h>
-#endif /* CONFIG_NET_RADIO */
-#ifdef CONFIG_PLIP
-extern int plip_init(void);
-#endif
-
-NET_PROFILE_DEFINE(dev_queue_xmit)
-NET_PROFILE_DEFINE(net_bh)
-NET_PROFILE_DEFINE(net_bh_skb)
-
-
-const char *if_port_text[] = {
- "unknown",
- "BNC",
- "10baseT",
- "AUI",
- "100baseT",
- "100baseTX",
- "100baseFX"
-};
-
-/*
- * The list of packet types we will receive (as opposed to discard)
- * and the routines to invoke.
- *
- * Why 16. Because with 16 the only overlap we get on a hash of the
- * low nibble of the protocol value is RARP/SNAP/X.25.
- *
- * 0800 IP
- * 0001 802.3
- * 0002 AX.25
- * 0004 802.2
- * 8035 RARP
- * 0005 SNAP
- * 0805 X.25
- * 0806 ARP
- * 8137 IPX
- * 0009 Localtalk
- * 86DD IPv6
- */
-
-struct packet_type *ptype_base[16]; /* 16 way hashed list */
-struct packet_type *ptype_all = NULL; /* Taps */
-
-/*
- * Device list lock. Setting it provides that interface
- * will not disappear unexpectedly while kernel sleeps.
- */
-
-atomic_t dev_lockct = ATOMIC_INIT(0);
-
-/*
- * Our notifier list
- */
-
-#ifdef _HURD_
-struct notifier_block *netdev_chain=NULL;
-#else
-static struct notifier_block *netdev_chain=NULL;
-#endif
-
-/*
- * Device drivers call our routines to queue packets here. We empty the
- * queue in the bottom half handler.
- */
-
-static struct sk_buff_head backlog;
-
-#ifdef CONFIG_NET_FASTROUTE
-int netdev_fastroute;
-int netdev_fastroute_obstacles;
-struct net_fastroute_stats dev_fastroute_stat;
-#endif
-
-static void dev_clear_backlog(struct device *dev);
-
-
-/******************************************************************************************
-
- Protocol management and registration routines
-
-*******************************************************************************************/
-
-/*
- * For efficiency
- */
-
-int netdev_nit=0;
-
-/*
- * Add a protocol ID to the list. Now that the input handler is
- * smarter we can dispense with all the messy stuff that used to be
- * here.
- *
- * BEWARE!!! Protocol handlers, mangling input packets,
- * MUST BE last in hash buckets and checking protocol handlers
- * MUST start from promiscous ptype_all chain in net_bh.
- * It is true now, do not change it.
- * Explantion follows: if protocol handler, mangling packet, will
- * be the first on list, it is not able to sense, that packet
- * is cloned and should be copied-on-write, so that it will
- * change it and subsequent readers will get broken packet.
- * --ANK (980803)
- */
-
-void dev_add_pack(struct packet_type *pt)
-{
- int hash;
-#ifdef CONFIG_NET_FASTROUTE
- /* Hack to detect packet socket */
- if (pt->data) {
- netdev_fastroute_obstacles++;
- dev_clear_fastroute(pt->dev);
- }
-#endif
- if(pt->type==htons(ETH_P_ALL))
- {
- netdev_nit++;
- pt->next=ptype_all;
- ptype_all=pt;
- }
- else
- {
- hash=ntohs(pt->type)&15;
- pt->next = ptype_base[hash];
- ptype_base[hash] = pt;
- }
-}
-
-
-/*
- * Remove a protocol ID from the list.
- */
-
-void dev_remove_pack(struct packet_type *pt)
-{
- struct packet_type **pt1;
- if(pt->type==htons(ETH_P_ALL))
- {
- netdev_nit--;
- pt1=&ptype_all;
- }
- else
- pt1=&ptype_base[ntohs(pt->type)&15];
- for(; (*pt1)!=NULL; pt1=&((*pt1)->next))
- {
- if(pt==(*pt1))
- {
- *pt1=pt->next;
- synchronize_bh();
-#ifdef CONFIG_NET_FASTROUTE
- if (pt->data)
- netdev_fastroute_obstacles--;
-#endif
- return;
- }
- }
- printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);
-}
-
-/*****************************************************************************************
-
- Device Interface Subroutines
-
-******************************************************************************************/
-
-/*
- * Find an interface by name.
- */
-
-struct device *dev_get(const char *name)
-{
- struct device *dev;
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (strcmp(dev->name, name) == 0)
- return(dev);
- }
- return NULL;
-}
-
-struct device * dev_get_by_index(int ifindex)
-{
- struct device *dev;
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (dev->ifindex == ifindex)
- return(dev);
- }
- return NULL;
-}
-
-struct device *dev_getbyhwaddr(unsigned short type, char *ha)
-{
- struct device *dev;
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (dev->type == type &&
- memcmp(dev->dev_addr, ha, dev->addr_len) == 0)
- return(dev);
- }
- return(NULL);
-}
-
-/*
- * Passed a format string - eg "lt%d" it will try and find a suitable
- * id. Not efficient for many devices, not called a lot..
- */
-
-int dev_alloc_name(struct device *dev, const char *name)
-{
- int i;
- /*
- * If you need over 100 please also fix the algorithm...
- */
- for(i=0;i<100;i++)
- {
- sprintf(dev->name,name,i);
- if(dev_get(dev->name)==NULL)
- return i;
- }
- return -ENFILE; /* Over 100 of the things .. bail out! */
-}
-
-struct device *dev_alloc(const char *name, int *err)
-{
- struct device *dev=kmalloc(sizeof(struct device)+16, GFP_KERNEL);
- if(dev==NULL)
- {
- *err=-ENOBUFS;
- return NULL;
- }
- dev->name=(char *)(dev+1); /* Name string space */
- *err=dev_alloc_name(dev,name);
- if(*err<0)
- {
- kfree(dev);
- return NULL;
- }
- return dev;
-}
-
-void netdev_state_change(struct device *dev)
-{
- if (dev->flags&IFF_UP)
- notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
-}
-
-
-/*
- * Find and possibly load an interface.
- */
-
-#ifdef CONFIG_KMOD
-
-void dev_load(const char *name)
-{
- if(!dev_get(name) && capable(CAP_SYS_MODULE))
- request_module(name);
-}
-
-#else
-
-extern inline void dev_load(const char *unused){;}
-
-#endif
-
-static int default_rebuild_header(struct sk_buff *skb)
-{
- printk(KERN_DEBUG "%s: default_rebuild_header called -- BUG!\n", skb->dev ? skb->dev->name : "NULL!!!");
- kfree_skb(skb);
- return 1;
-}
-
-/*
- * Prepare an interface for use.
- */
-
-int dev_open(struct device *dev)
-{
- int ret = 0;
-
- /*
- * Is it already up?
- */
-
- if (dev->flags&IFF_UP)
- return 0;
-
- /*
- * Call device private open method
- */
-
- if (dev->open)
- ret = dev->open(dev);
-
- /*
- * If it went open OK then:
- */
-
- if (ret == 0)
- {
- /*
- * nil rebuild_header routine,
- * that should be never called and used as just bug trap.
- */
-
- if (dev->rebuild_header == NULL)
- dev->rebuild_header = default_rebuild_header;
-
- /*
- * Set the flags.
- */
- dev->flags |= (IFF_UP | IFF_RUNNING);
-
- /*
- * Initialize multicasting status
- */
- dev_mc_upload(dev);
-
- /*
- * Wakeup transmit queue engine
- */
- dev_activate(dev);
-
- /*
- * ... and announce new interface.
- */
- notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
-
- }
- return(ret);
-}
-
-#ifdef CONFIG_NET_FASTROUTE
-
-static __inline__ void dev_do_clear_fastroute(struct device *dev)
-{
- if (dev->accept_fastpath) {
- int i;
-
- for (i=0; i<=NETDEV_FASTROUTE_HMASK; i++)
- dst_release_irqwait(xchg(dev->fastpath+i, NULL));
- }
-}
-
-void dev_clear_fastroute(struct device *dev)
-{
- if (dev) {
- dev_do_clear_fastroute(dev);
- } else {
- for (dev = dev_base; dev; dev = dev->next)
- dev_do_clear_fastroute(dev);
- }
-}
-#endif
-
-/*
- * Completely shutdown an interface.
- */
-
-int dev_close(struct device *dev)
-{
- if (!(dev->flags&IFF_UP))
- return 0;
-
- dev_deactivate(dev);
-
- dev_lock_wait();
-
- /*
- * Call the device specific close. This cannot fail.
- * Only if device is UP
- */
-
- if (dev->stop)
- dev->stop(dev);
-
- if (dev->start)
- printk("dev_close: bug %s still running\n", dev->name);
-
- /*
- * Device is now down.
- */
- dev_clear_backlog(dev);
-
- dev->flags&=~(IFF_UP|IFF_RUNNING);
-#ifdef CONFIG_NET_FASTROUTE
- dev_clear_fastroute(dev);
-#endif
-
- /*
- * Tell people we are going down
- */
- notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
-
- return(0);
-}
-
-
-/*
- * Device change register/unregister. These are not inline or static
- * as we export them to the world.
- */
-
-int register_netdevice_notifier(struct notifier_block *nb)
-{
- return notifier_chain_register(&netdev_chain, nb);
-}
-
-int unregister_netdevice_notifier(struct notifier_block *nb)
-{
- return notifier_chain_unregister(&netdev_chain,nb);
-}
-
-/*
- * Support routine. Sends outgoing frames to any network
- * taps currently in use.
- */
-
-void dev_queue_xmit_nit(struct sk_buff *skb, struct device *dev)
-{
- struct packet_type *ptype;
- get_fast_time(&skb->stamp);
-
- for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next)
- {
- /* Never send packets back to the socket
- * they originated from - MvS (miquels@drinkel.ow.org)
- */
- if ((ptype->dev == dev || !ptype->dev) &&
- ((struct sock *)ptype->data != skb->sk))
- {
- struct sk_buff *skb2;
- if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
- break;
-
- /* Code, following below is wrong.
-
- The only reason, why it does work is that
- ONLY packet sockets receive outgoing
- packets. If such a packet will be (occasionally)
- received by normal packet handler, which expects
- that mac header is pulled...
- */
-
- /* More sensible variant. skb->nh should be correctly
- set by sender, so that the second statement is
- just protection against buggy protocols.
- */
- skb2->mac.raw = skb2->data;
-
- if (skb2->nh.raw < skb2->data || skb2->nh.raw >= skb2->tail) {
- if (net_ratelimit())
- printk(KERN_DEBUG "protocol %04x is buggy, dev %s\n", skb2->protocol, dev->name);
- skb2->nh.raw = skb2->data;
- if (dev->hard_header)
- skb2->nh.raw += dev->hard_header_len;
- }
-
- skb2->h.raw = skb2->nh.raw;
- skb2->pkt_type = PACKET_OUTGOING;
- ptype->func(skb2, skb->dev, ptype);
- }
- }
-}
-
-/*
- * Fast path for loopback frames.
- */
-
-void dev_loopback_xmit(struct sk_buff *skb)
-{
- struct sk_buff *newskb=skb_clone(skb, GFP_ATOMIC);
- if (newskb==NULL)
- return;
-
- newskb->mac.raw = newskb->data;
- skb_pull(newskb, newskb->nh.raw - newskb->data);
- newskb->pkt_type = PACKET_LOOPBACK;
- newskb->ip_summed = CHECKSUM_UNNECESSARY;
- if (newskb->dst==NULL)
- printk(KERN_DEBUG "BUG: packet without dst looped back 1\n");
- netif_rx(newskb);
-}
-
-int dev_queue_xmit(struct sk_buff *skb)
-{
- struct device *dev = skb->dev;
- struct Qdisc *q;
- char *str1 = "pfinet: dev_queue_xmit check point 1.\n";
- char *str2 = "pfinet: dev_queue_xmit check point 2.\n";
- char *str3 = "pfinet: dev_queue_xmit check point 3.\n";
- char *str4 = "pfinet: dev_queue_xmit check point 4.\n";
- int stderr_fd = fileno (stderr);
-
- write (stderr_fd, str1, strlen (str1) + 1);
- fflush (stderr);
-
-#ifdef CONFIG_NET_PROFILE
- start_bh_atomic();
- NET_PROFILE_ENTER(dev_queue_xmit);
-#endif
-
- start_bh_atomic();
- q = dev->qdisc;
- write (stderr_fd, str2, strlen (str2) + 1);
- fflush (stderr);
- if (q->enqueue) {
- q->enqueue(skb, q);
- qdisc_wakeup(dev);
- end_bh_atomic();
-
-#ifdef CONFIG_NET_PROFILE
- NET_PROFILE_LEAVE(dev_queue_xmit);
- end_bh_atomic();
-#endif
-
- return 0;
- }
- write (stderr_fd, str3, strlen (str3) + 1);
- fflush (stderr);
-
- /* The device has no queue. Common case for software devices:
- loopback, all the sorts of tunnels...
-
- Really, it is unlikely that bh protection is necessary here:
- virtual devices do not generate EOI events.
- However, it is possible, that they rely on bh protection
- made by us here.
- */
- if (dev->flags&IFF_UP) {
- write (stderr_fd, str4, strlen (str4) + 1);
- fflush (stderr);
- if (netdev_nit)
- dev_queue_xmit_nit(skb,dev);
- write (stderr_fd, str5, strlen (str5) + 1);
- fflush (stderr);
- if (dev->hard_start_xmit(skb, dev) == 0) {
- end_bh_atomic();
-
-#ifdef CONFIG_NET_PROFILE
- NET_PROFILE_LEAVE(dev_queue_xmit);
- end_bh_atomic();
-#endif
- write (stderr_fd, str6, strlen (str6) + 1);
- fflush (stderr);
-
- return 0;
- }
- if (net_ratelimit())
- printk(KERN_DEBUG "Virtual device %s asks to queue packet!\n", dev->name);
- }
- end_bh_atomic();
- write (stderr_fd, str6, strlen (str6) + 1);
- fflush (stderr);
-
- kfree_skb(skb);
-
-#ifdef CONFIG_NET_PROFILE
- NET_PROFILE_LEAVE(dev_queue_xmit);
- end_bh_atomic();
-#endif
-
- return 0;
-}
-
-
-/*=======================================================================
- Receiver rotutines
- =======================================================================*/
-
-int netdev_dropping = 0;
-int netdev_max_backlog = 300;
-atomic_t netdev_rx_dropped;
-#ifdef CONFIG_CPU_IS_SLOW
-int net_cpu_congestion;
-#endif
-
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-int netdev_throttle_events;
-static unsigned long netdev_fc_mask = 1;
-unsigned long netdev_fc_xoff = 0;
-
-static struct
-{
- void (*stimul)(struct device *);
- struct device *dev;
-} netdev_fc_slots[32];
-
-int netdev_register_fc(struct device *dev, void (*stimul)(struct device *dev))
-{
- int bit = 0;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (netdev_fc_mask != ~0UL) {
- bit = ffz(netdev_fc_mask);
- netdev_fc_slots[bit].stimul = stimul;
- netdev_fc_slots[bit].dev = dev;
- set_bit(bit, &netdev_fc_mask);
- clear_bit(bit, &netdev_fc_xoff);
- }
- restore_flags(flags);
- return bit;
-}
-
-void netdev_unregister_fc(int bit)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (bit > 0) {
- netdev_fc_slots[bit].stimul = NULL;
- netdev_fc_slots[bit].dev = NULL;
- clear_bit(bit, &netdev_fc_mask);
- clear_bit(bit, &netdev_fc_xoff);
- }
- restore_flags(flags);
-}
-
-static void netdev_wakeup(void)
-{
- unsigned long xoff;
-
- cli();
- xoff = netdev_fc_xoff;
- netdev_fc_xoff = 0;
- netdev_dropping = 0;
- netdev_throttle_events++;
- while (xoff) {
- int i = ffz(~xoff);
- xoff &= ~(1<<i);
- netdev_fc_slots[i].stimul(netdev_fc_slots[i].dev);
- }
- sti();
-}
-#endif
-
-static void dev_clear_backlog(struct device *dev)
-{
- struct sk_buff *curr;
- unsigned long flags;
-
- /*
- *
- * Let now clear backlog queue. -AS
- *
- * We are competing here both with netif_rx() and net_bh().
- * We don't want either of those to mess with skb ptrs
- * while we work on them, thus we must grab the
- * skb_queue_lock.
- */
-
- if (backlog.qlen) {
- repeat:
- spin_lock_irqsave(&skb_queue_lock, flags);
- for (curr = backlog.next;
- curr != (struct sk_buff *)(&backlog);
- curr = curr->next)
- if (curr->dev == dev)
- {
- __skb_unlink(curr, &backlog);
- spin_unlock_irqrestore(&skb_queue_lock, flags);
- kfree_skb(curr);
- goto repeat;
- }
- spin_unlock_irqrestore(&skb_queue_lock, flags);
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (netdev_dropping)
- netdev_wakeup();
-#else
- netdev_dropping = 0;
-#endif
- }
-}
-
-/*
- * Receive a packet from a device driver and queue it for the upper
- * (protocol) levels. It always succeeds.
- */
-
-void netif_rx(struct sk_buff *skb)
-{
-#ifndef CONFIG_CPU_IS_SLOW
- if(skb->stamp.tv_sec==0)
- get_fast_time(&skb->stamp);
-#else
- skb->stamp = xtime;
-#endif
-
- /* The code is rearranged so that the path is the most
- short when CPU is congested, but is still operating.
- */
-
- if (backlog.qlen <= netdev_max_backlog) {
- if (backlog.qlen) {
- if (netdev_dropping == 0) {
- skb_queue_tail(&backlog,skb);
- mark_bh(NET_BH);
- return;
- }
- atomic_inc(&netdev_rx_dropped);
- kfree_skb(skb);
- return;
- }
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (netdev_dropping)
- netdev_wakeup();
-#else
- netdev_dropping = 0;
-#endif
- skb_queue_tail(&backlog,skb);
- mark_bh(NET_BH);
- return;
- }
- netdev_dropping = 1;
- atomic_inc(&netdev_rx_dropped);
- kfree_skb(skb);
-}
-
-#ifdef CONFIG_BRIDGE
-static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
-{
- /*
- * The br_stats.flags is checked here to save the expense of a
- * function call.
- */
- if ((br_stats.flags & BR_UP) && br_call_bridge(skb, type))
- {
- /*
- * We pass the bridge a complete frame. This means
- * recovering the MAC header first.
- */
-
- int offset;
-
- skb=skb_clone(skb, GFP_ATOMIC);
- if(skb==NULL)
- return;
-
- offset=skb->data-skb->mac.raw;
- skb_push(skb,offset); /* Put header back on for bridge */
-
- if(br_receive_frame(skb))
- return;
- kfree_skb(skb);
- }
- return;
-}
-#endif
-
-/*
- * When we are called the queue is ready to grab, the interrupts are
- * on and hardware can interrupt and queue to the receive queue as we
- * run with no problems.
- * This is run as a bottom half after an interrupt handler that does
- * mark_bh(NET_BH);
- */
-
-void net_bh(void)
-{
- struct packet_type *ptype;
- struct packet_type *pt_prev;
- unsigned short type;
-#ifndef _HURD_
- unsigned long start_time = jiffies;
-#ifdef CONFIG_CPU_IS_SLOW
- static unsigned long start_busy = 0;
- static unsigned long ave_busy = 0;
-
- if (start_busy == 0)
- start_busy = start_time;
- net_cpu_congestion = ave_busy>>8;
-#endif
-#endif
-
- NET_PROFILE_ENTER(net_bh);
- /*
- * Can we send anything now? We want to clear the
- * decks for any more sends that get done as we
- * process the input. This also minimises the
- * latency on a transmit interrupt bh.
- */
-
- if (qdisc_head.forw != &qdisc_head)
- qdisc_run_queues();
-
- /*
- * Any data left to process. This may occur because a
- * mark_bh() is done after we empty the queue including
- * that from the device which does a mark_bh() just after
- */
-
- /*
- * While the queue is not empty..
- *
- * Note that the queue never shrinks due to
- * an interrupt, so we can do this test without
- * disabling interrupts.
- */
-
- while (!skb_queue_empty(&backlog))
- {
- struct sk_buff * skb;
-
-#ifndef _HURD_
- /* Give chance to other bottom halves to run */
- if (jiffies - start_time > 1)
- goto net_bh_break;
-#endif
-
- /*
- * We have a packet. Therefore the queue has shrunk
- */
- skb = skb_dequeue(&backlog);
-
-#ifndef _HURD_
-#ifdef CONFIG_CPU_IS_SLOW
- if (ave_busy > 128*16) {
- kfree_skb(skb);
- while ((skb = skb_dequeue(&backlog)) != NULL)
- kfree_skb(skb);
- break;
- }
-#endif
-#endif
-
-
-#if 0
- NET_PROFILE_SKB_PASSED(skb, net_bh_skb);
-#endif
-#ifdef CONFIG_NET_FASTROUTE
- if (skb->pkt_type == PACKET_FASTROUTE) {
- dev_queue_xmit(skb);
- continue;
- }
-#endif
-
- /*
- * Bump the pointer to the next structure.
- *
- * On entry to the protocol layer. skb->data and
- * skb->nh.raw point to the MAC and encapsulated data
- */
-
- /* XXX until we figure out every place to modify.. */
- skb->h.raw = skb->nh.raw = skb->data;
-
- if (skb->mac.raw < skb->head || skb->mac.raw > skb->data) {
- printk(KERN_CRIT "%s: wrong mac.raw ptr, proto=%04x\n", skb->dev->name, skb->protocol);
- kfree_skb(skb);
- continue;
- }
-
- /*
- * Fetch the packet protocol ID.
- */
-
- type = skb->protocol;
-
-#ifdef CONFIG_BRIDGE
- /*
- * If we are bridging then pass the frame up to the
- * bridging code (if this protocol is to be bridged).
- * If it is bridged then move on
- */
- handle_bridge(skb, type);
-#endif
-
- /*
- * We got a packet ID. Now loop over the "known protocols"
- * list. There are two lists. The ptype_all list of taps (normally empty)
- * and the main protocol list which is hashed perfectly for normal protocols.
- */
-
- pt_prev = NULL;
- for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)
- {
- if (!ptype->dev || ptype->dev == skb->dev) {
- if(pt_prev)
- {
- struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
- if(skb2)
- pt_prev->func(skb2,skb->dev, pt_prev);
- }
- pt_prev=ptype;
- }
- }
-
- for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)
- {
- if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
- {
- /*
- * We already have a match queued. Deliver
- * to it and then remember the new match
- */
- if(pt_prev)
- {
- struct sk_buff *skb2;
-
- skb2=skb_clone(skb, GFP_ATOMIC);
-
- /*
- * Kick the protocol handler. This should be fast
- * and efficient code.
- */
-
- if(skb2)
- pt_prev->func(skb2, skb->dev, pt_prev);
- }
- /* Remember the current last to do */
- pt_prev=ptype;
- }
- } /* End of protocol list loop */
-
- /*
- * Is there a last item to send to ?
- */
-
- if(pt_prev) {
- pt_prev->func(skb, skb->dev, pt_prev);
- }
- /*
- * Has an unknown packet has been received ?
- */
-
- else {
- kfree_skb(skb);
- }
- } /* End of queue loop */
-
- /*
- * We have emptied the queue
- */
-
- /*
- * One last output flush.
- */
-
- if (qdisc_head.forw != &qdisc_head)
- qdisc_run_queues();
-
-#ifndef _HURD_
-#ifdef CONFIG_CPU_IS_SLOW
- if (1) {
- unsigned long start_idle = jiffies;
- ave_busy += ((start_idle - start_busy)<<3) - (ave_busy>>4);
- start_busy = 0;
- }
-#endif
-#endif
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (netdev_dropping)
- netdev_wakeup();
-#else
- netdev_dropping = 0;
-#endif
- NET_PROFILE_LEAVE(net_bh);
- return;
-
-#ifndef _HURD_
-net_bh_break:
- mark_bh(NET_BH);
- NET_PROFILE_LEAVE(net_bh);
- return;
-#endif
-}
-
-/* Protocol dependent address dumping routines */
-
-static gifconf_func_t * gifconf_list [NPROTO];
-
-int register_gifconf(unsigned int family, gifconf_func_t * gifconf)
-{
- if (family>=NPROTO)
- return -EINVAL;
- gifconf_list[family] = gifconf;
- return 0;
-}
-
-
-/*
- * Map an interface index to its name (SIOCGIFNAME)
- */
-
-/*
- * This call is useful, but I'd remove it too.
- *
- * The reason is purely aestetical, it is the only call
- * from SIOC* family using struct ifreq in reversed manner.
- * Besides that, it is pretty silly to put "drawing" facility
- * to kernel, it is useful only to print ifindices
- * in readable form, is not it? --ANK
- *
- * We need this ioctl for efficient implementation of the
- * if_indextoname() function required by the IPv6 API. Without
- * it, we would have to search all the interfaces to find a
- * match. --pb
- */
-
-static int dev_ifname(struct ifreq *arg)
-{
- struct device *dev;
- struct ifreq ifr;
- int err;
-
- /*
- * Fetch the caller's info block.
- */
-
- err = copy_from_user(&ifr, arg, sizeof(struct ifreq));
- if (err)
- return -EFAULT;
-
- dev = dev_get_by_index(ifr.ifr_ifindex);
- if (!dev)
- return -ENODEV;
-
- strcpy(ifr.ifr_name, dev->name);
-
- err = copy_to_user(arg, &ifr, sizeof(struct ifreq));
- return (err)?-EFAULT:0;
-}
-
-/*
- * Perform a SIOCGIFCONF call. This structure will change
- * size eventually, and there is nothing I can do about it.
- * Thus we will need a 'compatibility mode'.
- */
-
-#ifdef _HURD_
-int dev_ifconf(char *arg)
-#else
-static int dev_ifconf(char *arg)
-#endif
-{
- struct ifconf ifc;
- struct device *dev;
- char *pos;
- int len;
- int total;
- int i;
-
- /*
- * Fetch the caller's info block.
- */
-
- if (copy_from_user(&ifc, arg, sizeof(struct ifconf)))
- return -EFAULT;
-
- pos = ifc.ifc_buf;
- len = ifc.ifc_len;
-
- /*
- * Loop over the interfaces, and write an info block for each.
- */
-
- total = 0;
- for (dev = dev_base; dev != NULL; dev = dev->next) {
- for (i=0; i<NPROTO; i++) {
- if (gifconf_list[i]) {
- int done;
- if (pos==NULL) {
- done = gifconf_list[i](dev, NULL, 0);
- } else {
- done = gifconf_list[i](dev, pos+total, len-total);
- }
- if (done<0)
- return -EFAULT;
- total += done;
- }
- }
- }
-
- /*
- * All done. Write the updated control block back to the caller.
- */
- ifc.ifc_len = total;
-
- if (copy_to_user(arg, &ifc, sizeof(struct ifconf)))
- return -EFAULT;
-
- /*
- * Both BSD and Solaris return 0 here, so we do too.
- */
- return 0;
-}
-
-/*
- * This is invoked by the /proc filesystem handler to display a device
- * in detail.
- */
-
-#ifdef CONFIG_PROC_FS
-static int sprintf_stats(char *buffer, struct device *dev)
-{
- struct net_device_stats *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
- int size;
-
- if (stats)
- size = sprintf(buffer, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu %8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
- dev->name,
- stats->rx_bytes,
- stats->rx_packets, stats->rx_errors,
- stats->rx_dropped + stats->rx_missed_errors,
- stats->rx_fifo_errors,
- stats->rx_length_errors + stats->rx_over_errors
- + stats->rx_crc_errors + stats->rx_frame_errors,
- stats->rx_compressed, stats->multicast,
- stats->tx_bytes,
- stats->tx_packets, stats->tx_errors, stats->tx_dropped,
- stats->tx_fifo_errors, stats->collisions,
- stats->tx_carrier_errors + stats->tx_aborted_errors
- + stats->tx_window_errors + stats->tx_heartbeat_errors,
- stats->tx_compressed);
- else
- size = sprintf(buffer, "%6s: No statistics available.\n", dev->name);
-
- return size;
-}
-
-/*
- * Called from the PROCfs module. This now uses the new arbitrary sized /proc/net interface
- * to create /proc/net/dev
- */
-
-int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
- int len=0;
- off_t begin=0;
- off_t pos=0;
- int size;
-
- struct device *dev;
-
-
- size = sprintf(buffer,
- "Inter-| Receive | Transmit\n"
- " face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n");
-
- pos+=size;
- len+=size;
-
-
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- size = sprintf_stats(buffer+len, dev);
- len+=size;
- pos=begin+len;
-
- if(pos<offset)
- {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- break;
- }
-
- *start=buffer+(offset-begin); /* Start of wanted data */
- len-=(offset-begin); /* Start slop */
- if(len>length)
- len=length; /* Ending slop */
- return len;
-}
-
-static int dev_proc_stats(char *buffer, char **start, off_t offset,
- int length, int *eof, void *data)
-{
- int len;
-
- len = sprintf(buffer, "%08x %08x %08x %08x %08x\n",
- atomic_read(&netdev_rx_dropped),
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- netdev_throttle_events,
-#else
- 0,
-#endif
-#ifdef CONFIG_NET_FASTROUTE
- dev_fastroute_stat.hits,
- dev_fastroute_stat.succeed,
- dev_fastroute_stat.deferred
-#else
- 0, 0, 0
-#endif
- );
-
- len -= offset;
-
- if (len > length)
- len = length;
- if(len < 0)
- len = 0;
-
- *start = buffer + offset;
- *eof = 1;
-
- return len;
-}
-
-#endif /* CONFIG_PROC_FS */
-
-
-#ifdef CONFIG_NET_RADIO
-#ifdef CONFIG_PROC_FS
-
-/*
- * Print one entry of /proc/net/wireless
- * This is a clone of /proc/net/dev (just above)
- */
-static int sprintf_wireless_stats(char *buffer, struct device *dev)
-{
- /* Get stats from the driver */
- struct iw_statistics *stats = (dev->get_wireless_stats ?
- dev->get_wireless_stats(dev) :
- (struct iw_statistics *) NULL);
- int size;
-
- if(stats != (struct iw_statistics *) NULL)
- {
- size = sprintf(buffer,
- "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d\n",
- dev->name,
- stats->status,
- stats->qual.qual,
- stats->qual.updated & 1 ? '.' : ' ',
- stats->qual.level,
- stats->qual.updated & 2 ? '.' : ' ',
- stats->qual.noise,
- stats->qual.updated & 4 ? '.' : ' ',
- stats->discard.nwid,
- stats->discard.code,
- stats->discard.misc);
- stats->qual.updated = 0;
- }
- else
- size = 0;
-
- return size;
-}
-
-/*
- * Print info for /proc/net/wireless (print all entries)
- * This is a clone of /proc/net/dev (just above)
- */
-int dev_get_wireless_info(char * buffer, char **start, off_t offset,
- int length, int dummy)
-{
- int len = 0;
- off_t begin = 0;
- off_t pos = 0;
- int size;
-
- struct device * dev;
-
- size = sprintf(buffer,
- "Inter-| sta-| Quality | Discarded packets\n"
- " face | tus | link level noise | nwid crypt misc\n"
- );
-
- pos+=size;
- len+=size;
-
- for(dev = dev_base; dev != NULL; dev = dev->next)
- {
- size = sprintf_wireless_stats(buffer+len, dev);
- len+=size;
- pos=begin+len;
-
- if(pos < offset)
- {
- len=0;
- begin=pos;
- }
- if(pos > offset + length)
- break;
- }
-
- *start = buffer + (offset - begin); /* Start of wanted data */
- len -= (offset - begin); /* Start slop */
- if(len > length)
- len = length; /* Ending slop */
-
- return len;
-}
-#endif /* CONFIG_PROC_FS */
-#endif /* CONFIG_NET_RADIO */
-
-void dev_set_promiscuity(struct device *dev, int inc)
-{
- unsigned short old_flags = dev->flags;
-
- dev->flags |= IFF_PROMISC;
- if ((dev->promiscuity += inc) == 0)
- dev->flags &= ~IFF_PROMISC;
- if (dev->flags^old_flags) {
-#ifdef CONFIG_NET_FASTROUTE
- if (dev->flags&IFF_PROMISC) {
- netdev_fastroute_obstacles++;
- dev_clear_fastroute(dev);
- } else
- netdev_fastroute_obstacles--;
-#endif
- dev_mc_upload(dev);
- printk(KERN_INFO "device %s %s promiscuous mode\n",
- dev->name, (dev->flags&IFF_PROMISC) ? "entered" : "left");
- }
-}
-
-void dev_set_allmulti(struct device *dev, int inc)
-{
- unsigned short old_flags = dev->flags;
-
- dev->flags |= IFF_ALLMULTI;
- if ((dev->allmulti += inc) == 0)
- dev->flags &= ~IFF_ALLMULTI;
- if (dev->flags^old_flags)
- dev_mc_upload(dev);
-}
-
-int dev_change_flags(struct device *dev, unsigned flags)
-{
- int ret;
- int old_flags = dev->flags;
-
- /*
- * Set the flags on our device.
- */
-
- dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_RUNNING|IFF_NOARP|
- IFF_SLAVE|IFF_MASTER|IFF_DYNAMIC|
- IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) |
- (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI));
-
- /*
- * Load in the correct multicast list now the flags have changed.
- */
-
- dev_mc_upload(dev);
-
- /*
- * Have we downed the interface. We handle IFF_UP ourselves
- * according to user attempts to set it, rather than blindly
- * setting it.
- */
-
- ret = 0;
- if ((old_flags^flags)&IFF_UP) /* Bit is different ? */
- {
- ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
-
- if (ret == 0)
- dev_mc_upload(dev);
- }
-
- if (dev->flags&IFF_UP &&
- ((old_flags^dev->flags)&~(IFF_UP|IFF_RUNNING|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE)))
- notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
-
- if ((flags^dev->gflags)&IFF_PROMISC) {
- int inc = (flags&IFF_PROMISC) ? +1 : -1;
- dev->gflags ^= IFF_PROMISC;
- dev_set_promiscuity(dev, inc);
- }
-
- /* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI
- is important. Some (broken) drivers set IFF_PROMISC, when
- IFF_ALLMULTI is requested not asking us and not reporting.
- */
- if ((flags^dev->gflags)&IFF_ALLMULTI) {
- int inc = (flags&IFF_ALLMULTI) ? +1 : -1;
- dev->gflags ^= IFF_ALLMULTI;
- dev_set_allmulti(dev, inc);
- }
-
- return ret;
-}
-
-#ifdef _HURD_
-
-#define dev_ioctl 0
-
-#else
-
-/*
- * Perform the SIOCxIFxxx calls.
- */
-
-static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
-{
- struct device *dev;
- int err;
-
- if ((dev = dev_get(ifr->ifr_name)) == NULL)
- return -ENODEV;
-
- switch(cmd)
- {
- case SIOCGIFFLAGS: /* Get interface flags */
- ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
- |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
- return 0;
-
- case SIOCSIFFLAGS: /* Set interface flags */
- return dev_change_flags(dev, ifr->ifr_flags);
-
- case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */
- ifr->ifr_metric = 0;
- return 0;
-
- case SIOCSIFMETRIC: /* Set the metric on the interface (currently unused) */
- return -EOPNOTSUPP;
-
- case SIOCGIFMTU: /* Get the MTU of a device */
- ifr->ifr_mtu = dev->mtu;
- return 0;
-
- case SIOCSIFMTU: /* Set the MTU of a device */
- if (ifr->ifr_mtu == dev->mtu)
- return 0;
-
- /*
- * MTU must be positive.
- */
-
- if (ifr->ifr_mtu<=0)
- return -EINVAL;
-
- if (dev->change_mtu)
- err = dev->change_mtu(dev, ifr->ifr_mtu);
- else {
- dev->mtu = ifr->ifr_mtu;
- err = 0;
- }
- if (!err && dev->flags&IFF_UP)
- notifier_call_chain(&netdev_chain, NETDEV_CHANGEMTU, dev);
- return err;
-
- case SIOCGIFHWADDR:
- memcpy(ifr->ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN);
- ifr->ifr_hwaddr.sa_family=dev->type;
- return 0;
-
- case SIOCSIFHWADDR:
- if(dev->set_mac_address==NULL)
- return -EOPNOTSUPP;
- if(ifr->ifr_hwaddr.sa_family!=dev->type)
- return -EINVAL;
- err=dev->set_mac_address(dev,&ifr->ifr_hwaddr);
- if (!err)
- notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
- return err;
-
- case SIOCSIFHWBROADCAST:
- if(ifr->ifr_hwaddr.sa_family!=dev->type)
- return -EINVAL;
- memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, MAX_ADDR_LEN);
- notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
- return 0;
-
- case SIOCGIFMAP:
- ifr->ifr_map.mem_start=dev->mem_start;
- ifr->ifr_map.mem_end=dev->mem_end;
- ifr->ifr_map.base_addr=dev->base_addr;
- ifr->ifr_map.irq=dev->irq;
- ifr->ifr_map.dma=dev->dma;
- ifr->ifr_map.port=dev->if_port;
- return 0;
-
- case SIOCSIFMAP:
- if (dev->set_config)
- return dev->set_config(dev,&ifr->ifr_map);
- return -EOPNOTSUPP;
-
- case SIOCADDMULTI:
- if(dev->set_multicast_list==NULL ||
- ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
- return -EINVAL;
- dev_mc_add(dev,ifr->ifr_hwaddr.sa_data, dev->addr_len, 1);
- return 0;
-
- case SIOCDELMULTI:
- if(dev->set_multicast_list==NULL ||
- ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
- return -EINVAL;
- dev_mc_delete(dev,ifr->ifr_hwaddr.sa_data,dev->addr_len, 1);
- return 0;
-
- case SIOCGIFINDEX:
- ifr->ifr_ifindex = dev->ifindex;
- return 0;
-
- case SIOCGIFTXQLEN:
- ifr->ifr_qlen = dev->tx_queue_len;
- return 0;
-
- case SIOCSIFTXQLEN:
- if(ifr->ifr_qlen<0)
- return -EINVAL;
- dev->tx_queue_len = ifr->ifr_qlen;
- return 0;
-
- case SIOCSIFNAME:
- if (dev->flags&IFF_UP)
- return -EBUSY;
- if (dev_get(ifr->ifr_newname))
- return -EEXIST;
- memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
- dev->name[IFNAMSIZ-1] = 0;
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
- return 0;
-
- /*
- * Unknown or private ioctl
- */
-
- default:
- if(cmd >= SIOCDEVPRIVATE &&
- cmd <= SIOCDEVPRIVATE + 15) {
- if (dev->do_ioctl)
- return dev->do_ioctl(dev, ifr, cmd);
- return -EOPNOTSUPP;
- }
-
-#ifdef CONFIG_NET_RADIO
- if(cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
- if (dev->do_ioctl)
- return dev->do_ioctl(dev, ifr, cmd);
- return -EOPNOTSUPP;
- }
-#endif /* CONFIG_NET_RADIO */
-
- }
- return -EINVAL;
-}
-
-
-/*
- * This function handles all "interface"-type I/O control requests. The actual
- * 'doing' part of this is dev_ifsioc above.
- */
-
-int dev_ioctl(unsigned int cmd, void *arg)
-{
- struct ifreq ifr;
- int ret;
- char *colon;
-
- /* One special case: SIOCGIFCONF takes ifconf argument
- and requires shared lock, because it sleeps writing
- to user space.
- */
-
- if (cmd == SIOCGIFCONF) {
- rtnl_shlock();
- ret = dev_ifconf((char *) arg);
- rtnl_shunlock();
- return ret;
- }
- if (cmd == SIOCGIFNAME) {
- return dev_ifname((struct ifreq *)arg);
- }
-
- if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
- return -EFAULT;
-
- ifr.ifr_name[IFNAMSIZ-1] = 0;
-
- colon = strchr(ifr.ifr_name, ':');
- if (colon)
- *colon = 0;
-
- /*
- * See which interface the caller is talking about.
- */
-
- switch(cmd)
- {
- /*
- * These ioctl calls:
- * - can be done by all.
- * - atomic and do not require locking.
- * - return a value
- */
-
- case SIOCGIFFLAGS:
- case SIOCGIFMETRIC:
- case SIOCGIFMTU:
- case SIOCGIFHWADDR:
- case SIOCGIFSLAVE:
- case SIOCGIFMAP:
- case SIOCGIFINDEX:
- case SIOCGIFTXQLEN:
- dev_load(ifr.ifr_name);
- ret = dev_ifsioc(&ifr, cmd);
- if (!ret) {
- if (colon)
- *colon = ':';
- if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- }
- return ret;
-
- /*
- * These ioctl calls:
- * - require superuser power.
- * - require strict serialization.
- * - do not return a value
- */
-
- case SIOCSIFFLAGS:
- case SIOCSIFMETRIC:
- case SIOCSIFMTU:
- case SIOCSIFMAP:
- case SIOCSIFHWADDR:
- case SIOCSIFSLAVE:
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- case SIOCSIFHWBROADCAST:
- case SIOCSIFTXQLEN:
- case SIOCSIFNAME:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- dev_load(ifr.ifr_name);
- rtnl_lock();
- ret = dev_ifsioc(&ifr, cmd);
- rtnl_unlock();
- return ret;
-
- case SIOCGIFMEM:
- /* Get the per device memory space. We can add this but currently
- do not support it */
- case SIOCSIFMEM:
- /* Set the per device memory buffer space. Not applicable in our case */
- case SIOCSIFLINK:
- return -EINVAL;
-
- /*
- * Unknown or private ioctl.
- */
-
- default:
- if (cmd >= SIOCDEVPRIVATE &&
- cmd <= SIOCDEVPRIVATE + 15) {
- dev_load(ifr.ifr_name);
- rtnl_lock();
- ret = dev_ifsioc(&ifr, cmd);
- rtnl_unlock();
- if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- return ret;
- }
-#ifdef CONFIG_NET_RADIO
- if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
- dev_load(ifr.ifr_name);
- if (IW_IS_SET(cmd)) {
- if (!suser())
- return -EPERM;
- rtnl_lock();
- }
- ret = dev_ifsioc(&ifr, cmd);
- if (IW_IS_SET(cmd))
- rtnl_unlock();
- if (!ret && IW_IS_GET(cmd) &&
- copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- return ret;
- }
-#endif /* CONFIG_NET_RADIO */
- return -EINVAL;
- }
-}
-
-#endif
-
-int dev_new_index(void)
-{
- static int ifindex;
- for (;;) {
- if (++ifindex <= 0)
- ifindex=1;
- if (dev_get_by_index(ifindex) == NULL)
- return ifindex;
- }
-}
-
-static int dev_boot_phase = 1;
-
-
-int register_netdevice(struct device *dev)
-{
- struct device *d, **dp;
-
- if (dev_boot_phase) {
- /* This is NOT bug, but I am not sure, that all the
- devices, initialized before netdev module is started
- are sane.
-
- Now they are chained to device boot list
- and probed later. If a module is initialized
- before netdev, but assumes that dev->init
- is really called by register_netdev(), it will fail.
-
- So that this message should be printed for a while.
- */
- printk(KERN_INFO "early initialization of device %s is deferred\n", dev->name);
-
- /* Check for existence, and append to tail of chain */
- for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
- if (d == dev || strcmp(d->name, dev->name) == 0)
- return -EEXIST;
- }
- dev->next = NULL;
- *dp = dev;
- return 0;
- }
-
- dev->iflink = -1;
-
- /* Init, if this function is available */
- if (dev->init && dev->init(dev) != 0)
- return -EIO;
-
- /* Check for existence, and append to tail of chain */
- for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
- if (d == dev || strcmp(d->name, dev->name) == 0)
- return -EEXIST;
- }
- dev->next = NULL;
- dev_init_scheduler(dev);
- dev->ifindex = dev_new_index();
- if (dev->iflink == -1)
- dev->iflink = dev->ifindex;
- *dp = dev;
-
- /* Notify protocols, that a new device appeared. */
- notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
-
- return 0;
-}
-
-int unregister_netdevice(struct device *dev)
-{
- struct device *d, **dp;
-
- if (dev_boot_phase == 0) {
- /* If device is running, close it.
- It is very bad idea, really we should
- complain loudly here, but random hackery
- in linux/drivers/net likes it.
- */
- if (dev->flags & IFF_UP)
- dev_close(dev);
-
-#ifdef CONFIG_NET_FASTROUTE
- dev_clear_fastroute(dev);
-#endif
-
- /* Shutdown queueing discipline. */
- dev_shutdown(dev);
-
- /* Notify protocols, that we are about to destroy
- this device. They should clean all the things.
- */
- notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
-
- /*
- * Flush the multicast chain
- */
- dev_mc_discard(dev);
-
- /* To avoid pointers looking to nowhere,
- we wait for end of critical section */
- dev_lock_wait();
- }
-
- /* And unlink it from device chain. */
- for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {
- if (d == dev) {
- *dp = d->next;
- synchronize_bh();
- d->next = NULL;
-
- if (dev->destructor)
- dev->destructor(dev);
- return 0;
- }
- }
- return -ENODEV;
-}
-
-
-/*
- * Initialize the DEV module. At boot time this walks the device list and
- * unhooks any devices that fail to initialise (normally hardware not
- * present) and leaves us with a valid list of present and active devices.
- *
- */
-extern int lance_init(void);
-extern int bpq_init(void);
-extern int scc_init(void);
-extern void sdla_setup(void);
-extern void sdla_c_setup(void);
-extern void dlci_setup(void);
-extern int dmascc_init(void);
-extern int sm_init(void);
-
-extern int baycom_ser_fdx_init(void);
-extern int baycom_ser_hdx_init(void);
-extern int baycom_par_init(void);
-
-extern int lapbeth_init(void);
-extern int comx_init(void);
-extern void arcnet_init(void);
-extern void ip_auto_config(void);
-#ifdef CONFIG_8xx
-extern int cpm_enet_init(void);
-#endif /* CONFIG_8xx */
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_dev = {
- PROC_NET_DEV, 3, "dev",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- dev_get_info
-};
-#endif
-
-#ifdef CONFIG_NET_RADIO
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_wireless = {
- PROC_NET_WIRELESS, 8, "wireless",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- dev_get_wireless_info
-};
-#endif /* CONFIG_PROC_FS */
-#endif /* CONFIG_NET_RADIO */
-
-__initfunc(int net_dev_init(void))
-{
- struct device *dev, **dp;
-
-#ifdef CONFIG_NET_SCHED
- pktsched_init();
-#endif
-
- /*
- * Initialise the packet receive queue.
- */
-
- skb_queue_head_init(&backlog);
-
- /*
- * The bridge has to be up before the devices
- */
-
-#ifdef CONFIG_BRIDGE
- br_init();
-#endif
-
- /*
- * This is Very Ugly(tm).
- *
- * Some devices want to be initialized early..
- */
-
-#if defined(CONFIG_SCC)
- scc_init();
-#endif
-#if defined(CONFIG_DMASCC)
- dmascc_init();
-#endif
-#if defined(CONFIG_BPQETHER)
- bpq_init();
-#endif
-#if defined(CONFIG_DLCI)
- dlci_setup();
-#endif
-#if defined(CONFIG_SDLA)
- sdla_c_setup();
-#endif
-#if defined(CONFIG_BAYCOM_PAR)
- baycom_par_init();
-#endif
-#if defined(CONFIG_BAYCOM_SER_FDX)
- baycom_ser_fdx_init();
-#endif
-#if defined(CONFIG_BAYCOM_SER_HDX)
- baycom_ser_hdx_init();
-#endif
-#if defined(CONFIG_SOUNDMODEM)
- sm_init();
-#endif
-#if defined(CONFIG_LAPBETHER)
- lapbeth_init();
-#endif
-#if defined(CONFIG_PLIP)
- plip_init();
-#endif
-#if defined(CONFIG_ARCNET)
- arcnet_init();
-#endif
-#if defined(CONFIG_8xx)
- cpm_enet_init();
-#endif
-#if defined(CONFIG_COMX)
- comx_init();
-#endif
- /*
- * SLHC if present needs attaching so other people see it
- * even if not opened.
- */
-
-#ifdef CONFIG_INET
-#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
- || defined(CONFIG_PPP) \
- || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
- slhc_install();
-#endif
-#endif
-
-#ifdef CONFIG_NET_PROFILE
- net_profile_init();
- NET_PROFILE_REGISTER(dev_queue_xmit);
- NET_PROFILE_REGISTER(net_bh);
-#if 0
- NET_PROFILE_REGISTER(net_bh_skb);
-#endif
-#endif
- /*
- * Add the devices.
- * If the call to dev->init fails, the dev is removed
- * from the chain disconnecting the device until the
- * next reboot.
- */
-
- dp = &dev_base;
- while ((dev = *dp) != NULL)
- {
- dev->iflink = -1;
- if (dev->init && dev->init(dev))
- {
- /*
- * It failed to come up. Unhook it.
- */
- *dp = dev->next;
- synchronize_bh();
- }
- else
- {
- dp = &dev->next;
- dev->ifindex = dev_new_index();
- if (dev->iflink == -1)
- dev->iflink = dev->ifindex;
- dev_init_scheduler(dev);
- }
- }
-
-#ifdef CONFIG_PROC_FS
- proc_net_register(&proc_net_dev);
- {
- struct proc_dir_entry *ent = create_proc_entry("net/dev_stat", 0, 0);
- ent->read_proc = dev_proc_stats;
- }
-#endif
-
-#ifdef CONFIG_NET_RADIO
-#ifdef CONFIG_PROC_FS
- proc_net_register(&proc_net_wireless);
-#endif /* CONFIG_PROC_FS */
-#endif /* CONFIG_NET_RADIO */
-
- init_bh(NET_BH, net_bh);
-
- dev_boot_phase = 0;
-
- dev_mcast_init();
-
-#ifdef CONFIG_BRIDGE
- /*
- * Register any statically linked ethernet devices with the bridge
- */
- br_spacedevice_register();
-#endif
-
-#ifdef CONFIG_IP_PNP
- ip_auto_config();
-#endif
-
- return 0;
-}