Blame view

net/ax25/ax25_addr.c 6.03 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * 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)
   */
  #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
19
20
21
22
23
24
  #include <linux/timer.h>
  #include <linux/string.h>
  #include <linux/sockios.h>
  #include <linux/net.h>
  #include <net/ax25.h>
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
  #include <asm/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
  #include <linux/fcntl.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
  
  /*
15b1c0e82   Ralf Baechle   [AX.25]: Fix defa...
30
31
32
   * The default broadcast address of an interface is QST-0; the default address
   * is LINUX-1.  The null address is defined as a callsign of all spaces with
   * an SSID of zero.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

15b1c0e82   Ralf Baechle   [AX.25]: Fix defa...
35
36
37
38
39
40
41
42
43
  const ax25_address ax25_bcast =
  	{{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}};
  const ax25_address ax25_defaddr =
  	{{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, 1 << 1}};
  const ax25_address null_ax25_address =
  	{{' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}};
  
  EXPORT_SYMBOL_GPL(ax25_bcast);
  EXPORT_SYMBOL_GPL(ax25_defaddr);
70868eace   Ralf Baechle   [AX.25]: Move AX....
44
  EXPORT_SYMBOL(null_ax25_address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
  /*
   *	ax25 -> ascii conversion
   */
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
48
  char *ax2asc(char *buf, const ax25_address *a)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  	char c, *s;
  	int n;
  
  	for (n = 0, s = buf; n < 6; n++) {
  		c = (a->ax25_call[n] >> 1) & 0x7F;
  
  		if (c != ' ') *s++ = c;
  	}
  
  	*s++ = '-';
  
  	if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
  		*s++ = '1';
  		n -= 10;
  	}
  
  	*s++ = n + '0';
  	*s++ = '\0';
  
  	if (*buf == '\0' || *buf == '-')
  	   return "*";
  
  	return buf;
  
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
75
  EXPORT_SYMBOL(ax2asc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
  /*
   *	ascii -> ax25 conversion
   */
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
79
  void asc2ax(ax25_address *addr, const char *callsign)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  {
f654c854d   Ralf Baechle   [HAMRADIO]: Fix b...
81
  	const char *s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
84
85
  	int n;
  
  	for (s = callsign, n = 0; n < 6; n++) {
  		if (*s != '\0' && *s != '-')
baed16a7f   Ralf Baechle   [AX.25]: Make asc...
86
  			addr->ax25_call[n] = *s++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  		else
baed16a7f   Ralf Baechle   [AX.25]: Make asc...
88
89
90
  			addr->ax25_call[n] = ' ';
  		addr->ax25_call[n] <<= 1;
  		addr->ax25_call[n] &= 0xFE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
  	}
  
  	if (*s++ == '\0') {
baed16a7f   Ralf Baechle   [AX.25]: Make asc...
94
95
  		addr->ax25_call[6] = 0x00;
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  	}
baed16a7f   Ralf Baechle   [AX.25]: Make asc...
97
  	addr->ax25_call[6] = *s++ - '0';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
  
  	if (*s != '\0') {
baed16a7f   Ralf Baechle   [AX.25]: Make asc...
100
101
  		addr->ax25_call[6] *= 10;
  		addr->ax25_call[6] += *s++ - '0';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  	}
baed16a7f   Ralf Baechle   [AX.25]: Make asc...
103
104
  	addr->ax25_call[6] <<= 1;
  	addr->ax25_call[6] &= 0x1E;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
106
  EXPORT_SYMBOL(asc2ax);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
  /*
   *	Compare two ax.25 addresses
   */
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
110
  int ax25cmp(const ax25_address *a, const ax25_address *b)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
115
116
117
118
  {
  	int ct = 0;
  
  	while (ct < 6) {
  		if ((a->ax25_call[ct] & 0xFE) != (b->ax25_call[ct] & 0xFE))	/* Clean off repeater bits */
  			return 1;
  		ct++;
  	}
528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
119
120
  	if ((a->ax25_call[ct] & 0x1E) == (b->ax25_call[ct] & 0x1E))	/* SSID without control bit */
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121

528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
122
  	return 2;			/* Partial match */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
124
  EXPORT_SYMBOL(ax25cmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
  /*
   *	Compare two AX.25 digipeater paths.
   */
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
128
  int ax25digicmp(const ax25_digi *digi1, const ax25_digi *digi2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  {
  	int i;
  
  	if (digi1->ndigi != digi2->ndigi)
  		return 1;
  
  	if (digi1->lastrepeat != digi2->lastrepeat)
  		return 1;
  
  	for (i = 0; i < digi1->ndigi; i++)
  		if (ax25cmp(&digi1->calls[i], &digi2->calls[i]) != 0)
  			return 1;
  
  	return 0;
  }
  
  /*
   *	Given an AX.25 address pull of to, from, digi list, command/response and the start of data
   *
   */
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
149
150
151
  const unsigned char *ax25_addr_parse(const unsigned char *buf, int len,
  	ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags,
  	int *dama)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  {
  	int d = 0;
  
  	if (len < 14) return NULL;
  
  	if (flags != NULL) {
  		*flags = 0;
  
  		if (buf[6] & AX25_CBIT)
  			*flags = AX25_COMMAND;
  		if (buf[13] & AX25_CBIT)
  			*flags = AX25_RESPONSE;
  	}
  
  	if (dama != NULL)
  		*dama = ~buf[13] & AX25_DAMA_FLAG;
  
  	/* Copy to, from */
  	if (dest != NULL)
  		memcpy(dest, buf + 0, AX25_ADDR_LEN);
  	if (src != NULL)
  		memcpy(src,  buf + 7, AX25_ADDR_LEN);
  
  	buf += 2 * AX25_ADDR_LEN;
  	len -= 2 * AX25_ADDR_LEN;
  
  	digi->lastrepeat = -1;
  	digi->ndigi      = 0;
  
  	while (!(buf[-1] & AX25_EBIT)) {
5c9df5fed   Dan Carpenter   small cleanup in ...
182
183
184
185
  		if (d >= AX25_MAX_DIGIS)
  			return NULL;
  		if (len < AX25_ADDR_LEN)
  			return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  
  		memcpy(&digi->calls[d], buf, AX25_ADDR_LEN);
  		digi->ndigi = d + 1;
  
  		if (buf[6] & AX25_HBIT) {
  			digi->repeated[d] = 1;
  			digi->lastrepeat  = d;
  		} else {
  			digi->repeated[d] = 0;
  		}
  
  		buf += AX25_ADDR_LEN;
  		len -= AX25_ADDR_LEN;
  		d++;
  	}
  
  	return buf;
  }
  
  /*
   *	Assemble an AX.25 header from the bits
   */
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
208
209
  int ax25_addr_build(unsigned char *buf, const ax25_address *src,
  	const ax25_address *dest, const ax25_digi *d, int flag, int modulus)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  {
  	int len = 0;
  	int ct  = 0;
  
  	memcpy(buf, dest, AX25_ADDR_LEN);
  	buf[6] &= ~(AX25_EBIT | AX25_CBIT);
  	buf[6] |= AX25_SSSID_SPARE;
  
  	if (flag == AX25_COMMAND) buf[6] |= AX25_CBIT;
  
  	buf += AX25_ADDR_LEN;
  	len += AX25_ADDR_LEN;
  
  	memcpy(buf, src, AX25_ADDR_LEN);
  	buf[6] &= ~(AX25_EBIT | AX25_CBIT);
  	buf[6] &= ~AX25_SSSID_SPARE;
  
  	if (modulus == AX25_MODULUS)
  		buf[6] |= AX25_SSSID_SPARE;
  	else
  		buf[6] |= AX25_ESSID_SPARE;
  
  	if (flag == AX25_RESPONSE) buf[6] |= AX25_CBIT;
  
  	/*
  	 *	Fast path the normal digiless path
  	 */
  	if (d == NULL || d->ndigi == 0) {
  		buf[6] |= AX25_EBIT;
  		return 2 * AX25_ADDR_LEN;
  	}
  
  	buf += AX25_ADDR_LEN;
  	len += AX25_ADDR_LEN;
  
  	while (ct < d->ndigi) {
  		memcpy(buf, &d->calls[ct], AX25_ADDR_LEN);
  
  		if (d->repeated[ct])
  			buf[6] |= AX25_HBIT;
  		else
  			buf[6] &= ~AX25_HBIT;
  
  		buf[6] &= ~AX25_EBIT;
  		buf[6] |= AX25_SSSID_SPARE;
  
  		buf += AX25_ADDR_LEN;
  		len += AX25_ADDR_LEN;
  		ct++;
  	}
  
  	buf[-1] |= AX25_EBIT;
  
  	return len;
  }
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
265
  int ax25_addr_size(const ax25_digi *dp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
269
270
271
272
273
274
275
  {
  	if (dp == NULL)
  		return 2 * AX25_ADDR_LEN;
  
  	return AX25_ADDR_LEN * (2 + dp->ndigi);
  }
  
  /*
   *	Reverse Digipeat List. May not pass both parameters as same struct
   */
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
276
  void ax25_digi_invert(const ax25_digi *in, ax25_digi *out)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  {
  	int ct;
  
  	out->ndigi      = in->ndigi;
  	out->lastrepeat = in->ndigi - in->lastrepeat - 2;
  
  	/* Invert the digipeaters */
  	for (ct = 0; ct < in->ndigi; ct++) {
  		out->calls[ct] = in->calls[in->ndigi - ct - 1];
  
  		if (ct <= out->lastrepeat) {
  			out->calls[ct].ax25_call[6] |= AX25_HBIT;
  			out->repeated[ct]            = 1;
  		} else {
  			out->calls[ct].ax25_call[6] &= ~AX25_HBIT;
  			out->repeated[ct]            = 0;
  		}
  	}
  }