aboutsummaryrefslogtreecommitdiff
path: root/src/util/strings.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-26 12:36:51 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-26 12:36:51 +0000
commitaeb922926c639ffdd992f96cd125e47bb0e2c301 (patch)
tree85097e40305035ad337f0c0e8dc0f95343dbed3a /src/util/strings.c
parent7679eb4a51b8d0e9e4671dae00ca83c9f1b22de7 (diff)
downloadgnunet-aeb922926c639ffdd992f96cd125e47bb0e2c301.tar.gz
gnunet-aeb922926c639ffdd992f96cd125e47bb0e2c301.zip
-moving code to parse IPv4/IPv6 subnet specifications to strings and making it part of the public API
Diffstat (limited to 'src/util/strings.c')
-rw-r--r--src/util/strings.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/src/util/strings.c b/src/util/strings.c
index 581ac013d..c50669e62 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -1328,4 +1328,285 @@ GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *co
1328#endif 1328#endif
1329} 1329}
1330 1330
1331
1332/**
1333 * Parse an IPv4 network policy. The argument specifies a list of
1334 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
1335 * must be terminated with a semicolon). The network must be given in
1336 * dotted-decimal notation. The netmask can be given in CIDR notation
1337 * (/16) or in dotted-decimal (/255.255.0.0).
1338 *
1339 * @param routeList a string specifying the IPv4 subnets
1340 * @return the converted list, terminated with all zeros;
1341 * NULL if the synatx is flawed
1342 */
1343struct GNUNET_STRINGS_IPv4NetworkPolicy *
1344GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1345{
1346 unsigned int count;
1347 unsigned int i;
1348 unsigned int j;
1349 unsigned int len;
1350 int cnt;
1351 unsigned int pos;
1352 unsigned int temps[8];
1353 int slash;
1354 struct GNUNET_STRINGS_IPv4NetworkPolicy *result;
1355
1356 if (NULL == routeList)
1357 return NULL;
1358 len = strlen (routeList);
1359 if (0 == len)
1360 return NULL;
1361 count = 0;
1362 for (i = 0; i < len; i++)
1363 if (routeList[i] == ';')
1364 count++;
1365 result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv4NetworkPolicy) * (count + 1));
1366 i = 0;
1367 pos = 0;
1368 while (i < count)
1369 {
1370 cnt =
1371 SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
1372 &temps[1], &temps[2], &temps[3], &temps[4], &temps[5],
1373 &temps[6], &temps[7]);
1374 if (8 == cnt)
1375 {
1376 for (j = 0; j < 8; j++)
1377 if (temps[j] > 0xFF)
1378 {
1379 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
1380 &routeList[pos]);
1381 GNUNET_free (result);
1382 return NULL;
1383 }
1384 result[i].network.s_addr =
1385 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1386 temps[3]);
1387 result[i].netmask.s_addr =
1388 htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
1389 temps[7]);
1390 while (routeList[pos] != ';')
1391 pos++;
1392 pos++;
1393 i++;
1394 continue;
1395 }
1396 /* try second notation */
1397 cnt =
1398 SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
1399 &temps[2], &temps[3], &slash);
1400 if (5 == cnt)
1401 {
1402 for (j = 0; j < 4; j++)
1403 if (temps[j] > 0xFF)
1404 {
1405 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
1406 &routeList[pos]);
1407 GNUNET_free (result);
1408 return NULL;
1409 }
1410 result[i].network.s_addr =
1411 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1412 temps[3]);
1413 if ((slash <= 32) && (slash >= 0))
1414 {
1415 result[i].netmask.s_addr = 0;
1416 while (slash > 0)
1417 {
1418 result[i].netmask.s_addr =
1419 (result[i].netmask.s_addr >> 1) + 0x80000000;
1420 slash--;
1421 }
1422 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1423 while (';' != routeList[pos])
1424 pos++;
1425 pos++;
1426 i++;
1427 continue;
1428 }
1429 else
1430 {
1431 LOG (GNUNET_ERROR_TYPE_ERROR,
1432 _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1433 slash);
1434 GNUNET_free (result);
1435 return NULL; /* error */
1436 }
1437 }
1438 /* try third notation */
1439 slash = 32;
1440 cnt =
1441 SSCANF (&routeList[pos],
1442 "%u.%u.%u.%u;",
1443 &temps[0],
1444 &temps[1],
1445 &temps[2],
1446 &temps[3]);
1447 if (4 == cnt)
1448 {
1449 for (j = 0; j < 4; j++)
1450 if (temps[j] > 0xFF)
1451 {
1452 LOG (GNUNET_ERROR_TYPE_ERROR,
1453 _("Invalid format for IP: `%s'\n"),
1454 &routeList[pos]);
1455 GNUNET_free (result);
1456 return NULL;
1457 }
1458 result[i].network.s_addr =
1459 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1460 temps[3]);
1461 result[i].netmask.s_addr = 0;
1462 while (slash > 0)
1463 {
1464 result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
1465 slash--;
1466 }
1467 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1468 while (routeList[pos] != ';')
1469 pos++;
1470 pos++;
1471 i++;
1472 continue;
1473 }
1474 LOG (GNUNET_ERROR_TYPE_ERROR,
1475 _("Invalid format for IP: `%s'\n"),
1476 &routeList[pos]);
1477 GNUNET_free (result);
1478 return NULL; /* error */
1479 }
1480 if (pos < strlen (routeList))
1481 {
1482 LOG (GNUNET_ERROR_TYPE_ERROR,
1483 _("Invalid format for IP: `%s'\n"),
1484 &routeList[pos]);
1485 GNUNET_free (result);
1486 return NULL; /* oops */
1487 }
1488 return result; /* ok */
1489}
1490
1491
1492/**
1493 * Parse an IPv6 network policy. The argument specifies a list of
1494 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
1495 * must be terminated with a semicolon). The network must be given in
1496 * colon-hex notation. The netmask must be given in CIDR notation
1497 * (/16) or can be omitted to specify a single host.
1498 *
1499 * @param routeListX a string specifying the policy
1500 * @return the converted list, 0-terminated, NULL if the synatx is flawed
1501 */
1502struct GNUNET_STRINGS_IPv6NetworkPolicy *
1503GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1504{
1505 unsigned int count;
1506 unsigned int i;
1507 unsigned int len;
1508 unsigned int pos;
1509 int start;
1510 int slash;
1511 int ret;
1512 char *routeList;
1513 struct GNUNET_STRINGS_IPv6NetworkPolicy *result;
1514 unsigned int bits;
1515 unsigned int off;
1516 int save;
1517
1518 if (NULL == routeListX)
1519 return NULL;
1520 len = strlen (routeListX);
1521 if (0 == len)
1522 return NULL;
1523 routeList = GNUNET_strdup (routeListX);
1524 count = 0;
1525 for (i = 0; i < len; i++)
1526 if (';' == routeList[i])
1527 count++;
1528 if (';' != routeList[len - 1])
1529 {
1530 LOG (GNUNET_ERROR_TYPE_ERROR,
1531 _("Invalid network notation (does not end with ';': `%s')\n"),
1532 routeList);
1533 GNUNET_free (routeList);
1534 return NULL;
1535 }
1536
1537 result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv6NetworkPolicy) * (count + 1));
1538 i = 0;
1539 pos = 0;
1540 while (i < count)
1541 {
1542 start = pos;
1543 while (';' != routeList[pos])
1544 pos++;
1545 slash = pos;
1546 while ((slash >= start) && (routeList[slash] != '/'))
1547 slash--;
1548 if (slash < start)
1549 {
1550 memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr));
1551 slash = pos;
1552 }
1553 else
1554 {
1555 routeList[pos] = '\0';
1556 ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
1557 if (ret <= 0)
1558 {
1559 save = errno;
1560 if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128))
1561 {
1562 if (0 == ret)
1563 LOG (GNUNET_ERROR_TYPE_ERROR,
1564 _("Wrong format `%s' for netmask\n"),
1565 &routeList[slash + 1]);
1566 else
1567 {
1568 errno = save;
1569 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
1570 }
1571 GNUNET_free (result);
1572 GNUNET_free (routeList);
1573 return NULL;
1574 }
1575 off = 0;
1576 while (bits > 8)
1577 {
1578 result[i].netmask.s6_addr[off++] = 0xFF;
1579 bits -= 8;
1580 }
1581 while (bits > 0)
1582 {
1583 result[i].netmask.s6_addr[off] =
1584 (result[i].netmask.s6_addr[off] >> 1) + 0x80;
1585 bits--;
1586 }
1587 }
1588 }
1589 routeList[slash] = '\0';
1590 ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
1591 if (ret <= 0)
1592 {
1593 if (0 == ret)
1594 LOG (GNUNET_ERROR_TYPE_ERROR,
1595 _("Wrong format `%s' for network\n"),
1596 &routeList[slash + 1]);
1597 else
1598 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1599 "inet_pton");
1600 GNUNET_free (result);
1601 GNUNET_free (routeList);
1602 return NULL;
1603 }
1604 pos++;
1605 i++;
1606 }
1607 GNUNET_free (routeList);
1608 return result;
1609}
1610
1611
1331/* end of strings.c */ 1612/* end of strings.c */