Merge pull request #2 from 0x1eef/iscidraddr
Add support for CIDR notation (iscidraddr).
This commit is contained in:
commit
fa580011e1
8 changed files with 202 additions and 17 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
test/runner
|
||||
test/isinetaddr
|
||||
test/iscidraddr
|
||||
|
|
8
Makefile
8
Makefile
|
@ -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
|
||||
|
|
68
README.md
68
README.md
|
@ -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)
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
#pragma once
|
||||
int isinetaddr(const char *str);
|
||||
int iscidraddr(const char *str);
|
||||
|
|
34
share/isinetaddr/examples/iscidraddr.c
Normal file
34
share/isinetaddr/examples/iscidraddr.c
Normal 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;
|
||||
}
|
|
@ -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
62
test/iscidraddr_test.c
Normal 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;
|
||||
}
|
|
@ -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[] = {
|
||||
|
|
Loading…
Reference in a new issue