/** * @file ipaddr.h * @author Ambroz Bizjak * * @section LICENSE * * This file is part of BadVPN. * * BadVPN is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * BadVPN is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * @section DESCRIPTION * * IP address parsing functions. */ #ifndef BADVPN_MISC_IPADDR_H #define BADVPN_MISC_IPADDR_H #include #include #include #include struct ipv4_ifaddr { uint32_t addr; int prefix; }; static int ipaddr_parse_ipv4_addr (char *name, size_t name_len, uint32_t *out_addr); static int ipaddr_parse_ipv4_ifaddr (char *str, struct ipv4_ifaddr *out); static int ipaddr_ipv4_ifaddr_from_addr_mask (uint32_t addr, uint32_t mask, struct ipv4_ifaddr *out); static int ipaddr_char_is_digit (char c) { return (c >= '0' && c <= '9'); } static int ipaddr_parse_number (char *data, size_t data_len, int *out) { if (data_len == 0) { return 0; } for (size_t i = 0; i < data_len; i++) { if (!ipaddr_char_is_digit(data[i])) { return 0; } } char data2[data_len + 1]; memcpy(data2, data, data_len); data2[data_len] = '\0'; *out = atoi(data2); return 1; } int ipaddr_parse_ipv4_addr (char *name, size_t name_len, uint32_t *out_addr) { for (size_t i = 0; ; i++) { size_t j; for (j = 0; j < name_len && name[j] != '.'; j++) { if (!ipaddr_char_is_digit(name[j])) { return 0; } } if ((j == name_len && i < 3) || (j < name_len && i == 3)) { return 0; } if (j < 1 || j > 3) { return 0; } int d; if (!ipaddr_parse_number(name, j, &d)) { return 0; } if (d > 255) { return 0; } ((uint8_t *)out_addr)[i] = d; if (i == 3) { return 1; } name += j + 1; name_len -= j + 1; } } int ipaddr_parse_ipv4_ifaddr (char *str, struct ipv4_ifaddr *out) { char *slash = strstr(str, "/"); if (!slash) { return 0; } if (!ipaddr_parse_ipv4_addr(str, (slash - str), &out->addr)) { return 0; } char *prefix = slash + 1; size_t prefix_len = strlen(prefix); if (prefix_len > 2) { return 0; } if (!ipaddr_parse_number(prefix, prefix_len, &out->prefix)) { return 0; } if (out->prefix > 32) { return 0; } return 1; } int ipaddr_ipv4_ifaddr_from_addr_mask (uint32_t addr, uint32_t mask, struct ipv4_ifaddr *out) { // check mask uint32_t t = 0; int i; for (i = 0; i <= 32; i++) { if (ntoh32(mask) == t) { break; } if (i < 32) { t |= (1 << (32 - i - 1)); } } if (!(i <= 32)) { return 0; } out->addr = addr; out->prefix = i; return 1; } #endif