Blame view

net/ax25/ax25_addr.c 6.07 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
25
26
27
28
29
30
  #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>
  #include <asm/system.h>
  #include <linux/fcntl.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
  
  /*
15b1c0e82   Ralf Baechle   [AX.25]: Fix defa...
31
32
33
   * 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
34
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

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

528930b91   YOSHIFUJI Hideaki   [NET] AX25: Fix w...
123
  	return 2;			/* Partial match */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
125
  EXPORT_SYMBOL(ax25cmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
  /*
   *	Compare two AX.25 digipeater paths.
   */
e8cc49bb0   Ralf Baechle   [AX.25]: Constify...
129
  int ax25digicmp(const ax25_digi *digi1, const ax25_digi *digi2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  {
  	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...
150
151
152
  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
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  {
  	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)) {
  		if (d >= AX25_MAX_DIGIS)  return NULL;	/* Max of 6 digis */
  		if (len < 7) return NULL;	/* Short packet */
  
  		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...
207
208
  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
209
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
  {
  	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...
264
  int ax25_addr_size(const ax25_digi *dp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
269
270
271
272
273
274
  {
  	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...
275
  void ax25_digi_invert(const ax25_digi *in, ax25_digi *out)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  {
  	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;
  		}
  	}
  }