net_kern.c 19.5 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * James Leu (jleu@mindspring.net).
 * Copyright (C) 2001 by various other people who didn't put their name here.
 * Licensed under the GPL.
 */

#include "linux/kernel.h"
#include "linux/netdevice.h"
#include "linux/rtnetlink.h"
#include "linux/skbuff.h"
#include "linux/socket.h"
#include "linux/spinlock.h"
#include "linux/module.h"
#include "linux/init.h"
#include "linux/etherdevice.h"
#include "linux/list.h"
#include "linux/inetdevice.h"
#include "linux/ctype.h"
#include "linux/bootmem.h"
#include "linux/ethtool.h"
22
#include "linux/platform_device.h"
L
Linus Torvalds 已提交
23 24 25 26 27 28 29 30 31
#include "asm/uaccess.h"
#include "kern_util.h"
#include "net_kern.h"
#include "net_user.h"
#include "mconsole_kern.h"
#include "init.h"
#include "irq_user.h"
#include "irq_kern.h"

32 33 34 35 36
static inline void set_ether_mac(struct net_device *dev, unsigned char *addr)
{
	memcpy(dev->dev_addr, addr, ETH_ALEN);
}

L
Linus Torvalds 已提交
37 38 39
#define DRIVER_NAME "uml-netdev"

static DEFINE_SPINLOCK(opened_lock);
40
static LIST_HEAD(opened);
L
Linus Torvalds 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

static int uml_net_rx(struct net_device *dev)
{
	struct uml_net_private *lp = dev->priv;
	int pkt_len;
	struct sk_buff *skb;

	/* If we can't allocate memory, try again next round. */
	skb = dev_alloc_skb(dev->mtu);
	if (skb == NULL) {
		lp->stats.rx_dropped++;
		return 0;
	}

	skb->dev = dev;
	skb_put(skb, dev->mtu);
57
	skb_reset_mac_header(skb);
L
Linus Torvalds 已提交
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
	pkt_len = (*lp->read)(lp->fd, &skb, lp);

	if (pkt_len > 0) {
		skb_trim(skb, pkt_len);
		skb->protocol = (*lp->protocol)(skb);
		netif_rx(skb);

		lp->stats.rx_bytes += skb->len;
		lp->stats.rx_packets++;
		return pkt_len;
	}

	kfree_skb(skb);
	return pkt_len;
}

74
static void uml_dev_close(struct work_struct *work)
75
{
76 77 78
	struct uml_net_private *lp =
		container_of(work, struct uml_net_private, work);
	dev_close(lp->dev);
79 80
}

A
Al Viro 已提交
81
irqreturn_t uml_net_interrupt(int irq, void *dev_id)
L
Linus Torvalds 已提交
82 83 84 85 86 87 88 89 90 91 92
{
	struct net_device *dev = dev_id;
	struct uml_net_private *lp = dev->priv;
	int err;

	if(!netif_running(dev))
		return(IRQ_NONE);

	spin_lock(&lp->lock);
	while((err = uml_net_rx(dev)) > 0) ;
	if(err < 0) {
93 94
		printk(KERN_ERR
		       "Device '%s' read returned %d, shutting it down\n",
L
Linus Torvalds 已提交
95
		       dev->name, err);
96 97 98 99
		/* dev_close can't be called in interrupt context, and takes
		 * again lp->lock.
		 * And dev_close() can be safely called multiple times on the
		 * same device, since it tests for (dev->flags & IFF_UP). So
100 101 102 103
		 * there's no harm in delaying the device shutdown.
		 * Furthermore, the workqueue will not re-enqueue an already
		 * enqueued work item. */
		schedule_work(&lp->work);
L
Linus Torvalds 已提交
104 105 106 107
		goto out;
	}
	reactivate_fd(lp->fd, UM_ETH_IRQ);

108
out:
L
Linus Torvalds 已提交
109
	spin_unlock(&lp->lock);
110
	return IRQ_HANDLED;
L
Linus Torvalds 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
}

