Merge pull request #2 from 0x1eef/iscidraddr

Add support for CIDR notation (iscidraddr).
This commit is contained in:
0x1eef 2023-08-26 23:40:13 -03:00 committed by GitHub
commit fa580011e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 202 additions and 17 deletions

3
.gitignore vendored
View file

@ -1 +1,2 @@
test/runner
test/isinetaddr
test/iscidraddr

View file

@ -7,7 +7,11 @@ CC = cc
CFLAGS = -fstack-protector-all -I$(INCDIR) -Wall -Wextra -pedantic
test:
$(CC) $(CFLAGS) $(SRCDIR)/isinetaddr.c $(TESTDIR)/isinetaddr_test.c -o $(TESTBIN)
$(TESTBIN)
@$(CC) $(CFLAGS) $(SRCDIR)/isinetaddr.c $(TESTDIR)/isinetaddr_test.c -o $(TESTDIR)/isinetaddr
@echo -n test/isinetaddr: ''
@$(TESTDIR)/isinetaddr
@$(CC) $(CFLAGS) $(SRCDIR)/isinetaddr.c $(TESTDIR)/iscidraddr_test.c -o $(TESTDIR)/iscidraddr
@echo -n test/iscidraddr: ''
@$(TESTDIR)/isinetaddr
.PHONY: test

View file

