diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-10-26 12:36:51 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-10-26 12:36:51 +0000 |
commit | aeb922926c639ffdd992f96cd125e47bb0e2c301 (patch) | |
tree | 85097e40305035ad337f0c0e8dc0f95343dbed3a /src/util/strings.c | |
parent | 7679eb4a51b8d0e9e4671dae00ca83c9f1b22de7 (diff) | |
download | gnunet-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.c | 281 |
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 | */ | ||
1343 | struct GNUNET_STRINGS_IPv4NetworkPolicy * | ||
1344 | GNUNET_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 | */ | ||
1502 | struct GNUNET_STRINGS_IPv6NetworkPolicy * | ||
1503 | GNUNET_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 */ |