HEX
Server: Apache
System: Linux s198.coreserver.jp 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC 2025 x86_64
User: nagasaki (10062)
PHP: 7.1.33
Disabled: NONE
Upload Files
File: //usr/local/qlibs/ip6.c
#include "fmt.h"
#include "byte.h"
#include "scan.h"
#include "ip.h"
#include "str.h"

/**
	@file ip6.c
	@author djb, fefe, feh
	@source ucspi-tcp, ucspi-tcp6
	@brief handling of IPv6 addresses
*/

/***
 @brief ip6_fmt
        convert IPv6 address to compactified IPv6 address string
 @param input:  IPv6 char array
        output: pointer to IPv6 address string
 @return int length of address (ok > 0)
 */

unsigned int ip6_fmt(char *s,char ip[16])
{
  unsigned int len;
  unsigned int i;
  unsigned int temp, temp0;
  unsigned int compressing;
  unsigned int compressed;
  int j;

  len = 0;
  compressing = 0;
  compressed = 0;

  for (j = 0; j < 16; j += 2) {
    if (j == 12 && ip6_isv4mapped(ip)) {
      len += ip4_fmt(s,ip+12);
      break;
    }

    temp = ((unsigned long) (unsigned char) ip[j] << 8) +
            (unsigned long) (unsigned char) ip[j+1];

    temp0 = 0;
    if (!compressing && j < 16)
      temp0 = ((unsigned long) (unsigned char) ip[j+2] << 8) +
               (unsigned long) (unsigned char) ip[j+3];

    if (temp == 0 && temp0 == 0 && !compressed) {
      if (!compressing) {
        compressing = 1;
        if (j == 0) {
          if (s) *s++ = ':';
          ++len;
        }
      }
    } else {
      if (compressing) {
        compressing = 0;
        ++compressed;
        if (s) *s++ = ':';
        ++len;
      }
      i = fmt_xlong(s,temp);
      len += i;
      if (s) s += i;
      if (j < 14) {
        if (s) *s++ = ':';
        ++len;
      }
    }
  }
  if (compressing) { *s++ = ':'; ++len; }

  return len;
}

/***
 @brief ip6_fmt_flat
        convert IPv6 address to IPv6 address string
 @param input:  IPv6 char array
        output: pointer to IPv6 address string
 @return int length of address (ok > 0)
 */

unsigned int ip6_fmt_flat(char *s,char ip[16])
{
  int i;
  for (i = 0; i < 16; i++) {
    *s++ = tohex((unsigned char)ip[i] >> 4);
    *s++ = tohex((unsigned char)ip[i] & 15);
  }
  return 32;
}

/***
 @brief ia6_fmt
        convert IPv6 address to inverse DNS nibble format
        1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.arpa 
 @param input:  IPv6 char array
        output: pointer to IPv6 address string
 @return int length of address 
 */

unsigned int ia6_fmt(char *s,char ip[16])
{
  unsigned int i;
  unsigned int len;
  int j;

  static char data[] = "0123456789abcdef";
  len = 0;

  for (j = 15; j >= 0; j--) {
    i = fmt_str(s,&data[ip[j] & 0x0f]); len += i; if (s) s += i;
    i = fmt_str(s,"."); len += i; if (s) s += i;
    i = fmt_str(s,&data[ip[j] >> 4 & 0x0f]); len += i; if (s) s += i;
    i = fmt_str(s,"."); len += i; if (s) s += i;
  }
  i = fmt_str(s,"ip6.arpa."); len += i; if (s) s += i;

  return len;
}


/***
 @brief ip6_scan_flat
        convert IPv6 address string to IPv6 address array
 @param input:  pointer to IPv6 address string
        output: IPv6 char array
 @return int length of address (ok > 0)
 */

unsigned int ip6_scan_flat(const char *s,char ip[16])
{
  int i, tmp;

  for (i = 0; i < 16; i++) {
    tmp = fromhex(*s++);
    if (tmp < 0) return 0;
    ip[i] = tmp << 4;
    tmp = fromhex(*s++);
    if (tmp < 0) return 0;
    ip[i] += tmp;
  }
  return 32;
}

/***
 @brief ip6_scan
        parse compactified IPv6 address string and convert to IPv6 address array
 @param input:  pointer to IPv6 address string
        output: IPv6 char array
 @return int length of ip6_address/ip
 */

