/* ================================================== */
+int
+CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits)
+{
+ char *p, *net, *slash;
+ uint32_t a, b, c;
+ int bits, len, n;
+
+ p = CPS_SplitWord(line);
+
+ if (strcmp(line, "all") == 0) {
+ *all = 1;
+ net = p;
+ p = CPS_SplitWord(p);
+ } else {
+ *all = 0;
+ net = line;
+ }
+
+ /* Make sure there are no other arguments */
+ if (*p)
+ return 0;
+
+ /* No specified address or network means all IPv4 and IPv6 addresses */
+ if (!*net) {
+ ip->family = IPADDR_UNSPEC;
+ *subnet_bits = 0;
+ return 1;
+ }
+
+ slash = strchr(net, '/');
+ if (slash) {
+ if (sscanf(slash + 1, "%d%n", &bits, &len) != 1 || slash[len + 1] || bits < 0)
+ return 0;
+ *slash = '\0';
+ } else {
+ bits = -1;
+ }
+
+ if (UTI_StringToIP(net, ip)) {
+ if (bits >= 0)
+ *subnet_bits = bits;
+ else
+ *subnet_bits = ip->family == IPADDR_INET6 ? 128 : 32;
+ return 1;
+ }
+
+ /* Check for a shortened IPv4 network notation using only 1, 2, or 3 decimal
+ numbers. This is different than the numbers-and-dots notation accepted
+ by inet_aton()! */
+
+ a = b = c = 0;
+ n = sscanf(net, "%"PRIu32"%n.%"PRIu32"%n.%"PRIu32"%n", &a, &len, &b, &len, &c, &len);
+
+ if (n > 0 && !net[len]) {
+ if (a > 255 || b > 255 || c > 255)
+ return 0;
+
+ ip->family = IPADDR_INET4;
+ ip->addr.in4 = (a << 24) | (b << 16) | (c << 8);
+
+ if (bits >= 0)
+ *subnet_bits = bits;
+ else
+ *subnet_bits = n * 8;
+
+ return 1;
+ }
+
+ /* The last possibility is a hostname */
+ if (bits < 0 && DNS_Name2IPAddress(net, ip, 1) == DNS_Success) {
+ *subnet_bits = ip->family == IPADDR_INET6 ? 128 : 32;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* ================================================== */
+
int
CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance)
{
static void
parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
{
- char *p;
- unsigned long a, b, c, d, n;
- int all = 0;
- AllowDeny *new_node = NULL;
- IPAddr ip_addr;
-
- p = line;
-
- if (!strncmp(p, "all", 3)) {
- all = 1;
- p = CPS_SplitWord(line);
- }
+ int all, subnet_bits;
+ AllowDeny *node;
+ IPAddr ip;
- if (!*p) {
- /* Empty line applies to all addresses */
- new_node = (AllowDeny *)ARR_GetNewElement(restrictions);
- new_node->allow = allow;
- new_node->all = all;
- new_node->ip.family = IPADDR_UNSPEC;
- new_node->subnet_bits = 0;
- } else {
- char *slashpos;
- slashpos = strchr(p, '/');
- if (slashpos) *slashpos = 0;
-
- check_number_of_args(p, 1);
- n = 0;
- if (UTI_StringToIP(p, &ip_addr) ||
- (n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) >= 1) {
- new_node = (AllowDeny *)ARR_GetNewElement(restrictions);
- new_node->allow = allow;
- new_node->all = all;
-
- if (n == 0) {
- new_node->ip = ip_addr;
- if (ip_addr.family == IPADDR_INET6)
- new_node->subnet_bits = 128;
- else
- new_node->subnet_bits = 32;
- } else {
- new_node->ip.family = IPADDR_INET4;
-
- a &= 0xff;
- b &= 0xff;
- c &= 0xff;
- d &= 0xff;
-
- switch (n) {
- case 1:
- new_node->ip.addr.in4 = (a<<24);
- new_node->subnet_bits = 8;
- break;
- case 2:
- new_node->ip.addr.in4 = (a<<24) | (b<<16);
- new_node->subnet_bits = 16;
- break;
- case 3:
- new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8);
- new_node->subnet_bits = 24;
- break;
- case 4:
- new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
- new_node->subnet_bits = 32;
- break;
- default:
- assert(0);
- }
- }
-
- if (slashpos) {
- int specified_subnet_bits, n;
- n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
- if (n == 1) {
- new_node->subnet_bits = specified_subnet_bits;
- } else {
- command_parse_error();
- }
- }
+ if (!CPS_ParseAllowDeny(line, &all, &ip, &subnet_bits))
+ command_parse_error();
- } else {
- if (!slashpos && DNS_Name2IPAddress(p, &ip_addr, 1) == DNS_Success) {
- new_node = (AllowDeny *)ARR_GetNewElement(restrictions);
- new_node->allow = allow;
- new_node->all = all;
- new_node->ip = ip_addr;
- if (ip_addr.family == IPADDR_INET6)
- new_node->subnet_bits = 128;
- else
- new_node->subnet_bits = 32;
- } else {
- command_parse_error();
- }
- }
- }
+ node = ARR_GetNewElement(restrictions);
+ node->allow = allow;
+ node->all = all;
+ node->ip = ip;
+ node->subnet_bits = subnet_bits;
}
/* ================================================== */