File: //usr/local/fehQlibs-23/ip4.c
#include "fmt.h"
#include "scan.h"
#include "str.h"
#include "ip.h"
/**
@file ip4.c
@author djb, fefe, feh, kp
@source ucspi-tcp, ucspi-tcp6
@brief handling of IPv4 addresses
*/
/**
@brief ip4_fmt
converts IPv4 address to dotted decimal string format
@param input: IPv4 char array
output: IPv4 address string
@return int length of address (ok > 0)
*/
unsigned int ip4_fmt(char *s,char ip[4])
{
unsigned int len;
unsigned int i;
len = 0;
i = fmt_ulong(s,(unsigned long) (unsigned char) ip[0]); len += i; if (s) s += i;
if (s) { *s++ = '.'; } ++len;
i = fmt_ulong(s,(unsigned long) (unsigned char) ip[1]); len += i; if (s) s += i;
if (s) { *s++ = '.'; } ++len;
i = fmt_ulong(s,(unsigned long) (unsigned char) ip[2]); len += i; if (s) s += i;
if (s) { *s++ = '.'; } ++len;
i = fmt_ulong(s,(unsigned long) (unsigned char) ip[3]); len += i; if (s) s += i;
return len;
}
/**
@brief ia4_fmt
converts IPv4 address into DNS inverse nibble format
@param input: IPv4 char array
output: IPv4 address string
@return int length of address (ok > 0)
*/
unsigned int ia4_fmt(char *s,char ip[4])
{
unsigned int i;
unsigned int len;
len = 0;
i = fmt_ulong(s,(unsigned long) ip[3]); len += i; if (s) s += i;
i = fmt_str(s,"."); len += i; if (s) s += i;
i = fmt_ulong(s,(unsigned long) ip[2]); len += i; if (s) s += i;
i = fmt_str(s,"."); len += i; if (s) s += i;
i = fmt_ulong(s,(unsigned long) ip[1]); len += i; if (s) s += i;
i = fmt_str(s,"."); len += i; if (s) s += i;
i = fmt_ulong(s,(unsigned long) ip[0]); len += i; if (s) s += i;
i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i;
return len;
}
/**
@brief ip4_scan
parse IPv4 address string and convert to IP address array
@param input: IPv4 address string
output: IPv4 char array
@return int length of ip_address (ok > 0)
*/
unsigned int ip4_scan(const char *s,char ip[4])
{
unsigned int i;
unsigned int len;
unsigned long u;
byte_zero(ip,4);
len = 0;
i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[0] = u; s += i; len += i;
if (*s != '.') { return 0; } ++s; ++len;
i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[1] = u; s += i; len += i;
if (*s != '.') { return 0; } ++s; ++len;
i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[2] = u; s += i; len += i;
if (*s != '.') { return 0; } ++s; ++len;
i = scan_ulong((char *)s,&u); if (!i) { return 0; } ip[3] = u; s += i; len += i;
return len;
}
/**
@brief ip4_scanbracket
parse IPv4 address string enclosed in brackets and convert to IP address array
@param input: IPv4 char array
output: IPv4 char array
@return int length of ip_address (ok > 0)
*/
unsigned int ip4_scanbracket(const char *s,char ip[4])
{
unsigned int len;
if (*s != '[') return 0;
len = ip4_scan(s + 1,ip);
if (!len) return 0;
if (s[len + 1] != ']') return 0;
return len + 2;
}
/**
@brief ip4_cidr
parse IPv4 address string
concatinated with the prefix length: 192.168.1/24
@param input: IPv6 char array
output: IPv6 char array, long plen
@return int length of ip6_address/ip
*/
unsigned int ip4_cidr(char *s,char ip[4],unsigned long *plen)
{
unsigned int j = 0;
*plen = 32UL;
j = str_chr(s,'/');
if (s[j] == '/') {
s[j] = 0;
j = scan_ulong(s + j + 1,plen);
}
return ip4_scan((const char *)s,ip);
}
/**
@brief ip4_bytestring
parse IPv4 address and represent as char string with length prefix
@param input: IPv4 char array, prefix length
output: pointer to stralloc bytestring
@return n: number of bytes, if ok; -1: memory shortage; -2: input error
*/
unsigned int ip4_bytestring(stralloc *ipstring,char ip[4],int prefix)
{
int i, j, n = 0;
unsigned char number;
if (!stralloc_readyplus(ipstring,32)) return -1;
if (!stralloc_copys(ipstring,"")) return -1;
for (i = 0; i < 4; i++) {
number = (unsigned char) ip[i];
if (number > 255) return -2;
for (j = 7; j >= 0; j--) {
if (number & (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;
}