Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/poc-code/access-list/Makefile.am b/poc-code/access-list/Makefile.am
new file mode 100644
index 00000000..1a96a37e
--- /dev/null
+++ b/poc-code/access-list/Makefile.am
@@ -0,0 +1,4 @@
+
+test_ipcheck: test_ipcheck.c ipcheck.c
+ $(CC) -Wall -O0 -g ipcheck.c test_ipcheck.c -o test_ipcheck
+
diff --git a/poc-code/access-list/ipcheck.c b/poc-code/access-list/ipcheck.c
new file mode 100644
index 00000000..b71ac5c1
--- /dev/null
+++ b/poc-code/access-list/ipcheck.c
@@ -0,0 +1,210 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdint.h>
+#include <string.h>
+#include <malloc.h>
+#include "ipcheck.h"
+
+struct ip_match_entry {
+ ipcheck_type_t type;
+ ipcheck_acceptreject_t acceptreject;
+ struct sockaddr_storage addr1; /* Actual IP address, mask top or low IP */
+ struct sockaddr_storage addr2; /* high IP address or address bitmask */
+ struct ip_match_entry *next;
+};
+
+
+/* Lists of things to match against. These are dummy structs to provide a quick list head */
+static struct ip_match_entry match_entry_head_v4;
+static struct ip_match_entry match_entry_head_v6;
+
+/*
+ * IPv4 See if the address we have matches the current match entry
+ *
+ */
+static int ip_matches_v4(struct sockaddr_storage *checkip, struct ip_match_entry *match_entry)
+{
+ struct sockaddr_in *ip_to_check;
+ struct sockaddr_in *match1;
+ struct sockaddr_in *match2;
+
+ ip_to_check = (struct sockaddr_in *)checkip;
+ match1 = (struct sockaddr_in *)&match_entry->addr1;
+ match2 = (struct sockaddr_in *)&match_entry->addr2;
+
+ switch(match_entry->type) {
+ case IPCHECK_TYPE_ADDRESS:
+ if (ip_to_check->sin_addr.s_addr == match1->sin_addr.s_addr)
+ return 1;
+ break;
+ case IPCHECK_TYPE_MASK:
+ if ((ip_to_check->sin_addr.s_addr & match2->sin_addr.s_addr) ==
+ match1->sin_addr.s_addr)
+ return 1;
+ break;
+ case IPCHECK_TYPE_RANGE:
+ if ((ntohl(ip_to_check->sin_addr.s_addr) >= ntohl(match1->sin_addr.s_addr)) &&
+ (ntohl(ip_to_check->sin_addr.s_addr) <= ntohl(match2->sin_addr.s_addr)))
+ return 1;
+ break;
+
+ }
+ return 0;
+}
+
+/* Compare two IPv6 addresses */
+static int ip6addr_cmp(struct in6_addr *a, struct in6_addr *b)
+{
+ uint64_t a_high, a_low;
+ uint64_t b_high, b_low;
+
+ /* Not sure why '&' doesn't work below, so I used '+' instead which is effectively
+ the same thing because the bottom 32bits are always zero and the value unsigned */
+ a_high = ((uint64_t)htonl(a->s6_addr32[0]) << 32) + (uint64_t)htonl(a->s6_addr32[1]);
+ a_low = ((uint64_t)htonl(a->s6_addr32[2]) << 32) + (uint64_t)htonl(a->s6_addr32[3]);
+
+ b_high = ((uint64_t)htonl(b->s6_addr32[0]) << 32) + (uint64_t)htonl(b->s6_addr32[1]);
+ b_low = ((uint64_t)htonl(b->s6_addr32[2]) << 32) + (uint64_t)htonl(b->s6_addr32[3]);
+
+ if (a_high > b_high)
+ return 1;
+ if (a_high < b_high)
+ return -1;
+
+ if (a_low > b_low)
+ return 1;
+ if (a_low < b_low)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * IPv6 See if the address we have matches the current match entry
+ *
+ */
+static int ip_matches_v6(struct sockaddr_storage *checkip, struct ip_match_entry *match_entry)
+{
+ struct sockaddr_in6 *ip_to_check;
+ struct sockaddr_in6 *match1;
+ struct sockaddr_in6 *match2;
+ int i;
+
+ ip_to_check = (struct sockaddr_in6 *)checkip;
+ match1 = (struct sockaddr_in6 *)&match_entry->addr1;
+ match2 = (struct sockaddr_in6 *)&match_entry->addr2;
+
+ switch(match_entry->type) {
+ case IPCHECK_TYPE_ADDRESS:
+ if (!memcmp(ip_to_check->sin6_addr.s6_addr32, match1->sin6_addr.s6_addr32, sizeof(struct in6_addr)))
+ return 1;
+ break;
+
+ case IPCHECK_TYPE_MASK:
+ /*
+ * Note that this little loop will quit early if there is a non-match so the
+ * comparison might look backwards compared to the IPv4 one
+ */
+ for (i=sizeof(struct in6_addr)/4-1; i>=0; i--) {
+ if ((ip_to_check->sin6_addr.s6_addr32[i] & match2->sin6_addr.s6_addr32[i]) !=
+ match1->sin6_addr.s6_addr32[i])
+ return 0;
+ }
+ return 1;
+ case IPCHECK_TYPE_RANGE:
+ if ((ip6addr_cmp(&ip_to_check->sin6_addr, &match1->sin6_addr) >= 0) &&
+ (ip6addr_cmp(&ip_to_check->sin6_addr, &match2->sin6_addr) <= 0))
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+
+/*
+ * YOU ARE HERE
+ */
+int ipcheck_validate(struct sockaddr_storage *checkip)
+{
+ struct ip_match_entry *match_entry;
+ int (*match_fn)(struct sockaddr_storage *checkip, struct ip_match_entry *match_entry);
+
+ if (checkip->ss_family == AF_INET){
+ match_entry = match_entry_head_v4.next;
+ match_fn = ip_matches_v4;
+ } else {
+ match_entry = match_entry_head_v6.next;
+ match_fn = ip_matches_v6;
+ }
+ while (match_entry) {
+ if (match_fn(checkip, match_entry)) {
+ if (match_entry->acceptreject == IPCHECK_ACCEPT)
+ return 1;
+ else
+ return 0;
+ }
+ match_entry = match_entry->next;
+ }
+ return 0; /* Default reject */
+}
+
+/*
+ * Routines to manuipulate the lists
+ */
+
+void ipcheck_clear(void)
+{
+ struct ip_match_entry *match_entry;
+ struct ip_match_entry *next_match_entry;
+
+ match_entry = match_entry_head_v4.next;
+ while (match_entry) {
+ next_match_entry = match_entry->next;
+ free(match_entry);
+ match_entry = next_match_entry;
+ }
+
+ match_entry = match_entry_head_v6.next;
+ while (match_entry) {
+ next_match_entry = match_entry->next;
+ free(match_entry);
+ match_entry = next_match_entry;
+ }
+}
+
+int ipcheck_addip(struct sockaddr_storage *ip1, struct sockaddr_storage *ip2,
+ ipcheck_type_t type, ipcheck_acceptreject_t acceptreject)
+{
+ struct ip_match_entry *match_entry;
+ struct ip_match_entry *new_match_entry;
+
+ if (type == IPCHECK_TYPE_RANGE &&
+ (ip1->ss_family != ip2->ss_family))
+ return -1;
+
+ if (ip1->ss_family == AF_INET){
+ match_entry = &match_entry_head_v4;
+ } else {
+ match_entry = &match_entry_head_v6;
+ }
+
+
+ new_match_entry = malloc(sizeof(struct ip_match_entry));
+ if (!new_match_entry)
+ return -1;
+
+ memcpy(&new_match_entry->addr1, ip1, sizeof(struct sockaddr_storage));
+ memcpy(&new_match_entry->addr2, ip2, sizeof(struct sockaddr_storage));
+ new_match_entry->type = type;
+ new_match_entry->acceptreject = acceptreject;
+ new_match_entry->next = NULL;
+
+ /* Find the end of the list */
+ /* is this OK, or should we use a doubly-linked list or bulk-load API call? */
+ while (match_entry->next) {
+ match_entry = match_entry->next;
+ }
+ match_entry->next = new_match_entry;
+
+ return 0;
+}
diff --git a/poc-code/access-list/ipcheck.h b/poc-code/access-list/ipcheck.h
new file mode 100644
index 00000000..c7b3fee6
--- /dev/null
+++ b/poc-code/access-list/ipcheck.h
@@ -0,0 +1,10 @@
+
+
+typedef enum {IPCHECK_TYPE_ADDRESS, IPCHECK_TYPE_MASK, IPCHECK_TYPE_RANGE} ipcheck_type_t;
+typedef enum {IPCHECK_ACCEPT, IPCHECK_REJECT} ipcheck_acceptreject_t;
+
+int ipcheck_validate(struct sockaddr_storage *checkip);
+
+void ipcheck_clear(void);
+int ipcheck_addip(struct sockaddr_storage *ip1, struct sockaddr_storage *ip2,
+ ipcheck_type_t type, ipcheck_acceptreject_t acceptreject);
diff --git a/poc-code/access-list/test_ipcheck.c b/poc-code/access-list/test_ipcheck.c
new file mode 100644
index 00000000..9c814748
--- /dev/null
+++ b/poc-code/access-list/test_ipcheck.c
@@ -0,0 +1,185 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <malloc.h>
+#include "ipcheck.h"
+
+/* This is a test program .. remember! */
+#define BUFLEN 1024
+
+static int get_ipaddress(char *buf, struct sockaddr_storage *addr)
+{
+ struct addrinfo *info;
+ struct addrinfo hints;
+ int res;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+
+ res = getaddrinfo(buf, NULL, &hints, &info);
+ if (!res) {
+ memcpy(addr, info->ai_addr, info->ai_addrlen);
+ free(info);
+ }
+ return res;
+}
+
+static int read_address(char *buf, struct sockaddr_storage *addr)
+{
+ return get_ipaddress(buf, addr);
+}
+
+static int read_mask(char *buf, struct sockaddr_storage *addr, struct sockaddr_storage *addr2)
+{
+ char tmpbuf[BUFLEN];
+ char *slash;
+ int ret;
+
+ slash = strchr(buf, '/');
+ if (!slash)
+ return 1;
+
+ strncpy(tmpbuf, buf, slash-buf);
+ tmpbuf[slash-buf] = '\0';
+
+ ret = get_ipaddress(tmpbuf, addr);
+ if (ret)
+ return ret;
+
+ ret = get_ipaddress(slash+1, addr2);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int read_range(char *buf, struct sockaddr_storage *addr1, struct sockaddr_storage *addr2)
+{
+ char tmpbuf[BUFLEN];
+ char *hyphen;
+ int ret;
+
+ hyphen = strchr(buf, '-');
+ if (!hyphen)
+ return 1;
+
+ strncpy(tmpbuf, buf, hyphen-buf);
+ tmpbuf[hyphen-buf] = '\0';
+
+ ret = get_ipaddress(tmpbuf, addr1);
+ if (ret)
+ return ret;
+
+ ret = get_ipaddress(hyphen+1, addr2);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+
+static int load_file()
+{
+ FILE *filterfile;
+ char filebuf[BUFLEN];
+ int line = 0;
+ int ret;
+ ipcheck_type_t type;
+ ipcheck_acceptreject_t acceptreject;
+ struct sockaddr_storage addr1;
+ struct sockaddr_storage addr2;
+
+ ipcheck_clear();
+
+ filterfile = fopen("test_ipcheck.txt", "r");
+ if (!filterfile) {
+ fprintf(stderr, "Cannot open test_ipcheck.txt\n");
+ return 1;
+ }
+
+ while (fgets(filebuf, sizeof(filebuf), filterfile)) {
+ filebuf[strlen(filebuf)-1] = '\0'; /* remove trailing LF */
+ line++;
+
+ /*
+ * First char is A (accept) or R (Reject)
+ */
+ switch(filebuf[0] & 0x5F) {
+ case 'A':
+ acceptreject = IPCHECK_ACCEPT;
+ break;
+ case 'R':
+ acceptreject = IPCHECK_REJECT;
+ break;
+ default:
+ fprintf(stderr, "Unknown record type on line %d: %s\n", line, filebuf);
+ goto next_record;
+ }
+
+ /*
+ * Second char is the filter type:
+ * A Address
+ * M Mask
+ * R Range
+ */
+ switch(filebuf[1] & 0x5F) {
+ case 'A':
+ type = IPCHECK_TYPE_ADDRESS;
+ ret = read_address(filebuf+2, &addr1);
+ break;
+ case 'M':
+ type = IPCHECK_TYPE_MASK;
+ ret = read_mask(filebuf+2, &addr1, &addr2);
+ break;
+ case 'R':
+ type = IPCHECK_TYPE_RANGE;
+ ret = read_range(filebuf+2, &addr1, &addr2);
+ break;
+ default:
+ fprintf(stderr, "Unknown filter type on line %d: %s\n", line, filebuf);
+ goto next_record;
+ break;
+ }
+ if (ret) {
+ fprintf(stderr, "Failed to parse address on line %d: %s\n", line, filebuf);
+ }
+ else {
+ ipcheck_addip(&addr1, &addr2, type, acceptreject);
+ }
+ next_record: {} /* empty statement to mollify the compiler */
+ }
+ fclose(filterfile);
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ struct sockaddr_storage saddr;
+ int ret;
+ int i;
+
+ if (load_file())
+ return 1;
+
+ for (i=1; i<argc; i++) {
+ ret = get_ipaddress(argv[i], &saddr);
+ if (ret) {
+ fprintf(stderr, "Cannot parse address %s\n", argv[i]);
+ }
+ else {
+ if (ipcheck_validate(&saddr)) {
+ printf("%s is VALID\n", argv[i]);
+ }
+ else {
+ printf("%s is not allowed\n", argv[i]);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/poc-code/access-list/test_ipcheck.txt b/poc-code/access-list/test_ipcheck.txt
new file mode 100644
index 00000000..5776d54f
--- /dev/null
+++ b/poc-code/access-list/test_ipcheck.txt
@@ -0,0 +1,8 @@
+AA192.168.1.1
+AA192.168.1.2
+RA192.168.0.3
+AR192.168.0.0-192.168.0.250
+AM192.168.2.0/255.255.255.0
+AM1740::0/FFF0::0
+RA1000::666
+AR1000::1-2000::7FF

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jun 25, 4:53 AM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1952210
Default Alt Text
(11 KB)

Event Timeline