/**
- * Convert the utf-8 input string to lowercase
- * Output needs to be allocated appropriately
+ * Convert the utf-8 input string to lowercase.
+ * Output needs to be allocated appropriately.
*
* @param input input string
* @param output output buffer
*/
void
-GNUNET_STRINGS_utf8_tolower(const char* input, char** output)
+GNUNET_STRINGS_utf8_tolower (const char *input,
+ char *output)
{
uint8_t *tmp_in;
size_t len;
tmp_in = u8_tolower ((uint8_t*)input, strlen ((char *) input),
NULL, UNINORM_NFD, NULL, &len);
- memcpy(*output, tmp_in, len);
- (*output)[len] = '\0';
+ memcpy(output, tmp_in, len);
+ output[len] = '\0';
free(tmp_in);
}
/**
- * Convert the utf-8 input string to uppercase
- * Output needs to be allocated appropriately
+ * Convert the utf-8 input string to uppercase.
+ * Output needs to be allocated appropriately.
*
* @param input input string
* @param output output buffer
*/
void
-GNUNET_STRINGS_utf8_toupper(const char* input, char** output)
+GNUNET_STRINGS_utf8_toupper(const char *input,
+ char *output)
{
uint8_t *tmp_in;
size_t len;
tmp_in = u8_toupper ((uint8_t*)input, strlen ((char *) input),
NULL, UNINORM_NFD, NULL, &len);
- memcpy(*output, tmp_in, len);
- (*output)[len] = '\0';
- free(tmp_in);
+ memcpy (output, tmp_in, len);
+ output[len] = '\0';
+ free (tmp_in);
}
return a - '0';
if ((a >= 'A') && (a <= 'V'))
return (a - 'A' + 10);
+ if ((a >= 'a') && (a <= 'v'))
+ return (a - 'a' + 10);
return -1;
}
* out_size must match exactly the size of the data before it was encoded.
*
* @param enc the encoding
- * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing)
+ * @param enclen number of characters in @a enc (without 0-terminator, which can be missing)
* @param out location where to store the decoded data
- * @param out_size size of the output buffer
- * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding
+ * @param out_size size of the output buffer @a out
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding
*/
int
GNUNET_STRINGS_string_to_data (const char *enc, size_t enclen,
/**
- * Check whether 'filename' is absolute or not, and if it's an URI
+ * Check whether @a filename is absolute or not, and if it's an URI
*
* @param filename filename to check
- * @param can_be_uri GNUNET_YES to check for being URI, GNUNET_NO - to
+ * @param can_be_uri #GNUNET_YES to check for being URI, #GNUNET_NO - to
* assume it's not URI
- * @param r_is_uri a pointer to an int that is set to GNUNET_YES if 'filename'
- * is URI and to GNUNET_NO otherwise. Can be NULL. If 'can_be_uri' is
- * not GNUNET_YES, *r_is_uri is set to GNUNET_NO.
+ * @param r_is_uri a pointer to an int that is set to #GNUNET_YES if @a filename
+ * is URI and to #GNUNET_NO otherwise. Can be NULL. If @a can_be_uri is
+ * not #GNUNET_YES, `* r_is_uri` is set to #GNUNET_NO.
* @param r_uri_scheme a pointer to a char * that is set to a pointer to URI scheme.
* The string is allocated by the function, and should be freed with
- * GNUNET_free (). Can be NULL.
- * @return GNUNET_YES if 'filename' is absolute, GNUNET_NO otherwise.
+ * GNUNET_free(). Can be NULL.
+ * @return #GNUNET_YES if @a filename is absolute, #GNUNET_NO otherwise.
*/
int
-GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri,
- int *r_is_uri, char **r_uri_scheme)
+GNUNET_STRINGS_path_is_absolute (const char *filename,
+ int can_be_uri,
+ int *r_is_uri,
+ char **r_uri_scheme)
{
#if WINDOWS
size_t len;
/**
- * Perform 'checks' on 'filename'
+ * Perform @a checks on @a filename.
*
* @param filename file to check
* @param checks checks to perform
- * @return GNUNET_YES if all checks pass, GNUNET_NO if at least one of them
- * fails, GNUNET_SYSERR when a check can't be performed
+ * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them
+ * fails, #GNUNET_SYSERR when a check can't be performed
*/
int
GNUNET_STRINGS_check_filename (const char *filename,
* The string is expected to have the format "[ABCD::01]:80".
*
* @param zt_addr 0-terminated string. May be mangled by the function.
- * @param addrlen length of zt_addr (not counting 0-terminator).
+ * @param addrlen length of @a zt_addr (not counting 0-terminator).
* @param r_buf a buffer to fill. Initially gets filled with zeroes,
* then its sin6_port, sin6_family and sin6_addr are set appropriately.
- * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
- * case the contents of r_buf are undefined.
+ * @return #GNUNET_OK if conversion succeded.
+ * #GNUNET_SYSERR otherwise, in which
+ * case the contents of @a r_buf are undefined.
*/
int
GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
* The string is expected to have the format "1.2.3.4:80".
*
* @param zt_addr 0-terminated string. May be mangled by the function.
- * @param addrlen length of zt_addr (not counting 0-terminator).
+ * @param addrlen length of @a zt_addr (not counting 0-terminator).
* @param r_buf a buffer to fill.
- * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which case
- * the contents of r_buf are undefined.
+ * @return #GNUNET_OK if conversion succeded.
+ * #GNUNET_SYSERR otherwise, in which case
+ * the contents of @a r_buf are undefined.
*/
int
GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
/**
- * Tries to convert 'addr' string to an IP (v4 or v6) address.
+ * Tries to convert @a addr string to an IP (v4 or v6) address.
* Will automatically decide whether to treat 'addr' as v4 or v6 address.
*
* @param addr a string, may not be 0-terminated.
- * @param addrlen number of bytes in addr (if addr is 0-terminated,
+ * @param addrlen number of bytes in @a addr (if addr is 0-terminated,
* 0-terminator should not be counted towards addrlen).
* @param r_buf a buffer to fill.
- * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
+ * @return #GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
* case the contents of r_buf are undefined.
*/
int
struct sockaddr_storage *r_buf)
{
if (addr[0] == '[')
- return GNUNET_STRINGS_to_address_ipv6 (addr, addrlen, (struct sockaddr_in6 *) r_buf);
- return GNUNET_STRINGS_to_address_ipv4 (addr, addrlen, (struct sockaddr_in *) r_buf);
+ return GNUNET_STRINGS_to_address_ipv6 (addr,
+ addrlen,
+ (struct sockaddr_in6 *) r_buf);
+ return GNUNET_STRINGS_to_address_ipv4 (addr,
+ addrlen,
+ (struct sockaddr_in *) r_buf);
}
* freed with a single call to GNUNET_free ();
*/
static char *const *
-_make_continuous_arg_copy (int argc, char *const *argv)
+_make_continuous_arg_copy (int argc,
+ char *const *argv)
{
size_t argvsize = 0;
int i;
* @param argv argv (as given by main())
* @param u8argc a location to store new argc in (though it's th same as argc)
* @param u8argv a location to store new argv in
- * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
*/
int
GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv)
}
+/**
+ * Parse the given port policy. The format is
+ * "[!]SPORT[-DPORT]".
+ *
+ * @param port_policy string to parse
+ * @param pp policy to fill in
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ * @a port_policy is malformed
+ */
+static int
+parse_port_policy (const char *port_policy,
+ struct GNUNET_STRINGS_PortPolicy *pp)
+{
+ const char *pos;
+ int s;
+ int e;
+ char eol[2];
+
+ pos = port_policy;
+ if ('!' == *pos)
+ {
+ pp->negate_portrange = GNUNET_YES;
+ pos++;
+ }
+ if (2 == sscanf (pos,
+ "%u-%u%1s",
+ &s, &e, eol))
+ {
+ if ( (0 == s) ||
+ (s > 0xFFFF) ||
+ (e < s) ||
+ (e > 0xFFFF) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Port not in range\n"));
+ return GNUNET_SYSERR;
+ }
+ pp->start_port = (uint16_t) s;
+ pp->end_port = (uint16_t) e;
+ return GNUNET_OK;
+ }
+ if (1 == sscanf (pos,
+ "%u%1s",
+ &s,
+ eol))
+ {
+ if ( (0 == s) ||
+ (s > 0xFFFF) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Port not in range\n"));
+ return GNUNET_SYSERR;
+ }
+
+ pp->start_port = (uint16_t) s;
+ pp->end_port = (uint16_t) s;
+ return GNUNET_OK;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Malformed port policy `%s'\n"),
+ port_policy);
+ return GNUNET_SYSERR;
+}
+
+
/**
* Parse an IPv4 network policy. The argument specifies a list of
- * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
- * must be terminated with a semicolon). The network must be given in
+ * subnets. The format is
+ * <tt>(network[/netmask][:SPORT[-DPORT]];)*</tt> (no whitespace, must
+ * be terminated with a semicolon). The network must be given in
* dotted-decimal notation. The netmask can be given in CIDR notation
* (/16) or in dotted-decimal (/255.255.0.0).
*
- * @param routeList a string specifying the IPv4 subnets
+ * @param routeListX a string specifying the IPv4 subnets
* @return the converted list, terminated with all zeros;
* NULL if the synatx is flawed
*/
struct GNUNET_STRINGS_IPv4NetworkPolicy *
-GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
+GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
{
unsigned int count;
unsigned int i;
unsigned int temps[8];
int slash;
struct GNUNET_STRINGS_IPv4NetworkPolicy *result;
+ int colon;
+ int end;
+ char *routeList;
- if (NULL == routeList)
+ if (NULL == routeListX)
return NULL;
- len = strlen (routeList);
+ len = strlen (routeListX);
if (0 == len)
return NULL;
+ routeList = GNUNET_strdup (routeListX);
count = 0;
for (i = 0; i < len; i++)
if (routeList[i] == ';')
pos = 0;
while (i < count)
{
+ for (colon = pos; ':' != routeList[colon]; colon++)
+ if ( (';' == routeList[colon]) ||
+ ('\0' == routeList[colon]) )
+ break;
+ end = colon;
+ for (end = colon; ';' != routeList[end]; end++)
+ if ('\0' == routeList[end])
+ break;
+ if ('\0' == routeList[end])
+ break;
+ routeList[end] = '\0';
+ if (':' == routeList[colon])
+ {
+ routeList[colon] = '\0';
+ if (GNUNET_OK != parse_port_policy (&routeList[colon + 1],
+ &result[i].pp))
+ break;
+ }
cnt =
- SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
- &temps[1], &temps[2], &temps[3], &temps[4], &temps[5],
- &temps[6], &temps[7]);
+ SSCANF (&routeList[pos],
+ "%u.%u.%u.%u/%u.%u.%u.%u",
+ &temps[0],
+ &temps[1],
+ &temps[2],
+ &temps[3],
+ &temps[4],
+ &temps[5],
+ &temps[6],
+ &temps[7]);
if (8 == cnt)
{
for (j = 0; j < 8; j++)
if (temps[j] > 0xFF)
{
- LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ _("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL;
}
result[i].network.s_addr =
result[i].netmask.s_addr =
htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
temps[7]);
- while (routeList[pos] != ';')
- pos++;
- pos++;
+ pos = end + 1;
i++;
continue;
}
/* try second notation */
cnt =
- SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
- &temps[2], &temps[3], &slash);
+ SSCANF (&routeList[pos],
+ "%u.%u.%u.%u/%u",
+ &temps[0],
+ &temps[1],
+ &temps[2],
+ &temps[3],
+ &slash);
if (5 == cnt)
{
for (j = 0; j < 4; j++)
if (temps[j] > 0xFF)
{
- LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ _("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL;
}
result[i].network.s_addr =
slash--;
}
result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
- while (';' != routeList[pos])
- pos++;
- pos++;
+ pos = end + 1;
i++;
continue;
}
else
{
- LOG (GNUNET_ERROR_TYPE_ERROR,
+ LOG (GNUNET_ERROR_TYPE_WARNING,
_("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
slash);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL; /* error */
}
}
slash = 32;
cnt =
SSCANF (&routeList[pos],
- "%u.%u.%u.%u;",
+ "%u.%u.%u.%u",
&temps[0],
&temps[1],
&temps[2],
for (j = 0; j < 4; j++)
if (temps[j] > 0xFF)
{
- LOG (GNUNET_ERROR_TYPE_ERROR,
+ LOG (GNUNET_ERROR_TYPE_WARNING,
_("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL;
}
result[i].network.s_addr =
slash--;
}
result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
- while (routeList[pos] != ';')
- pos++;
- pos++;
+ pos = end + 1;
i++;
continue;
}
- LOG (GNUNET_ERROR_TYPE_ERROR,
+ LOG (GNUNET_ERROR_TYPE_WARNING,
_("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL; /* error */
}
if (pos < strlen (routeList))
{
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid format for IP: `%s'\n"),
- &routeList[pos]);
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ _("Invalid format: `%s'\n"),
+ &routeListX[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL; /* oops */
}
+ GNUNET_free (routeList);
return result; /* ok */
}
/**
* Parse an IPv6 network policy. The argument specifies a list of
- * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
- * must be terminated with a semicolon). The network must be given in
- * colon-hex notation. The netmask must be given in CIDR notation
- * (/16) or can be omitted to specify a single host.
+ * subnets. The format is <tt>(network[/netmask[:SPORT[-DPORT]]];)*</tt>
+ * (no whitespace, must be terminated with a semicolon). The network
+ * must be given in colon-hex notation. The netmask must be given in
+ * CIDR notation (/16) or can be omitted to specify a single host.
+ * Note that the netmask is mandatory if ports are specified.
*
* @param routeListX a string specifying the policy
* @return the converted list, 0-terminated, NULL if the synatx is flawed
unsigned int bits;
unsigned int off;
int save;
+ int colon;
if (NULL == routeListX)
return NULL;
count++;
if (';' != routeList[len - 1])
{
- LOG (GNUNET_ERROR_TYPE_ERROR,
+ LOG (GNUNET_ERROR_TYPE_WARNING,
_("Invalid network notation (does not end with ';': `%s')\n"),
routeList);
GNUNET_free (routeList);
slash = pos;
while ((slash >= start) && (routeList[slash] != '/'))
slash--;
+
if (slash < start)
{
- memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr));
+ memset (&result[i].netmask,
+ 0xFF,
+ sizeof (struct in6_addr));
slash = pos;
}
else
{
routeList[pos] = '\0';
+ for (colon = pos; ':' != routeList[colon]; colon--)
+ if ('/' == routeList[colon])
+ break;
+ if (':' == routeList[colon])
+ {
+ routeList[colon] = '\0';
+ if (GNUNET_OK != parse_port_policy (&routeList[colon + 1],
+ &result[i].pp))
+ {
+ GNUNET_free (result);
+ GNUNET_free (routeList);
+ return NULL;
+ }
+ }
ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
if (ret <= 0)
{
save = errno;
- if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128))
+ if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits > 128))
{
if (0 == ret)
- LOG (GNUNET_ERROR_TYPE_ERROR,
+ LOG (GNUNET_ERROR_TYPE_WARNING,
_("Wrong format `%s' for netmask\n"),
&routeList[slash + 1]);
else
{
errno = save;
- LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
+ LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_pton");
}
GNUNET_free (result);
GNUNET_free (routeList);
if (ret <= 0)
{
if (0 == ret)
- LOG (GNUNET_ERROR_TYPE_ERROR,
+ LOG (GNUNET_ERROR_TYPE_WARNING,
_("Wrong format `%s' for network\n"),
&routeList[slash + 1]);
else