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 (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 8 */ 9 #include <linux/errno.h> 10 #include <linux/types.h> 11 #include <linux/socket.h> 12 #include <linux/in.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/sched.h> 16 #include <linux/timer.h> 17 #include <linux/string.h> 18 #include <linux/sockios.h> 19 #include <linux/net.h> 20 #include <net/ax25.h> 21 #include <linux/inet.h> 22 #include <linux/netdevice.h> 23 #include <linux/skbuff.h> 24 #include <net/sock.h> 25 #include <asm/uaccess.h> 26 #include <asm/system.h> 27 #include <linux/fcntl.h> 28 #include <linux/mm.h> 29 #include <linux/interrupt.h> 30 31 /* 32 * The null address is defined as a callsign of all spaces with an 33 * SSID of zero. 34 */ 35 ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}}; 36 37 EXPORT_SYMBOL(null_ax25_address); 38 39 /* 40 * ax25 -> ascii conversion 41 */ 42 char *ax2asc(char *buf, ax25_address *a) 43 { 44 char c, *s; 45 int n; 46 47 for (n = 0, s = buf; n < 6; n++) { 48 c = (a->ax25_call[n] >> 1) & 0x7F; 49 50 if (c != ' ') *s++ = c; 51 } 52 53 *s++ = '-'; 54 55 if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) { 56 *s++ = '1'; 57 n -= 10; 58 } 59 60 *s++ = n + '0'; 61 *s++ = '\0'; 62 63 if (*buf == '\0' || *buf == '-') 64 return "*"; 65 66 return buf; 67 68 } 69 70 EXPORT_SYMBOL(ax2asc); 71 72 /* 73 * ascii -> ax25 conversion 74 */ 75 void asc2ax(ax25_address *addr, char *callsign) 76 { 77 char *s; 78 int n; 79 80 for (s = callsign, n = 0; n < 6; n++) { 81 if (*s != '\0' && *s != '-') 82 addr->ax25_call[n] = *s++; 83 else 84 addr->ax25_call[n] = ' '; 85 addr->ax25_call[n] <<= 1; 86 addr->ax25_call[n] &= 0xFE; 87 } 88 89 if (*s++ == '\0') { 90 addr->ax25_call[6] = 0x00; 91 return; 92 } 93 94 addr->ax25_call[6] = *s++ - '0'; 95 96 if (*s != '\0') { 97 addr->ax25_call[6] *= 10; 98 addr->ax25_call[6] += *s++ - '0'; 99 } 100 101 addr->ax25_call[6] <<= 1; 102 addr->ax25_call[6] &= 0x1E; 103 } 104 105 EXPORT_SYMBOL(asc2ax); 106 107 /* 108 * Compare two ax.25 addresses 109 */ 110 int ax25cmp(ax25_address *a, ax25_address *b) 111 { 112 int ct = 0; 113 114 while (ct < 6) { 115 if ((a->ax25_call[ct] & 0xFE) != (b->ax25_call[ct] & 0xFE)) /* Clean off repeater bits */ 116 return 1; 117 ct++; 118 } 119 120 if ((a->ax25_call[ct] & 0x1E) == (b->ax25_call[ct] & 0x1E)) /* SSID without control bit */ 121 return 0; 122 123 return 2; /* Partial match */ 124 } 125 126 EXPORT_SYMBOL(ax25cmp); 127 128 /* 129 * Compare two AX.25 digipeater paths. 130 */ 131 int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2) 132 { 133 int i; 134 135 if (digi1->ndigi != digi2->ndigi) 136 return 1; 137 138 if (digi1->lastrepeat != digi2->lastrepeat) 139 return 1; 140 141 for (i = 0; i < digi1->ndigi; i++) 142 if (ax25cmp(&digi1->calls[i], &digi2->calls[i]) != 0) 143 return 1; 144 145 return 0; 146 } 147 148 /* 149 * Given an AX.25 address pull of to, from, digi list, command/response and the start of data 150 * 151 */ 152 unsigned char *ax25_addr_parse(unsigned char *buf, int len, ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags, int *dama) 153 { 154 int d = 0; 155 156 if (len < 14) return NULL; 157 158 if (flags != NULL) { 159 *flags = 0; 160 161 if (buf[6] & AX25_CBIT) 162 *flags = AX25_COMMAND; 163 if (buf[13] & AX25_CBIT) 164 *flags = AX25_RESPONSE; 165 } 166 167 if (dama != NULL) 168 *dama = ~buf[13] & AX25_DAMA_FLAG; 169 170 /* Copy to, from */ 171 if (dest != NULL) 172 memcpy(dest, buf + 0, AX25_ADDR_LEN); 173 if (src != NULL) 174 memcpy(src, buf + 7, AX25_ADDR_LEN); 175 176 buf += 2 * AX25_ADDR_LEN; 177 len -= 2 * AX25_ADDR_LEN; 178 179 digi->lastrepeat = -1; 180 digi->ndigi = 0; 181 182 while (!(buf[-1] & AX25_EBIT)) { 183 if (d >= AX25_MAX_DIGIS) return NULL; /* Max of 6 digis */ 184 if (len < 7) return NULL; /* Short packet */ 185 186 memcpy(&digi->calls[d], buf, AX25_ADDR_LEN); 187 digi->ndigi = d + 1; 188 189 if (buf[6] & AX25_HBIT) { 190 digi->repeated[d] = 1; 191 digi->lastrepeat = d; 192 } else { 193 digi->repeated[d] = 0; 194 } 195 196 buf += AX25_ADDR_LEN; 197 len -= AX25_ADDR_LEN; 198 d++; 199 } 200 201 return buf; 202 } 203 204 /* 205 * Assemble an AX.25 header from the bits 206 */ 207 int ax25_addr_build(unsigned char *buf, ax25_address *src, ax25_address *dest, ax25_digi *d, int flag, int modulus) 208 { 209 int len = 0; 210 int ct = 0; 211 212 memcpy(buf, dest, AX25_ADDR_LEN); 213 buf[6] &= ~(AX25_EBIT | AX25_CBIT); 214 buf[6] |= AX25_SSSID_SPARE; 215 216 if (flag == AX25_COMMAND) buf[6] |= AX25_CBIT; 217 218 buf += AX25_ADDR_LEN; 219 len += AX25_ADDR_LEN; 220 221 memcpy(buf, src, AX25_ADDR_LEN); 222 buf[6] &= ~(AX25_EBIT | AX25_CBIT); 223 buf[6] &= ~AX25_SSSID_SPARE; 224 225 if (modulus == AX25_MODULUS) 226 buf[6] |= AX25_SSSID_SPARE; 227 else 228 buf[6] |= AX25_ESSID_SPARE; 229 230 if (flag == AX25_RESPONSE) buf[6] |= AX25_CBIT; 231 232 /* 233 * Fast path the normal digiless path 234 */ 235 if (d == NULL || d->ndigi == 0) { 236 buf[6] |= AX25_EBIT; 237 return 2 * AX25_ADDR_LEN; 238 } 239 240 buf += AX25_ADDR_LEN; 241 len += AX25_ADDR_LEN; 242 243 while (ct < d->ndigi) { 244 memcpy(buf, &d->calls[ct], AX25_ADDR_LEN); 245 246 if (d->repeated[ct]) 247 buf[6] |= AX25_HBIT; 248 else 249 buf[6] &= ~AX25_HBIT; 250 251 buf[6] &= ~AX25_EBIT; 252 buf[6] |= AX25_SSSID_SPARE; 253 254 buf += AX25_ADDR_LEN; 255 len += AX25_ADDR_LEN; 256 ct++; 257 } 258 259 buf[-1] |= AX25_EBIT; 260 261 return len; 262 } 263 264 int ax25_addr_size(ax25_digi *dp) 265 { 266 if (dp == NULL) 267 return 2 * AX25_ADDR_LEN; 268 269 return AX25_ADDR_LEN * (2 + dp->ndigi); 270 } 271 272 /* 273 * Reverse Digipeat List. May not pass both parameters as same struct 274 */ 275 void ax25_digi_invert(ax25_digi *in, ax25_digi *out) 276 { 277 int ct; 278 279 out->ndigi = in->ndigi; 280 out->lastrepeat = in->ndigi - in->lastrepeat - 2; 281 282 /* Invert the digipeaters */ 283 for (ct = 0; ct < in->ndigi; ct++) { 284 out->calls[ct] = in->calls[in->ndigi - ct - 1]; 285 286 if (ct <= out->lastrepeat) { 287 out->calls[ct].ax25_call[6] |= AX25_HBIT; 288 out->repeated[ct] = 1; 289 } else { 290 out->calls[ct].ax25_call[6] &= ~AX25_HBIT; 291 out->repeated[ct] = 0; 292 } 293 } 294 } 295 296