@ -1,8 +1,9 @@
## About
isinetaddr is a simple C library that provides an interface that can
be used to validate one or more IPv4 addresses. The library is guided
by easy to extend [testcases](test/) that help verify safety and correctness.
be used to validate one or more IPv4 addresses (with optional support
for CIDR notation as well). The library is guided by easy to extend
[testcases](test/) that help verify safety and correctness.
## Examples
@ -58,6 +59,69 @@ foobar is an invalid IPv4 address
0.0.0.0.0 is an invalid IPv4 address
```
### CIDR notation (IPv4)
The `iscidraddr` function supports the same feature set as `isinetaddr`, and
in addition supports
[CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation).
The following example builds on the previous example:
```C
#include <isinetaddr.h>
#include <stdio.h>
#include <stdlib.h>
const char *strings[] = {
/* valid */
"127.0.0.1",
"1.1.1.1",
"0.0.0.0",
"127.0.0.1/8",
"127.0.0.1/16",
"127.0.0.1/32",
/* invalid */
"foobar",
"0.0.0.0.0",
"127.0.0.1/33",
"127.0.0.1/64"
};
int
main(void)
{
const char *str;
const int i = sizeof(strings) / sizeof(strings[0]);
for (int j = 0; j < i; j++) {
str = strings[j];
if (iscidraddr(str)) {
printf("%s is a valid IPv4 address\n", str);
} else {
printf("%s is an invalid IPv4 address\n", str);
}
}
return EXIT_SUCCESS;
}
```
When the above source code is compiled and run the output is
expected to be as follows:
```
$ cc -Iinclude src/isinetaddr.c share/isinetaddr/examples/iscidraddr.c -o example
$ ./example
127.0.0.1 is a valid IPv4 address
1.1.1.1 is a valid IPv4 address
0.0.0.0 is a valid IPv4 address
127.0.0.1/8 is a valid IPv4 address
127.0.0.1/16 is a valid IPv4 address
127.0.0.1/32 is a valid IPv4 address
foobar is an invalid IPv4 address
0.0.0.0.0 is an invalid IPv4 address
127.0.0.1/33 is an invalid IPv4 address
127.0.0.1/64 is an invalid IPv4 address
```
## Sources
* [Source code (GitHub)](https://github.com/0x1eef/isinetaddr#readme)

View file

@ -1,2 +1,3 @@
#pragma once
int isinetaddr(const char *str);
int iscidraddr(const char *str);

View file

@ -0,0 +1,34 @@
#include <isinetaddr.h>
#include <stdio.h>
#include <stdlib.h>
const char *strings[] = {
/* valid */
"127.0.0.1",
"1.1.1.1",
"0.0.0.0",
"127.0.0.1/8",
"127.0.0.1/16",
"127.0.0.1/32",
/* invalid */
"foobar",
"0.0.0.0.0",
"127.0.0.1/33",
};
int
main(void)
{
const char *str;
const int i = sizeof(strings) / sizeof(strings[0]);
for (int j = 0; j < i; j++) {
str = strings[j];
if (iscidraddr(str)) {
printf("%s is a valid IPv4 address\n", str);
} else {
printf("%s is an invalid IPv4 address\n", str);
}
}
return EXIT_SUCCESS;
}

View file

@ -4,7 +4,7 @@
#include <isinetaddr.h>
#include <errno.h>
static int in_range(char buf[4], int buflen);
static int in_range(char buf[4], int min, int max);
static void register_octet(int *octets, char *buf, int *buflen);
static void register_digit(char digit, int *digits, char *buf, int *buflen);
@ -19,7 +19,7 @@ isinetaddr(const char *str)
if (str[l] == '.') {
if (buflen == 0) {
return 0;
} else if (!in_range(buf, buflen)) {
} else if (!in_range(buf, 0, 255)) {
return 0;
} else {
register_octet(&octets, buf, &buflen);
@ -35,24 +35,43 @@ isinetaddr(const char *str)
}
}
if (octets == 4) {
return digits <= 12 && in_range(buf, buflen) && buflen > 0;
return buflen > 0 && digits <= 12 && in_range(buf, 0, 255);
} else {
return 0;
}
}
int
iscidraddr(const char *str)
{
size_t offset = 0;
size_t len = (str == NULL ? 0 : strnlen(str, 20));
for(size_t i = 0; i < len; i++) {
if(str[i] == '/') {
offset = i;
}
}
if (offset == 0) {
return isinetaddr(str);
} else {
char addr[offset], cidr[3];
char *c = (char*)&str[offset + 1];
memcpy(addr, str, offset);
memcpy(cidr, c, 2);
addr[offset] = '\0';
return isinetaddr(addr) && in_range(cidr, 0, 32);
}
}
static int
in_range(char buf[4], int buflen)
in_range(char buf[4], int min, int max)
{
char *err;
long r;
if (buflen < 3) {
return 1;
} else {
errno = 0;
r = strtol(buf, &err, 10);
return *err == '\0' && errno == 0 && (r >= 0 && r <= 255);
}
errno = 0;
r = strtol(buf, &err, 10);
return *err == '\0' && errno == 0 && (r >= min && r <= max);
}
static void

62
test/iscidraddr_test.c Normal file
View file

@ -0,0 +1,62 @@
#include <isinetaddr.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
const char *valid[] = {
"192.168.1.1",
"0.0.0.0",
"255.255.255.255",
"123.45.67.89",
"123.45.67.255",
"10.0.0.1/32"
};
const char *invalid[] = {
"123.45.67.891",
"192.168.500.1",
".192.168.1.1",
"192..168.1.1",
"192.168.1.1.",
"192.168.1.1..",
"192.168.1.1a",
"555555555555555555555555555555555555",
"",
".",
".......",
"192.2.2.",
"...4",
"4...4",
"10.0.0.1/33",
"127.0.0.1/64",
"127.0.0.1/",
"127.0.0.1/a",
"/",
"/123.",
"127/2",
NULL
};
int
main(void) {
size_t len;
/* IPv4: valid */
len = sizeof(valid) / sizeof(valid[0]);
for (size_t i = 0; i < len; i++) {
if (iscidraddr(valid[i]) != 1) {
fprintf(stderr, "assertion failed: '%s' should be valid\n", valid[i]);
abort();
}
}
/* IPv4: invalid */
len = sizeof(invalid) / sizeof(invalid[0]);
for (size_t i = 0; i < len; i++) {
if (iscidraddr(invalid[i]) != 0) {
fprintf(stderr, "assertion failed: '%s' should NOT be valid\n", invalid[i]);
abort();
}
}
/* Done */
printf("OK\n");
return EXIT_SUCCESS;
}

View file

@ -8,7 +8,7 @@ const char *valid[] = {
"0.0.0.0",
"255.255.255.255",
"123.45.67.89",
"123.45.67.255",
"123.45.67.255"
};
const char *invalid[] = {