iproute2/lib/ax25_ntop.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0+ */
   2
   3#include <errno.h>
   4#include <sys/socket.h>
   5#include <netax25/ax25.h>
   6
   7#include "utils.h"
   8
   9const char *ax25_ntop1(const ax25_address *src, char *dst, socklen_t size);
  10
  11/*
  12 * AX.25 addresses are based on Amateur radio callsigns followed by an SSID
  13 * like XXXXXX-SS where the callsign consists of up to 6 ASCII characters
  14 * which are either letters or digits and the SSID is a decimal number in the
  15 * range 0..15.
  16 * Amateur radio callsigns are assigned by a country's relevant authorities
  17 * and are 3..6 characters though a few countries have assigned callsigns
  18 * longer than that.  AX.25 is not able to handle such longer callsigns.
  19 * There are further restrictions on the format of valid callsigns by
  20 * applicable national and international law.  Linux doesn't need to care and
  21 * will happily accept anything that consists of 6 ASCII characters in the
  22 * range of A-Z and 0-9 for a callsign such as the default AX.25 MAC address
  23 * LINUX-1 and the default broadcast address QST-0.
  24 * The SSID is just a number and not encoded in ASCII digits.
  25 *
  26 * Being based on HDLC AX.25 encodes addresses by shifting them one bit left
  27 * thus zeroing bit 0, the HDLC extension bit for all but the last bit of
  28 * a packet's address field but for our purposes here we're not considering
  29 * the HDLC extension bit that is it will always be zero.
  30 *
  31 * Linux' internal representation of AX.25 addresses in Linux is very similar
  32 * to this on the on-air or on-the-wire format.  The callsign is padded to
  33 * 6 octets by adding spaces, followed by the SSID octet then all 7 octets
  34 * are left-shifted by one bit.
  35 *
  36 * For example, for the address "LINUX-1" the callsign is LINUX and SSID is 1
  37 * the internal format is 98:92:9c:aa:b0:40:02.
  38 */
  39
  40const char *ax25_ntop1(const ax25_address *src, char *dst, socklen_t size)
  41{
  42        char c, *s;
  43        int n;
  44
  45        for (n = 0, s = dst; n < 6; n++) {
  46                c = (src->ax25_call[n] >> 1) & 0x7f;
  47                if (c != ' ')
  48                        *s++ = c;
  49        }
  50
  51        *s++ = '-';
  52
  53        n = ((src->ax25_call[6] >> 1) & 0x0f);
  54        if (n > 9) {
  55                *s++ = '1';
  56                n -= 10;
  57        }
  58
  59        *s++ = n + '0';
  60        *s++ = '\0';
  61
  62        if (*dst == '\0' || *dst == '-') {
  63                dst[0] = '*';
  64                dst[1] = '\0';
  65        }
  66
  67        return dst;
  68}
  69
  70const char *ax25_ntop(int af, const void *addr, char *buf, socklen_t buflen)
  71{
  72        switch (af) {
  73        case AF_AX25:
  74                errno = 0;
  75                return ax25_ntop1((ax25_address *)addr, buf, buflen);
  76
  77        default:
  78                errno = EAFNOSUPPORT;
  79        }
  80
  81        return NULL;
  82}
  83