static int uml_net_open(struct net_device *dev)
{
	struct uml_net_private *lp = dev->priv;
	int err;

	if(lp->fd >= 0){
		err = -ENXIO;
		goto out;
	}

	lp->fd = (*lp->open)(&lp->user);
	if(lp->fd < 0){
		err = lp->fd;
		goto out;
	}

	err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt,
130
			     IRQF_DISABLED | IRQF_SHARED, dev->name, dev);
L
Linus Torvalds 已提交
131 132 133
	if(err != 0){
		printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err);
		err = -ENETUNREACH;
134
		goto out_close;
L
Linus Torvalds 已提交
135 136 137 138 139 140 141 142 143 144 145
	}

	lp->tl.data = (unsigned long) &lp->user;
	netif_start_queue(dev);

	/* clear buffer - it can happen that the host side of the interface
	 * is full when we get here.  In this case, new data is never queued,
	 * SIGIOs never arrive, and the net never works.
	 */
	while((err = uml_net_rx(dev)) > 0) ;

146 147 148 149 150 151 152 153 154 155
	spin_lock(&opened_lock);
	list_add(&lp->list, &opened);
	spin_unlock(&opened_lock);

	return 0;
out_close:
	if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
	lp->fd = -1;
out:
	return err;
L
Linus Torvalds 已提交
156 157 158 159 160
}

static int uml_net_close(struct net_device *dev)
{
	struct uml_net_private *lp = dev->priv;
161

L
Linus Torvalds 已提交
162 163 164 165 166 167 168
	netif_stop_queue(dev);

	free_irq(dev->irq, dev);
	if(lp->close != NULL)
		(*lp->close)(lp->fd, &lp->user);
	lp->fd = -1;

169 170 171 172
	spin_lock(&opened_lock);
	list_del(&lp->list);
	spin_unlock(&opened_lock);

L
Linus Torvalds 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
	return 0;
}

static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct uml_net_private *lp = dev->priv;
	unsigned long flags;
	int len;

	netif_stop_queue(dev);

	spin_lock_irqsave(&lp->lock, flags);

	len = (*lp->write)(lp->fd, &skb, lp);

	if(len == skb->len) {
		lp->stats.tx_packets++;
		lp->stats.tx_bytes += skb->len;
		dev->trans_start = jiffies;
		netif_start_queue(dev);

		/* this is normally done in the interrupt when tx finishes */
		netif_wake_queue(dev);
196
	}
L
Linus Torvalds 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
	else if(len == 0){
		netif_start_queue(dev);
		lp->stats.tx_dropped++;
	}
	else {
		netif_start_queue(dev);
		printk(KERN_ERR "uml_net_start_xmit: failed(%d)\n", len);
	}

	spin_unlock_irqrestore(&lp->lock, flags);

	dev_kfree_skb(skb);

	return 0;
}

static struct net_device_stats *uml_net_get_stats(struct net_device *dev)
{
	struct uml_net_private *lp = dev->priv;
	return &lp->stats;
}

static void uml_net_set_multicast_list(struct net_device *dev)
{
	if (dev->flags & IFF_PROMISC) return;
	else if (dev->mc_count)	dev->flags |= IFF_ALLMULTI;
	else dev->flags &= ~IFF_ALLMULTI;
}

static void uml_net_tx_timeout(struct net_device *dev)
{
	dev->trans_start = jiffies;
	netif_wake_queue(dev);
}

static int uml_net_set_mac(struct net_device *dev, void *addr)
{
	struct uml_net_private *lp = dev->priv;
	struct sockaddr *hwaddr = addr;

237
	spin_lock_irq(&lp->lock);
238
	set_ether_mac(dev, hwaddr->sa_data);
239
	spin_unlock_irq(&lp->lock);
L
Linus Torvalds 已提交
240

241
	return 0;
L
Linus Torvalds 已提交
242 243 244 245 246 247 248
}

