xref: /linux/net/rose/rose_dev.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
3*1da177e4SLinus Torvalds  * it under the terms of the GNU General Public License as published by
4*1da177e4SLinus Torvalds  * the Free Software Foundation; either version 2 of the License, or
5*1da177e4SLinus Torvalds  * (at your option) any later version.
6*1da177e4SLinus Torvalds  *
7*1da177e4SLinus Torvalds  * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8*1da177e4SLinus Torvalds  */
9*1da177e4SLinus Torvalds #include <linux/config.h>
10*1da177e4SLinus Torvalds #include <linux/module.h>
11*1da177e4SLinus Torvalds #include <linux/proc_fs.h>
12*1da177e4SLinus Torvalds #include <linux/kernel.h>
13*1da177e4SLinus Torvalds #include <linux/sched.h>
14*1da177e4SLinus Torvalds #include <linux/interrupt.h>
15*1da177e4SLinus Torvalds #include <linux/fs.h>
16*1da177e4SLinus Torvalds #include <linux/types.h>
17*1da177e4SLinus Torvalds #include <linux/sysctl.h>
18*1da177e4SLinus Torvalds #include <linux/string.h>
19*1da177e4SLinus Torvalds #include <linux/socket.h>
20*1da177e4SLinus Torvalds #include <linux/errno.h>
21*1da177e4SLinus Torvalds #include <linux/fcntl.h>
22*1da177e4SLinus Torvalds #include <linux/in.h>
23*1da177e4SLinus Torvalds #include <linux/if_ether.h>
24*1da177e4SLinus Torvalds 
25*1da177e4SLinus Torvalds #include <asm/system.h>
26*1da177e4SLinus Torvalds #include <asm/io.h>
27*1da177e4SLinus Torvalds 
28*1da177e4SLinus Torvalds #include <linux/inet.h>
29*1da177e4SLinus Torvalds #include <linux/netdevice.h>
30*1da177e4SLinus Torvalds #include <linux/etherdevice.h>
31*1da177e4SLinus Torvalds #include <linux/if_arp.h>
32*1da177e4SLinus Torvalds #include <linux/skbuff.h>
33*1da177e4SLinus Torvalds 
34*1da177e4SLinus Torvalds #include <net/ip.h>
35*1da177e4SLinus Torvalds #include <net/arp.h>
36*1da177e4SLinus Torvalds 
37*1da177e4SLinus Torvalds #include <net/ax25.h>
38*1da177e4SLinus Torvalds #include <net/rose.h>
39*1da177e4SLinus Torvalds 
40*1da177e4SLinus Torvalds static int rose_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
41*1da177e4SLinus Torvalds 	void *daddr, void *saddr, unsigned len)
42*1da177e4SLinus Torvalds {
43*1da177e4SLinus Torvalds 	unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2);
44*1da177e4SLinus Torvalds 
45*1da177e4SLinus Torvalds 	*buff++ = ROSE_GFI | ROSE_Q_BIT;
46*1da177e4SLinus Torvalds 	*buff++ = 0x00;
47*1da177e4SLinus Torvalds 	*buff++ = ROSE_DATA;
48*1da177e4SLinus Torvalds 	*buff++ = 0x7F;
49*1da177e4SLinus Torvalds 	*buff++ = AX25_P_IP;
50*1da177e4SLinus Torvalds 
51*1da177e4SLinus Torvalds 	if (daddr != NULL)
52*1da177e4SLinus Torvalds 		return 37;
53*1da177e4SLinus Torvalds 
54*1da177e4SLinus Torvalds 	return -37;
55*1da177e4SLinus Torvalds }
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds static int rose_rebuild_header(struct sk_buff *skb)
58*1da177e4SLinus Torvalds {
59*1da177e4SLinus Torvalds 	struct net_device *dev = skb->dev;
60*1da177e4SLinus Torvalds 	struct net_device_stats *stats = netdev_priv(dev);
61*1da177e4SLinus Torvalds 	unsigned char *bp = (unsigned char *)skb->data;
62*1da177e4SLinus Torvalds 	struct sk_buff *skbn;
63*1da177e4SLinus Torvalds 
64*1da177e4SLinus Torvalds #ifdef CONFIG_INET
65*1da177e4SLinus Torvalds 	if (arp_find(bp + 7, skb)) {
66*1da177e4SLinus Torvalds 		return 1;
67*1da177e4SLinus Torvalds 	}
68*1da177e4SLinus Torvalds 
69*1da177e4SLinus Torvalds 	if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
70*1da177e4SLinus Torvalds 		kfree_skb(skb);
71*1da177e4SLinus Torvalds 		return 1;
72*1da177e4SLinus Torvalds 	}
73*1da177e4SLinus Torvalds 
74*1da177e4SLinus Torvalds 	if (skb->sk != NULL)
75*1da177e4SLinus Torvalds 		skb_set_owner_w(skbn, skb->sk);
76*1da177e4SLinus Torvalds 
77*1da177e4SLinus Torvalds 	kfree_skb(skb);
78*1da177e4SLinus Torvalds 
79*1da177e4SLinus Torvalds 	if (!rose_route_frame(skbn, NULL)) {
80*1da177e4SLinus Torvalds 		kfree_skb(skbn);
81*1da177e4SLinus Torvalds 		stats->tx_errors++;
82*1da177e4SLinus Torvalds 		return 1;
83*1da177e4SLinus Torvalds 	}
84*1da177e4SLinus Torvalds 
85*1da177e4SLinus Torvalds 	stats->tx_packets++;
86*1da177e4SLinus Torvalds 	stats->tx_bytes += skbn->len;
87*1da177e4SLinus Torvalds #endif
88*1da177e4SLinus Torvalds 	return 1;
89*1da177e4SLinus Torvalds }
90*1da177e4SLinus Torvalds 
91*1da177e4SLinus Torvalds static int rose_set_mac_address(struct net_device *dev, void *addr)
92*1da177e4SLinus Torvalds {
93*1da177e4SLinus Torvalds 	struct sockaddr *sa = addr;
94*1da177e4SLinus Torvalds 
95*1da177e4SLinus Torvalds 	rose_del_loopback_node((rose_address *)dev->dev_addr);
96*1da177e4SLinus Torvalds 
97*1da177e4SLinus Torvalds 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
98*1da177e4SLinus Torvalds 
99*1da177e4SLinus Torvalds 	rose_add_loopback_node((rose_address *)dev->dev_addr);
100*1da177e4SLinus Torvalds 
101*1da177e4SLinus Torvalds 	return 0;
102*1da177e4SLinus Torvalds }
103*1da177e4SLinus Torvalds 
104*1da177e4SLinus Torvalds static int rose_open(struct net_device *dev)
105*1da177e4SLinus Torvalds {
106*1da177e4SLinus Torvalds 	netif_start_queue(dev);
107*1da177e4SLinus Torvalds 	rose_add_loopback_node((rose_address *)dev->dev_addr);
108*1da177e4SLinus Torvalds 	return 0;
109*1da177e4SLinus Torvalds }
110*1da177e4SLinus Torvalds 
111*1da177e4SLinus Torvalds static int rose_close(struct net_device *dev)
112*1da177e4SLinus Torvalds {
113*1da177e4SLinus Torvalds 	netif_stop_queue(dev);
114*1da177e4SLinus Torvalds 	rose_del_loopback_node((rose_address *)dev->dev_addr);
115*1da177e4SLinus Torvalds 	return 0;
116*1da177e4SLinus Torvalds }
117*1da177e4SLinus Torvalds 
118*1da177e4SLinus Torvalds static int rose_xmit(struct sk_buff *skb, struct net_device *dev)
119*1da177e4SLinus Torvalds {
120*1da177e4SLinus Torvalds 	struct net_device_stats *stats = netdev_priv(dev);
121*1da177e4SLinus Torvalds 
122*1da177e4SLinus Torvalds 	if (!netif_running(dev)) {
123*1da177e4SLinus Torvalds 		printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
124*1da177e4SLinus Torvalds 		return 1;
125*1da177e4SLinus Torvalds 	}
126*1da177e4SLinus Torvalds 	dev_kfree_skb(skb);
127*1da177e4SLinus Torvalds 	stats->tx_errors++;
128*1da177e4SLinus Torvalds 	return 0;
129*1da177e4SLinus Torvalds }
130*1da177e4SLinus Torvalds 
131*1da177e4SLinus Torvalds static struct net_device_stats *rose_get_stats(struct net_device *dev)
132*1da177e4SLinus Torvalds {
133*1da177e4SLinus Torvalds 	return netdev_priv(dev);
134*1da177e4SLinus Torvalds }
135*1da177e4SLinus Torvalds 
136*1da177e4SLinus Torvalds void rose_setup(struct net_device *dev)
137*1da177e4SLinus Torvalds {
138*1da177e4SLinus Torvalds 	SET_MODULE_OWNER(dev);
139*1da177e4SLinus Torvalds 	dev->mtu		= ROSE_MAX_PACKET_SIZE - 2;
140*1da177e4SLinus Torvalds 	dev->hard_start_xmit	= rose_xmit;
141*1da177e4SLinus Torvalds 	dev->open		= rose_open;
142*1da177e4SLinus Torvalds 	dev->stop		= rose_close;
143*1da177e4SLinus Torvalds 
144*1da177e4SLinus Torvalds 	dev->hard_header	= rose_header;
145*1da177e4SLinus Torvalds 	dev->hard_header_len	= AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN;
146*1da177e4SLinus Torvalds 	dev->addr_len		= ROSE_ADDR_LEN;
147*1da177e4SLinus Torvalds 	dev->type		= ARPHRD_ROSE;
148*1da177e4SLinus Torvalds 	dev->rebuild_header	= rose_rebuild_header;
149*1da177e4SLinus Torvalds 	dev->set_mac_address    = rose_set_mac_address;
150*1da177e4SLinus Torvalds 
151*1da177e4SLinus Torvalds 	/* New-style flags. */
152*1da177e4SLinus Torvalds 	dev->flags		= 0;
153*1da177e4SLinus Torvalds 	dev->get_stats = rose_get_stats;
154*1da177e4SLinus Torvalds }
155