* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
- * Copyright (C) 2005-2006 charybdis development team
+ * Copyright (C) 2005-2008 charybdis development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
#include "stdinc.h"
-#include "memory.h"
#include "ircd_defs.h"
#include "s_conf.h"
#include "hostmask.h"
#include "numeric.h"
#include "send.h"
-#include "irc_string.h"
+#include "match.h"
+#include "ipv4_from_ipv6.h"
-#ifdef IPV6
+#ifdef RB_IPV6
static unsigned long hash_ipv6(struct sockaddr *, int);
#endif
static unsigned long hash_ipv4(struct sockaddr *, int);
-/* int parse_netmask(const char *, struct irc_sockaddr_storage *, 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),
{
char *ip = LOCAL_COPY(text);
char *ptr;
- struct irc_sockaddr_storage *addr, xaddr;
+ struct rb_sockaddr_storage *addr, xaddr;
int *b, xb;
if(nb == NULL)
b = &xb;
b = nb;
if(naddr == NULL)
- addr = (struct irc_sockaddr_storage *)&xaddr;
+ addr = (struct rb_sockaddr_storage *)&xaddr;
else
- addr = (struct irc_sockaddr_storage *)naddr;
-
-#ifdef IPV6
+ addr = (struct rb_sockaddr_storage *)naddr;
+
+ if(strpbrk(ip, "*?") != NULL)
+ {
+ return HM_HOST;
+ }
+#ifdef RB_IPV6
if(strchr(ip, ':'))
{
if((ptr = strchr(ip, '/')))
*b = atoi(ptr);
if(*b > 128)
*b = 128;
+ else if(*b < 0)
+ return HM_HOST;
} else
*b = 128;
- if(inetpton_sock(ip, (struct sockaddr *)addr) > 0)
+ if(rb_inet_pton_sock(ip, (struct sockaddr *)addr) > 0)
return HM_IPV6;
else
return HM_HOST;
*b = atoi(ptr);
if(*b > 32)
*b = 32;
+ else if(*b < 0)
+ return HM_HOST;
} else
*b = 32;
- if(inetpton_sock(ip, (struct sockaddr *)addr) > 0)
+ if(rb_inet_pton_sock(ip, (struct sockaddr *)addr) > 0)
return HM_IPV4;
else
return HM_HOST;
memset(&atable, 0, sizeof(atable));
}
-/* unsigned long hash_ipv4(struct irc_sockaddr_storage*)
+/* unsigned long hash_ipv4(struct rb_sockaddr_storage*)
* Input: An IP address.
* Output: A hash value of the IP address.
* Side effects: None
return 0;
}
-/* unsigned long hash_ipv6(struct irc_sockaddr_storage*)
+/* unsigned long hash_ipv6(struct rb_sockaddr_storage*)
* Input: An IP address.
* Output: A hash value of the IP address.
* Side effects: None
*/
-#ifdef IPV6
+#ifdef RB_IPV6
static unsigned long
hash_ipv6(struct sockaddr *saddr, int bits)
{
return hash_text(text);
}
-/* struct ConfItem* find_conf_by_address(const char*, struct irc_sockaddr_storage*,
+/* struct ConfItem* find_conf_by_address(const char*, struct rb_sockaddr_storage*,
* int type, int fam, const char *username)
* Input: The hostname, the address, the type of mask to find, the address
* family, the username.
find_conf_by_address(const char *name, const char *sockhost,
const char *orighost,
struct sockaddr *addr, int type, int fam,
- const char *username)
+ const char *username, const char *auth_user)
{
unsigned long hprecv = 0;
struct ConfItem *hprec = NULL;
if(addr)
{
/* Check for IPV6 matches... */
-#ifdef IPV6
+#ifdef RB_IPV6
if(fam == AF_INET6)
{
if(arec->type == (type & ~0x1) &&
arec->masktype == HM_IPV6 &&
comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr,
- arec->Mask.ipa.bits) && (type & 0x1
- ||
- match(arec->
- username,
- username))
- && arec->precedence > hprecv)
+ arec->Mask.ipa.bits) &&
+ (type & 0x1 || match(arec-> username, username)) &&
+ (type != CONF_CLIENT || !arec->auth_user ||
+ (auth_user && match(arec->auth_user, auth_user))) &&
+ arec->precedence > hprecv)
{
hprecv = arec->precedence;
hprec = arec->aconf;
for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
if(arec->type == (type & ~0x1) &&
arec->masktype == HM_IPV4 &&
- arec->precedence > hprecv &&
comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr,
arec->Mask.ipa.bits) &&
- (type & 0x1 || match(arec->username, username)))
+ (type & 0x1 || match(arec->username, username)) &&
+ (type != CONF_CLIENT || !arec->auth_user ||
+ (auth_user && match(arec->auth_user, auth_user))) &&
+ arec->precedence > hprecv)
{
hprecv = arec->precedence;
hprec = arec->aconf;
(arec->masktype == HM_HOST) &&
arec->precedence > hprecv &&
match(arec->Mask.hostname, orighost) &&
+ (type != CONF_CLIENT || !arec->auth_user ||
+ (auth_user && match(arec->auth_user, auth_user))) &&
(type & 0x1 || match(arec->username, username)))
{
hprecv = arec->precedence;
arec->precedence > hprecv &&
(match(arec->Mask.hostname, orighost) ||
(sockhost && match(arec->Mask.hostname, sockhost))) &&
+ (type != CONF_CLIENT || !arec->auth_user ||
+ (auth_user && match(arec->auth_user, auth_user))) &&
(type & 0x1 || match(arec->username, username)))
{
hprecv = arec->precedence;
(arec->masktype == HM_HOST) &&
arec->precedence > hprecv &&
match(arec->Mask.hostname, name) &&
+ (type != CONF_CLIENT || !arec->auth_user ||
+ (auth_user && match(arec->auth_user, auth_user))) &&
(type & 0x1 || match(arec->username, username)))
{
hprecv = arec->precedence;
arec->precedence > hprecv &&
(match(arec->Mask.hostname, name) ||
(sockhost && match(arec->Mask.hostname, sockhost))) &&
+ (type != CONF_CLIENT || !arec->auth_user ||
+ (auth_user && match(arec->auth_user, auth_user))) &&
(type & 0x1 || match(arec->username, username)))
{
hprecv = arec->precedence;
}
/* struct ConfItem* find_address_conf(const char*, const char*,
- * struct irc_sockaddr_storage*, int);
+ * struct rb_sockaddr_storage*, int);
* Input: The hostname, username, address, address family.
* Output: The applicable ConfItem.
* Side-effects: None
*/
struct ConfItem *
find_address_conf(const char *host, const char *sockhost, const char *user,
- const char *notildeuser, struct sockaddr *ip, int aftype)
+ const char *notildeuser, struct sockaddr *ip, int aftype, char *auth_user)
{
struct ConfItem *iconf, *kconf;
const char *vuser;
+#ifdef RB_IPV6
+ struct sockaddr_in ip4;
+#endif
/* Find the best I-line... If none, return NULL -A1kmm */
- if(!(iconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_CLIENT, aftype, user)))
+ if(!(iconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_CLIENT, aftype, user, auth_user)))
return NULL;
/* Find what their visible username will be.
* Note that the username without tilde may contain one char more.
return iconf;
/* Find the best K-line... -A1kmm */
- kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, user);
+ kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, user, NULL);
/* If they are K-lined, return the K-line */
if(kconf)
/* if theres a spoof, check it against klines.. */
if(IsConfDoSpoofIp(iconf))
{
- char *p = strchr(iconf->name, '@');
+ char *p = strchr(iconf->info.name, '@');
/* note, we dont need to pass sockhost here, as its
* guaranteed to not match by whats above.. --anfl
if(p)
{
*p = '\0';
- kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->name);
+ kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->info.name, NULL);
*p = '@';
}
else
- kconf = find_conf_by_address(iconf->name, NULL, NULL, ip, CONF_KILL, aftype, vuser);
+ kconf = find_conf_by_address(iconf->info.name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL);
if(kconf)
return kconf;
* -- jilles */
if(user != vuser)
{
- kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, vuser);
+ kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, vuser, NULL);
if(kconf)
return kconf;
}
- /* hunt for a gline */
- if(ConfigFileEntry.glines)
+#ifdef RB_IPV6
+ if(ip != NULL && ip->sa_family == AF_INET6 &&
+ ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)ip, &ip4))
{
- kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_GLINE, aftype, user);
-
- if((kconf != NULL) && !IsConfExemptGline(iconf))
+ kconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&ip4, CONF_KILL, AF_INET, vuser, NULL);
+ if(kconf)
return kconf;
}
+#endif /* RB_IPV6 */
return iconf;
}
-/* struct ConfItem* find_dline(struct irc_sockaddr_storage*, int)
+/* struct ConfItem* find_dline(struct rb_sockaddr_storage*, int)
* Input: An address, an address family.
* Output: The best matching D-line or exempt line.
* Side effects: None.
struct ConfItem *
find_dline(struct sockaddr *addr, int aftype)
{
- struct ConfItem *eline;
- eline = find_conf_by_address(NULL, NULL, NULL, addr, CONF_EXEMPTDLINE | 1, aftype, NULL);
- if(eline)
- return eline;
- return find_conf_by_address(NULL, NULL, NULL, addr, CONF_DLINE | 1, aftype, NULL);
+ struct ConfItem *aconf;
+#ifdef RB_IPV6
+ struct sockaddr_in addr2;
+#endif
+
+ aconf = find_conf_by_address(NULL, NULL, NULL, addr, CONF_EXEMPTDLINE | 1, aftype, NULL, NULL);
+ if(aconf)
+ return aconf;
+ aconf = find_conf_by_address(NULL, NULL, NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL);
+ if(aconf)
+ return aconf;
+#ifdef RB_IPV6
+ if(addr->sa_family == AF_INET6 &&
+ ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)addr, &addr2))
+ {
+ aconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&addr2, CONF_DLINE | 1, AF_INET, NULL, NULL);
+ if(aconf)
+ return aconf;
+ }
+#endif
+ return NULL;
}
/* void find_exact_conf_by_address(const char*, int, const char *)
int masktype, bits;
unsigned long hv;
struct AddressRec *arec;
- struct irc_sockaddr_storage addr;
+ struct rb_sockaddr_storage addr;
if(address == NULL)
address = "/NOMATCH!/";
- arec = MyMalloc(sizeof(struct AddressRec));
masktype = parse_netmask(address, (struct sockaddr *)&addr, &bits);
-#ifdef IPV6
+#ifdef RB_IPV6
if(masktype == HM_IPV6)
{
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
* Side-effects: Adds this entry to the hash table.
*/
void
-add_conf_by_address(const char *address, int type, const char *username, struct ConfItem *aconf)
+add_conf_by_address(const char *address, int type, const char *username, const char *auth_user, struct ConfItem *aconf)
{
static unsigned long prec_value = 0xFFFFFFFF;
int masktype, bits;
if(address == NULL)
address = "/NOMATCH!/";
- arec = MyMalloc(sizeof(struct AddressRec));
+ arec = rb_malloc(sizeof(struct AddressRec));
masktype = parse_netmask(address, (struct sockaddr *)&arec->Mask.ipa.addr, &bits);
arec->Mask.ipa.bits = bits;
arec->masktype = masktype;
-#ifdef IPV6
+#ifdef RB_IPV6
if(masktype == HM_IPV6)
{
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
atable[hv] = arec;
}
arec->username = username;
+ arec->auth_user = auth_user;
arec->aconf = aconf;
arec->precedence = prec_value--;
arec->type = type;
int masktype, bits;
unsigned long hv;
struct AddressRec *arec, *arecl = NULL;
- struct irc_sockaddr_storage addr;
+ struct rb_sockaddr_storage addr;
masktype = parse_netmask(address, (struct sockaddr *)&addr, &bits);
-#ifdef IPV6
+#ifdef RB_IPV6
if(masktype == HM_IPV6)
{
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
aconf->status |= CONF_ILLEGAL;
if(!aconf->clients)
free_conf(aconf);
- MyFree(arec);
+ rb_free(arec);
return;
}
arecl = arec;
arec->aconf->status |= CONF_ILLEGAL;
if(!arec->aconf->clients)
free_conf(arec->aconf);
- MyFree(arec);
+ rb_free(arec);
}
}
*store_next = NULL;
arec->aconf->status |= CONF_ILLEGAL;
if(!arec->aconf->clients)
free_conf(arec->aconf);
- MyFree(arec);
+ rb_free(arec);
}
}
*store_next = NULL;
*prefix_ptr++ = '+';
if(IsConfDoSpoofIp(aconf))
*prefix_ptr++ = '=';
- if(MyOper(sptr) && IsConfExemptKline(aconf))
+ if(IsOper(sptr) && IsConfExemptFlood(aconf))
+ *prefix_ptr++ = '|';
+ if(IsOper(sptr) && IsConfExemptDNSBL(aconf) && !IsConfExemptKline(aconf))
+ *prefix_ptr++ = '$';
+ if(IsOper(sptr) && IsConfExemptKline(aconf))
*prefix_ptr++ = '^';
- if(MyOper(sptr) && IsConfExemptLimits(aconf))
+ if(IsOper(sptr) && IsConfExemptLimits(aconf))
*prefix_ptr++ = '>';
- if(MyOper(sptr) && IsConfIdlelined(aconf))
- *prefix_ptr++ = '<';
*prefix_ptr = '\0';
strncpy(prefix_ptr, name, USERLEN);
return (prefix_of_host);
{
aconf = arec->aconf;
- if(!MyOper(client_p) && IsConfDoSpoofIp(aconf))
+ if(!IsOper(client_p) && IsConfDoSpoofIp(aconf))
continue;
get_printable_conf(aconf, &name, &host, &pass, &user, &port,
&classname);
+
+ if(!EmptyString(aconf->spasswd))
+ pass = aconf->spasswd;
sendto_one_numeric(client_p, RPL_STATSILINE,
form_str(RPL_STATSILINE),
- name, show_iline_prefix(client_p, aconf, user),
+ name, pass, show_iline_prefix(client_p, aconf, user),
show_ip_conf(aconf, client_p) ? host : "255.255.255.255",
port, classname);
}