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