Beispiel #1
0
void
ilog(ilogfile dest, const char *format, ...)
{
    FILE *logfile = *log_table[dest].logfile;
    char buf[BUFSIZE];
    char buf2[BUFSIZE];
    va_list args;

    if(logfile == NULL)
        return;

    va_start(args, format);
    ircvsnprintf(buf, sizeof(buf), format, args);
    va_end(args);

    ircsnprintf(buf2, sizeof(buf2), "%s %s\n", smalldate(), buf);

    if(fputs(buf2, logfile) < 0)
    {
        fclose(logfile);
        *log_table[dest].logfile = NULL;
    }

    fflush(logfile);
}
Beispiel #2
0
static void
write_log(const char *message)
{
	char buf[LOG_BUFSIZE];
	size_t nbytes = 0;

	if(logFile == NULL)
		return;

#ifdef _WIN32
	nbytes = snprintf(buf, sizeof(buf), "[%s] %s\r\n", smalldate(CurrentTime), message);
#else
	nbytes = snprintf(buf, sizeof(buf), "[%s] %s\n", smalldate(CurrentTime), message);
#endif
	fbputs(buf, logFile, nbytes);
}
Beispiel #3
0
/* writes a string to the logfile prefixing with the current time */
static void write_log(const char* message)
{
  char buf[LOG_BUFSIZE];
  snprintf(buf, LOG_BUFSIZE, "[%s] %s\n", smalldate(CurrentTime), message);
  if(logFile == -1)
    printf("%s", buf);
  else
    write(logFile, buf, strlen(buf));
}
Beispiel #4
0
static void
log_va(const ilogfile dest, const unsigned int snomask, const char *const fmt, va_list ap)
{
	FILE *const logfile = *log_table[dest].logfile;
	if(!logfile && !snomask)
		return;

	char buf[BUFSIZE];
	vsnprintf(buf, sizeof(buf), fmt, ap);

	if(snomask)
		sendto_realops_snomask(snomask, L_ALL, "%s", buf);

	if(fprintf(logfile, "%s %s\n", smalldate(rb_current_time()), buf) < 0)
	{
		fclose(logfile);
		*log_table[dest].logfile = NULL;
	} else {
		fflush(logfile);
	}
}
Beispiel #5
0
static void
ms_dline(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
  char def_reason[] = CONF_NOREASON;
  char *dlhost, *reason;
  const char *creason;
  const struct Client *target_p = NULL;
  struct irc_ssaddr daddr;
  struct MaskItem *conf=NULL;
  time_t tkline_time=0;
  int bits = 0, aftype = 0, t = 0;
  const char *current_date = NULL;
  time_t cur_time;
  char hostip[HOSTIPLEN + 1];
  char buffer[IRCD_BUFSIZE];

  if (parc != 5 || EmptyString(parv[4]))
    return;

  /* parv[0]  parv[1]        parv[2]      parv[3]  parv[4] */
  /* oper     target_server  tkline_time  host     reason  */
  sendto_match_servs(source_p, parv[1], CAP_DLN,
                     "DLINE %s %s %s :%s",
                     parv[1], parv[2], parv[3], parv[4]);

  if (match(parv[1], me.name))
    return;

  tkline_time = valid_tkline(parv[2], TK_SECONDS);
  dlhost = parv[3];
  reason = parv[4];

  if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(CONF_ULINE, source_p->servptr->name,
                              source_p->username, source_p->host,
                              SHARED_DLINE))
  {
    if (!IsClient(source_p))
      return;
    if ((t = parse_netmask(dlhost, NULL, &bits)) == HM_HOST)
    {
      if ((target_p = find_chasing(client_p, source_p, dlhost, NULL)) == NULL)
        return;

      if (!MyConnect(target_p))
      {
        sendto_one(source_p,
                   ":%s NOTICE %s :Can't DLINE nick on another server",
                   me.name, source_p->name);
        return;
      }

      if (IsExemptKline(target_p))
      {
        sendto_one(source_p,
                   ":%s NOTICE %s :%s is E-lined", me.name,
                   source_p->name, target_p->name);
        return;
      }

      getnameinfo((struct sockaddr *)&target_p->localClient->ip,
                  target_p->localClient->ip.ss_len, hostip,
                  sizeof(hostip), NULL, 0, NI_NUMERICHOST);
      dlhost = hostip;
      t = parse_netmask(dlhost, NULL, &bits);
      assert(t == HM_IPV4 || t == HM_IPV6);
    }

    if (bits < 8)
    {
      sendto_one(source_p,
                 ":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.",
                 me.name, source_p->name);
      return;
    }

#ifdef IPV6
    if (t == HM_IPV6)
      aftype= AF_INET6;
    else
#endif
      aftype = AF_INET;

    parse_netmask(dlhost, &daddr, NULL);

    if ((conf = find_dline_conf(&daddr, aftype)) != NULL)
    {
      creason = conf->reason ? conf->reason : def_reason;
      if (IsConfExemptKline(conf))
        sendto_one(source_p,
                   ":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s",
                   me.name, source_p->name, dlhost, conf->host, creason);
      else
        sendto_one(source_p,
                   ":%s NOTICE %s :[%s] already D-lined by [%s] - %s",
                   me.name, source_p->name, dlhost, conf->host, creason);
      return;
    }

    cur_time = CurrentTime;
    current_date = smalldate(cur_time);

    if (!valid_comment(source_p, reason, 1))
      return;

    conf = conf_make(CONF_DLINE);
    conf->host = xstrdup(dlhost);

    if (tkline_time != 0)
      snprintf(buffer, sizeof(buffer), "Temporary D-line %d min. - %s (%s)",
               (int)(tkline_time/60), reason, current_date);
    else
      snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date);

    conf->reason = xstrdup(buffer);
    apply_dline(source_p, conf, tkline_time);
    rehashed_klines = 1;
  }
}
Beispiel #6
0
/* mo_dline()
 *
 * inputs	- pointer to server
 *		- pointer to client
 *		- parameter count
 *		- parameter list
 * output	-
 * side effects - D line is added
 *
 */
