xref: /openbmc/linux/net/netrom/nr_dev.c (revision d5cb9783536a41df9f9cba5b0a1d78047ed787f7)
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8  */
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/proc_fs.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/interrupt.h>
15 #include <linux/fs.h>
16 #include <linux/types.h>
17 #include <linux/sysctl.h>
18 #include <linux/string.h>
19 #include <linux/socket.h>
20 #include <linux/errno.h>
21 #include <linux/fcntl.h>
22 #include <linux/in.h>
23 #include <linux/if_ether.h>	/* For the statistics structure. */
24 
25 #include <asm/system.h>
26 #include <asm/uaccess.h>
27 #include <asm/io.h>
28 
29 #include <linux/inet.h>
30 #include <linux/netdevice.h>
31 #include <linux/etherdevice.h>
32 #include <linux/if_arp.h>
33 #include <linux/skbuff.h>
34 
35 #include <net/ip.h>
36 #include <net/arp.h>
37 
38 #include <net/ax25.h>
39 #include <net/netrom.h>
40 
41 /*
42  *	Only allow IP over NET/ROM frames through if the netrom device is up.
43  */
44 
45 int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
46 {
47 	struct net_device_stats *stats = netdev_priv(dev);
48 
49 	if (!netif_running(dev)) {
50 		stats->rx_dropped++;
51 		return 0;
52 	}
53 
54 	stats->rx_packets++;
55 	stats->rx_bytes += skb->len;
56 
57 	skb->protocol = htons(ETH_P_IP);
58 
59 	/* Spoof incoming device */
60 	skb->dev      = dev;
61 	skb->mac.raw  = skb->nh.raw;
62 	skb->nh.raw   = skb->data;
63 	skb->pkt_type = PACKET_HOST;
64 
65 	netif_rx(skb);
66 
67 	return 1;
68 }
69 
70 #ifdef CONFIG_INET
71 
72 static int nr_rebuild_header(struct sk_buff *skb)
73 {
74 	unsigned char *bp = skb->data;
75 
76 	if (arp_find(bp + 7, skb))
77 		return 1;
78 
79 	bp[6] &= ~AX25_CBIT;
80 	bp[6] &= ~AX25_EBIT;
81 	bp[6] |= AX25_SSSID_SPARE;
82 	bp    += AX25_ADDR_LEN;
83 
84 	bp[6] &= ~AX25_CBIT;
85 	bp[6] |= AX25_EBIT;
86 	bp[6] |= AX25_SSSID_SPARE;
87 
88 	return 0;
89 }
90 
91 #else
92 
93 static int nr_rebuild_header(struct sk_buff *skb)
94 {
95 	return 1;
96 }
97 
98 #endif
99 
100 static int nr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
101 	void *daddr, void *saddr, unsigned len)
102 {
103 	unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
104 
105 	memcpy(buff, (saddr != NULL) ? saddr : dev->dev_addr, dev->addr_len);
106 	buff[6] &= ~AX25_CBIT;
107 	buff[6] &= ~AX25_EBIT;
108 	buff[6] |= AX25_SSSID_SPARE;
109 	buff    += AX25_ADDR_LEN;
110 
111 	if (daddr != NULL)
112 		memcpy(buff, daddr, dev->addr_len);
113 	buff[6] &= ~AX25_CBIT;
114 	buff[6] |= AX25_EBIT;
115 	buff[6] |= AX25_SSSID_SPARE;
116 	buff    += AX25_ADDR_LEN;
117 
118 	*buff++ = sysctl_netrom_network_ttl_initialiser;
119 
120 	*buff++ = NR_PROTO_IP;
121 	*buff++ = NR_PROTO_IP;
122 	*buff++ = 0;
123 	*buff++ = 0;
124 	*buff++ = NR_PROTOEXT;
125 
126 	if (daddr != NULL)
127 		return 37;
128 
129 	return -37;
130 }
131 
132 static int nr_set_mac_address(struct net_device *dev, void *addr)
133 {
134 	struct sockaddr *sa = addr;
135 
136 	if (dev->flags & IFF_UP)
137 		ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
138 
139 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
140 
141 	if (dev->flags & IFF_UP)
142 		ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
143 
144 	return 0;
145 }
146 
147 static int nr_open(struct net_device *dev)
148 {
149 	netif_start_queue(dev);
150 	ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
151 	return 0;
152 }
153 
154 static int nr_close(struct net_device *dev)
155 {
156 	ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
157 	netif_stop_queue(dev);
158 	return 0;
159 }
160 
161 static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
162 {
163 	struct nr_private *nr = netdev_priv(dev);
164 	struct net_device_stats *stats = &nr->stats;
165 	unsigned int len = skb->len;
166 
167 	if (!nr_route_frame(skb, NULL)) {
168 		kfree_skb(skb);
169 		stats->tx_errors++;
170 		return 0;
171 	}
172 
173 	stats->tx_packets++;
174 	stats->tx_bytes += len;
175 
176 	return 0;
177 }
178 
179 static struct net_device_stats *nr_get_stats(struct net_device *dev)
180 {
181 	struct nr_private *nr = netdev_priv(dev);
182 
183 	return &nr->stats;
184 }
185 
186 void nr_setup(struct net_device *dev)
187 {
188 	SET_MODULE_OWNER(dev);
189 	dev->mtu		= NR_MAX_PACKET_SIZE;
190 	dev->hard_start_xmit	= nr_xmit;
191 	dev->open		= nr_open;
192 	dev->stop		= nr_close;
193 
194 	dev->hard_header	= nr_header;
195 	dev->hard_header_len	= NR_NETWORK_LEN + NR_TRANSPORT_LEN;
196 	dev->addr_len		= AX25_ADDR_LEN;
197 	dev->type		= ARPHRD_NETROM;
198 	dev->rebuild_header	= nr_rebuild_header;
199 	dev->set_mac_address    = nr_set_mac_address;
200 
201 	/* New-style flags. */
202 	dev->flags		= IFF_NOARP;
203 
204 	dev->get_stats 		= nr_get_stats;
205 }
206