static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
{
	struct uml_net_private *lp = dev->priv;
	int err = 0;

249
	spin_lock_irq(&lp->lock);
L
Linus Torvalds 已提交
250 251 252 253 254 255 256 257 258 259

	new_mtu = (*lp->set_mtu)(new_mtu, &lp->user);
	if(new_mtu < 0){
		err = new_mtu;
		goto out;
	}

	dev->mtu = new_mtu;

 out:
260
	spin_unlock_irq(&lp->lock);
L
Linus Torvalds 已提交
261 262 263
	return err;
}

264 265
static void uml_net_get_drvinfo(struct net_device *dev,
				struct ethtool_drvinfo *info)
L
Linus Torvalds 已提交
266
{
267 268
	strcpy(info->driver, DRIVER_NAME);
	strcpy(info->version, "42");
L
Linus Torvalds 已提交
269 270
}

271 272 273 274 275
static struct ethtool_ops uml_net_ethtool_ops = {
	.get_drvinfo	= uml_net_get_drvinfo,
	.get_link	= ethtool_op_get_link,
};

L
Linus Torvalds 已提交
276 277 278 279 280 281 282 283 284 285
void uml_net_user_timer_expire(unsigned long _conn)
{
#ifdef undef
	struct connection *conn = (struct connection *)_conn;

	dprintk(KERN_INFO "uml_net_user_timer_expire [%p]\n", conn);
	do_connect(conn);
#endif
}

286
static void setup_etheraddr(char *str, unsigned char *addr, char *name)
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
{
	char *end;
	int i;

	if(str == NULL)
		goto random;

	for(i=0;i<6;i++){
		addr[i] = simple_strtoul(str, &end, 16);
		if((end == str) ||
		   ((*end != ':') && (*end != ',') && (*end != '\0'))){
			printk(KERN_ERR
			       "setup_etheraddr: failed to parse '%s' "
			       "as an ethernet address\n", str);
			goto random;
		}
		str = end + 1;
	}
305
	if (is_multicast_ether_addr(addr)) {
306
		printk(KERN_ERR
307
		       "Attempt to assign a multicast ethernet address to a "
308 309 310
		       "device disallowed\n");
		goto random;
	}
311 312 313 314 315 316 317 318
	if (!is_valid_ether_addr(addr)) {
		printk(KERN_ERR
		       "Attempt to assign an invalid ethernet address to a "
		       "device disallowed\n");
		goto random;
	}
	if (!is_local_ether_addr(addr)) {
		printk(KERN_WARNING
J
Jeff Dike 已提交
319 320 321 322 323 324 325 326
		       "Warning: attempt to assign a globally valid ethernet "
		       "address to a device\n");
		printk(KERN_WARNING "You should better enable the 2nd "
		       "rightmost bit in the first byte of the MAC,\n");
		printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n",
		       addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
		       addr[5]);
		goto random;
327
	}
328 329 330
	return;

random:
331 332
	printk(KERN_INFO
	       "Choosing a random ethernet address for device %s\n", name);
O
Ollie Wild 已提交
333
	random_ether_addr(addr);
334 335
}

L
Linus Torvalds 已提交
336
static DEFINE_SPINLOCK(devices_lock);
337
static LIST_HEAD(devices);
L
Linus Torvalds 已提交
338

339 340 341 342
static struct platform_driver uml_net_driver = {
	.driver = {
		.name  = DRIVER_NAME,
	},
L
Linus Torvalds 已提交
343 344 345
};
static int driver_registered;

J
Jeff Dike 已提交
346 347 348 349 350 351 352 353 354 355 356 357 358
static void net_device_release(struct device *dev)
{
	struct uml_net *device = dev->driver_data;
	struct net_device *netdev = device->dev;
	struct uml_net_private *lp = netdev->priv;

	if(lp->remove != NULL)
		(*lp->remove)(&lp->user);
	list_del(&device->list);
	kfree(device);
	free_netdev(netdev);
}

