xref: /openbmc/linux/net/netrom/nr_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 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>	/* For the statistics structure. */
24*1da177e4SLinus Torvalds 
25*1da177e4SLinus Torvalds #include <asm/system.h>
26*1da177e4SLinus Torvalds #include <asm/uaccess.h>
27*1da177e4SLinus Torvalds #include <asm/io.h>
28*1da177e4SLinus Torvalds 
29*1da177e4SLinus Torvalds #include <linux/inet.h>
30*1da177e4SLinus Torvalds #include <linux/netdevice.h>
31*1da177e4SLinus Torvalds #include <linux/etherdevice.h>
32*1da177e4SLinus Torvalds #include <linux/if_arp.h>
33*1da177e4SLinus Torvalds #include <linux/skbuff.h>
34*1da177e4SLinus Torvalds 
35*1da177e4SLinus Torvalds #include <net/ip.h>
36*1da177e4SLinus Torvalds #include <net/arp.h>
37*1da177e4SLinus Torvalds 
38*1da177e4SLinus Torvalds #include <net/ax25.h>
39*1da177e4SLinus Torvalds #include <net/netrom.h>
40*1da177e4SLinus Torvalds 
41*1da177e4SLinus Torvalds #ifdef CONFIG_INET
42*1da177e4SLinus Torvalds 
43*1da177e4SLinus Torvalds /*
44*1da177e4SLinus Torvalds  *	Only allow IP over NET/ROM frames through if the netrom device is up.
45*1da177e4SLinus Torvalds  */
46*1da177e4SLinus Torvalds 
47*1da177e4SLinus Torvalds int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
48*1da177e4SLinus Torvalds {
49*1da177e4SLinus Torvalds 	struct net_device_stats *stats = netdev_priv(dev);
50*1da177e4SLinus Torvalds 
51*1da177e4SLinus Torvalds 	if (!netif_running(dev)) {
52*1da177e4SLinus Torvalds 		stats->rx_errors++;
53*1da177e4SLinus Torvalds 		return 0;
54*1da177e4SLinus Torvalds 	}
55*1da177e4SLinus Torvalds 
56*1da177e4SLinus Torvalds 	stats->rx_packets++;
57*1da177e4SLinus Torvalds 	stats->rx_bytes += skb->len;
58*1da177e4SLinus Torvalds 
59*1da177e4SLinus Torvalds 	skb->protocol = htons(ETH_P_IP);
60*1da177e4SLinus Torvalds 
61*1da177e4SLinus Torvalds 	/* Spoof incoming device */
62*1da177e4SLinus Torvalds 	skb->dev      = dev;
63*1da177e4SLinus Torvalds 	skb->h.raw    = skb->data;
64*1da177e4SLinus Torvalds 	skb->nh.raw   = skb->data;
65*1da177e4SLinus Torvalds 	skb->pkt_type = PACKET_HOST;
66*1da177e4SLinus Torvalds 
67*1da177e4SLinus Torvalds 	ip_rcv(skb, skb->dev, NULL);
68*1da177e4SLinus Torvalds 
69*1da177e4SLinus Torvalds 	return 1;
70*1da177e4SLinus Torvalds }
71*1da177e4SLinus Torvalds 
72*1da177e4SLinus Torvalds 
73*1da177e4SLinus Torvalds static int nr_rebuild_header(struct sk_buff *skb)
74*1da177e4SLinus Torvalds {
75*1da177e4SLinus Torvalds 	struct net_device *dev = skb->dev;
76*1da177e4SLinus Torvalds 	struct net_device_stats *stats = netdev_priv(dev);
77*1da177e4SLinus Torvalds 	struct sk_buff *skbn;
78*1da177e4SLinus Torvalds 	unsigned char *bp = skb->data;
79*1da177e4SLinus Torvalds 	int len;
80*1da177e4SLinus Torvalds 
81*1da177e4SLinus Torvalds 	if (arp_find(bp + 7, skb)) {
82*1da177e4SLinus Torvalds 		return 1;
83*1da177e4SLinus Torvalds 	}
84*1da177e4SLinus Torvalds 
85*1da177e4SLinus Torvalds 	bp[6] &= ~AX25_CBIT;
86*1da177e4SLinus Torvalds 	bp[6] &= ~AX25_EBIT;
87*1da177e4SLinus Torvalds 	bp[6] |= AX25_SSSID_SPARE;
88*1da177e4SLinus Torvalds 	bp    += AX25_ADDR_LEN;
89*1da177e4SLinus Torvalds 
90*1da177e4SLinus Torvalds 	bp[6] &= ~AX25_CBIT;
91*1da177e4SLinus Torvalds 	bp[6] |= AX25_EBIT;
92*1da177e4SLinus Torvalds 	bp[6] |= AX25_SSSID_SPARE;
93*1da177e4SLinus Torvalds 
94*1da177e4SLinus Torvalds 	if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
95*1da177e4SLinus Torvalds 		kfree_skb(skb);
96*1da177e4SLinus Torvalds 		return 1;
97*1da177e4SLinus Torvalds 	}
98*1da177e4SLinus Torvalds 
99*1da177e4SLinus Torvalds 	if (skb->sk != NULL)
100*1da177e4SLinus Torvalds 		skb_set_owner_w(skbn, skb->sk);
101*1da177e4SLinus Torvalds 
102*1da177e4SLinus Torvalds 	kfree_skb(skb);
103*1da177e4SLinus Torvalds 
104*1da177e4SLinus Torvalds 	len = skbn->len;
105*1da177e4SLinus Torvalds 
106*1da177e4SLinus Torvalds 	if (!nr_route_frame(skbn, NULL)) {
107*1da177e4SLinus Torvalds 		kfree_skb(skbn);
108*1da177e4SLinus Torvalds 		stats->tx_errors++;
109*1da177e4SLinus Torvalds 	}
110*1da177e4SLinus Torvalds 
111*1da177e4SLinus Torvalds 	stats->tx_packets++;
112*1da177e4SLinus Torvalds 	stats->tx_bytes += len;
113*1da177e4SLinus Torvalds 
114*1da177e4SLinus Torvalds 	return 1;
115*1da177e4SLinus Torvalds }
116*1da177e4SLinus Torvalds 
117*1da177e4SLinus Torvalds #else
118*1da177e4SLinus Torvalds 
119*1da177e4SLinus Torvalds static int nr_rebuild_header(struct sk_buff *skb)
120*1da177e4SLinus Torvalds {
121*1da177e4SLinus Torvalds 	return 1;
122*1da177e4SLinus Torvalds }
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds #endif
125*1da177e4SLinus Torvalds 
126*1da177e4SLinus Torvalds static int nr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
127*1da177e4SLinus Torvalds 	void *daddr, void *saddr, unsigned len)
128*1da177e4SLinus Torvalds {
129*1da177e4SLinus Torvalds 	unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
130*1da177e4SLinus Torvalds 
131*1da177e4SLinus Torvalds 	memcpy(buff, (saddr != NULL) ? saddr : dev->dev_addr, dev->addr_len);
132*1da177e4SLinus Torvalds 	buff[6] &= ~AX25_CBIT;
133*1da177e4SLinus Torvalds 	buff[6] &= ~AX25_EBIT;
134*1da177e4SLinus Torvalds 	buff[6] |= AX25_SSSID_SPARE;
135*1da177e4SLinus Torvalds 	buff    += AX25_ADDR_LEN;
136*1da177e4SLinus Torvalds 
137*1da177e4SLinus Torvalds 	if (daddr != NULL)
138*1da177e4SLinus Torvalds 		memcpy(buff, daddr, dev->addr_len);
139*1da177e4SLinus Torvalds 	buff[6] &= ~AX25_CBIT;
140*1da177e4SLinus Torvalds 	buff[6] |= AX25_EBIT;
141*1da177e4SLinus Torvalds 	buff[6] |= AX25_SSSID_SPARE;
142*1da177e4SLinus Torvalds 	buff    += AX25_ADDR_LEN;
143*1da177e4SLinus Torvalds 
144*1da177e4SLinus Torvalds 	*buff++ = sysctl_netrom_network_ttl_initialiser;
145*1da177e4SLinus Torvalds 
146*1da177e4SLinus Torvalds 	*buff++ = NR_PROTO_IP;
147*1da177e4SLinus Torvalds 	*buff++ = NR_PROTO_IP;
148*1da177e4SLinus Torvalds 	*buff++ = 0;
149*1da177e4SLinus Torvalds 	*buff++ = 0;
150*1da177e4SLinus Torvalds 	*buff++ = NR_PROTOEXT;
151*1da177e4SLinus Torvalds 
152*1da177e4SLinus Torvalds 	if (daddr != NULL)
153*1da177e4SLinus Torvalds 		return 37;
154*1da177e4SLinus Torvalds 
155*1da177e4SLinus Torvalds 	return -37;
156*1da177e4SLinus Torvalds }
157*1da177e4SLinus Torvalds 
158*1da177e4SLinus Torvalds static int nr_set_mac_address(struct net_device *dev, void *addr)
159*1da177e4SLinus Torvalds {
160*1da177e4SLinus Torvalds 	struct sockaddr *sa = addr;
161*1da177e4SLinus Torvalds 
162*1da177e4SLinus Torvalds 	if (dev->flags & IFF_UP)
163*1da177e4SLinus Torvalds 		ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
164*1da177e4SLinus Torvalds 
165*1da177e4SLinus Torvalds 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
166*1da177e4SLinus Torvalds 
167*1da177e4SLinus Torvalds 	if (dev->flags & IFF_UP)
168*1da177e4SLinus Torvalds 		ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
169*1da177e4SLinus Torvalds 
170*1da177e4SLinus Torvalds 	return 0;
171*1da177e4SLinus Torvalds }
172*1da177e4SLinus Torvalds 
173*1da177e4SLinus Torvalds static int nr_open(struct net_device *dev)
174*1da177e4SLinus Torvalds {
175*1da177e4SLinus Torvalds 	netif_start_queue(dev);
176*1da177e4SLinus Torvalds 	ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
177*1da177e4SLinus Torvalds 	return 0;
178*1da177e4SLinus Torvalds }
179*1da177e4SLinus Torvalds 
180*1da177e4SLinus Torvalds static int nr_close(struct net_device *dev)
181*1da177e4SLinus Torvalds {
182*1da177e4SLinus Torvalds 	ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
183*1da177e4SLinus Torvalds 	netif_stop_queue(dev);
184*1da177e4SLinus Torvalds 	return 0;
185*1da177e4SLinus Torvalds }
186*1da177e4SLinus Torvalds 
187*1da177e4SLinus Torvalds static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
188*1da177e4SLinus Torvalds {
189*1da177e4SLinus Torvalds 	struct net_device_stats *stats = netdev_priv(dev);
190*1da177e4SLinus Torvalds 	dev_kfree_skb(skb);
191*1da177e4SLinus Torvalds 	stats->tx_errors++;
192*1da177e4SLinus Torvalds 	return 0;
193*1da177e4SLinus Torvalds }
194*1da177e4SLinus Torvalds 
195*1da177e4SLinus Torvalds static struct net_device_stats *nr_get_stats(struct net_device *dev)
196*1da177e4SLinus Torvalds {
197*1da177e4SLinus Torvalds 	return netdev_priv(dev);
198*1da177e4SLinus Torvalds }
199*1da177e4SLinus Torvalds 
200*1da177e4SLinus Torvalds void nr_setup(struct net_device *dev)
201*1da177e4SLinus Torvalds {
202*1da177e4SLinus Torvalds 	SET_MODULE_OWNER(dev);
203*1da177e4SLinus Torvalds 	dev->mtu		= NR_MAX_PACKET_SIZE;
204*1da177e4SLinus Torvalds 	dev->hard_start_xmit	= nr_xmit;
205*1da177e4SLinus Torvalds 	dev->open		= nr_open;
206*1da177e4SLinus Torvalds 	dev->stop		= nr_close;
207*1da177e4SLinus Torvalds 
208*1da177e4SLinus Torvalds 	dev->hard_header	= nr_header;
209*1da177e4SLinus Torvalds 	dev->hard_header_len	= NR_NETWORK_LEN + NR_TRANSPORT_LEN;
210*1da177e4SLinus Torvalds 	dev->addr_len		= AX25_ADDR_LEN;
211*1da177e4SLinus Torvalds 	dev->type		= ARPHRD_NETROM;
212*1da177e4SLinus Torvalds 	dev->tx_queue_len	= 40;
213*1da177e4SLinus Torvalds 	dev->rebuild_header	= nr_rebuild_header;
214*1da177e4SLinus Torvalds 	dev->set_mac_address    = nr_set_mac_address;
215*1da177e4SLinus Torvalds 
216*1da177e4SLinus Torvalds 	/* New-style flags. */
217*1da177e4SLinus Torvalds 	dev->flags		= 0;
218*1da177e4SLinus Torvalds 
219*1da177e4SLinus Torvalds 	dev->get_stats 		= nr_get_stats;
220*1da177e4SLinus Torvalds }
221