Add option to debug Client block selections. Fix related buglet in
authorMichael Poole <mdpoole@troilus.org>
Sat, 9 Apr 2005 03:37:15 +0000 (03:37 +0000)
committerMichael Poole <mdpoole@troilus.org>
Sat, 9 Apr 2005 03:37:15 +0000 (03:37 +0000)
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

ChangeLog
include/s_conf.h
ircd/ircd.c
ircd/ircd_string.c
ircd/m_whowas.c
ircd/s_conf.c

index 3a3bee8b5b4164e0bbaf237cd31f0fd8d4e171d2..774cd73beae9439f76cc81c5a8c4fbbfc8a1ceea 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2005-04-08  Michael Poole <mdpoole@troilus.org>
+
+       * 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 <mdpoole@troilus.org>
 
        * ircd/m_burst.c (ms_burst): Clear channel manager bit when wiping
index d2a38245149dc3782f80b6f4e2601ff7ab94aabe..377542701c4e076cda91db10018b17e932ed6b17 100644 (file)
@@ -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);
 
index 7bc4f7c2c30aeb2910a6cac07290c2abf787d90a..aee6c7aee3562181169888860438cb749310f2a8 100644 (file)
@@ -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;
   }
index 25c749c1dd9c7eae1f556a9b8f8e151d216245a1..9ff635b6bc45c60ecaa14b354d7fcfcf2da4aab6 100644 (file)
@@ -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;
index 3053a4103a915520fdfb9f629c27353796dc86a2..b24e5c49304c6955178e2da7d782777f4bd69d65 100644 (file)
@@ -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) :
index 64e41c822bb69e87f8751e698d1b54d0ade76893..7b198e7531afd6c89159eea02caab6940dd572c2 100644 (file)
@@ -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