359 360
static void eth_configure(int n, void *init, char *mac,
			  struct transport *transport)
L
Linus Torvalds 已提交
361 362 363 364
{
	struct uml_net *device;
	struct net_device *dev;
	struct uml_net_private *lp;
365
	int err, size;
L
Linus Torvalds 已提交
366

367
	size = transport->private_size + sizeof(struct uml_net_private);
L
Linus Torvalds 已提交
368

369
	device = kzalloc(sizeof(*device), GFP_KERNEL);
L
Linus Torvalds 已提交
370
	if (device == NULL) {
371 372
		printk(KERN_ERR "eth_configure failed to allocate struct "
		       "uml_net\n");
373
		return;
L
Linus Torvalds 已提交
374 375
	}

376 377 378 379 380 381 382
	dev = alloc_etherdev(size);
	if (dev == NULL) {
		printk(KERN_ERR "eth_configure: failed to allocate struct "
		       "net_device for eth%d\n", n);
		goto out_free_device;
	}

L
Linus Torvalds 已提交
383 384 385
	INIT_LIST_HEAD(&device->list);
	device->index = n;

386 387 388 389
	/* If this name ends up conflicting with an existing registered
	 * netdevice, that is OK, register_netdev{,ice}() will notice this
	 * and fail.
	 */
390
	snprintf(dev->name, sizeof(dev->name), "eth%d", n);
391

392
	setup_etheraddr(mac, device->mac, dev->name);
L
Linus Torvalds 已提交
393 394

	printk(KERN_INFO "Netdevice %d ", n);
395 396 397 398
	printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
	       device->mac[0], device->mac[1],
	       device->mac[2], device->mac[3],
	       device->mac[4], device->mac[5]);
L
Linus Torvalds 已提交
399 400
	printk(": ");

401 402 403 404
	lp = dev->priv;
	/* This points to the transport private data. It's still clear, but we
	 * must memset it to 0 *now*. Let's help the drivers. */
	memset(lp, 0, size);
405
	INIT_WORK(&lp->work, uml_dev_close);
406

L
Linus Torvalds 已提交
407 408
	/* sysfs register */
	if (!driver_registered) {
409
		platform_driver_register(&uml_net_driver);
L
Linus Torvalds 已提交
410 411 412 413
		driver_registered = 1;
	}
	device->pdev.id = n;
	device->pdev.name = DRIVER_NAME;
J
Jeff Dike 已提交
414 415
	device->pdev.dev.release = net_device_release;
	device->pdev.dev.driver_data = device;
416 417
	if(platform_device_register(&device->pdev))
		goto out_free_netdev;
L
Linus Torvalds 已提交
418 419 420 421
	SET_NETDEV_DEV(dev,&device->pdev.dev);

	device->dev = dev;

422 423 424 425
	/*
	 * These just fill in a data structure, so there's no failure
	 * to be worried about.
	 */
