From: Michael Poole Date: Sat, 9 Apr 2005 03:37:15 +0000 (+0000) Subject: Add option to debug Client block selections. Fix related buglet in X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=commitdiff_plain;h=a8aaf2a7fbfbff14f3d8cd869fcca8b9c9c459cf Add option to debug Client block selections. Fix related buglet in ircd_aton(). Clarify oper-specific output of /whowas. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1358 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/ChangeLog b/ChangeLog index 3a3bee8..774cd73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2005-04-08 Michael Poole + + * include/s_conf.h (conf_debug_iline): Declare new function. + + * ircd/ircd.c (dbg_client): New file-scoped variable. + (parse_command_line): Set it from the new -c option. + (main): If dbg_client is set during chkconf, use it. + + * ircd/ircd_string.c (ircd_aton): Generate IPv4-mapped addresses, + not IPv4-compatible addresses, to match ipmask_parse(). + + * ircd/m_whowas.c (m_whowas): Split display of real host to a + separate line, in hopes of not confusing opers in the future. + + * ircd/s_conf.c (conf_debug_iline): Implement new function. + 2005-04-06 Michael Poole * ircd/m_burst.c (ms_burst): Clear channel manager bit when wiping diff --git a/include/s_conf.h b/include/s_conf.h index d2a3824..3775427 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -183,6 +183,7 @@ extern int find_kill(struct Client *cptr); extern const char *find_quarantine(const char* chname); extern void lookup_confhost(struct ConfItem *aconf); extern void conf_parse_userhost(struct ConfItem *aconf, char *host); +extern struct ConfItem *conf_debug_iline(const char *client); extern void yyerror(const char *msg); diff --git a/ircd/ircd.c b/ircd/ircd.c index 7bc4f7c..aee6c7a 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -108,6 +108,7 @@ char *configfile = CPATH; /**< Server configuration file */ int debuglevel = -1; /**< Server debug level */ char *debugmode = ""; /**< Server debug level */ static char *dpath = DPATH; /**< Working directory for daemon */ +static char *dbg_client; /**< Client specifier for chkconf */ static struct Timer connect_timer; /**< timer structure for try_connections() */ static struct Timer ping_timer; /**< timer structure for check_pings() */ @@ -451,7 +452,7 @@ static void check_pings(struct Event* ev) { * @param[in,out] argv Command-lne arguments. */ static void parse_command_line(int argc, char** argv) { - const char *options = "d:f:h:nktvx:"; + const char *options = "d:f:h:nktvx:c:"; int opt; if (thisServer.euid != thisServer.uid) @@ -463,6 +464,7 @@ static void parse_command_line(int argc, char** argv) { while ((opt = getopt(argc, argv, options)) != EOF) switch (opt) { case 'k': thisServer.bootopt |= BOOT_CHKCONF | BOOT_TTY; break; + case 'c': dbg_client = optarg; break; case 'n': case 't': thisServer.bootopt |= BOOT_TTY; break; case 'd': dpath = optarg; break; @@ -487,7 +489,7 @@ static void parse_command_line(int argc, char** argv) { exit(0); break; - + case 'x': debuglevel = atoi(optarg); if (debuglevel < 0) @@ -675,6 +677,8 @@ int main(int argc, char **argv) { } if (thisServer.bootopt & BOOT_CHKCONF) { + if (dbg_client) + conf_debug_iline(dbg_client); fprintf(stderr, "Configuration file %s checked okay.\n", configfile); return 0; } diff --git a/ircd/ircd_string.c b/ircd/ircd_string.c index 25c749c..9ff635b 100644 --- a/ircd/ircd_string.c +++ b/ircd/ircd_string.c @@ -667,6 +667,7 @@ ircd_aton(struct irc_in_addr *ip, const char *input) unsigned int addr; int len = ircd_aton_ip4(input, &addr); if (len) { + ip->in6_16[5] = htons(65535); ip->in6_16[6] = htons(ntohl(addr) >> 16); ip->in6_16[7] = htons(ntohl(addr) & 65535); return len; diff --git a/ircd/m_whowas.c b/ircd/m_whowas.c index 3053a41..b24e5c4 100644 --- a/ircd/m_whowas.c +++ b/ircd/m_whowas.c @@ -137,8 +137,9 @@ int m_whowas(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) if (0 == ircd_strcmp(nick, temp->name)) { send_reply(sptr, RPL_WHOWASUSER, temp->name, temp->username, - (IsAnOper(sptr) && temp->realhost) ? temp->realhost : temp->hostname, temp->realname); + if (IsAnOper(sptr) && strcmp(temp->hostname, temp->realhost)) + send_reply(sptr, RPL_WHOISACTUALLY, temp->name, temp->username, temp->realhost); send_reply(sptr, RPL_WHOISSERVER, temp->name, (feature_bool(FEAT_HIS_WHOIS_SERVERNAME) && !IsOper(sptr)) ? feature_str(FEAT_HIS_SERVERNAME) : diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 64e41c8..7b198e7 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -383,6 +383,9 @@ enum AuthorizationCheckResult attach_iline(struct Client* cptr) for (aconf = GlobalConfList; aconf; aconf = aconf->next) { if (aconf->status != CONF_CLIENT) continue; + /* If you change any of this logic, please make corresponding + * changes in conf_debug_iline() below. + */ if (aconf->address.port && aconf->address.port != cli_listener(cptr)->addr.port) continue; if (aconf->username) { @@ -400,6 +403,103 @@ enum AuthorizationCheckResult attach_iline(struct Client* cptr) return ACR_NO_AUTHORIZATION; } +/** Interpret \a client as a client specifier and show which Client + * block(s) match that client. + * + * The client specifier may contain an IP address, hostname, listener + * port, or a combination of those separated by commas. IP addresses + * and hostnamese may be preceded by "username@"; the last given + * username will be used for the match. + * + * @param[in] client Client specifier. + * @return Matching Client block structure. + */ +struct ConfItem *conf_debug_iline(const char *client) +{ + struct irc_in_addr address; + struct ConfItem *aconf; + char *sep; + unsigned short listener; + char username[USERLEN+1], hostname[HOSTLEN+1]; + + /* Initialize variables. */ + listener = 0; + memset(&address, 0, sizeof(address)); + memset(&username, 0, sizeof(username)); + memset(&hostname, 0, sizeof(hostname)); + + /* Parse client specifier. */ + while (*client) { + struct irc_in_addr tmpaddr; + long tmp; + + /* Try to parse as listener port number first. */ + tmp = strtol(client, &sep, 10); + if (tmp && (*sep == '\0' || *sep == ',')) { + listener = tmp; + client = sep + (*sep != '\0'); + continue; + } + + /* Maybe username@ before an IP address or hostname? */ + tmp = strcspn(client, ",@"); + if (client[tmp] == '@') { + if (tmp > USERLEN) + tmp = USERLEN; + ircd_strncpy(username, client, tmp); + /* and fall through */ + client += tmp + 1; + } + + /* Looks like an IP address? */ + tmp = ircd_aton(&tmpaddr, client); + if (tmp && (client[tmp] == '\0' || client[tmp] == ',')) { + memcpy(&address, &tmpaddr, sizeof(address)); + client += tmp + (client[tmp] != '\0'); + continue; + } + + /* Else must be a hostname. */ + tmp = strcspn(client, ","); + if (tmp > HOSTLEN) + tmp = HOSTLEN; + ircd_strncpy(hostname, client, tmp); + client += tmp + (client[tmp] != '\0'); + } + + /* Walk configuration to find matching Client block. */ + for (aconf = GlobalConfList; aconf; aconf = aconf->next) { + if (aconf->status != CONF_CLIENT) + continue; + if (aconf->address.port && aconf->address.port != listener) { + fprintf(stdout, "Listener port mismatch: %u != %u\n", aconf->address.port, listener); + continue; + } + if (aconf->username && match(aconf->username, username)) { + fprintf(stdout, "Username mismatch: %s != %s\n", aconf->username, username); + continue; + } + if (aconf->host && match(aconf->host, hostname)) { + fprintf(stdout, "Hostname mismatch: %s != %s\n", aconf->host, hostname); + continue; + } + if ((aconf->addrbits >= 0) + && !ipmask_check(&address, &aconf->address.addr, aconf->addrbits)) { + fprintf(stdout, "IP address mismatch: %s != %s\n", aconf->name, ircd_ntoa(&address)); + continue; + } + fprintf(stdout, "Match! username=%s host=%s ip=%s class=%s maxlinks=%u password=%s\n", + (aconf->username ? aconf->username : "(null)"), + (aconf->host ? aconf->host : "(null)"), + (aconf->name ? aconf->name : "(null)"), + ConfClass(aconf), aconf->maximum, aconf->passwd); + return aconf; + } + + fprintf(stdout, "No matches found.\n"); + return NULL; +} + /** Check whether a particular ConfItem is already attached to a * Client. * @param aconf ConfItem to search for