static void
mo_dline(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
  char def_reason[] = CONF_NOREASON;
  char *dlhost = NULL, *reason = NULL;
  char *target_server = NULL;
  const char *creason;
  const struct Client *target_p = NULL;
  struct irc_ssaddr daddr;
  struct MaskItem *conf=NULL;
  time_t tkline_time=0;
  int bits = 0, aftype = 0, t = 0;
  const char *current_date = NULL;
  time_t cur_time;
  char hostip[HOSTIPLEN + 1];
  char buffer[IRCD_BUFSIZE];

  if (!HasOFlag(source_p, OPER_FLAG_DLINE))
  {
    sendto_one(source_p, form_str(ERR_NOPRIVS),
               me.name, source_p->name, "dline");
    return;
  }

  if (parse_aline("DLINE", source_p,  parc, parv, AWILD, &dlhost,
                  NULL, &tkline_time, &target_server, &reason) < 0)
    return;

  if (target_server != NULL)
  {
    if (HasID(source_p))
    {
      sendto_server(NULL, CAP_DLN|CAP_TS6, NOCAPS,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->id, target_server, (unsigned long)tkline_time,
                    dlhost, reason);
      sendto_server(NULL, CAP_DLN, CAP_TS6,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->name, target_server, (unsigned long)tkline_time,
                    dlhost, reason);
    }
    else
      sendto_server(NULL, CAP_DLN, NOCAPS,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->name, target_server, (unsigned long)tkline_time,
                    dlhost, reason);

    /* Allow ON to apply local kline as well if it matches */
    if (match(target_server, me.name))
      return;
  }
  else
    cluster_a_line(source_p, "DLINE", CAP_DLN, SHARED_DLINE,
                   "%d %s :%s", tkline_time, dlhost, reason);

  if ((t = parse_netmask(dlhost, NULL, &bits)) == HM_HOST)
  {
    if ((target_p = find_chasing(client_p, source_p, dlhost, NULL)) == NULL)
      return;

    if (!MyConnect(target_p))
    {
      sendto_one(source_p,
                 ":%s NOTICE %s :Can't DLINE nick on another server",
                 me.name, source_p->name);
      return;
    }

    if (IsExemptKline(target_p))
    {
      sendto_one(source_p,
                 ":%s NOTICE %s :%s is E-lined", me.name,
                 source_p->name, target_p->name);
      return;
    }

    getnameinfo((struct sockaddr *)&target_p->localClient->ip,
                target_p->localClient->ip.ss_len, hostip,
                sizeof(hostip), NULL, 0, NI_NUMERICHOST);
    dlhost = hostip;
    t = parse_netmask(dlhost, NULL, &bits);
    assert(t == HM_IPV4 || t == HM_IPV6);
  }

  if (bits < 8)
  {
    sendto_one(source_p,
               ":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.",
               me.name, source_p->name);
    return;
  }

#ifdef IPV6
  if (t == HM_IPV6)
    aftype = AF_INET6;
  else
#endif
    aftype = AF_INET;

  parse_netmask(dlhost, &daddr, NULL);

  if ((conf = find_dline_conf(&daddr, aftype)) != NULL)
  {
    creason = conf->reason ? conf->reason : def_reason;
    if (IsConfExemptKline(conf))
      sendto_one(source_p,
		 ":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s",
		 me.name, source_p->name, dlhost, conf->host, creason);
    else
      sendto_one(source_p,
		 ":%s NOTICE %s :[%s] already D-lined by [%s] - %s",
		 me.name, source_p->name, dlhost, conf->host, creason);
    return;
  }

  cur_time = CurrentTime;
  current_date = smalldate(cur_time);

  if (!valid_comment(source_p, reason, 1))
    return;

  conf = conf_make(CONF_DLINE);
  conf->host = xstrdup(dlhost);

  if (tkline_time != 0)
    snprintf(buffer, sizeof(buffer), "Temporary D-line %d min. - %s (%s)",
             (int)(tkline_time/60), reason, current_date);
  else
    snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date);

  conf->reason = xstrdup(buffer);
  apply_dline(source_p, conf, tkline_time);
  rehashed_klines = 1;
}
int
m_scan_unklines(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[])
{
  char *mask = NULL;
  int list = 1, count = 0, listed_so_far = 0;
  int list_max = 100;
  int i;
  struct unkline_record **ukr, *ukr2;

  if (!HasUmode(sptr,UMODE_SEEKLINES))
    {
      if (SeesOperMessages(sptr))
	sendto_one(sptr,":%s NOTICE %s :You have no 2 umode", me.name, parv[0]);
      else
	sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (parc < 2)
    {
      if (!IsServer(sptr))
	sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
		   me.name, parv[0], "SCAN UNKLINES");
      return 0;
    }

  for (i = 2; i < parc; i++)
    {
      if (!irccmp(parv[i], "no-list"))
	list = 0;
      else if (!irccmp(parv[i], "list"))
	list = 1;
      else if (i < (parc - 1))
	{
	  if (!irccmp(parv[i], "list-max"))
	    {
	      list_max = atoi(parv[++i]);
	    }
	  else if (!irccmp(parv[i], "mask"))
	    {
	      mask = parv[++i];
	    }
	}
    }

  for (ukr = &recorded_unklines; (ukr2 = *ukr); ukr = &ukr2->next)
    {
      if ((ukr2->placed + UNKLINE_CACHE_TIME) < CurrentTime)
	  {
	    *ukr = ukr2->next;
	    MyFree(ukr2->mask);
	    MyFree(ukr2);
	    /* And put stuff back, safety in case we can't loop again */
	    if (!(ukr2 = *ukr))
	      break;
	  }
      else
        {
          if (mask && !match(mask, ukr2->mask))
            continue;
          count++;
          if (list && (list_max > ++listed_so_far))
/*             send_markup(sptr, &me, "SCAN-UNKLINE", */
/*                         "!begin<1>%s!end<1> unklined at !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>)", */
/*                         ukr2->mask, ukr2->placed, ukr2->placed - CurrentTime); */
            send_markup(sptr, &me, "SCAN-UNKLINE",
                        "%s unklined at %s (%s)",
                        ukr2->mask, smalldate(ukr2->placed), smalltime(ukr2->placed - CurrentTime));
        }
    }

  send_markup(sptr, &me, "UNKLINE-END", "End of unkline list");
/*   send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */
  send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count);

  return 0;
}
int
m_scan_klines(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[])
{
  char *host_mask = NULL, *user_mask = NULL;
  int list = 1, count = 0, listed_so_far = 0;
  int list_max = 100;
  int expired = 0;
  char *placed_by = NULL;
  int i;
  struct ConfItem *aconf;

  if (!HasUmode(sptr,UMODE_SEEKLINES))
    {
      if (SeesOperMessages(sptr))
	sendto_one(sptr,":%s NOTICE %s :You have no 2 umode", me.name, parv[0]);
      else
	sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (parc < 2)
    {
      if (!IsServer(sptr))
	sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
		   me.name, parv[0], "SCAN KLINES");
      return 0;
    }

  for (i = 2; i < parc; i++)
    {
      if (!irccmp(parv[i], "no-list"))
	list = 0;
      else if (!irccmp(parv[i], "list"))
	list = 1;
      else if (!irccmp(parv[i], "not-expired"))
	expired = 0;
      else if (!irccmp(parv[i], "expired"))
	expired = 1;
      else if (i < (parc - 1))
	{
	  if (!irccmp(parv[i], "list-max"))
	    {
	      list_max = strtoul(parv[++i], NULL, 0);
	    }
	  else if (!irccmp(parv[i], "host-mask"))
	    {
	      host_mask = parv[++i];
	    }
	  else if (!irccmp(parv[i], "user-mask"))
	    {
	      user_mask = parv[++i];
	    }
	  else if (!irccmp(parv[i], "placed-by"))
	    {
	      placed_by = parv[++i];
	    }
	}
    }

  for (aconf = kline_list; aconf; aconf = aconf->kline_next)
    {
      char *p;
      if (aconf->status != CONF_KILL)
	continue;
      if (host_mask && !match(host_mask, aconf->host))
	continue;
      if (user_mask && !match(user_mask, aconf->user))
	continue;
      /* extract the user who placed the K:line */
      if ((p = strchr(aconf->passwd, ';')))
	{
	  int skip = 0;
	  *p = '\0';
	  skip = placed_by && !match(placed_by, aconf->passwd);
	  *p = ';';
	  if (skip)
	    continue;
	}
      /* true if:
       *            (can expire     (and has expired           ))
       * (we want expired and have expired, or vice versa        )
       */
      if (expired ^ (aconf->hold && (aconf->hold <= CurrentTime)))
	continue;

      count++;
      if (list && (list_max > ++listed_so_far))
	{
          /* p points to the semicolon in the comment field, if there is one */
	  if (p)
	    *p = '\0';
          if (aconf->hold)
            {
              if (p)
                {
/*                   send_markup(sptr, &me, "SCAN-KLINE", */
/*                               "!begin<1>%s@%s!end<1> klined " */
/*                               "until !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>) " */
/*                               "by !begin<4>%s!end<4>, because: %s", */
/*                               aconf->user, aconf->host, aconf->hold, aconf->hold - CurrentTime, aconf->passwd, p + 2); */
                  send_markup(sptr, &me, "SCAN-KLINE",
                              "%s@%s klined "
                              "until %s (%s) "
                              "by %s, because: %s",
                              aconf->user, aconf->host, smalldate(aconf->hold), smalltime(aconf->hold - CurrentTime), aconf->passwd, p + 2);
                }
              else
                {
/*                   send_markup(sptr, &me, "SCAN-KLINE", */
/*                               "!begin<1>%s@%s!end<1> klined " */
/*                               "until !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>) " */
/*                               "by !begin<4>%s!end<4>", */
/*                               aconf->user, aconf->host, aconf->hold, aconf->hold - CurrentTime, aconf->passwd); */
                  send_markup(sptr, &me, "SCAN-KLINE",
                              "%s@%s klined "
                              "until %s (%s) "
                              "by %s",
                              aconf->user, aconf->host, smalldate(aconf->hold), smalltime(aconf->hold - CurrentTime), aconf->passwd);
                }
            }
          else
            {
              if (p)
                {
/*                   send_markup(sptr, &me, "SCAN-KLINE", */
/*                               "!begin<1>%s@%s!end<1> klined !begin<2>permanently!end<2> " */
/*                               "by !begin<4>%s!end<4>, because: %s", */
/*                               aconf->user, aconf->host, aconf->passwd, p + 2); */
                  send_markup(sptr, &me, "SCAN-KLINE",
                              "%s@%s klined permanently "
                              "by %s, because: %s",
                              aconf->user, aconf->host, aconf->passwd, p + 2);
                }
              else
                {
/*                   send_markup(sptr, &me, "SCAN-KLINE", */
/*                               "!begin<1>%s@%s!end<1> klined !begin<2>permanently!end<2> " */
/*                               "by !begin<4>%s!end<4>", */
/*                               aconf->user, aconf->host, aconf->passwd); */
                  send_markup(sptr, &me, "SCAN-KLINE",
                              "%s@%s klined permanently "
                              "by %s",
                              aconf->user, aconf->host, aconf->passwd);
                }
            }
	  if (p)
	    {
	      *p = ';';
	    }
	}
    }

  send_markup(sptr, &me, "KLINE-END", "End of kline list");
/*   send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */
  send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count);

  return 0;
}
Beispiel #9
0
/*
 * m_gline
 * Add a local user@host ban.
 *
 *    parv[0] = sender
 *    parv[1] = duration (optional)
 *    parv[2] = nick or user@host mask
 *    parv[3] = reason (optional)
 */