L
Linus Torvalds 已提交
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
	(*transport->kern->init)(dev, init);

	*lp = ((struct uml_net_private)
		{ .list  		= LIST_HEAD_INIT(lp->list),
		  .dev 			= dev,
		  .fd 			= -1,
		  .mac 			= { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
		  .protocol 		= transport->kern->protocol,
		  .open 		= transport->user->open,
		  .close 		= transport->user->close,
		  .remove 		= transport->user->remove,
		  .read 		= transport->kern->read,
		  .write 		= transport->kern->write,
		  .add_address 		= transport->user->add_address,
		  .delete_address  	= transport->user->delete_address,
441
		  .set_mtu 		= transport->user->set_mtu });
L
Linus Torvalds 已提交
442 443 444 445

	init_timer(&lp->tl);
	spin_lock_init(&lp->lock);
	lp->tl.function = uml_net_user_timer_expire;
446
	memcpy(lp->mac, device->mac, sizeof(lp->mac));
L
Linus Torvalds 已提交
447

448 449 450
	if ((transport->user->init != NULL) &&
	    ((*transport->user->init)(&lp->user, dev) != 0))
		goto out_unregister;
L
Linus Torvalds 已提交
451

452
	set_ether_mac(dev, device->mac);
453 454 455 456 457 458 459 460 461 462 463 464
	dev->mtu = transport->user->max_packet;
	dev->open = uml_net_open;
	dev->hard_start_xmit = uml_net_start_xmit;
	dev->stop = uml_net_close;
	dev->get_stats = uml_net_get_stats;
	dev->set_multicast_list = uml_net_set_multicast_list;
	dev->tx_timeout = uml_net_tx_timeout;
	dev->set_mac_address = uml_net_set_mac;
	dev->change_mtu = uml_net_change_mtu;
	dev->ethtool_ops = &uml_net_ethtool_ops;
	dev->watchdog_timeo = (HZ >> 1);
	dev->irq = UM_ETH_IRQ;
L
Linus Torvalds 已提交
465

466 467 468 469 470 471 472 473 474 475 476 477 478
	rtnl_lock();
	err = register_netdevice(dev);
	rtnl_unlock();
	if (err)
		goto out_undo_user_init;

	spin_lock(&devices_lock);
	list_add(&device->list, &devices);
	spin_unlock(&devices_lock);

	return;

out_undo_user_init:
479
	if (transport->user->remove != NULL)
480 481 482
		(*transport->user->remove)(&lp->user);
out_unregister:
	platform_device_unregister(&device->pdev);
J
Jeff Dike 已提交
483
	return; /* platform_device_unregister frees dev and device */
484 485
out_free_netdev:
	free_netdev(dev);
486
out_free_device:
487
	kfree(device);
L
Linus Torvalds 已提交
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
}

static struct uml_net *find_device(int n)
{
	struct uml_net *device;
	struct list_head *ele;

	spin_lock(&devices_lock);
	list_for_each(ele, &devices){
		device = list_entry(ele, struct uml_net, list);
		if(device->index == n)
			goto out;
	}
	device = NULL;
 out:
	spin_unlock(&devices_lock);
504
	return device;
L
Linus Torvalds 已提交
505 506
}

507 508
static int eth_parse(char *str, int *index_out, char **str_out,
		     char **error_out)
L
Linus Torvalds 已提交
509 510
{
	char *end;
511
	int n, err = -EINVAL;;
L
Linus Torvalds 已提交
512 513 514

	n = simple_strtoul(str, &end, 0);
	if(end == str){
515 516
		*error_out = "Bad device number";
		return err;
L
Linus Torvalds 已提交
517
	}
518

L
Linus Torvalds 已提交
519 520
	str = end;
	if(*str != '='){
521 522
		*error_out = "Expected '=' after device number";
		return err;
L
Linus Torvalds 已提交
523
	}
524

L
Linus Torvalds 已提交
525 526
	str++;
	if(find_device(n)){
527 528
		*error_out = "Device already configured";
		return err;
L
Linus Torvalds 已提交
529
	}
530 531

	*index_out = n;
L
Linus Torvalds 已提交
532
	*str_out = str;
533
	return 0;
L
Linus Torvalds 已提交
534 535 536 537 538 539 540 541
}

struct eth_init {
	struct list_head list;
	char *init;
	int index;
};

542 543
static DEFINE_SPINLOCK(transports_lock);
static LIST_HEAD(transports);
L
Linus Torvalds 已提交
544 545

/* Filled in during early boot */
546
static LIST_HEAD(eth_cmd_line);
L
Linus Torvalds 已提交
547 548 549 550 551 552 553 554

