diff --git a/networking/httpd.c b/networking/httpd.c index a7473ede9..0b4e305d9 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -289,17 +289,26 @@ static ALWAYS_INLINE void free_Htaccess_IP_list(Htaccess_IP **pptr) free_llist((has_next_ptr**)pptr); } -static int scan_ip(const char **ep, unsigned *ip, unsigned char endc) +//#undef isdigit +//#define isdigit(a) ((unsigned)((a) - '0') <= 9) +//#define notdigit(a) ((unsigned)((a) - '0') > 9) + +/* Returns presumed mask width in bits or < 0 on error. + * Updates strp, stores IP at provided pointer */ +static int scan_ip(const char **strp, unsigned *ipp, unsigned char endc) { - const char *p = *ep; + const char *p = *strp; int auto_mask = 8; + unsigned ip = 0; int j; - *ip = 0; + if (*p == '/') + return -auto_mask; + for (j = 0; j < 4; j++) { unsigned octet; - if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != '\0') + if ((*p < '0' || *p > '9') && *p != '/' && *p) return -auto_mask; octet = 0; while (*p >= '0' && *p <= '9') { @@ -311,55 +320,61 @@ static int scan_ip(const char **ep, unsigned *ip, unsigned char endc) } if (*p == '.') p++; - if (*p != '/' && *p != '\0') + if (*p != '/' && *p) auto_mask += 8; - *ip = ((*ip) << 8) | octet; + ip = (ip << 8) | octet; } - if (*p != '\0') { + if (*p) { if (*p != endc) return -auto_mask; p++; if (*p == '\0') return -auto_mask; } - *ep = p; + *ipp = ip; + *strp = p; return auto_mask; } -static int scan_ip_mask(const char *ipm, unsigned *ip, unsigned *mask) +/* Returns 0 on success. Stores IP and mask at provided pointers */ +static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp) { int i; - unsigned msk; + unsigned mask; + char *p; - i = scan_ip(&ipm, ip, '/'); + i = scan_ip(&str, ipp, '/'); if (i < 0) return i; - if (*ipm) { - const char *p = ipm; - i = 0; - while (*p) { - if (*p < '0' || *p > '9') { - if (*p == '.') { - i = scan_ip(&ipm, mask, 0); - return i != 32; - } - return -1; - } - i *= 10; - i += *p - '0'; - p++; + if (*str) { + /* there is /xxx after dotted-IP address */ + i = bb_strtou(str, &p, 10); + if (*p == '.') { + /* 'xxx' itself is dotted-IP mask, parse it */ + /* (return 0 (success) only if it has N.N.N.N form) */ + return scan_ip(&str, maskp, '\0') - 32; } + if (*p) + return -1; } - if (i > 32 || i < 0) + + if (i > 32) return -1; - msk = 0x80000000; - *mask = 0; - while (i > 0) { - *mask |= msk; - msk >>= 1; - i--; + + if (sizeof(unsigned) == 4 && i == 32) { + /* mask >>= 32 below may not work */ + mask = 0; + } else { + mask = 0xffffffff; + mask >>= i; } + /* i == 0 -> *maskp = 0x00000000 + * i == 1 -> *maskp = 0x80000000 + * i == 4 -> *maskp = 0xf0000000 + * i == 31 -> *maskp = 0xfffffffe + * i == 32 -> *maskp = 0xffffffff */ + *maskp = (uint32_t)(~mask); return 0; }