mirror of
https://github.com/cesanta/mongoose.git
synced 2025-01-14 09:48:01 +08:00
Add mg_check_ip_acl()
This commit is contained in:
parent
1c456fc2df
commit
fc9c454518
@ -10,8 +10,6 @@ by a vast number of open source and commercial products - it even runs on the
|
|||||||
International Space Station! Mongoose makes embedded network programming fast,
|
International Space Station! Mongoose makes embedded network programming fast,
|
||||||
robust, and easy.
|
robust, and easy.
|
||||||
|
|
||||||
## Concept
|
|
||||||
|
|
||||||
Mongoose has three basic data structures:
|
Mongoose has three basic data structures:
|
||||||
|
|
||||||
- `struct mg_mgr` - an event manager that holds all active connections
|
- `struct mg_mgr` - an event manager that holds all active connections
|
||||||
@ -1213,7 +1211,7 @@ The glob pattern matching rules are as follows:
|
|||||||
- any other character matches itself
|
- any other character matches itself
|
||||||
|
|
||||||
|
|
||||||
### mg\_next\_comma\_entry()
|
### mg\_comma()
|
||||||
|
|
||||||
```c
|
```c
|
||||||
bool mg_comma(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
bool mg_comma(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
||||||
@ -1374,3 +1372,25 @@ uint32_t mg_crc32(uint32_t crc, const uint8_t *buf, size_t len);
|
|||||||
|
|
||||||
Calculate CRC32 checksum for a given buffer. An initial `crc` value should
|
Calculate CRC32 checksum for a given buffer. An initial `crc` value should
|
||||||
be `0`.
|
be `0`.
|
||||||
|
|
||||||
|
### mg\_check\_ip\_acl()
|
||||||
|
|
||||||
|
```c
|
||||||
|
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
||||||
|
```
|
||||||
|
|
||||||
|
Check IPv4 address `remote_ip` against the IP ACL `acl`. Parameters:
|
||||||
|
|
||||||
|
- `acl` - an ACL string, e.g. `-0.0.0.0/0,+1.2.3.4`
|
||||||
|
- `remote_ip` - IPv4 address in network byte order
|
||||||
|
|
||||||
|
Return value: 1 if `remote_ip` is allowed, 0 if not, and <0 if `acl` is
|
||||||
|
invalid.
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
|
||||||
|
```
|
||||||
|
if (mg_check_ip_acl(mg_str("-0.0.0.0/0,+1.2.3.4"), c->peer.ip) != 1) {
|
||||||
|
LOG(LL_INFO, ("NOT ALLOWED!"));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
39
mongoose.c
39
mongoose.c
@ -4249,7 +4249,7 @@ uint32_t mg_ntohl(uint32_t net) {
|
|||||||
uint16_t mg_ntohs(uint16_t net) {
|
uint16_t mg_ntohs(uint16_t net) {
|
||||||
uint8_t data[2] = {0, 0};
|
uint8_t data[2] = {0, 0};
|
||||||
memcpy(&data, &net, sizeof(data));
|
memcpy(&data, &net, sizeof(data));
|
||||||
return (uint16_t)((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
|
return (uint16_t) ((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mg_hexdump(const void *buf, size_t len) {
|
char *mg_hexdump(const void *buf, size_t len) {
|
||||||
@ -4292,10 +4292,9 @@ char *mg_hex(const void *buf, size_t len, char *to) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char mg_unhex_nimble(unsigned char c) {
|
static unsigned char mg_unhex_nimble(unsigned char c) {
|
||||||
return (c >= '0' && c <= '9')
|
return (c >= '0' && c <= '9') ? (unsigned char) (c - '0')
|
||||||
? (unsigned char) (c - '0')
|
: (c >= 'A' && c <= 'F') ? (unsigned char) (c - '7')
|
||||||
: (c >= 'A' && c <= 'F') ? (unsigned char) (c - '7')
|
: (unsigned char) (c - 'W');
|
||||||
: (unsigned char) (c - 'W');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long mg_unhexn(const char *s, size_t len) {
|
unsigned long mg_unhexn(const char *s, size_t len) {
|
||||||
@ -4388,6 +4387,36 @@ uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
|
|||||||
return ~crc;
|
return ~crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int isbyte(int n) {
|
||||||
|
return n >= 0 && n <= 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) {
|
||||||
|
int n, a, b, c, d, slash = 32, len = 0;
|
||||||
|
if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
|
||||||
|
sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
|
||||||
|
isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 &&
|
||||||
|
slash < 33) {
|
||||||
|
len = n;
|
||||||
|
*net = ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t) c << 8) |
|
||||||
|
(uint32_t) d;
|
||||||
|
*mask = slash ? (uint32_t) (0xffffffffU << (32 - slash)) : (uint32_t) 0;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip) {
|
||||||
|
struct mg_str k, v;
|
||||||
|
int allowed = acl.len == 0 ? '+' : '-'; // If any ACL is set, deny by default
|
||||||
|
while (mg_comma(&acl, &k, &v)) {
|
||||||
|
uint32_t net, mask;
|
||||||
|
if (k.ptr[0] != '+' && k.ptr[0] != '-') return -1;
|
||||||
|
if (parse_net(&k.ptr[1], &net, &mask) == 0) return -2;
|
||||||
|
if ((remote_ip & mask) == net) allowed = k.ptr[0];
|
||||||
|
}
|
||||||
|
return allowed == '+';
|
||||||
|
}
|
||||||
|
|
||||||
double mg_time(void) {
|
double mg_time(void) {
|
||||||
#if MG_ARCH == MG_ARCH_WIN32
|
#if MG_ARCH == MG_ARCH_WIN32
|
||||||
SYSTEMTIME sysnow;
|
SYSTEMTIME sysnow;
|
||||||
|
@ -512,14 +512,15 @@ void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param);
|
|||||||
struct mg_timer {
|
struct mg_timer {
|
||||||
unsigned long period_ms; // Timer period in milliseconds
|
unsigned long period_ms; // Timer period in milliseconds
|
||||||
unsigned flags; // Possible flags values below
|
unsigned flags; // Possible flags values below
|
||||||
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
|
||||||
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
|
||||||
void (*fn)(void *); // Function to call
|
void (*fn)(void *); // Function to call
|
||||||
void *arg; // Function argument
|
void *arg; // Function argument
|
||||||
unsigned long expire; // Expiration timestamp in milliseconds
|
unsigned long expire; // Expiration timestamp in milliseconds
|
||||||
struct mg_timer *next; // Linkage in g_timers list
|
struct mg_timer *next; // Linkage in g_timers list
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
||||||
|
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||||||
|
|
||||||
extern struct mg_timer *g_timers; // Global list of timers
|
extern struct mg_timer *g_timers; // Global list of timers
|
||||||
|
|
||||||
void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
|
void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
|
||||||
@ -547,6 +548,7 @@ unsigned long mg_unhexn(const char *s, size_t len);
|
|||||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||||
int64_t mg_to64(struct mg_str str);
|
int64_t mg_to64(struct mg_str str);
|
||||||
|
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
||||||
double mg_time(void);
|
double mg_time(void);
|
||||||
unsigned long mg_millis(void);
|
unsigned long mg_millis(void);
|
||||||
void mg_usleep(unsigned long usecs);
|
void mg_usleep(unsigned long usecs);
|
||||||
|
39
src/util.c
39
src/util.c
@ -127,7 +127,7 @@ uint32_t mg_ntohl(uint32_t net) {
|
|||||||
uint16_t mg_ntohs(uint16_t net) {
|
uint16_t mg_ntohs(uint16_t net) {
|
||||||
uint8_t data[2] = {0, 0};
|
uint8_t data[2] = {0, 0};
|
||||||
memcpy(&data, &net, sizeof(data));
|
memcpy(&data, &net, sizeof(data));
|
||||||
return (uint16_t)((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
|
return (uint16_t) ((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mg_hexdump(const void *buf, size_t len) {
|
char *mg_hexdump(const void *buf, size_t len) {
|
||||||
@ -170,10 +170,9 @@ char *mg_hex(const void *buf, size_t len, char *to) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char mg_unhex_nimble(unsigned char c) {
|
static unsigned char mg_unhex_nimble(unsigned char c) {
|
||||||
return (c >= '0' && c <= '9')
|
return (c >= '0' && c <= '9') ? (unsigned char) (c - '0')
|
||||||
? (unsigned char) (c - '0')
|
: (c >= 'A' && c <= 'F') ? (unsigned char) (c - '7')
|
||||||
: (c >= 'A' && c <= 'F') ? (unsigned char) (c - '7')
|
: (unsigned char) (c - 'W');
|
||||||
: (unsigned char) (c - 'W');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long mg_unhexn(const char *s, size_t len) {
|
unsigned long mg_unhexn(const char *s, size_t len) {
|
||||||
@ -266,6 +265,36 @@ uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
|
|||||||
return ~crc;
|
return ~crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int isbyte(int n) {
|
||||||
|
return n >= 0 && n <= 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) {
|
||||||
|
int n, a, b, c, d, slash = 32, len = 0;
|
||||||
|
if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
|
||||||
|
sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
|
||||||
|
isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 &&
|
||||||
|
slash < 33) {
|
||||||
|
len = n;
|
||||||
|
*net = ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t) c << 8) |
|
||||||
|
(uint32_t) d;
|
||||||
|
*mask = slash ? (uint32_t) (0xffffffffU << (32 - slash)) : (uint32_t) 0;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip) {
|
||||||
|
struct mg_str k, v;
|
||||||
|
int allowed = acl.len == 0 ? '+' : '-'; // If any ACL is set, deny by default
|
||||||
|
while (mg_comma(&acl, &k, &v)) {
|
||||||
|
uint32_t net, mask;
|
||||||
|
if (k.ptr[0] != '+' && k.ptr[0] != '-') return -1;
|
||||||
|
if (parse_net(&k.ptr[1], &net, &mask) == 0) return -2;
|
||||||
|
if ((remote_ip & mask) == net) allowed = k.ptr[0];
|
||||||
|
}
|
||||||
|
return allowed == '+';
|
||||||
|
}
|
||||||
|
|
||||||
double mg_time(void) {
|
double mg_time(void) {
|
||||||
#if MG_ARCH == MG_ARCH_WIN32
|
#if MG_ARCH == MG_ARCH_WIN32
|
||||||
SYSTEMTIME sysnow;
|
SYSTEMTIME sysnow;
|
||||||
|
@ -19,6 +19,7 @@ unsigned long mg_unhexn(const char *s, size_t len);
|
|||||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||||
int64_t mg_to64(struct mg_str str);
|
int64_t mg_to64(struct mg_str str);
|
||||||
|
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
||||||
double mg_time(void);
|
double mg_time(void);
|
||||||
unsigned long mg_millis(void);
|
unsigned long mg_millis(void);
|
||||||
void mg_usleep(unsigned long usecs);
|
void mg_usleep(unsigned long usecs);
|
||||||
|
@ -1461,8 +1461,22 @@ static void test_udp(void) {
|
|||||||
ASSERT(mgr.conns == NULL);
|
ASSERT(mgr.conns == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_check_ip_acl(void) {
|
||||||
|
uint32_t ip = 0x01020304;
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str(NULL), ip) == 1);
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str(""), ip) == 1);
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str("invalid"), ip) == -1);
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str("+hi"), ip) == -2);
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str("+//"), ip) == -2);
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str("-0.0.0.0/0"), ip) == 0);
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str("-0.0.0.0/0,+1.0.0.0/8"), ip) == 1);
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str("-0.0.0.0/0,+1.2.3.4"), ip) == 1);
|
||||||
|
ASSERT(mg_check_ip_acl(mg_str("-0.0.0.0/0,+1.0.0.0/16"), ip) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
mg_log_set("3");
|
mg_log_set("3");
|
||||||
|
test_check_ip_acl();
|
||||||
test_udp();
|
test_udp();
|
||||||
test_pipe();
|
test_pipe();
|
||||||
test_packed();
|
test_packed();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user