Workshop o mikrokontrolérech na SKSP 2024.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
2.6 KiB

2 months ago
/*
* UCW Library -- IP address access lists
*
* (c) 1997--2007 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
*/
#include <ucw/lib.h>
#include <ucw/clists.h>
#include <ucw/conf.h>
#include <ucw/getopt.h>
#include <ucw/fastbuf.h>
#include <ucw/ipaccess.h>
#include <string.h>
struct ipaccess_entry {
cnode n;
int allow;
struct ip_addrmask addr;
};
static char *
addrmask_parser(char *c, void *ptr)
{
/*
* This is tricky: addrmasks will be compared by memcmp(), so we must ensure
* that even the padding between structure members is zeroed out.
*/
struct ip_addrmask *am = ptr;
bzero(am, sizeof(*am));
char *p = strchr(c, '/');
if (p)
*p++ = 0;
char *err = cf_parse_ip(c, &am->addr);
if (err)
return err;
if (p)
{
uint len;
if (!cf_parse_int(p, &len) && len <= 32)
am->mask = ~(len == 32 ? 0 : ~0U >> len);
else if (cf_parse_ip(p, &am->mask))
return "Invalid prefix length or netmask";
}
else
am->mask = ~0U;
return NULL;
}
static void
addrmask_dumper(struct fastbuf *fb, void *ptr)
{
struct ip_addrmask *am = ptr;
bprintf(fb, "%08x/%08x ", am->addr, am->mask);
}
struct cf_user_type ip_addrmask_type = {
.size = sizeof(struct ip_addrmask),
.name = "ip_addrmask",
.parser = addrmask_parser,
.dumper = addrmask_dumper
};
struct cf_section ipaccess_cf = {
CF_TYPE(struct ipaccess_entry),
CF_ITEMS {
CF_LOOKUP("Mode", PTR_TO(struct ipaccess_entry, allow), ((const char* const []) { "deny", "allow", NULL })),
CF_USER("IP", PTR_TO(struct ipaccess_entry, addr), &ip_addrmask_type),
CF_END
}
};
int ip_addrmask_match(struct ip_addrmask *am, u32 ip)
{
return !((ip ^ am->addr) & am->mask);
}
int
ipaccess_check(clist *l, u32 ip)
{
CLIST_FOR_EACH(struct ipaccess_entry *, a, *l)
if (ip_addrmask_match(&a->addr, ip))
return a->allow;
return 0;
}
#ifdef TEST
#include <stdio.h>
static clist t;
static struct cf_section test_cf = {
CF_ITEMS {
CF_LIST("A", &t, &ipaccess_cf),
CF_END
}
};
int main(int argc, char **argv)
{
cf_declare_section("T", &test_cf, 0);
if (cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) != -1)
die("Invalid arguments");
byte buf[256];
while (fgets(buf, sizeof(buf), stdin))
{
char *c = strchr(buf, '\n');
if (c)
*c = 0;
u32 ip;
if (cf_parse_ip(buf, &ip))
puts("Invalid IP address");
else if (ipaccess_check(&t, ip))
puts("Allowed");
else
puts("Denied");
}
return 0;
}
#endif