static int check_transport(struct transport *transport, char *eth, int n,
			   void **init_out, char **mac_out)
{
	int len;

	len = strlen(transport->name);
	if(strncmp(eth, transport->name, len))
555
		return 0;
L
Linus Torvalds 已提交
556 557 558 559 560

	eth += len;
	if(*eth == ',')
		eth++;
	else if(*eth != '\0')
561
		return 0;
L
Linus Torvalds 已提交
562 563 564

	*init_out = kmalloc(transport->setup_size, GFP_KERNEL);
	if(*init_out == NULL)
565
		return 1;
L
Linus Torvalds 已提交
566 567 568 569 570

	if(!transport->setup(eth, mac_out, *init_out)){
		kfree(*init_out);
		*init_out = NULL;
	}
571
	return 1;
L
Linus Torvalds 已提交
572 573 574 575 576 577 578 579 580 581
}

void register_transport(struct transport *new)
{
	struct list_head *ele, *next;
	struct eth_init *eth;
	void *init;
	char *mac = NULL;
	int match;

582 583
	spin_lock(&transports_lock);
	BUG_ON(!list_empty(&new->list));
L
Linus Torvalds 已提交
584
	list_add(&new->list, &transports);
585
	spin_unlock(&transports_lock);
L
Linus Torvalds 已提交
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606

	list_for_each_safe(ele, next, &eth_cmd_line){
		eth = list_entry(ele, struct eth_init, list);
		match = check_transport(new, eth->init, eth->index, &init,
					&mac);
		if(!match)
			continue;
		else if(init != NULL){
			eth_configure(eth->index, init, mac, new);
			kfree(init);
		}
		list_del(&eth->list);
	}
}

static int eth_setup_common(char *str, int index)
{
	struct list_head *ele;
	struct transport *transport;
	void *init;
	char *mac = NULL;
607
	int found = 0;
L
Linus Torvalds 已提交
608

609
	spin_lock(&transports_lock);
L
Linus Torvalds 已提交
610 611 612 613 614 615 616 617
	list_for_each(ele, &transports){
		transport = list_entry(ele, struct transport, list);
	        if(!check_transport(transport, str, index, &init, &mac))
			continue;
		if(init != NULL){
			eth_configure(index, init, mac, transport);
			kfree(init);
		}
618 619
		found = 1;
		break;
L
Linus Torvalds 已提交
620
	}
621 622 623

	spin_unlock(&transports_lock);
	return found;
L
Linus Torvalds 已提交
624 625
}

J
Jeff Dike 已提交
626
static int __init eth_setup(char *str)
L
Linus Torvalds 已提交
627 628
{
	struct eth_init *new;
629
	char *error;
L
Linus Torvalds 已提交
630 631
	int n, err;

632 633 634 635
	err = eth_parse(str, &n, &str, &error);
	if(err){
		printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n",
		       str, error);
J
Jeff Dike 已提交
636
		return 1;
637
	}
L
Linus Torvalds 已提交
638

J
Jeff Dike 已提交
639
	new = alloc_bootmem(sizeof(*new));
L
Linus Torvalds 已提交
640 641
	if (new == NULL){
		printk("eth_init : alloc_bootmem failed\n");
J
Jeff Dike 已提交
642
		return 1;
L
Linus Torvalds 已提交
643 644 645 646 647 648 649
	}

	INIT_LIST_HEAD(&new->list);
	new->index = n;
	new->init = str;

	list_add_tail(&new->list, &eth_cmd_line);
J
Jeff Dike 已提交
650
	return 1;
L
Linus Torvalds 已提交
651 652 653 654 655 656 657 658
}

__setup("eth", eth_setup);
__uml_help(eth_setup,
"eth[0-9]+=<transport>,<options>\n"
"    Configure a network device.\n\n"
);

