UDTs IN_ADDR and IN6_ADDR Comments.

  While using Windows' API functions InetNtopW and InetPtonW I made comment in my post demonstrating those functions that IMO (In My Opinion) the UNIONs for the numeric/binary form of IP numbers are overly complicated. I also found a couple out-of-date REMs in the #INCLUDE files.

For reference I'll start with Microsoft's definitions at:
IN_ADDR for IPv4 and: IN6_ADDR for IPv6 (in C++).
struct in_addr {
  union {
    struct {
      u_char s_b1;
      u_char s_b2;
      u_char s_b3;
      u_char s_b4;
    } S_un_b;
    struct {
      u_short s_w1;
      u_short s_w2;
    } S_un_w;
    u_long S_addr;
  } S_un;
};
typedef struct in6_addr {
  union {
    u_char  Byte[16];
    u_short Word[8];
  } u;
} IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR;
IN_ADDR from PB installed directory \WinAPI\inaddr.inc and IN6_ADDR from PB installed directory \WinAPI\in6addr.inc
TYPE IN_ADDR_union_type1
    s_b1 AS BYTE
    s_b2 AS BYTE
    s_b3 AS BYTE
    s_b4 AS BYTE
END TYPE

TYPE IN_ADDR_union_type2
    s_w1 AS WORD
    s_w2 AS WORD
END TYPE

UNION IN_ADDR_union
    S_un_b AS IN_ADDR_union_type1
    S_un_w AS IN_ADDR_union_type2
    S_addr AS DWORD
END UNION

TYPE IN_ADDR
    S_un AS IN_ADDR_union
END TYPE
MACROs that ref IMP REMed out, see below my comments.
UNION IN6_ADDR_union
    nByte(15) AS BYTE
    nWord(7)  AS WORD
END UNION

TYPE IN6_ADDR
    u AS IN6_ADDR_union
END TYPE

TYPE in_addr6
    in6_addr
END TYPE

MACRO s6_bytes = u.Byte
MACRO s6_words = u.Word
in_addr from file \inaddr_JR.inc and in6_addr from file in6addr_JR.inc for by PB José Roca.
' // Size = 4 bytes
TYPE S_un_b_type BYTE
   s_b1 AS BYTE
   s_b2 AS BYTE
   s_b3 AS BYTE
   s_b4 AS BYTE
END TYPE

' // Size = 4 bytes
TYPE S_un_w_type WORD
   s_w1 AS WORD
   s_w2 AS WORD
END TYPE

' // Size = 4 bytes
UNION S_un
   S_un_b AS S_un_b_type
   S_un_w AS S_un_w_type
   S_addr AS DWORD
   s AS STRING * 4
END UNION

' // Size = 4 bytes
UNION in_addr
   S_un
   S_un AS S_un
END UNION

' can be used for most tcp & ip code
MACRO s_addrm = S_un.S_addr

' host on imp
MACRO s_hostm = S_Un.S_un_b.s_b2

' network
MACRO s_netm = S_Un.S_un_b.s_b1

' imp
MACRO s_impm = S_un.S_un_w.s_w2

' imp #
MACRO s_impnom = S_un.S_un_b.s_b4

' logical host
MACRO s_lhm = S_un.S_un_b.s_b3
UNION IN6_ADDR_UNION BYTE
   Byte(15) AS BYTE
   Word(7)  AS WORD
   nByte(15) AS BYTE
   nWord(7)  AS WORD
END UNION
MACRO S6_un = IN6_ADDR_UNION

UNION IN6_ADDR_UNION_2 BYTE
   IN6_ADDR_UNION
   u AS IN6_ADDR_UNION
END UNION

' // Size = 16 bytes
TYPE in6_addr BYTE
   IN6_ADDR_UNION_2
END TYPE

'#define in_addr6 in6_addr
MACRO in_addr6 = in6_addr

'//
'// Defines to match RFC 2553. 
'//
'#define _S6_un      u
'#define _S6_u8      Byte
'#define s6_addr     _S6_un._S6_u8

'//
'// Defines for our implementation.
'//
'#define s6_bytes    u.Byte
'#define s6_words    u.Word

MACRO s6_bytes = u.Byte
MACRO s6_words = u.Word
Comment Items
  1. IN_ADDR (IPv4) of all three sources have member names for the four bytes. Meaning access to each byte must be hard coded. The IN6_ADDR of all three use an array to access the bytes. This allows hard code with literals or use of a variable (i.g. for access in a loop). In the UNION I propose, and use, the array is applied to IN_ADDR too.
  2. In the PB include the TYPE IN_ADDR's only member is the IN_ADDR_union, which has two TYPEs as members, one for BYTEs with BYTE members and one for WORDs with WORD members. WORDs are not really applicable in IPv4. The variable construction to access s_b1, for example, is "VarName.S_un.S_un_b.s_b1". A single UNION containing BYTE array, DWORD and fixed length string members is shortened to "VarName.byt(0)". (See below about the string.) José's include is different but similarly convoluted, having multiple MACROs to shorten the variable and member construction.(he did put a string member)
  3. PB's TYPE IN6_ADDR only has IN6_ADDR_union as a member. Just rename the UNION to IN6_ADDR and skip the ".u" in variable - member construction. What is TYPE in_addr6 for, expected bad (keyboard) typing? A single UNION makes the MACROs redundant. José put has redundant nByte() and nWord() in "IN6_ADDR_UNION". And TYPE, UNION, UNION organization with MACROs. Interesting, here José did not put a string member though it would be more useful than in IPv4 due to 16 byte size of IPv6.
  4. The REMs referencing "imp" (Interface Message Processor) are for ARPANET which was decommissioned in 1990. José's copyright in this file is 10 years after that! Making the "host", "logical host" and "network" for the BYTEs not applicable when the file was created. Which bytes were network or host depended on the "class" in Classful networking in effect at the time. Classful has long since been replaced by CIDR.
  5. To send or receive an IP number in numeric form via TCP or UDP it must be a string type. For IPv4 MKDWD$ CVDWD can be used. IPv6 would require two MKQ$s or CVQs and a concatenation or two pokes(?)((MAK() can't join two QUADs AFAIK)) A string member avoids all that with "VarName.str"
  6. (repeat from a PB Forum post) The names IN_Addr (UNION) and %AF_INET (family) became slightly ambiguous when %AF_INET6 and IN6_Addr were added to support IPv6. I've added "4" to the older names here. ("6" and no "6" are unique (but is it IPv4 or was the "6" forgotten, check context to clarify)
Proposed UNIONs
UNION IN4_Addr DWORD
  byt(3) AS BYTE         'zero based index
  dwd    AS DWORD        'beware endian
  str    AS STRING * 4   'not text, string of bytes
END UNION
'
UNION IN6_Addr QWORD     '(64 bit OS?, ignored in 32) 
  byt(15) AS BYTE        'zero based index
  wrd(7)  AS WORD        'beware endian
  str     AS STRING * 16 'not text, string of bytes
END UNION

Why keep in two files? I suggest they be put in Ws2Def.inc with ADDRINFOW and ADDRINFOEXW ("A" versions should be considered legacy IMO).


Created on 15 February 2024.

To Dale's Notebook
go to Dale's Notebook index
To Programs
go to Programs index