int
m_gline(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    char rbuf[512];
    char *target;
    char *user;
    char *host;
    char *reason = "<no reason>";
    int tgminutes = DEFAULT_GLINE_TIME;
    int tgseconds;
    long lval;
    struct userBan *ban;
    struct userBan *existing;

    if (!IsPrivileged(sptr))
    {
        sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
        return 0;
    }

    if (parc < 2)
    {
        sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
                   "gline");
        return 0;
    }

    lval = strtol(parv[1], &target, 10);
    if (*target != 0)
    {
        target = parv[1];
        if (parc > 2)
            reason = parv[2];
    }
    else
    {
        /* valid expiration time */
        tgminutes = lval;

        if (parc < 3)
        {
            sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
                       "Gline");
            return 0;
        }

        target = parv[2];

        if (parc > 3)
            reason = parv[3];
    }

    /* negative times, or times greater than a year, are permanent */
    if (tgminutes < 0 || tgminutes > (365 * 24 * 60))
        tgminutes = 0;
    tgseconds = tgminutes * 60;

    if ((host = strchr(target, '@')))
    {
        *host++ = 0;
        user = target;
    }
    else
    {
        user = "******";
        host = target;
    }

    if (!match(user, "akjhfkahfasfjd") &&
        !match(host, "ldksjfl.kss...kdjfd.jfklsjf"))
    {
        sendto_one(sptr, ":%s NOTICE %s :gline: %s@%s mask is too wide",
                   me.name, parv[0], user, host);
        return 0;
    }

    /*
     * XXX: nick target support to be re-added
     */

    if (!(ban = make_hostbased_ban(user, host)))
    {
        sendto_one(sptr, ":%s NOTICE %s :gline: invalid ban mask %s@%s",
                   me.name, parv[0], user, host);
        return 0;
    }

    ban->flags |= UBAN_GLINE;

    /* only looks for duplicate glines, not akills */
    if ((existing = find_userban_exact(ban, UBAN_GLINE)))
    {
        if (!IsServer(sptr))
        sendto_one(sptr, ":%s NOTICE %s :gline: %s@%s is already %s: %s",
                   me.name, parv[0], user, host, NETWORK_GLINE_NAME,
                   existing->reason ? existing->reason : "<no reason>");
        userban_free(ban);
        return 0;
    }

    if (MyClient(sptr) && user_match_ban(sptr, ban))
    {
        sendto_one(sptr, ":%s NOTICE %s :gline: %s@%s matches you, rejected",
                   me.name, parv[0], user, host);
        userban_free(ban);
        return 0;
    }

    if (!IsServer(sptr))
        ircsnprintf(rbuf, sizeof(rbuf), "%s (%s)", reason, smalldate(0));
    else
        ircsnprintf(rbuf, sizeof(rbuf), "%s", reason);

    ban->reason = MyMalloc(strlen(rbuf) + 1);
    strcpy(ban->reason, rbuf);

    if (tgseconds)
    {
        ban->flags |= UBAN_TEMPORARY;
        ban->timeset = NOW;
        ban->duration = tgseconds;
    }

    add_hostbased_userban(ban);

    if (!tgminutes || tgminutes >= GLINE_MIN_STORE_TIME)
        glinestore_add(ban);

    userban_sweep(ban);

    host = get_userban_host(ban, rbuf, sizeof(rbuf));

    sendto_serv_butone(MyConnect(sptr) ? NULL : cptr, ":%s GLINE %l %s@%s :%s", sptr->name, tgseconds, user, host, reason);

    if (tgminutes)

        sendto_realops("%s added temporary %d min. "NETWORK_GLINE_NAME" for"
                       " [%s@%s] [%s]", parv[0], tgminutes, user, host,
                       reason);
    else

        sendto_realops("%s added "NETWORK_GLINE_NAME" for [%s@%s] [%s]", parv[0],
                       user, host, reason);

    return 0;
}
Beispiel #10
0
/*
 * m_kline
 * Add a local user@host ban.
 *
 *    parv[0] = sender
 *    parv[1] = duration (optional)
 *    parv[2] = nick or user@host mask
 *    parv[3] = reason (optional)
 */