659
static int net_config(char *str, char **error_out)
L
Linus Torvalds 已提交
660 661 662
{
	int n, err;

663 664 665
	err = eth_parse(str, &n, &str, error_out);
	if(err)
		return err;
L
Linus Torvalds 已提交
666

667 668 669
	/* This string is broken up and the pieces used by the underlying
	 * driver.  So, it is freed only if eth_setup_common fails.
	 */
J
Jeff Dike 已提交
670
	str = kstrdup(str, GFP_KERNEL);
L
Linus Torvalds 已提交
671
	if(str == NULL){
672 673
	        *error_out = "net_config failed to strdup string";
		return -ENOMEM;
L
Linus Torvalds 已提交
674 675
	}
	err = !eth_setup_common(str, n);
676
	if(err)
L
Linus Torvalds 已提交
677 678 679 680
		kfree(str);
	return(err);
}

J
Jeff Dike 已提交
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
static int net_id(char **str, int *start_out, int *end_out)
{
        char *end;
        int n;

	n = simple_strtoul(*str, &end, 0);
	if((*end != '\0') || (end == *str))
		return -1;

        *start_out = n;
        *end_out = n;
        *str = end;
        return n;
}

696
static int net_remove(int n, char **error_out)
L
Linus Torvalds 已提交
697 698 699 700 701 702 703
{
	struct uml_net *device;
	struct net_device *dev;
	struct uml_net_private *lp;

	device = find_device(n);
	if(device == NULL)
J
Jeff Dike 已提交
704
		return -ENODEV;
L
Linus Torvalds 已提交
705 706 707

	dev = device->dev;
	lp = dev->priv;
J
Jeff Dike 已提交
708
	if(lp->fd > 0)
709
		return -EBUSY;
L
Linus Torvalds 已提交
710 711 712
	unregister_netdev(dev);
	platform_device_unregister(&device->pdev);

J
Jeff Dike 已提交
713
	return 0;
L
Linus Torvalds 已提交
714 715 716
}

static struct mc_device net_mc = {
J
Jeff Dike 已提交
717
	.list		= LIST_HEAD_INIT(net_mc.list),
L
Linus Torvalds 已提交
718 719 720
	.name		= "eth",
	.config		= net_config,
	.get_config	= NULL,
721
	.id		= net_id,
L
Linus Torvalds 已提交
722 723 724 725 726 727 728 729 730 731 732 733
	.remove		= net_remove,
};

static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
			      void *ptr)
{
	struct in_ifaddr *ifa = ptr;
	struct net_device *dev = ifa->ifa_dev->dev;
	struct uml_net_private *lp;
	void (*proc)(unsigned char *, unsigned char *, void *);
	unsigned char addr_buf[4], netmask_buf[4];

734 735
	if(dev->open != uml_net_open)
		return NOTIFY_DONE;
L
Linus Torvalds 已提交
736 737 738 739 740 741 742 743 744 745 746 747 748

	lp = dev->priv;

	proc = NULL;
	switch (event){
	case NETDEV_UP:
		proc = lp->add_address;
		break;
	case NETDEV_DOWN:
		proc = lp->delete_address;
		break;
	}
	if(proc != NULL){
749 750
		memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf));
		memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf));
L
Linus Torvalds 已提交
751 752
		(*proc)(addr_buf, netmask_buf, &lp->user);
	}
753
	return NOTIFY_DONE;
L
Linus Torvalds 已提交
754 755
}

756
/* uml_net_init shouldn't be called twice on two CPUs at the same time */
L
Linus Torvalds 已提交
757 758 759 760 761 762 763
struct notifier_block uml_inetaddr_notifier = {
	.notifier_call		= uml_inetaddr_event,
};

static int uml_net_init(void)
{
	struct list_head *ele;
764
	struct uml_net_private *lp;
L
Linus Torvalds 已提交
765 766 767 768 769 770 771 772 773 774
	struct in_device *ip;
	struct in_ifaddr *in;

	mconsole_register_dev(&net_mc);
	register_inetaddr_notifier(&uml_inetaddr_notifier);

	/* Devices may have been opened already, so the uml_inetaddr_notifier
	 * didn't get a chance to run for them.  This fakes it so that
	 * addresses which have already been set up get handled properly.
	 */
775
	spin_lock(&opened_lock);
L
Linus Torvalds 已提交
776 777 778
	list_for_each(ele, &opened){
		lp = list_entry(ele, struct uml_net_private, list);
		ip = lp->dev->ip_ptr;
779 780
		if(ip == NULL)
			continue;
L
Linus Torvalds 已提交
781 782 783 784 785
		in = ip->ifa_list;
		while(in != NULL){
			uml_inetaddr_event(NULL, NETDEV_UP, in);
			in = in->ifa_next;
		}
786
	}
787
	spin_unlock(&opened_lock);
L
Linus Torvalds 已提交
788

789
	return 0;
L
Linus Torvalds 已提交
790 791 792 793 794 795 796 797 798
}

