#define INCLUDE_hostmask_h 1
enum
{
+ HM_ERROR,
HM_HOST,
HM_IPV4,
HM_IPV6,
};
int parse_netmask(const char *, struct rb_sockaddr_storage *, int *);
+int parse_netmask_strict(const char *, struct rb_sockaddr_storage *, int *);
struct ConfItem *find_conf_by_address(const char *host, const char *sockhost,
const char *orighost, struct sockaddr *,
int, int, const char *, const char *);
static unsigned long hash_ipv4(struct sockaddr *, int);
-/* int parse_netmask(const char *, struct rb_sockaddr_storage *, int *);
- * Input: A hostmask, or an IPV4/6 address.
- * Output: An integer describing whether it is an IPV4, IPV6 address or a
- * hostmask, an address(if it is an IP mask),
- * a bitlength(if it is IP mask).
- * Side effects: None
- */
-int
-parse_netmask(const char *text, struct rb_sockaddr_storage *naddr, int *nb)
+static int
+_parse_netmask(const char *text, struct rb_sockaddr_storage *naddr, int *nb, bool strict)
{
char *ip = LOCAL_COPY(text);
char *ptr;
+ char *endp;
struct rb_sockaddr_storage *addr, xaddr;
int *b, xb;
if(nb == NULL)
{
*ptr = '\0';
ptr++;
- *b = atoi(ptr);
- if(*b > 128)
- *b = 128;
- else if(*b < 0)
+ long n = strtol(ptr, &endp, 10);
+ if (endp == ptr || n < 0)
return HM_HOST;
+ if (n > 128 || *endp != '\0')
+ if (strict)
+ return HM_ERROR;
+ else
+ n = 128;
+ *b = n;
} else
*b = 128;
if(rb_inet_pton_sock(ip, addr) > 0)
{
*ptr = '\0';
ptr++;
- *b = atoi(ptr);
- if(*b > 32)
- *b = 32;
- else if(*b < 0)
+ long n = strtol(ptr, &endp, 10);
+ if (endp == ptr || n < 0)
return HM_HOST;
+ if (n > 32 || *endp != '\0')
+ if (strict)
+ return HM_ERROR;
+ else
+ n = 32;
+ *b = n;
} else
*b = 32;
if(rb_inet_pton_sock(ip, addr) > 0)
return HM_HOST;
}
+/* int parse_netmask(const char *, struct rb_sockaddr_storage *, int *);
+ * Input: A hostmask, or an IPV4/6 address.
+ * Output: An integer describing whether it is an IPV4, IPV6 address or a
+ * hostmask, an address(if it is an IP mask),
+ * a bitlength(if it is IP mask).
+ * Side effects: None
+ */
+int parse_netmask(const char *mask, struct rb_sockaddr_storage *addr, int *blen)
+{
+ return _parse_netmask(mask, addr, blen, false);
+}
+
+int parse_netmask_strict(const char *mask, struct rb_sockaddr_storage *addr, int *blen)
+{
+ return _parse_netmask(mask, addr, blen, true);
+}
+
/* Hashtable stuff...now external as its used in m_stats.c */
struct AddressRec *atable[ATABLE_SIZE];
conf_set_exempt_ip(void *data)
{
struct ConfItem *yy_tmp;
+ int masktype = parse_netmask_strict(data, NULL, NULL);
- if(parse_netmask(data, NULL, NULL) == HM_HOST)
+ if(masktype != HM_IPV4 && masktype != HM_IPV6)
{
conf_report_error("Ignoring exempt -- invalid exempt::ip.");
return;
int t = AF_INET, ty, b;
const char *creason;
- ty = parse_netmask(dlhost, &daddr, &b);
- if(ty == HM_HOST)
+ ty = parse_netmask_strict(dlhost, &daddr, &b);
+ if(ty != HM_IPV4 && ty != HM_IPV6)
{
sendto_one(source_p, ":%s NOTICE %s :Invalid D-Line", me.name, source_p->name);
return;
if((aconf = find_dline((struct sockaddr *) &daddr, t)) != NULL)
{
int bx;
- parse_netmask(aconf->host, NULL, &bx);
- if(b >= bx)
+ int masktype = parse_netmask_strict(aconf->host, NULL, &bx);
+
+ if (masktype != HM_ERROR && b >= bx)
{
creason = aconf->passwd ? aconf->passwd : "<No Reason>";
if(IsConfExemptKline(aconf))
char buf[BUFSIZE];
struct ConfItem *aconf;
- if(parse_netmask(cidr, NULL, NULL) == HM_HOST)
+ int masktype = parse_netmask_strict(cidr, NULL, NULL);
+
+ if(masktype != HM_IPV4 && masktype != HM_IPV6)
{
sendto_one_notice(source_p, ":Invalid D-Line");
return;
reason = LOCAL_COPY(parv[loc]);
+ if(parse_netmask_strict(host, NULL, NULL) == HM_ERROR)
+ {
+ sendto_one_notice(source_p,
+ ":[%s@%s] looks like an ill-formed IP K-line, refusing to set it",
+ user, host);
+ return;
+ }
+
if(target_server != NULL)
{
propagate_generic(source_p, "KLINE", target_server, CAP_KLN,
if(aconf == NULL && ConfigFileEntry.non_redundant_klines)
{
bits = 0;
- if((t = parse_netmask(lhost, &iphost, &bits)) != HM_HOST)
- {
- if(t == HM_IPV6)
- t = AF_INET6;
- else
- t = AF_INET;
-
- piphost = &iphost;
- }
+ t = parse_netmask_strict(lhost, &iphost, &bits);
+ piphost = &iphost;
+ if (t == HM_IPV4)
+ t = AF_INET;
+ else if (t == HM_IPV6)
+ t = AF_INET6;
else
piphost = NULL;