int
m_kline(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    char rbuf[512];
    char hostbuf[HOSTIPLEN+3+1];
    char *target;
    char *user;
    char *host;
    char *reason = "<no reason>";
    int tkminutes = DEFAULT_KLINE_TIME;
    int tkseconds;
    long lval;
    struct userBan *ban;
    struct userBan *existing;
    aClient *acptr;

    if (!OPCanKline(sptr))
    {
        sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
        return 0;
    }

    if (parc < 2)
    {
        sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
                   "KLINE");
        return 0;
    }

    lval = strtol(parv[1], &target, 10);
    if (*target != 0)
    {
        target = parv[1];
        if (parc > 2 && !BadPtr(parv[2]))
            reason = parv[2];
    }
    else
    {
        /* valid expiration time */
        tkminutes = lval;

        if (parc < 3)
        {
            sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
                       "KLINE");
            return 0;
        }

        target = parv[2];

        if (parc > 3 && !BadPtr(parv[3]))
            reason = parv[3];
    }

    /* negative times, or times greater than a year, are permanent */
    if (tkminutes < 0 || tkminutes > (365 * 24 * 60))
        tkminutes = 0;
    tkseconds = tkminutes * 60;

    if ((host = strchr(target, '@')))
    {
        *host++ = 0;
        user = target;
    }
    else if (strchr(target, '*'))
    {
        user = "******";
        host = target;
    }
    else
    {
        if (!(acptr = find_chasing(sptr, target, NULL)))
            return 0;
        
        if (!acptr->user)
            return 0;
        
        user = acptr->user->username;
	if (acptr->ip_family == AF_INET)
	{
	    ircsprintf(hostbuf, "%s/24", acptr->hostip);
	    host = hostbuf;
	}
	else
	    host = acptr->hostip;
    }

    if (!match(user, "akjhfkahfasfjd") &&
        !match(host, "ldksjfl.kss...kdjfd.jfklsjf"))
    {
        sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s mask is too wide",
                   me.name, parv[0], user, host);
        return 0;
    }

    if (strchr(host, ' ') || !(ban = make_hostbased_ban(user, host)))
    {
        sendto_one(sptr, ":%s NOTICE %s :KLINE: invalid ban mask %s@%s",
                   me.name, parv[0], user, host);
        return 0;
    }

    ban->flags |= UBAN_LOCAL;

    /* only looks for duplicate klines, not akills */
    if ((existing = find_userban_exact(ban, UBAN_LOCAL)))
    {
        sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s is already %s: %s",
                   me.name, parv[0], user, host, LOCAL_BANNED_NAME,
                   existing->reason ? existing->reason : "<no reason>");
        userban_free(ban);
        return 0;
    }

    if (user_match_ban(sptr, ban))
    {
        sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s matches you, rejected",
                   me.name, parv[0], user, host);
        userban_free(ban);
        return 0;
    }

    ircsnprintf(rbuf, sizeof(rbuf), "%s (%s)", reason, smalldate(0));
    ban->reason = MyMalloc(strlen(rbuf) + 1);
    strcpy(ban->reason, rbuf);

    if (tkseconds)
    {
        ban->flags |= UBAN_TEMPORARY;
        ban->timeset = NOW;
        ban->duration = tkseconds;
    }

    add_hostbased_userban(ban);

    if (!tkminutes || tkminutes >= KLINE_MIN_STORE_TIME)
        klinestore_add(ban);

    userban_sweep(ban);

    host = get_userban_host(ban, rbuf, sizeof(rbuf));

    if (tkminutes)
        sendto_realops("%s added temporary %d min. "LOCAL_BAN_NAME" for"
                       " [%s@%s] [%s]", parv[0], tkminutes, user, host,
                       reason);
    else
        sendto_realops("%s added "LOCAL_BAN_NAME" for [%s@%s] [%s]", parv[0],
                       user, host, reason);

    return 0;
}