__initcall(uml_net_init);

static void close_devices(void)
{
	struct list_head *ele;
	struct uml_net_private *lp;

799
	spin_lock(&opened_lock);
L
Linus Torvalds 已提交
800 801
	list_for_each(ele, &opened){
		lp = list_entry(ele, struct uml_net_private, list);
802
		free_irq(lp->dev->irq, lp->dev);
L
Linus Torvalds 已提交
803 804
		if((lp->close != NULL) && (lp->fd >= 0))
			(*lp->close)(lp->fd, &lp->user);
805 806
		if(lp->remove != NULL)
			(*lp->remove)(&lp->user);
L
Linus Torvalds 已提交
807
	}
808
	spin_unlock(&opened_lock);
L
Linus Torvalds 已提交
809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
}

__uml_exitcall(close_devices);

struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
{
	if((skb != NULL) && (skb_tailroom(skb) < extra)){
	  	struct sk_buff *skb2;

		skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);
		dev_kfree_skb(skb);
		skb = skb2;
	}
	if(skb != NULL) skb_put(skb, extra);
	return(skb);
}

826 827
void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
					void *),
L
Linus Torvalds 已提交
828 829 830 831 832 833 834 835 836 837
		    void *arg)
{
	struct net_device *dev = d;
	struct in_device *ip = dev->ip_ptr;
	struct in_ifaddr *in;
	unsigned char address[4], netmask[4];

	if(ip == NULL) return;
	in = ip->ifa_list;
	while(in != NULL){
838 839
		memcpy(address, &in->ifa_address, sizeof(address));
		memcpy(netmask, &in->ifa_mask, sizeof(netmask));
L
Linus Torvalds 已提交
840 841 842 843 844 845 846 847 848 849
		(*cb)(address, netmask, arg);
		in = in->ifa_next;
	}
}

int dev_netmask(void *d, void *m)
{
	struct net_device *dev = d;
	struct in_device *ip = dev->ip_ptr;
	struct in_ifaddr *in;
A
Al Viro 已提交
850
	__be32 *mask_out = m;
L
Linus Torvalds 已提交
851

852
	if(ip == NULL)
L
Linus Torvalds 已提交
853 854 855
		return(1);

	in = ip->ifa_list;
856
	if(in == NULL)
L
Linus Torvalds 已提交
857 858 859 860 861 862 863 864 865 866 867 868 869
		return(1);

	*mask_out = in->ifa_mask;
	return(0);
}

void *get_output_buffer(int *len_out)
{
	void *ret;

	ret = (void *) __get_free_pages(GFP_KERNEL, 0);
	if(ret) *len_out = PAGE_SIZE;
	else *len_out = 0;
870
	return ret;
L
Linus Torvalds 已提交
871 872 873 874 875 876 877
}

void free_output_buffer(void *buffer)
{
	free_pages((unsigned long) buffer, 0);
}

878
int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out,
L
Linus Torvalds 已提交
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
		     char **gate_addr)
{
	char *remain;

	remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL);
	if(remain != NULL){
		printk("tap_setup_common - Extra garbage on specification : "
		       "'%s'\n", remain);
		return(1);
	}

	return(0);
}

unsigned short eth_protocol(struct sk_buff *skb)
{
	return(eth_type_trans(skb, skb->dev));
}