Skip to content

Commit

Permalink
IPv4 address 0.0.0.0 and IPv6 address :: correspond to empty strings …
Browse files Browse the repository at this point in the history
…in FTL settings

Signed-off-by: DL6ER <[email protected]>
  • Loading branch information
DL6ER committed Nov 15, 2023
1 parent a691305 commit a1aaa35
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 11 deletions.
19 changes: 16 additions & 3 deletions src/api/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ static cJSON *addJSONvalue(const enum conf_type conf_type, union conf_value *val
return cJSON_CreateStringReference(get_temp_unit_str(val->temp_unit));
case CONF_STRUCT_IN_ADDR:
{
// Special case 0.0.0.0 -> return empty string
if(val->in_addr.s_addr == INADDR_ANY)
return cJSON_CreateStringReference("");

// else: normal address
char addr4[INET_ADDRSTRLEN] = { 0 };
inet_ntop(AF_INET, &val->in_addr, addr4, INET_ADDRSTRLEN);
return cJSON_CreateString(addr4); // Performs a copy
Expand Down Expand Up @@ -400,10 +405,18 @@ static const char *getJSONvalue(struct conf_item *conf_item, cJSON *elem, struct
struct in_addr addr4 = { 0 };
if(!cJSON_IsString(elem))
return "not of type string";
if(!inet_pton(AF_INET, elem->valuestring, &addr4))
if(strlen(elem->valuestring) == 0)
{
// Special case: empty string -> 0.0.0.0
addr4.s_addr = INADDR_ANY;
}
else if(inet_pton(AF_INET, elem->valuestring, &addr4))
{
// Set item
memcpy(&conf_item->v.in_addr, &addr4, sizeof(addr4));
}
else
return "not a valid IPv4 address";
// Set item
memcpy(&conf_item->v.in_addr, &addr4, sizeof(addr4));
log_debug(DEBUG_CONFIG, "%s = %s", conf_item->k, elem->valuestring);
break;
}
Expand Down
14 changes: 12 additions & 2 deletions src/config/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,12 @@ static bool readStringValue(struct conf_item *conf_item, const char *value, stru
case CONF_STRUCT_IN_ADDR:
{
struct in_addr addr4 = { 0 };
if(inet_pton(AF_INET, value, &addr4))
if(strlen(value) == 0)
{
// Special case: empty string -> 0.0.0.0
conf_item->v.in_addr.s_addr = INADDR_ANY;
}
else if(inet_pton(AF_INET, value, &addr4))
memcpy(&conf_item->v.in_addr, &addr4, sizeof(addr4));
else
{
Expand All @@ -307,7 +312,12 @@ static bool readStringValue(struct conf_item *conf_item, const char *value, stru
case CONF_STRUCT_IN6_ADDR:
{
struct in6_addr addr6 = { 0 };
if(inet_pton(AF_INET6, value, &addr6))
if(strlen(value) == 0)
{
// Special case: empty string -> ::
conf_item->v.in6_addr = in6addr_any;
}
else if(inet_pton(AF_INET6, value, &addr6))
memcpy(&conf_item->v.in6_addr, &addr6, sizeof(addr6));
else
{
Expand Down
42 changes: 38 additions & 4 deletions src/config/toml_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,27 @@ void writeTOMLvalue(FILE * fp, const int indent, const enum conf_type t, union c
break;
case CONF_STRUCT_IN_ADDR:
{
// Special case: 0.0.0.0 -> return empty string
if(v->in_addr.s_addr == INADDR_ANY)
{
printTOMLstring(fp, "", toml);
break;
}
// else: normal address
char addr4[INET_ADDRSTRLEN] = { 0 };
inet_ntop(AF_INET, &v->in_addr, addr4, INET_ADDRSTRLEN);
printTOMLstring(fp, addr4, toml);
break;
}
case CONF_STRUCT_IN6_ADDR:
{
// Special case: :: -> return empty string
if(memcmp(&v->in6_addr, &in6addr_any, sizeof(in6addr_any)) == 0)
{
printTOMLstring(fp, "", toml);
break;
}
// else: normal address
char addr6[INET6_ADDRSTRLEN] = { 0 };
inet_ntop(AF_INET6, &v->in6_addr, addr6, INET6_ADDRSTRLEN);
printTOMLstring(fp, addr6, toml);
Expand Down Expand Up @@ -654,7 +668,12 @@ void readTOMLvalue(struct conf_item *conf_item, const char* key, toml_table_t *t
const toml_datum_t val = toml_string_in(toml, key);
if(val.ok)
{
if(inet_pton(AF_INET, val.u.s, &addr4))
if(strlen(val.u.s) == 0)
{
// Special case: empty string -> 0.0.0.0
conf_item->v.in_addr.s_addr = INADDR_ANY;
}
else if(inet_pton(AF_INET, val.u.s, &addr4))
memcpy(&conf_item->v.in_addr, &addr4, sizeof(addr4));
else
log_warn("Config %s is invalid (not of type IPv4 address)", conf_item->k);
Expand All @@ -670,7 +689,12 @@ void readTOMLvalue(struct conf_item *conf_item, const char* key, toml_table_t *t
const toml_datum_t val = toml_string_in(toml, key);
if(val.ok)
{
if(inet_pton(AF_INET6, val.u.s, &addr6))
if(strlen(val.u.s) == 0)
{
// Special case: empty string -> ::
conf_item->v.in6_addr = in6addr_any;
}
else if(inet_pton(AF_INET6, val.u.s, &addr6))
memcpy(&conf_item->v.in6_addr, &addr6, sizeof(addr6));
else
log_warn("Config %s is invalid (not of type IPv6 address)", conf_item->k);
Expand Down Expand Up @@ -910,7 +934,12 @@ bool readEnvValue(struct conf_item *conf_item, struct config *newconf)
case CONF_STRUCT_IN_ADDR:
{
struct in_addr addr4 = { 0 };
if(inet_pton(AF_INET, envvar, &addr4))
if(strlen(envvar) == 0)
{
// Special case: empty string -> 0.0.0.0
conf_item->v.in_addr.s_addr = INADDR_ANY;
}
else if(inet_pton(AF_INET, envvar, &addr4))
memcpy(&conf_item->v.in_addr, &addr4, sizeof(addr4));
else
log_warn("ENV %s is invalid (not of type IPv4 address)", envkey);
Expand All @@ -919,7 +948,12 @@ bool readEnvValue(struct conf_item *conf_item, struct config *newconf)
case CONF_STRUCT_IN6_ADDR:
{
struct in6_addr addr6 = { 0 };
if(inet_pton(AF_INET6, envvar, &addr6))
if(strlen(envvar) == 0)
{
// Special case: empty string -> ::
conf_item->v.in6_addr = in6addr_any;
}
else if(inet_pton(AF_INET6, envvar, &addr6))
memcpy(&conf_item->v.in6_addr, &addr6, sizeof(addr6));
else
log_warn("ENV %s is invalid (not of type IPv6 address)", envkey);
Expand Down
10 changes: 8 additions & 2 deletions test/api/libs/responseVerifyer.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ def verify_teleporter_zip(self, teleporter_archive: bytes):

# Check if a string is a valid IPv4 address
def valid_ipv4(self, addr: str) -> bool:
# Empty string is valid (0.0.0.0)
if len(addr) == 0:
return true
try:
if type(ipaddress.ip_address(addr)) is ipaddress.IPv4Address:
return True
Expand All @@ -232,6 +235,9 @@ def valid_ipv4(self, addr: str) -> bool:

# Check if a string is a valid IPv6 address
def valid_ipv6(self, addr: str) -> bool:
# Empty string is valid (::)
if len(addr) == 0:
return true
try:
if type(ipaddress.ip_address(addr)) is ipaddress.IPv6Address:
return True
Expand All @@ -253,10 +259,10 @@ def verify_type(self, prop: any, yaml_type: str, yaml_nullable: bool, yaml_forma
return False
if yaml_format is not None:
# Check if the format is correct
if yaml_format == "ipv4" and not type(ipaddress.ip_address(prop)) is ipaddress.IPv4Address:
if yaml_format == "ipv4" and not (len(prop) == 0 or type(ipaddress.ip_address(prop)) is ipaddress.IPv4Address):
self.errors.append("Property \"" + str(prop) + "\" is not a valid IPv4 address")
return False
elif yaml_format == "ipv6" and not type(ipaddress.ip_address(prop)) is ipaddress.IPv6Address:
elif yaml_format == "ipv6" and not (len(prop) == 0 or type(ipaddress.ip_address(prop)) is ipaddress.IPv6Address):
self.errors.append("Property \"" + str(prop) + "\" is not a valid IPv6 address")
return False
return prop_type in self.YAML_TYPES[yaml_type]
Expand Down

0 comments on commit a1aaa35

Please sign in to comment.