unsigned int ip6_scan(const char *s,char ip[16])
{
  unsigned int i, j;
  unsigned int len = 0;
  unsigned long u;

  char suffix[16];
  int prefixlen = 0;
  int suffixlen = 0;

 /* Always return IPv4 as IPv4-mapped IPv6 address */
  if ((i = ip4_scan(s,ip+12))) {	
    for (len = 0; len < 12; ++len) 
      ip[len] = V4mappedprefix[len];
    return i;
    if (byte_equal(ip+12,4,V4localnet)) {
      byte_copy(ip,16,V6localnet);
      return 16;
    }
  }
  byte_zero(ip,16);

  for (;;) {
    if (*s == ':') {
      len++;
      if (s[1] == ':') {        /* Found "::", skip to part 2 */
        s += 2; len++;
        break;
      }
      s++;
    }
    i = scan_xlong((char *)s,&u);
    if (!i) return 0;

    if (prefixlen == 12 && s[i] == '.') {
      /* the last 4 bytes may be written as IPv4 address */
      i = ip4_scan(s,ip+12);
      if (i) 
        return i+len;
      else
        return 0;
    }

    ip[prefixlen++] = (u >> 8);
    ip[prefixlen++] = (u & 255);
    s += i; len += i;
    if (prefixlen == 16) return len;
  }

/* part 2, after "::" */
  for (;;) {
    if (*s == ':') {
      if (suffixlen == 0) break;
      s++;
      len++;
    } else if (suffixlen != 0) break;

    i = scan_xlong((char *)s,&u);
    if (!i) {
      len--;
      break;
    }

    if (suffixlen + prefixlen <= 12 && s[i] == '.') {
      j = ip4_scan(s,suffix+suffixlen);
      if (j) {
        suffixlen += 4;
        len += j;
        break;
      } else
        prefixlen = 12 - suffixlen; /* make end-of-loop test true */
    }

    suffix[suffixlen++] = (u >> 8);
    suffix[suffixlen++] = (u & 255);
    s += i; len += i;
    if (prefixlen + suffixlen == 16) break;
  }

  for (i = 0; i < suffixlen; i++)
    ip[16 - suffixlen + i] = suffix[i];

  return len;
}

/***
 @brief ip6_scanbracket
        parse IPv6 string address enclosed in brackets
 @param input:  pointer to IPv6 address string
        output: IPv6 char array
 @return int length of ip_address (ok > 0)
 */

unsigned int ip6_scanbracket(const char *s,char ip[16])
{
  unsigned int len;

  if (*s != '[') return 0;
  len = ip6_scan(s + 1,ip);
  if (!len) return 0;
  if (s[len + 1] != ']') return 0;
  return len + 2;
}

/**
 @brief ip6_ifscan
        parse compactified IPv6 address string 
        concatinated with the interface name: fe80::1%eth0
 @param input:  pointer to IPv6 address string
        output: IPv6 char array, stralloc interface_name
 @return int length of ip6_address/ip
 */

unsigned int ip6_ifscan(char *s,char ip[16],stralloc *ifname)
{
  int i; 
  int j = 0;
  int k = 0; 
  if (!stralloc_copys(ifname,"0")) return 0;

  if ((j = str_chr(s,'%'))) {
    if ((i = str_chr(s+j+1,' '))) k = i;
    else if ((i = str_chr(s+j+1,'\n'))) k = i;
    else if ((i = str_chr(s+j+1,'\t'))) k = i;
    if (k) s[j+k+1] = '\0'; /* input might contain trailing chars */
    if (!stralloc_copys(ifname,s+j+1)) return 0;
    s[j] = 0;
  }
  if (!stralloc_0(ifname)) return 0;

  return ip6_scan(s,ip);
}

/**
 @brief ip6_cidr
        parse compactified IPv6 address string
        concatinated with the prefix length:  fe80::1/64
 @param input:  pointer to IPv6 address string
        output: IPv6 char array, long plen 
 @return int length of ip6_address/ip
 */

unsigned int ip6_cidr(char *s,char ip[16],unsigned long *plen)
{
  unsigned int j = 0;
  *plen = 128UL;

  j = str_chr(s,'/');
  if (s[j] == '/') {
     s[j] = 0;
     j = scan_ulong(s+j+1,plen);
  }
  return ip6_scan((const char *)s,ip);
}

/**
 @brief ip6_bytestring
        parse IPv6 address and represent as char string with length prefix
 @param input:  IPv6 char array, prefix length
        output: pointer to stralloc bit string;
 @return n: number of bytes, if ok; -1: memory shortage
 */

unsigned int ip6_bytestring(stralloc *ipstring,char ip[16],int prefix)
{
  int i, j, n = 0;
  unsigned char lowbyte, highbyte;

  if (!stralloc_readyplus(ipstring,128)) return -1;
  if (!stralloc_copys(ipstring,"")) return -1;

  for (i = 0; i < 16; i++) {
    lowbyte = (unsigned char) (ip[i]) & 0x0f;
    highbyte = (unsigned char) (ip[i] >> 4) & 0x0f;

    for (j = 3; j >= 0; j--) {
      if (highbyte & (1 << j)) {
			  n++;
        if (!stralloc_cats(ipstring,"1")) return -1;
      } else {
			  n++;
        if (!stralloc_cats(ipstring,"0")) return -1;
      }
      prefix--;
			if (!prefix) goto DONE;
    }
    for (j = 3; j >= 0; j--) {
      if (lowbyte & (1 << j)) {
			  n++;
        if (!stralloc_cats(ipstring,"1")) return -1;
      } else {
			  n++;
        if (!stralloc_cats(ipstring,"0")) return -1;
      }
      prefix--;
			if (!prefix) goto DONE;
    }
  }

DONE:
  if (!stralloc_0(ipstring)) return -1;

  return n;
}