]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/net/dummy.c
[VLAN]: Fix MAC address handling
[mirror_ubuntu-zesty-kernel.git] / drivers / net / dummy.c
CommitLineData
1da177e4
LT
1/* dummy.c: a dummy net driver
2
3 The purpose of this driver is to provide a device to point a
4 route through, but not to actually transmit packets.
5
6 Why? If you have a machine whose only connection is an occasional
7 PPP/SLIP/PLIP link, you can only connect to your own hostname
8 when the link is up. Otherwise you have to use localhost.
9 This isn't very consistent.
10
11 One solution is to set up a dummy link using PPP/SLIP/PLIP,
12 but this seems (to me) too much overhead for too little gain.
13 This driver provides a small alternative. Thus you can do
6aa20a22 14
1da177e4
LT
15 [when not running slip]
16 ifconfig dummy slip.addr.ess.here up
17 [to go to slip]
18 ifconfig dummy down
19 dip whatever
20
21 This was written by looking at Donald Becker's skeleton driver
22 and the loopback driver. I then threw away anything that didn't
23 apply! Thanks to Alan Cox for the key clue on what to do with
24 misguided packets.
25
26 Nick Holloway, 27th May 1994
27 [I tweaked this explanation a little but that's all]
28 Alan Cox, 30th May 1994
29*/
30
1da177e4
LT
31#include <linux/module.h>
32#include <linux/kernel.h>
33#include <linux/netdevice.h>
34#include <linux/etherdevice.h>
35#include <linux/init.h>
36#include <linux/moduleparam.h>
206c9fb2 37#include <linux/rtnetlink.h>
5d5cb173 38#include <net/rtnetlink.h>
206c9fb2
PM
39
40struct dummy_priv {
41 struct net_device *dev;
42 struct list_head list;
43};
1da177e4
LT
44
45static int numdummies = 1;
46
47static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
1da177e4
LT
48
49static int dummy_set_address(struct net_device *dev, void *p)
50{
51 struct sockaddr *sa = p;
52
6aa20a22 53 if (!is_valid_ether_addr(sa->sa_data))
1da177e4 54 return -EADDRNOTAVAIL;
6aa20a22 55
1da177e4
LT
56 memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
57 return 0;
58}
59
60/* fake multicast ability */
61static void set_multicast_list(struct net_device *dev)
62{
63}
64
5d5cb173 65static void dummy_setup(struct net_device *dev)
1da177e4
LT
66{
67 /* Initialize the device structure. */
1da177e4
LT
68 dev->hard_start_xmit = dummy_xmit;
69 dev->set_multicast_list = set_multicast_list;
70 dev->set_mac_address = dummy_set_address;
5d5cb173 71 dev->destructor = free_netdev;
1da177e4
LT
72
73 /* Fill in device structure with ethernet-generic values. */
74 ether_setup(dev);
75 dev->tx_queue_len = 0;
76 dev->change_mtu = NULL;
77 dev->flags |= IFF_NOARP;
78 dev->flags &= ~IFF_MULTICAST;
79 SET_MODULE_OWNER(dev);
80 random_ether_addr(dev->dev_addr);
81}
82
83static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
84{
58651b24
PM
85 dev->stats.tx_packets++;
86 dev->stats.tx_bytes += skb->len;
1da177e4
LT
87
88 dev_kfree_skb(skb);
89 return 0;
90}
91
206c9fb2 92static LIST_HEAD(dummies);
1da177e4 93
5d5cb173
PM
94static int dummy_newlink(struct net_device *dev,
95 struct nlattr *tb[], struct nlattr *data[])
96{
97 struct dummy_priv *priv = netdev_priv(dev);
98 int err;
99
100 err = register_netdevice(dev);
101 if (err < 0)
102 return err;
103
104 priv->dev = dev;
105 list_add_tail(&priv->list, &dummies);
106 return 0;
107}
108
109static void dummy_dellink(struct net_device *dev)
110{
111 struct dummy_priv *priv = netdev_priv(dev);
112
113 list_del(&priv->list);
114 unregister_netdevice(dev);
115}
116
117static struct rtnl_link_ops dummy_link_ops __read_mostly = {
118 .kind = "dummy",
119 .priv_size = sizeof(struct dummy_priv),
120 .setup = dummy_setup,
121 .newlink = dummy_newlink,
122 .dellink = dummy_dellink,
123};
124
1da177e4
LT
125/* Number of dummy devices to be set up by this module. */
126module_param(numdummies, int, 0);
127MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
128
206c9fb2 129static int __init dummy_init_one(void)
1da177e4
LT
130{
131 struct net_device *dev_dummy;
206c9fb2 132 struct dummy_priv *priv;
1da177e4
LT
133 int err;
134
206c9fb2
PM
135 dev_dummy = alloc_netdev(sizeof(struct dummy_priv), "dummy%d",
136 dummy_setup);
1da177e4
LT
137
138 if (!dev_dummy)
139 return -ENOMEM;
140
5d5cb173
PM
141 err = dev_alloc_name(dev_dummy, dev_dummy->name);
142 if (err < 0)
143 goto err;
1da177e4 144
5d5cb173
PM
145 dev_dummy->rtnl_link_ops = &dummy_link_ops;
146 err = register_netdevice(dev_dummy);
147 if (err < 0)
148 goto err;
1da177e4 149
5d5cb173
PM
150 priv = netdev_priv(dev_dummy);
151 priv->dev = dev_dummy;
152 list_add_tail(&priv->list, &dummies);
153 return 0;
206c9fb2 154
5d5cb173
PM
155err:
156 free_netdev(dev_dummy);
157 return err;
6aa20a22 158}
1da177e4
LT
159
160static int __init dummy_init_module(void)
6aa20a22 161{
206c9fb2 162 struct dummy_priv *priv, *next;
1da177e4 163 int i, err = 0;
206c9fb2 164
5d5cb173
PM
165 rtnl_lock();
166 err = __rtnl_link_register(&dummy_link_ops);
167
1da177e4 168 for (i = 0; i < numdummies && !err; i++)
206c9fb2 169 err = dummy_init_one();
5d5cb173 170 if (err < 0) {
206c9fb2 171 list_for_each_entry_safe(priv, next, &dummies, list)
5d5cb173
PM
172 dummy_dellink(priv->dev);
173 __rtnl_link_unregister(&dummy_link_ops);
1da177e4 174 }
5d5cb173
PM
175 rtnl_unlock();
176
1da177e4 177 return err;
6aa20a22 178}
1da177e4
LT
179
180static void __exit dummy_cleanup_module(void)
181{
206c9fb2
PM
182 struct dummy_priv *priv, *next;
183
5d5cb173 184 rtnl_lock();
206c9fb2 185 list_for_each_entry_safe(priv, next, &dummies, list)
5d5cb173
PM
186 dummy_dellink(priv->dev);
187
188 __rtnl_link_unregister(&dummy_link_ops);
189 rtnl_unlock();
1da177e4
LT
190}
191
192module_init(dummy_init_module);
193module_exit(dummy_cleanup_module);
194MODULE_LICENSE("GPL");
5d5cb173 195MODULE_ALIAS_RTNL_LINK("dummy");