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