Blame view

net/ax25/ax25_ip.c 5.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
  /*
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/in.h>
  #include <linux/kernel.h>
70868eace   Ralf Baechle   [AX.25]: Move AX....
14
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
  #include <linux/timer.h>
  #include <linux/string.h>
  #include <linux/sockios.h>
  #include <linux/net.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  #include <net/ax25.h>
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/if_arp.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
  #include <asm/uaccess.h>
  #include <asm/system.h>
  #include <linux/fcntl.h>
  #include <linux/termios.h>	/* For TIOCINQ/OUTQ */
  #include <linux/mm.h>
  #include <linux/interrupt.h>
  #include <linux/notifier.h>
  #include <linux/proc_fs.h>
  #include <linux/stat.h>
  #include <linux/netfilter.h>
  #include <linux/sysctl.h>
  #include <net/ip.h>
  #include <net/arp.h>
  
  /*
   *	IP over AX.25 encapsulation.
   */
  
  /*
   *	Shove an AX.25 UI header on an IP packet and handle ARP
   */
  
  #ifdef CONFIG_INET
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
49
50
51
  int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
  		     unsigned short type, const void *daddr,
  		     const void *saddr, unsigned len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
  {
  	unsigned char *buff;
  
  	/* they sometimes come back to us... */
  	if (type == ETH_P_AX25)
  		return 0;
528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
58
59
60
  	/* header is an AX.25 UI frame from us to them */
  	buff = skb_push(skb, AX25_HEADER_LEN);
  	*buff++ = 0x00;	/* KISS DATA */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
  
  	if (daddr != NULL)
  		memcpy(buff, daddr, dev->addr_len);	/* Address specified */
528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  	buff[6] &= ~AX25_CBIT;
  	buff[6] &= ~AX25_EBIT;
  	buff[6] |= AX25_SSSID_SPARE;
  	buff    += AX25_ADDR_LEN;
  
  	if (saddr != NULL)
  		memcpy(buff, saddr, dev->addr_len);
  	else
  		memcpy(buff, dev->dev_addr, dev->addr_len);
  
  	buff[6] &= ~AX25_CBIT;
  	buff[6] |= AX25_EBIT;
  	buff[6] |= AX25_SSSID_SPARE;
  	buff    += AX25_ADDR_LEN;
  
  	*buff++  = AX25_UI;	/* UI */
  
  	/* Append a suitable AX.25 PID */
  	switch (type) {
  	case ETH_P_IP:
  		*buff++ = AX25_P_IP;
  		break;
  	case ETH_P_ARP:
  		*buff++ = AX25_P_ARP;
  		break;
  	default:
  		printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x
  ", type);
  		*buff++ = 0;
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
  
  	if (daddr != NULL)
528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
97
  		return AX25_HEADER_LEN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
102
103
104
105
  
  	return -AX25_HEADER_LEN;	/* Unfinished header */
  }
  
  int ax25_rebuild_header(struct sk_buff *skb)
  {
  	struct sk_buff *ourskb;
  	unsigned char *bp  = skb->data;
006f68b84   Ralf Baechle   [AX.25]: Referenc...
106
107
  	ax25_route *route;
  	struct net_device *dev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  	ax25_address *src, *dst;
006f68b84   Ralf Baechle   [AX.25]: Referenc...
109
  	ax25_digi *digipeat = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  	ax25_dev *ax25_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  	ax25_cb *ax25;
006f68b84   Ralf Baechle   [AX.25]: Referenc...
112
  	char ip_mode = ' ';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
  
  	dst = (ax25_address *)(bp + 1);
  	src = (ax25_address *)(bp + 8);
528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
116
117
  	if (arp_find(bp + 1, skb))
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118

006f68b84   Ralf Baechle   [AX.25]: Referenc...
119
120
121
122
123
  	route = ax25_get_route(dst, NULL);
  	if (route) {
  		digipeat = route->digipeat;
  		dev = route->dev;
  		ip_mode = route->ip_mode;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
124
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
  
  	if (dev == NULL)
  		dev = skb->dev;
528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
128
129
  	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
  		goto put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
  	}
  
  	if (bp[16] == AX25_P_IP) {
006f68b84   Ralf Baechle   [AX.25]: Referenc...
133
  		if (ip_mode == 'V' || (ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  			/*
  			 *	We copy the buffer and release the original thereby
  			 *	keeping it straight
  			 *
  			 *	Note: we report 1 back so the caller will
  			 *	not feed the frame direct to the physical device
  			 *	We don't want that to happen. (It won't be upset
  			 *	as we have pulled the frame from the queue by
  			 *	freeing it).
  			 *
  			 *	NB: TCP modifies buffers that are still
  			 *	on a device queue, thus we use skb_copy()
  			 *      instead of using skb_clone() unless this
  			 *	gets fixed.
  			 */
  
  			ax25_address src_c;
  			ax25_address dst_c;
  
  			if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {
  				kfree_skb(skb);
  				goto put;
  			}
  
  			if (skb->sk != NULL)
  				skb_set_owner_w(ourskb, skb->sk);
  
  			kfree_skb(skb);
  			/* dl9sau: bugfix
  			 * after kfree_skb(), dst and src which were pointer
  			 * to bp which is part of skb->data would not be valid
  			 * anymore hope that after skb_pull(ourskb, ..) our
  			 * dsc_c and src_c will not become invalid
  			 */
  			bp  = ourskb->data;
  			dst_c = *(ax25_address *)(bp + 1);
  			src_c = *(ax25_address *)(bp + 8);
  
  			skb_pull(ourskb, AX25_HEADER_LEN - 1);	/* Keep PID */
c1d2bbe1c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
173
  			skb_reset_network_header(ourskb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
  
  			ax25=ax25_send_frame(
528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
176
177
  			    ourskb,
  			    ax25_dev->values[AX25_VALUES_PACLEN],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  			    &src_c,
006f68b84   Ralf Baechle   [AX.25]: Referenc...
179
  			    &dst_c, digipeat, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
185
  			if (ax25) {
  				ax25_cb_put(ax25);
  			}
  			goto put;
  		}
  	}
528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
186
187
188
  	bp[7]  &= ~AX25_CBIT;
  	bp[7]  &= ~AX25_EBIT;
  	bp[7]  |= AX25_SSSID_SPARE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189

528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
190
191
192
  	bp[14] &= ~AX25_CBIT;
  	bp[14] |= AX25_EBIT;
  	bp[14] |= AX25_SSSID_SPARE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
  
  	skb_pull(skb, AX25_KISS_HEADER_LEN);
006f68b84   Ralf Baechle   [AX.25]: Referenc...
195
  	if (digipeat != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
199
200
201
202
  		if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL) {
  			kfree_skb(skb);
  			goto put;
  		}
  
  		skb = ourskb;
  	}
29c4be51e   Arnaldo Carvalho de Melo   [AX25]: make ax25...
203
  	ax25_queue_xmit(skb, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
  
  put:
006f68b84   Ralf Baechle   [AX.25]: Referenc...
206
207
  	if (route)
  		ax25_put_route(route);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208

528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
209
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
  }
  
  #else	/* INET */
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
213
214
215
  int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
  		     unsigned short type, const void *daddr,
  		     const void *saddr, unsigned len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
221
222
223
224
225
  {
  	return -AX25_HEADER_LEN;
  }
  
  int ax25_rebuild_header(struct sk_buff *skb)
  {
  	return 1;
  }
  
  #endif
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
226
227
228
229
  const struct header_ops ax25_header_ops = {
  	.create = ax25_hard_header,
  	.rebuild = ax25_rebuild_header,
  };
70868eace   Ralf Baechle   [AX.25]: Move AX....
230
231
  EXPORT_SYMBOL(ax25_hard_header);
  EXPORT_SYMBOL(ax25_rebuild_header);
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
232
  EXPORT_SYMBOL(ax25_header_ops);