-/**
- * Parse a network specification. The argument specifies
- * a list of networks. The format is
- * <tt>[network/netmask;]*</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).
- * <p>
- * @param routeList a string specifying the forbidden networks
- * @return the converted list, NULL if the synatx is flawed
- */
-static struct IPv4NetworkSet *
-parse_ipv4_specification (const char *routeList)
-{
- unsigned int count;
- unsigned int i;
- unsigned int j;
- unsigned int len;
- int cnt;
- unsigned int pos;
- unsigned int temps[8];
- int slash;
- struct IPv4NetworkSet *result;
-
- if (routeList == NULL)
- return NULL;
- len = strlen (routeList);
- if (len == 0)
- return NULL;
- count = 0;
- for (i = 0; i < len; i++)
- if (routeList[i] == ';')
- count++;
- result = GNUNET_malloc (sizeof (struct IPv4NetworkSet) * (count + 1));
- /* add termination */
- memset (result, 0, sizeof (struct IPv4NetworkSet) * (count + 1));
- i = 0;
- pos = 0;
- while (i < count)
- {
- 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]);
- if (cnt == 8)
- {
- for (j = 0; j < 8; j++)
- if (temps[j] > 0xFF)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid format for IP: `%s'\n"), &routeList[pos]);
- GNUNET_free (result);
- return NULL;
- }
- result[i].network.s_addr
- =
- htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
- temps[3]);
- result[i].netmask.s_addr =
- htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
- temps[7]);
- while (routeList[pos] != ';')
- pos++;
- pos++;
- i++;
- continue;
- }
- /* try second notation */
- cnt = sscanf (&routeList[pos],
- "%u.%u.%u.%u/%u;",
- &temps[0], &temps[1], &temps[2], &temps[3], &slash);
- if (cnt == 5)
- {
- for (j = 0; j < 4; j++)
- if (temps[j] > 0xFF)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid format for IP: `%s'\n"), &routeList[pos]);
- GNUNET_free (result);
- return NULL;
- }
- result[i].network.s_addr
- =
- htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
- temps[3]);
- if ((slash <= 32) && (slash >= 0))
- {
- result[i].netmask.s_addr = 0;
- while (slash > 0)
- {
- result[i].netmask.s_addr
- = (result[i].netmask.s_addr >> 1) + 0x80000000;
- slash--;
- }
- result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
- while (routeList[pos] != ';')
- pos++;
- pos++;
- i++;
- continue;
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _
- ("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
- slash);
- GNUNET_free (result);
- return NULL; /* error */
- }
- }
- /* try third notation */
- slash = 32;
- cnt = sscanf (&routeList[pos],
- "%u.%u.%u.%u;", &temps[0], &temps[1], &temps[2], &temps[3]);
- if (cnt == 4)
- {
- for (j = 0; j < 4; j++)
- if (temps[j] > 0xFF)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid format for IP: `%s'\n"), &routeList[pos]);
- GNUNET_free (result);
- return NULL;
- }
- result[i].network.s_addr
- =
- htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
- temps[3]);
- result[i].netmask.s_addr = 0;
- while (slash > 0)
- {
- result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
- slash--;
- }
- result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
- while (routeList[pos] != ';')
- pos++;
- pos++;
- i++;
- continue;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid format for IP: `%s'\n"), &routeList[pos]);
- GNUNET_free (result);
- return NULL; /* error */
- }
- if (pos < strlen (routeList))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid format for IP: `%s'\n"), &routeList[pos]);
- GNUNET_free (result);
- return NULL; /* oops */
- }
- return result; /* ok */
-}