Exemplo n.º 1
0
static void join_notes(char *nick, char *uhost, char *handle, char *par)
{
  int i = -1, j;
  struct chanset_t *chan = chanset;

  if (notify_onjoin) {          /* drummer */
    for (j = 0; j < dcc_total; j++)
      if ((dcc[j].type->flags & DCT_CHAT) &&
          (!egg_strcasecmp(dcc[j].nick, handle)))
        return;                 /* They already know they have notes */

    while (chan) {
      if (ismember(chan, nick))
        return;                 /* They already know they have notes */
      chan = chan->next;
    }

    i = num_notes(handle);
    if (i) {
      dprintf(DP_HELP, NOTES_WAITING_NOTICE, nick, i, (i == 1) ? "" : "s", botname);
      dprintf(DP_HELP, "NOTICE %s :%s /MSG %s NOTES <pass> INDEX\n",
              nick, NOTES_FORLIST, botname);
    }
  }
}
Exemplo n.º 2
0
struct chanset_t* find_common_opped_chan(bd::String nick) {
  for (struct chanset_t* chan = chanset; chan; chan = chan->next) {
    if (channel_active(chan) && (me_op(chan) || me_voice(chan))) {
      if (ismember(chan, nick.c_str()))
        return chan;
    }
  }
  return NULL;
}
Exemplo n.º 3
0
	/**
	 * Remove an elementfrom the set. Running time O(1).
	 * Warning Using this method moves the last inserted element
	 * into the position of the removed element.
	 * Breaking the insertion order invariant - if you rely on that.
     */		
	void remove(unsigned int i){
	    if(!ismember(i)){
	    	return;
	    } 
	    unsigned int j = dense[n-1];
	    dense[sparse[i]] = j;
	    sparse[j] = sparse[i];
	    n--;
	}
Exemplo n.º 4
0
/*
 * Helper function that abort() on unexpected errors.
 * The expected error set is a zero-terminated array of scf_error_t
 */
static int
check_scf_error(scf_error_t e, const scf_error_t *errs)
{
	if (ismember(e, errs))
		return (1);

	assert(0);
	abort();

	/*NOTREACHED*/
}
Exemplo n.º 5
0
/* Check if I am a halfop. Returns boolean 1 or 0.
 */
static int me_halfop(struct chanset_t *chan)
{
    memberlist *mx = NULL;

    mx = ismember(chan, botname);
    if (!mx)
        return 0;
    if (chan_hashalfop(mx))
        return 1;
    else
        return 0;
}
Exemplo n.º 6
0
/* Check whether I'm voice. Returns boolean 1 or 0.
 */
static int me_voice(struct chanset_t *chan)
{
    memberlist *mx;

    mx = ismember(chan, botname);
    if (!mx)
        return 0;
    if (chan_hasvoice(mx))
        return 1;
    else
        return 0;
}
Exemplo n.º 7
0
/* onanychan():
 * checks if the given nickname is on any of the bot's chans.
 */
static struct chanset_t *onanychan(char *nick)
{
  struct chanset_t *ch;
  memberlist *m;

  for (ch = chanset; ch; ch = ch->next) {
    m = ismember(ch, nick);
    if (m && !chan_issplit(m))
      return ch;
  }
  return NULL;
}
Exemplo n.º 8
0
static int onchan(char *nick, char *chan)
{
  struct chanset_t *ch;
  memberlist *m;

  ch = findchan_by_dname(chan);
  if (!ch)
    return 0;
  m = ismember(ch, nick);
  if (!m)
    return 0;
  else if (chan_issplit(m))
    return 0;
  else
    return 1;
}
Exemplo n.º 9
0
char *
samechans(const char *nick, const char *delim)
{
  static char ret[1024] = "";
  struct chanset_t *chan = NULL;

  ret[0] = 0;		/* may be filled from last time */
  for (chan = chanset; chan; chan = chan->next) {
    if (ismember(chan, nick)) {
      strlcat(ret, chan->dname, sizeof(ret));
      strlcat(ret, delim, sizeof(ret));
    }
  }

  return ret;
}
Exemplo n.º 10
0
/* Expire mask originally set by `who' on `chan'?
 *
 * We might not want to expire masks in all cases, as other bots
 * often tend to immediately reset masks they've listed in their
 * internal ban list, making it quite senseless for us to remove
 * them in the first place.
 *
 * Returns 1 if a mask on `chan' by `who' may be expired and 0 if
 * not.
 */
static int expired_mask(struct chanset_t *chan, char *who)
{
  memberlist *m, *m2;
  char buf[UHOSTLEN], *snick, *sfrom;
  struct userrec *u;

  /* Always expire masks, regardless of who set it? */
  if (force_expire)
    return 1;

  strcpy(buf, who);
  sfrom = buf;
  snick = splitnick(&sfrom);

  if (!snick[0])
    return 1;

  m = ismember(chan, snick);
  if (!m)
    for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next)
      if (!egg_strcasecmp(sfrom, m2->userhost)) {
        m = m2;
        break;
      }

  if (!m || !chan_hasop(m) || !rfc_casecmp(m->nick, botname))
    return 1;

  /* At this point we know the person/bot who set the mask is currently
   * present in the channel and has op.
   */

  if (m->user)
    u = m->user;
  else {
    simple_sprintf(buf, "%s!%s", m->nick, m->userhost);
    u = get_user_by_host(buf);
  }
  /* Do not expire masks set by bots. */
  if (u && u->flags & USER_BOT)
    return 0;
  else
    return 1;
}
Exemplo n.º 11
0
static void schan_members_join(struct llist_header *head, char *nick, char *uhost, char *user, char *chan)
{
	struct stats_member *m;
	char *host;
#ifndef NO_EGG
	struct chanset_t *eggchan;
#endif

	m = schan_members_create();
	m->nick = nmalloc(strlen(nick) + 1);
	strcpy(m->nick, nick);
	m->uhost = nmalloc(strlen(uhost) + 1);
	strcpy(m->uhost, uhost);
	m->joined = now;
	if (user) {
		m->user = findsuser_by_name(user);
		if (!m->user) {
			m->user = addsuser(user, now, now);
			debug1("Stats.Mod: Created suserrec for %s.", user);
		}
	} else {
		host = nmalloc(strlen(nick) + 1 + strlen(uhost) + 1);
		sprintf(host, "%s!%s", nick, uhost);
		m->user = findsuser(host);
		nfree(host);
	}
	if (m->user) {
		m->user->laston = now;
		m->stats = findlocstats(chan, m->user->user);
		if (!m->stats)
			m->stats = initstats(chan, m->user->user);
	}
#ifndef NO_EGG
	eggchan = findchan_by_dname(chan);
	if (chan)
		m->eggmember = ismember(eggchan, nick);
	if (!m->eggmember)
		debug2("Warning[stats.mod]: Couldn't find eggmember for %s in %s.", nick, chan);
#endif
	llist_append(head, (void *) m);
}
Exemplo n.º 12
0
BOOLEAN ismemberdata(SYMBOL *sp)
{
    return !isfunction(sp->tp) && ismember(sp);
}
Exemplo n.º 13
0
	/**
	 * Adding a member to the set requires updating both of these arrays:
	 * this should be constant time.
	 */
	inline void insert(unsigned int i){
		if (!ismember(i)){
		    insert_new(i);
		}
	}
Exemplo n.º 14
0
int _setargv(int *argc, char ***argv)
{
    register int nargc;     /* New arguments counter */
    char **nargv;           /* New arguments pointers */
    register int i, j;
    int asize;              /* argv array size */
    char *arg;
    char lib[256];

    _errnum = 0;
    nargc = 0;          /* Initialise counter, size counter */
    asize = *argc;      /* and new argument vector to the */
                        /* current argv array size */

    if ((nargv = (char **) calloc((size_t) *argc, sizeof (void *))) != NULL) {
        /* For each initial argument */
        for (i = 0; i < *argc; i++) {
            arg = (*argv)[i];
#ifdef DEBUG
            fprintf(stderr, "checking arg: %s", arg);
#endif
            if (i == 0 || *arg == '-' || ! ismember(arg)) {
                /* if it begins with a dash or doesn't include
                 * a library name simply add it to the new array */
                if (! (asize = allocarg(nargc, asize, &nargv, arg)))
                    return 0;   /* Not enough memory */
                nargc++;
            } else {
                short insert;
                strcpy(lib, libname(arg));
                /* add library name if necessary */
                for (j = 2, insert = 1; i < nargc; i++) {
                    if (ismember(nargv[i])
                     && ! strcmp(lib, libname(nargv[i]))) {
                        insert = 0;
                        break;
                    }
                }
                if (insert) {
#ifdef DEBUG
                    fprintf(stderr, "inserting lib %s ", lib);
#endif
                    if (! (asize = allocarg(nargc, asize, &nargv, lib)))
                        return 0;   /* Not enough memory */
                    nargc++;
                }
                /* add file name */
#ifdef DEBUG
                fprintf(stderr, "inserting file %s", arg);
#endif
                if (! (asize = allocarg(nargc, asize, &nargv, arg)))
                    return 0;   /* Not enough memory */
                nargc++;
            }
#ifdef DEBUG
            fprintf(stderr, "\n");
#endif
        }
        /* Update caller's parameters */
        *argc = nargc;
        *argv = nargv;
        /* and sign on success */
        return nargc;
    }

    /* If it is not possible to allocate initial array, sign on error */
    _errnum = ENOMEM;
    return 0;
}
Exemplo n.º 15
0
static int msg_op(char *nick, char *host, struct userrec *u, char *par)
{
  struct chanset_t *chan = NULL;
  char *pass = NULL;
  struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };

  if (match_my_nick(nick))
    return BIND_RET_BREAK;
  pass = newsplit(&par);

  bd::String msg;

  if (homechan[0]) {
    struct chanset_t *hchan = NULL;

    hchan = findchan_by_dname(homechan);

    if (hchan && channel_active(hchan) && !ismember(hchan, nick)) {
      putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP %s (not in %s)", nick, host, par, homechan);
      if (par[0]) 
        msg = bd::String::printf("---- (%s!%s) attempted to OP for %s but is not currently in %s.", nick, host, par, homechan);
      else
        msg = bd::String::printf("---- (%s!%s) attempted to OP but is not currently in %s.", nick, host, homechan);
      privmsg(homechan, msg.c_str(), DP_SERVER);
      return BIND_RET_BREAK;
    }
  }

  if (u_pass_match(u, pass)) {
    if (!u_pass_match(u, "-")) {
      if (par[0]) {
        chan = findchan_by_dname(par);
        if (chan && channel_active(chan)) {
          get_user_flagrec(u, &fr, par, chan);
          if (chk_op(fr, chan)) {
            if (do_op(nick, chan, 0, 1)) {
              stats_add(u, 0, 1);
              putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP %s", nick, host, u->handle, par);
              if (manop_warn && chan->manop) {
                msg = bd::String::printf("%s is currently set to punish for manual op.", chan->dname);
                notice(nick, msg.c_str(), DP_HELP);
              }
            }
          }
          return BIND_RET_BREAK;
        }
      } else {
        int stats = 0;
        for (chan = chanset; chan; chan = chan->next) {
          get_user_flagrec(u, &fr, chan->dname, chan);
          if (chk_op(fr, chan)) {
            if (do_op(nick, chan, 0, 1)) {
              stats++;
              if (manop_warn && chan->manop) {
                msg = bd::String::printf("%s is currently set to punish for manual op.", chan->dname);
                notice(nick, msg.c_str(), DP_HELP);
              }
            }
          }
        }
        putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP", nick, host, u->handle);
        if (stats)
          stats_add(u, 0, 1);
        return BIND_RET_BREAK;
      }
    }
  }
  putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP", nick, host);
  return BIND_RET_BREAK;
}
Exemplo n.º 16
0
static int gotmode(char *from, char *origmsg)
{
  char *nick, *ch, *op, *chg, *msg;
  char s[UHOSTLEN], buf[511];
  char ms2[3];
  int z;
  struct userrec *u;
  memberlist *m;
  struct chanset_t *chan;

  strncpy(buf, origmsg, 510);
  buf[510] = 0;
  msg = buf;
  /* Usermode changes? */
  if (msg[0] && (strchr(CHANMETA, msg[0]) != NULL)) {
    ch = newsplit(&msg);
    chg = newsplit(&msg);
    reversing = 0;
    chan = findchan(ch);
    if (!chan) {
      putlog(LOG_MISC, "*", CHAN_FORCEJOIN, ch);
      dprintf(DP_SERVER, "PART %s\n", ch);
    } else if (channel_active(chan) || channel_pending(chan)) {
      z = strlen(msg);
      if (msg[--z] == ' ')      /* I hate cosmetic bugs :P -poptix */
        msg[z] = 0;
      putlog(LOG_MODES, chan->dname, "%s: mode change '%s %s' by %s", ch, chg,
             msg, from);
      u = get_user_by_host(from);
      get_user_flagrec(u, &user, ch);
      nick = splitnick(&from);
      m = ismember(chan, nick);
      if (m)
        m->last = now;
      if (m && channel_active(chan) && (me_op(chan) || (me_halfop(chan) &&
          !chan_hasop(m))) && !(glob_friend(user) || chan_friend(user) ||
          (channel_dontkickops(chan) && (chan_op(user) || (glob_op(user) &&
          !chan_deop(user))))) && !match_my_nick(nick)) {
        if (chan_fakeop(m) || chan_fakehalfop(m)) {
          putlog(LOG_MODES, ch, CHAN_FAKEMODE, ch);
          dprintf(DP_MODE, "KICK %s %s :%s\n", ch, nick, CHAN_FAKEMODE_KICK);
          m->flags |= SENTKICK;
          reversing = 1;
        } else if (!chan_hasop(m) && !chan_hashalfop(m) &&
                 !channel_nodesynch(chan)) {
          putlog(LOG_MODES, ch, CHAN_DESYNCMODE, ch);
          dprintf(DP_MODE, "KICK %s %s :%s\n", ch, nick, CHAN_DESYNCMODE_KICK);
          m->flags |= SENTKICK;
          reversing = 1;
        }
      }
      ms2[0] = '+';
      ms2[2] = 0;
      while ((ms2[1] = *chg)) {
        int todo = 0;

        switch (*chg) {
        case '+':
          ms2[0] = '+';
          break;
        case '-':
          ms2[0] = '-';
          break;
        case 'i':
          todo = CHANINV;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'p':
          todo = CHANPRIV;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 's':
          todo = CHANSEC;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'm':
          todo = CHANMODER;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'c':
          todo = CHANNOCLR;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'C':
          todo = CHANNOCTCP;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'R':
          todo = CHANREGON;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'M':
          todo = CHANMODREG;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'r':
          todo = CHANLONLY;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'D':
          todo = CHANDELJN;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'u':
          todo = CHANSTRIP;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'N':
          todo = CHANNONOTC;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'T':
          todo = CHANNOAMSG;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'd':
          todo = CHANINVIS;
          break;
        case 't':
          todo = CHANTOPIC;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'n':
          todo = CHANNOMSG;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'a':
          todo = CHANANON;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'q':
          todo = CHANQUIET;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'l':
          if (!nick[0] && bounce_modes)
            reversing = 1;
          if (ms2[0] == '-') {
            check_tcl_mode(nick, from, u, chan->dname, ms2, "");
            /* The Tcl proc might have modified/removed the chan or user */
            if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
              return 0;
            if (channel_active(chan)) {
              if (reversing && (chan->channel.maxmembers != 0)) {
                simple_sprintf(s, "%d", chan->channel.maxmembers);
                add_mode(chan, '+', 'l', s);
              } else if ((chan->limit_prot != 0) && !glob_master(user) &&
                         !chan_master(user) && !match_my_nick(nick)) {
                simple_sprintf(s, "%d", chan->limit_prot);
                add_mode(chan, '+', 'l', s);
              }
            }
            chan->channel.maxmembers = 0;
          } else {
            op = newsplit(&msg);
            fixcolon(op);
            if (op == '\0')
              break;
            chan->channel.maxmembers = atoi(op);
            check_tcl_mode(nick, from, u, chan->dname, ms2,
                           int_to_base10(chan->channel.maxmembers));
            /* The Tcl proc might have modified/removed the chan or user */
            if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
              return 0;
            if (channel_pending(chan))
              break;
            if ((reversing && !(chan->mode_pls_prot & CHANLIMIT)) ||
                ((chan->mode_mns_prot & CHANLIMIT) && !glob_master(user) &&
                !chan_master(user)))
              add_mode(chan, '-', 'l', "");
            if ((chan->limit_prot != chan->channel.maxmembers) &&
                (chan->mode_pls_prot & CHANLIMIT) && (chan->limit_prot != 0) &&
                !glob_master(user) && !chan_master(user)) {
              simple_sprintf(s, "%d", chan->limit_prot);
              add_mode(chan, '+', 'l', s);
            }
          }
          break;
        case 'k':
          if (ms2[0] == '+')
            chan->channel.mode |= CHANKEY;
          else
            chan->channel.mode &= ~CHANKEY;
          op = newsplit(&msg);
          fixcolon(op);
          if (op == '\0') {
            break;
          }
          check_tcl_mode(nick, from, u, chan->dname, ms2, op);
          /* The Tcl proc might have modified/removed the chan or user */
          if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
            return 0;
          if (ms2[0] == '+') {
            set_key(chan, op);
            if (channel_active(chan))
              got_key(chan, nick, from, op);
          } else {
            if (channel_active(chan)) {
              if (reversing && chan->channel.key[0])
                add_mode(chan, '+', 'k', chan->channel.key);
              else if (chan->key_prot[0] && !glob_master(user) &&
                       !chan_master(user) && !match_my_nick(nick))
                add_mode(chan, '+', 'k', chan->key_prot);
            }
            set_key(chan, NULL);
          }
          break;
        case 'o':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_op(chan, nick, from, op, u, &user);
          else
            got_deop(chan, nick, from, op, u);
          break;
        case 'h':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_halfop(chan, nick, from, op, u, &user);
          else
            got_dehalfop(chan, nick, from, op, u);
          break;
        case 'v':
          op = newsplit(&msg);
          fixcolon(op);
          m = ismember(chan, op);
          if (!m) {
            if (channel_pending(chan))
              break;
            putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, op);
            chan->status |= CHAN_PEND;
            refresh_who_chan(chan->name);
          } else {
            simple_sprintf(s, "%s!%s", m->nick, m->userhost);
            get_user_flagrec(m->user ? m->user : get_user_by_host(s),
                             &victim, chan->dname);
            if (ms2[0] == '+') {
              m->flags &= ~SENTVOICE;
              m->flags |= CHANVOICE;
              check_tcl_mode(nick, from, u, chan->dname, ms2, op);
              if (!(chan = modebind_refresh(ch, from, &user, s, &victim)))
                return 0;
              if (channel_active(chan) && !glob_master(user) &&
                  !chan_master(user) && !match_my_nick(nick)) {
                if (chan_quiet(victim) ||
                    (glob_quiet(victim) && !chan_voice(victim)))
                  add_mode(chan, '-', 'v', op);
                else if (reversing)
                  add_mode(chan, '-', 'v', op);
              }
            } else {
              m->flags &= ~SENTDEVOICE;
              m->flags &= ~CHANVOICE;
              check_tcl_mode(nick, from, u, chan->dname, ms2, op);
              if (!(chan = modebind_refresh(ch, from, &user, s, &victim)))
                return 0;
              if (channel_active(chan) && !glob_master(user) &&
                  !chan_master(user) && !match_my_nick(nick)) {
                if ((channel_autovoice(chan) && !chan_quiet(victim) &&
                    (chan_voice(victim) || glob_voice(victim))) ||
                    (!chan_quiet(victim) && (glob_gvoice(victim) ||
                    chan_gvoice(victim))))
                  add_mode(chan, '+', 'v', op);
                else if (reversing)
                  add_mode(chan, '+', 'v', op);
              }
            }
          }
          break;
        case 'b':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_ban(chan, nick, from, op, ch, u);
          else
            got_unban(chan, nick, from, op, ch, u);
          break;
        case 'e':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_exempt(chan, nick, from, op, ch, u);
          else
            got_unexempt(chan, nick, from, op, ch, u);
          break;
        case 'I':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_invite(chan, nick, from, op, ch, u);
          else
            got_uninvite(chan, nick, from, op, ch, u);
          break;
        }
        if (todo) {
          check_tcl_mode(nick, from, u, chan->dname, ms2, "");
          if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
            return 0;
          if (ms2[0] == '+')
            chan->channel.mode |= todo;
          else
            chan->channel.mode &= ~todo;
          if (channel_active(chan)) {
            if ((((ms2[0] == '+') && (chan->mode_mns_prot & todo)) ||
                ((ms2[0] == '-') && (chan->mode_pls_prot & todo))) &&
                !glob_master(user) && !chan_master(user) &&
                !match_my_nick(nick))
              add_mode(chan, ms2[0] == '+' ? '-' : '+', *chg, "");
            else if (reversing && ((ms2[0] == '+') ||
                     (chan->mode_pls_prot & todo)) && ((ms2[0] == '-') ||
                     (chan->mode_mns_prot & todo)))
              add_mode(chan, ms2[0] == '+' ? '-' : '+', *chg, "");
          }
        }
        chg++;
      }
      if (!me_op(chan) && !nick[0])
        chan->status |= CHAN_ASKEDMODES;
    }
  }
  return 0;
}
Exemplo n.º 17
0
/* Dependant on revenge_mode, punish the offender.
 */
static void punish_badguy(struct chanset_t *chan, char *whobad,
                          struct userrec *u, char *badnick, char *victim,
                          int mevictim, int type)
{
    char reason[1024], ct[81], *kick_msg;
    memberlist *m;
    struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };

    m = ismember(chan, badnick);
    if (!m)
        return;
    get_user_flagrec(u, &fr, chan->dname);

    /* Get current time into a string */
    egg_strftime(ct, 7, "%d %b", localtime(&now));

    /* Put together log and kick messages */
    reason[0] = 0;
    switch (type) {
    case REVENGE_KICK:
        kick_msg = IRC_KICK_PROTECT;
        simple_sprintf(reason, "kicked %s off %s", victim, chan->dname);
        break;
    case REVENGE_DEOP:
        simple_sprintf(reason, "deopped %s on %s", victim, chan->dname);
        kick_msg = IRC_DEOP_PROTECT;
        break;
    default:
        kick_msg = "revenge!";
    }
    putlog(LOG_MISC, chan->dname, "Punishing %s (%s)", badnick, reason);

    /* Set the offender +d */
    if ((chan->revenge_mode > 0) && !(chan_deop(fr) || glob_deop(fr))) {
        char s[UHOSTLEN], s1[UHOSTLEN];
        memberlist *mx = NULL;

        /* Removing op */
        if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) {
            fr.match = FR_CHAN;
            if (chan_op(fr))
                fr.chan &= ~USER_OP;
            else
                fr.chan |= USER_DEOP;
            set_user_flagrec(u, &fr, chan->dname);
            putlog(LOG_MISC, "*", "No longer opping %s[%s] (%s)", u->handle, whobad,
                   reason);
        }
        /* ... or just setting to deop */
        else if (u) {
            /* In the user list already, cool :) */
            fr.match = FR_CHAN;
            fr.chan |= USER_DEOP;
            set_user_flagrec(u, &fr, chan->dname);
            simple_sprintf(s, "(%s) %s", ct, reason);
            putlog(LOG_MISC, "*", "Now deopping %s[%s] (%s)", u->handle, whobad, s);
        }
        /* ... or creating new user and setting that to deop */
        else {
            strcpy(s1, whobad);
            maskaddr(s1, s, chan->ban_type);
            strcpy(s1, badnick);
            /* If that handle exists use "badX" (where X is an increasing number)
             * instead.
             */
            while (get_user_by_handle(userlist, s1)) {
                if (!strncmp(s1, "bad", 3)) {
                    int i;

                    i = atoi(s1 + 3);
                    simple_sprintf(s1 + 3, "%d", i + 1);
                } else
                    strcpy(s1, "bad1");   /* Start with '1' */
            }
            userlist = adduser(userlist, s1, s, "-", 0);
            fr.match = FR_CHAN;
            fr.chan = USER_DEOP;
            fr.udef_chan = 0;
            u = get_user_by_handle(userlist, s1);
            if ((mx = ismember(chan, badnick)))
                mx->user = u;
            set_user_flagrec(u, &fr, chan->dname);
            simple_sprintf(s, "(%s) %s (%s)", ct, reason, whobad);
            set_user(&USERENTRY_COMMENT, u, (void *) s);
            putlog(LOG_MISC, "*", "Now deopping %s (%s)", whobad, reason);
        }
    }

    /* Always try to deop the offender */
    if (!mevictim)
        add_mode(chan, '-', 'o', badnick);
    /* Ban. Should be done before kicking. */
    if (chan->revenge_mode > 2) {
        char s[UHOSTLEN], s1[UHOSTLEN];

        splitnick(&whobad);
        maskaddr(whobad, s1, chan->ban_type);
        simple_sprintf(s, "(%s) %s", ct, reason);
        u_addban(chan, s1, botnetnick, s, now + (60 * chan->ban_time), 0);
        if (!mevictim && HALFOP_CANDOMODE('b')) {
            add_mode(chan, '+', 'b', s1);
            flush_mode(chan, QUICK);
        }
    }
    /* Kick the offender */
    if (!mevictim && (chan->revenge_mode > 1) && (!channel_dontkickops(chan) ||
            (!chan_op(fr) && (!glob_op(fr) || chan_deop(fr)))) &&
            !chan_sentkick(m) && (me_op(chan) || (me_halfop(chan) &&
                                  !chan_hasop(m) && (strchr(NOHALFOPS_MODES, 'b') == NULL)))) {
        dprintf(DP_MODE, "KICK %s %s :%s\n", chan->name, badnick, kick_msg);
        m->flags |= SENTKICK;
    }
}
Exemplo n.º 18
0
static void do_seen(int idx, char *prefix, char *nick, char *hand,
                    char *channel, char *text)
{
  char stuff[512], word1[512], word2[512], whotarget[512], object[512],
       whoredirect[512], *oix, *lastonplace = 0;
  struct userrec *urec;
  struct chanset_t *chan;
  struct laston_info *li;
  struct chanuserrec *cr;
  memberlist *m = NULL;
  int onchan = 0, i;
  long tv;
  time_t laston = 0, work;

  whotarget[0]   = 0;
  whoredirect[0] = 0;
  object[0]      = 0;

  /* Was ANYONE specified */
  if (!text[0]) {
    dprintf(idx, "%sUm, %s, it might help if you ask me about _someone_...\n",
            prefix, nick);
    return;
  }

  wordshift(word1, text);
  oix = strchr(word1, '\'');
  /* Have we got a NICK's target? */
  if (oix == word1)
    return;                     /* Skip anything starting with ' */
  if (oix && *oix && ((oix[1] && (oix[1] == 's' || oix[1] == 'S') &&
      !oix[2]) || (!oix[1] && (oix[-1] == 's' || oix[-1] == 'z' ||
      oix[-1] == 'x' || oix[-1] == 'S' || oix[-1] == 'Z' ||
      oix[-1] == 'X')))) {
    strncpy(object, word1, oix - word1);
    object[oix - word1] = 0;
    wordshift(word1, text);
    if (!word1[0]) {
      dprintf(idx, "%s%s's what, %s?\n", prefix, object, nick);
      return;
    }
    urec = get_user_by_handle(userlist, object);
    if (!urec) {
      chan = chanset;
      while (chan) {
        onchan = 0;
        m = ismember(chan, object);
        if (m) {
          onchan = 1;
          sprintf(stuff, "%s!%s", object, m->userhost);
          urec = get_user_by_host(stuff);
          if (!urec || !egg_strcasecmp(object, urec->handle))
            break;
          strcat(whoredirect, object);
          strcat(whoredirect, " is ");
          strcat(whoredirect, urec->handle);
          strcat(whoredirect, ", and ");
          strcpy(object, urec->handle);
          break;
        }
        chan = chan->next;
      }
      if (!onchan) {
        dprintf(idx, "%sI don't think I know who %s is, %s.\n",
                prefix, object, nick);
        return;
      }
    }
    if (!egg_strcasecmp(word1, "bf") || !egg_strcasecmp(word1, "boyfriend")) {
      strcpy(whotarget, getxtra(object, "BF"));
      if (whotarget[0]) {
        sprintf(whoredirect, "%s boyfriend is %s, and ",
                fixnick(object), whotarget);
        goto targetcont;
      }
      dprintf(idx,
              "%sI don't know who %s boyfriend is, %s.\n",
              prefix, fixnick(object), nick);
      return;
    }
    if (!egg_strcasecmp(word1, "gf") || !egg_strcasecmp(word1, "girlfriend")) {
      strcpy(whotarget, getxtra(object, "GF"));
      if (whotarget[0]) {
        sprintf(whoredirect, "%s girlfriend is %s, and ",
                fixnick(object), whotarget);
        goto targetcont;
      }
      dprintf(idx,
              "%sI don't know who %s girlfriend is, %s.\n",
              prefix, fixnick(object), nick);
      return;
    }
    dprintf(idx,
            "%sWhy are you bothering me with questions about %s %s, %s?\n",
            prefix, fixnick(object), word1, nick);
    return;
  }
  /* Keyword "my" */
  if (!egg_strcasecmp(word1, "my")) {
    wordshift(word1, text);
    if (!word1[0]) {
      dprintf(idx, "%sYour what, %s?\n", prefix, nick);
      return;
    }
    /* Do I even KNOW the requestor? */
    if (hand[0] == '*' || !hand[0]) {
      dprintf(idx,
              "%sI don't know you, %s, so I don't know about your %s.\n",
              prefix, nick, word1);
      return;
    }
    /* "my boyfriend" */
    if (!egg_strcasecmp(word1, "boyfriend") || !egg_strcasecmp(word1, "bf")) {
      strcpy(whotarget, getxtra(hand, "BF"));
      if (whotarget[0]) {
        sprintf(whoredirect, "%s, your boyfriend is %s, and ", nick, whotarget);
      } else {
        dprintf(idx, "%sI didn't know you had a boyfriend, %s\n", prefix, nick);
        return;
      }
    }
    /* "my girlfriend" */
    else if (!egg_strcasecmp(word1, "girlfriend") ||
             !egg_strcasecmp(word1, "gf")) {
      strcpy(whotarget, getxtra(hand, "GF"));
      if (whotarget[0]) {
        sprintf(whoredirect, "%s, your girlfriend is %s, and ",
                nick, whotarget);
      } else {
        dprintf(idx, "%sI didn't know you had a girlfriend, %s\n", prefix,
                nick);
        return;
      }
    } else {
      dprintf(idx, "%sI don't know anything about your %s, %s.\n", prefix,
              word1, nick);
      return;
    }
  }
  /* "your" keyword */
  else if (!egg_strcasecmp(word1, "your")) {
    wordshift(word1, text);
    /* "your admin" */
    if (!egg_strcasecmp(word1, "owner") || !egg_strcasecmp(word1, "admin")) {
      if (admin[0]) {
        strcpy(word2, admin);
        wordshift(whotarget, word2);
        strcat(whoredirect, "My owner is ");
        strcat(whoredirect, whotarget);
        strcat(whoredirect, ", and ");
        if (!egg_strcasecmp(whotarget, hand)) {
          strcat(whoredirect, "that's YOU");
          if (!egg_strcasecmp(hand, nick))
            strcat(whoredirect, "!!!");
          else {
            strcat(whoredirect, ", ");
            strcat(whoredirect, nick);
            strcat(whoredirect, "!");
          }
          dprintf(idx, "%s%s\n", prefix, whoredirect);
          return;
        }
      } else {                    /* owner variable munged or not set */
        dprintf(idx,
                "%sI don't seem to recall who my owner is right now...\n",
                prefix);
        return;
      }
    } else {                      /* no "your" target specified */
      dprintf(idx, "%sLet's not get personal, %s.\n", prefix, nick);
      return;
    }
  }
  /* Check for keyword match in the internal table */
  else if (match_trigger(word1)) {
    sprintf(word2, "%s%s\n", prefix, match_trigger(word1));
    dprintf(idx, word2, nick);
    return;
  }
  /* Otherwise, make the target to the first word and continue */
  else
    strcpy(whotarget, word1);

targetcont:
  /* Looking for ones own nick? */
  if (!rfc_casecmp(nick, whotarget)) {
    dprintf(idx, "%s%sLooking for yourself, eh %s?\n",
            prefix, whoredirect, nick);
    return;
  }
  /* Check if nick is on a channel */
  chan = chanset;
  while (chan) {
    m = ismember(chan, whotarget);
    if (m) {
      onchan = 1;
      sprintf(word1, "%s!%s", whotarget, m->userhost);
      urec = get_user_by_host(word1);
      if (!urec || !egg_strcasecmp(whotarget, urec->handle))
        break;
      strcat(whoredirect, whotarget);
      strcat(whoredirect, " is ");
      strcat(whoredirect, urec->handle);
      strcat(whoredirect, ", and ");
      break;
    }
    chan = chan->next;
  }
  /* Check if nick is on a channel by xref'ing to handle */
  if (!onchan) {
    chan = chanset;
    while (chan) {
      m = chan->channel.member;
      while (m && m->nick[0]) {
        sprintf(word2, "%s!%s", m->nick, m->userhost);
        urec = get_user_by_host(word2);
        if (urec && !egg_strcasecmp(urec->handle, whotarget)) {
          onchan = 1;
          strcat(whoredirect, whotarget);
          strcat(whoredirect, " is ");
          strcat(whoredirect, m->nick);
          strcat(whoredirect, ", and ");
          strcpy(whotarget, m->nick);
          break;
        }
        m = m->next;
      }
      chan = chan->next;
    }
  }
  /* Check if the target was on the channel, but is netsplit */
  chan = findchan_by_dname(channel);
  if (chan) {
    m = ismember(chan, whotarget);
    if (m && chan_issplit(m)) {
      dprintf(idx, "%s%s%s was just here, but got netsplit.\n",
              prefix, whoredirect, whotarget);
      return;
    }
  }
  /* Check if the target IS on the channel */
  if (chan && m) {
    dprintf(idx, "%s%s%s is on the channel right now!\n",
            prefix, whoredirect, whotarget);
    return;
  }
  /* Target not on this channel.   Check other channels */
  chan = chanset;
  while (chan) {
    m = ismember(chan, whotarget);
    if (m && chan_issplit(m)) {
      dprintf(idx,
              "%s%s%s was just on %s, but got netsplit.\n",
              prefix, whoredirect, whotarget, chan->dname);
      return;
    }
    if (m) {
      dprintf(idx,
              "%s%s%s is on %s right now!\n",
              prefix, whoredirect, whotarget, chan->dname);
      return;
    }
    chan = chan->next;
  }
  /* Target isn't on any of my channels. */
  /* See if target matches a handle in my userlist. */
  urec = get_user_by_handle(userlist, whotarget);
  /* No match, then bail out */
  if (!urec) {
    dprintf(idx, "%s%sI don't know who %s is.\n",
            prefix, whoredirect, whotarget);
    return;
  }
  /* We had a userlist match to a handle */
  /* Is the target currently DCC CHAT to me on the botnet? */
  for (i = 0; i < dcc_total; i++) {
    if (dcc[i].type->flags & DCT_CHAT) {
      if (!egg_strcasecmp(whotarget, dcc[i].nick)) {
        if (!rfc_casecmp(channel, dcc[i].u.chat->con_chan) &&
            dcc[i].u.chat->con_flags & LOG_PUBLIC) {
          strcat(whoredirect, whotarget);
          strcat(whoredirect,
                 " is 'observing' this channel right now from my party line!");
          dprintf(idx, "%s%s\n", prefix, whoredirect);
        } else {
          dprintf(idx,
                  "%s%s%s is linked to me via DCC CHAT right now!\n",
                  prefix, whoredirect, whotarget);
        }
        return;
      }
    }
  }
  /* Target known, but nowhere to be seen.  Give last IRC and botnet time */
  wordshift(word1, text);
  if (!egg_strcasecmp(word1, "anywhere"))
    cr = NULL;
  else
    for (cr = urec->chanrec; cr; cr = cr->next) {
      if (!rfc_casecmp(cr->channel, channel)) {
        if (cr->laston) {
          laston = cr->laston;
          lastonplace = channel;
          break;
        }
      }
    }
  if (!cr) {
    li = get_user(&USERENTRY_LASTON, urec);
    if (!li || !li->lastonplace || !li->lastonplace[0]) {
      dprintf(idx, "%s%sI've never seen %s around.\n",
              prefix, whoredirect, whotarget);
      return;
    }
    lastonplace = li->lastonplace;
    laston = li->laston;
  }
  word1[0] = 0;
  word2[0] = 0;
  work = now - laston;
  if (work >= 86400) {
    tv = work / 86400;
    sprintf(word2, "%lu day%s, ", tv, (tv == 1) ? "" : "s");
    work = work % 86400;
  }
  if (work >= 3600) {
    tv = work / 3600;
    sprintf(word2 + strlen(word2), "%lu hour%s, ", tv, (tv == 1) ? "" : "s");
    work = work % 3600;
  }
  if (work >= 60) {
    tv = work / 60;
    sprintf(word2 + strlen(word2), "%lu minute%s, ", tv,
            (tv == 1) ? "" : "s");
  }
  if (!word2[0] && (work < 60)) {
    strcpy(word2, "just moments ago!!");
  } else {
    strcpy(word2 + strlen(word2) - 2, " ago.");
  }
  if (lastonplace[0] && (strchr(CHANMETA, lastonplace[0]) != NULL))
    sprintf(word1, "on IRC channel %s", lastonplace);
  else if (lastonplace[0] == '@')
    sprintf(word1, "on %s", lastonplace + 1);
  else if (lastonplace[0] != 0)
    sprintf(word1, "on my %s", lastonplace);
  else
    strcpy(word1, "seen");
  dprintf(idx, "%s%s%s was last %s %s\n",
          prefix, whoredirect, whotarget, word1, word2);
}
Exemplo n.º 19
0
/* Queue a channel mode change
 */
static void real_add_mode(struct chanset_t *chan,
                          char plus, char mode, char *op)
{
  int i, type, modes, l;
  masklist *m;
  memberlist *mx;
  char s[21];

  /* Some IRCds do not allow halfops to set certain modes. The modes halfops
   * are not allowed to set can be changed in chan.h. */
#ifdef NO_HALFOP_CHANMODES
  if (!me_op(chan))
#else
  if (HALFOP_CANTDOMODE(mode))
#endif
    return;

  if (mode == 'o' || mode == 'h' || mode == 'v') {
    mx = ismember(chan, op);
    if (!mx)
      return;
    if (plus == '-' && mode == 'o') {
      if (chan_sentdeop(mx) || !chan_hasop(mx))
        return;
      mx->flags |= SENTDEOP;
    }
    if (plus == '+' && mode == 'o') {
      if (chan_sentop(mx) || chan_hasop(mx))
        return;
      mx->flags |= SENTOP;
    }
    if (plus == '-' && mode == 'h') {
      if (chan_sentdehalfop(mx) || !chan_hashalfop(mx))
        return;
      mx->flags |= SENTDEHALFOP;
    }
    if (plus == '+' && mode == 'h') {
      if (chan_senthalfop(mx) || chan_hashalfop(mx))
        return;
      mx->flags |= SENTHALFOP;
    }
    if (plus == '-' && mode == 'v') {
      if (chan_sentdevoice(mx) || !chan_hasvoice(mx))
        return;
      mx->flags |= SENTDEVOICE;
    }
    if (plus == '+' && mode == 'v') {
      if (chan_sentvoice(mx) || chan_hasvoice(mx))
        return;
      mx->flags |= SENTVOICE;
    }
  }

  if (chan->compat == 0) {
    if (mode == 'e' || mode == 'I')
      chan->compat = 2;
    else
      chan->compat = 1;
  } else if (mode == 'e' || mode == 'I') {
    if (prevent_mixing && chan->compat == 1)
      flush_mode(chan, NORMAL);
  } else if (prevent_mixing && chan->compat == 2)
    flush_mode(chan, NORMAL);

  if (mode == 'o' || mode == 'h' || mode == 'b' || mode == 'v' || mode == 'e' ||
      mode == 'I') {
    type = (plus == '+' ? PLUS : MINUS) | (mode == 'o' ? CHOP : (mode == 'h' ?
           CHHOP : (mode == 'b' ? BAN : (mode == 'v' ? VOICE : (mode == 'e' ?
           EXEMPT : INVITE)))));
    /*
     * FIXME: Some networks remove overlapped bans,
     *        IRCnet does not (poptix/drummer)
     *
     * Note:  On IRCnet ischanXXX() should be used, otherwise isXXXed().
     */
    if ((plus == '-' && ((mode == 'b' && !ischanban(chan, op)) ||
        (mode == 'e' && !ischanexempt(chan, op)) ||
        (mode == 'I' && !ischaninvite(chan, op)))) || (plus == '+' &&
        ((mode == 'b' && ischanban(chan, op)) ||
        (mode == 'e' && ischanexempt(chan, op)) ||
        (mode == 'I' && ischaninvite(chan, op)))))
      return;

    /* If there are already max_bans bans, max_exempts exemptions,
     * max_invites invitations or max_modes +b/+e/+I modes on the
     * channel, don't try to add one more.
     */
    if (plus == '+' && (mode == 'b' || mode == 'e' || mode == 'I')) {
      int bans = 0, exempts = 0, invites = 0;

      for (m = chan->channel.ban; m && m->mask[0]; m = m->next)
        bans++;
      if ((mode == 'b') && (bans >= max_bans))
        return;

      for (m = chan->channel.exempt; m && m->mask[0]; m = m->next)
        exempts++;
      if ((mode == 'e') && (exempts >= max_exempts))
        return;

      for (m = chan->channel.invite; m && m->mask[0]; m = m->next)
        invites++;
      if ((mode == 'I') && (invites >= max_invites))
        return;

      if (bans + exempts + invites >= max_modes)
        return;
    }

    /* op-type mode change */
    for (i = 0; i < modesperline; i++)
      if (chan->cmode[i].type == type && chan->cmode[i].op != NULL &&
          !rfc_casecmp(chan->cmode[i].op, op))
        return;                 /* Already in there :- duplicate */
    l = strlen(op) + 1;
    if (chan->bytes + l > mode_buf_len)
      flush_mode(chan, NORMAL);
    for (i = 0; i < modesperline; i++)
      if (chan->cmode[i].type == 0) {
        chan->cmode[i].type = type;
        chan->cmode[i].op = (char *) channel_malloc(l);
        chan->bytes += l;       /* Add 1 for safety */
        strcpy(chan->cmode[i].op, op);
        break;
      }
  }

  /* +k ? store key */
  else if (plus == '+' && mode == 'k') {
    if (chan->key)
      nfree(chan->key);
    chan->key = (char *) channel_malloc(strlen(op) + 1);
    if (chan->key)
      strcpy(chan->key, op);
  }
  /* -k ? store removed key */
  else if (plus == '-' && mode == 'k') {
    if (chan->rmkey)
      nfree(chan->rmkey);
    chan->rmkey = (char *) channel_malloc(strlen(op) + 1);
    if (chan->rmkey)
      strcpy(chan->rmkey, op);
  }
  /* +l ? store limit */
  else if (plus == '+' && mode == 'l')
    chan->limit = atoi(op);
  else {
    /* Typical mode changes */
    if (plus == '+')
      strcpy(s, chan->pls);
    else
      strcpy(s, chan->mns);
    if (!strchr(s, mode)) {
      if (plus == '+') {
        chan->pls[strlen(chan->pls) + 1] = 0;
        chan->pls[strlen(chan->pls)] = mode;
      } else {
        chan->mns[strlen(chan->mns) + 1] = 0;
        chan->mns[strlen(chan->mns)] = mode;
      }
    }
  }
  modes = modesperline;         /* Check for full buffer. */
  for (i = 0; i < modesperline; i++)
    if (chan->cmode[i].type)
      modes--;
  if (include_lk && chan->limit)
    modes--;
  if (include_lk && chan->rmkey)
    modes--;
  if (include_lk && chan->key)
    modes--;
  if (modes < 1)
    flush_mode(chan, NORMAL);   /* Full buffer! Flush modes. */
}
Exemplo n.º 20
0
static void got_halfop(struct chanset_t *chan, char *nick, char *from,
                       char *who, struct userrec *opu,
                       struct flag_record *opper)
{
  memberlist *m;
  char s[UHOSTLEN];
  char ch[sizeof chan->name];
  struct userrec *u;
  int check_chan = 0;
  int snm = chan->stopnethack_mode;

  m = ismember(chan, who);
  if (!m) {
    if (channel_pending(chan))
      return;
    putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who);
    chan->status |= CHAN_PEND;
    refresh_who_chan(chan->name);
    return;
  }

  /* Did *I* just get halfopped? */
  if (!me_op(chan) && !me_halfop(chan) && match_my_nick(who))
    check_chan = 1;

  strcpy(ch, chan->name);
  simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  if (!m->user)
    u = get_user_by_host(s);
  else
    u = m->user;

  get_user_flagrec(u, &victim, chan->dname);
  /* Flags need to be set correctly right from the beginning now, so that
   * add_mode() doesn't get irritated.
   */
  m->flags |= CHANHALFOP;
  check_tcl_mode(nick, from, opu, chan->dname, "+h", who);
  if (!(chan = modebind_refresh(ch, from, opper, s, &victim)) ||
      !(m = ismember(chan, who)))
    return;
  m->flags &= ~SENTHALFOP;

  if (channel_pending(chan))
    return;

  if (nick[0] && HALFOP_CANDOMODE('h') && !match_my_nick(who) &&
      !match_my_nick(nick)) {
    if (channel_bitch(chan) && !(glob_master(*opper) || glob_bot(*opper)) &&
        !chan_master(*opper) && !(glob_halfop(victim) || glob_op(victim) ||
        glob_bot(victim)) && !chan_op(victim) && !chan_halfop(victim))
      add_mode(chan, '-', 'h', who);
    else if ((chan_dehalfop(victim) || (glob_dehalfop(victim) &&
             !chan_halfop(victim))) && !glob_master(*opper) &&
             !chan_master(*opper))
      add_mode(chan, '-', 'h', who);
    else if (reversing)
      add_mode(chan, '-', 'h', who);
  } else if (reversing && HALFOP_CANDOMODE('h') && !match_my_nick(who) &&
             !match_my_nick(nick))
    add_mode(chan, '-', 'h', who);
  if (!nick[0] && HALFOP_CANDOMODE('h') && !match_my_nick(who)) {
    if (chan_dehalfop(victim) || (glob_dehalfop(victim) &&
        !chan_halfop(victim))) {
      m->flags |= FAKEHALFOP;
      add_mode(chan, '-', 'h', who);
    } else if (snm > 0 && snm < 7 && !((channel_autohalfop(chan) ||
             glob_autohalfop(victim) || chan_autohalfop(victim)) &&
             (chan_halfop(victim) || (glob_halfop(victim) &&
             !chan_dehalfop(victim)))) && !glob_exempt(victim) &&
             !chan_exempt(victim)) {
      if (snm == 5)
        snm = channel_bitch(chan) ? 1 : 3;
      if (snm == 6)
        snm = channel_bitch(chan) ? 4 : 2;
      if (chan_washalfoptest(victim) || glob_washalfoptest(victim) || snm == 2) {
        if (!chan_washalfop(m)) {
          m->flags |= FAKEHALFOP;
          add_mode(chan, '-', 'h', who);
        }
      } else if (!(chan_halfop(victim) || (glob_halfop(victim) &&
               !chan_dehalfop(victim)))) {
        if (snm == 1 || snm == 4 || (snm == 3 && !chan_washalfop(m))) {
          add_mode(chan, '-', 'h', who);
          m->flags |= FAKEHALFOP;
        }
      } else if (snm == 4 && !chan_washalfop(m)) {
        add_mode(chan, '-', 'h', who);
        m->flags |= FAKEHALFOP;
      }
    }
  }
  m->flags |= WASHALFOP;
  if (check_chan)
    recheck_channel(chan, 1);
}
Exemplo n.º 21
0
/* only to be used by test_set_one_attr */
static void set_one_attr_int(struct osd_device *osd, uint64_t pid, uint64_t oid, 
			 uint32_t page, uint32_t number, uint64_t val)
{
	struct osd_command cmd;
	uint8_t sense_out[OSD_MAX_SENSE];
	int senselen_out;
	uint8_t *data_out = NULL;
	uint64_t data_out_len;
	uint64_t attrval;
	int ret;
	struct attribute_list attr = {
		.type = ATTR_SET,
		.page = page,
		.number = number,
		.len = 8,
		.val = &attrval,
	};

	set_htonll(&attrval, val);
	ret = osd_command_set_set_attributes(&cmd, pid, oid);
	assert(ret == 0);
	ret = osd_command_attr_build(&cmd, &attr, 1);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, cmd.outdata, cmd.outlen,
				&data_out, &data_out_len,
				sense_out, &senselen_out);
	assert(ret == 0);
	osd_command_attr_free(&cmd);
}

static void set_one_attr_val(struct osd_device *osd, uint64_t pid, uint64_t oid,
			 uint32_t page, uint32_t number, const void *val,
			 uint16_t len)
{
	struct osd_command cmd;
	uint8_t sense_out[OSD_MAX_SENSE];
	int senselen_out;
	uint8_t *data_out = NULL;
	uint64_t data_out_len;
	int ret,i;
	struct attribute_list attr = {
		.type = ATTR_SET,
		.page = page,
		.number = number,
		.len = len,
		.val = (void *)(uintptr_t) val,
	};

	ret = osd_command_set_set_attributes(&cmd, pid, oid);
	assert(ret == 0);
	ret = osd_command_attr_build(&cmd, &attr, 1);

	
	ret = osdemu_cmd_submit(osd, cmd.cdb, cmd.outdata, cmd.outlen,
				&data_out, &data_out_len,
				sense_out, &senselen_out);
	assert(ret == 0);
	osd_command_attr_free(&cmd);

	/* output cdbfmt , length , value */
	printf("cdbfmt is: %x \n", cmd.cdb[11]);
	printf("length is: %x \n", cmd.cdb[61]);
	printf("value is: ");
 	for(i=0; i<=len; i++){
	        printf("%c", cmd.cdb[62+i]);
	}
	printf("\n");     
}

static void test_set_one_attr (struct osd_device *osd)
{
	struct osd_command cmd;
	uint64_t pid = USEROBJECT_PID_LB;
       	uint64_t oid = USEROBJECT_OID_LB;
	uint8_t *data_out = NULL;
	uint64_t data_out_len;
	uint8_t sense_out[OSD_MAX_SENSE];
	int senselen_out;
	int ret;
    	uint32_t page = USEROBJECT_PG + LUN_PG_LB;
       	
	/* create a partition*/
	ret = osd_command_set_create_partition(&cmd, pid);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);
	
	/* creat one object */
	ret = osd_command_set_create(&cmd, USEROBJECT_PID_LB,
				     USEROBJECT_OID_LB, 1); 
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out, &data_out_len,
				sense_out, &senselen_out);
	assert(ret == 0);
		
	/* these cases should not generate error */
	set_one_attr_val(osd, pid, oid, page, 1, "test", 5);
	set_one_attr_val(osd, pid, oid, page, 1, "test_set_one_attr", 18);
	set_one_attr_int(osd, pid, oid, page, 1, 10);
	set_one_attr_int(osd, pid, oid, page, 1, 20);

	/* these cases must generate error */
	/* set_one_attr_val(osd, pid, oid, page, 1, "ttest_set_one_attr", 19); */
	/* set_one_attr_val(osd, pid, oid, page, 1, "", 0); */
}


/* only to be used by test_osd_query */
static void set_attr_int(struct osd_device *osd, uint64_t pid, uint64_t oid, 
			 uint32_t page, uint32_t number, uint64_t val)
{
	struct osd_command cmd;
	uint8_t sense_out[OSD_MAX_SENSE];
	int senselen_out;
	uint8_t *data_out = NULL;
	uint64_t data_out_len;
	uint64_t attrval;
	int ret;
	struct attribute_list attr = {
		.type = ATTR_SET,
		.page = page,
		.number = number,
		.len = 8,
		.val = &attrval,
	};

	set_htonll(&attrval, val);
	ret = osd_command_set_set_attributes(&cmd, pid, oid);
	assert(ret == 0);
	ret = osd_command_attr_build(&cmd, &attr, 1);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, cmd.outdata, cmd.outlen,
				&data_out, &data_out_len,
				sense_out, &senselen_out);
	assert(ret == 0);
	osd_command_attr_free(&cmd);
}

static void set_attr_val(struct osd_device *osd, uint64_t pid, uint64_t oid,
			 uint32_t page, uint32_t number, const void *val,
			 uint16_t len)
{
	struct osd_command cmd;
	uint8_t sense_out[OSD_MAX_SENSE];
	int senselen_out;
	uint8_t *data_out = NULL;
	uint64_t data_out_len;
	int ret;
	struct attribute_list attr = {
		.type = ATTR_SET,
		.page = page,
		.number = number,
		.len = len,
		.val = (void *)(uintptr_t) val,
	};

	ret = osd_command_set_set_attributes(&cmd, pid, oid);
	assert(ret == 0);
	ret = osd_command_attr_build(&cmd, &attr, 1);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, cmd.outdata, cmd.outlen,
				&data_out, &data_out_len,
				sense_out, &senselen_out);
	assert(ret == 0);
	osd_command_attr_free(&cmd);
}


static void set_qce(uint8_t *cp, uint32_t page, uint32_t number, 
		    uint16_t min_len, const void *min_val, 
		    uint16_t max_len, const void *max_val)
{
	uint16_t len = 4 + 4 + 2 + min_len + 2 + max_len;

	set_htons(&cp[2], len);
	set_htonl(&cp[4], page);
	set_htonl(&cp[8], number);
	set_htons(&cp[12], min_len);
	memcpy(&cp[14], min_val, min_len);
	set_htons(&cp[14+min_len], max_len);
	memcpy(&cp[16+min_len], max_val, max_len);
}

static int ismember(uint64_t needle, uint64_t *hay, uint64_t haysz)
{

	while (haysz--)
		if (needle == hay[haysz])
			return 1;
	return 0;
}

static void check_results(uint8_t *matches, uint64_t matchlen,
			  uint64_t *idlist, uint64_t idlistlen)
{
	uint32_t add_len = get_ntohll(&matches[0]);

	assert(add_len == (5+8*idlistlen));
	assert(matches[12] == (0x21 << 2));
	assert(matchlen == add_len+8);
	add_len -= 5;
	matches += MIN_ML_LEN;
	while (add_len) {
		assert(ismember(get_ntohll(matches), idlist, 8));
		matches += 8;
		add_len -= 8;
	}
}


void test_query(struct osd_device *osd)
{
	struct osd_command cmd;
	uint64_t pid = PARTITION_PID_LB;
	uint64_t cid = COLLECTION_OID_LB;
	uint64_t oid = USEROBJECT_OID_LB + 1;  /* leave room for cid */
	uint8_t *data_out = NULL;
	uint64_t data_out_len;
	uint8_t sense_out[OSD_MAX_SENSE];
	int senselen_out;
	int i, ret;

	/* create a collection and stick some objects in it */
	ret = osd_command_set_create_partition(&cmd, pid);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);
	ret = osd_command_set_create_collection(&cmd, pid, cid);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);

	/* but don't put all of the objects in the collection */
	for (i=0; i<10; i++) {
		uint64_t attrval;
		struct attribute_list attr = {
			.type = ATTR_SET,
			.page = USER_COLL_PG,
			.number = 1,
			.len = 8,
			.val = &attrval,
		};
		set_htonll(&attrval, cid);
		ret = osd_command_set_create(&cmd, pid, oid + i, 1);
		assert(ret == 0);
		if (!(i == 2 || i == 8)) {
			ret = osd_command_attr_build(&cmd, &attr, 1);
			assert(ret == 0);
		}
		ret = osdemu_cmd_submit(osd, cmd.cdb, cmd.outdata, cmd.outlen,
					&data_out, &data_out_len,
					sense_out, &senselen_out);
		assert(ret == 0);
		osd_command_attr_free(&cmd);
	}

	/*
	 * Set some random attributes for querying.
	 */
	uint32_t page = USEROBJECT_PG + LUN_PG_LB;
	set_attr_int(osd, pid, oid,   page, 1, 4);
	set_attr_int(osd, pid, oid+1, page, 1, 49);
	set_attr_int(osd, pid, oid+1, page, 2, 130);
	set_attr_int(osd, pid, oid+2, page, 1, 20);
	set_attr_int(osd, pid, oid+3, page, 1, 101);
	set_attr_int(osd, pid, oid+4, page, 1, 59);
	set_attr_int(osd, pid, oid+4, page, 2, 37);
	set_attr_int(osd, pid, oid+5, page, 1, 75);
	set_attr_int(osd, pid, oid+6, page, 1, 200);
	set_attr_int(osd, pid, oid+7, page, 1, 67);
	set_attr_int(osd, pid, oid+8, page, 1, 323);
	set_attr_int(osd, pid, oid+8, page, 2, 44);
	set_attr_int(osd, pid, oid+9, page, 1, 1);
	set_attr_int(osd, pid, oid+9, page, 2, 19);

	/*
	 * Various queries.
	 */
	/* run without query criteria */
	uint8_t buf[1024], *cp, *matches;
	uint32_t qll;
	uint64_t matchlen;
	uint64_t idlist[8];

	qll = MINQLISTLEN;
	memset(buf, 0, 1024);
	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);

	idlist[0] = oid;
	idlist[1] = oid+1;
	idlist[2] = oid+3;
	idlist[3] = oid+4;
	idlist[4] = oid+5;
	idlist[5] = oid+6;
	idlist[6] = oid+7;
	idlist[7] = oid+9;
	check_results(matches, matchlen, idlist, 8);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/* run one query without min/max constraints */
	qll = 0;
	memset(buf, 0, 1024);
	cp = buf;
	set_qce(&cp[4], page, 2, 0, NULL, 0, NULL);
	qll += 4 + (4+4+4+2+2);

	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);

	idlist[0] = oid+1; 
	idlist[1] = oid+4; 
	idlist[2] = oid+9;
	check_results(matches, matchlen, idlist, 3);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/* run one query with criteria */
	uint64_t min, max;
	qll = 0;
	min = 40, max= 80;
	set_htonll(&min, min);
	set_htonll(&max, max);
	memset(buf, 0, 1024);
	cp = buf;
	cp[0] = 0x0;
	set_qce(&cp[4], page, 1, sizeof(min), &min, sizeof(max), &max);
	qll += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));

	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);

	idlist[0] = oid+1; 
	idlist[1] = oid+4; 
	idlist[2] = oid+5;
	idlist[3] = oid+7;
	check_results(matches, matchlen, idlist, 4);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/* run union of two query criteria */
	qll = 0;

	/* first query */
	min = 100, max = 180;
	set_htonll(&min, min);
	set_htonll(&max, max);
	memset(buf, 0, 1024);
	cp = buf;
	cp[0] = 0x0; /* UNION */
	set_qce(&cp[4], page, 1, sizeof(min), &min, sizeof(max), &max);
	qll += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));
	cp += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));

	/* second query */
	min = 200, max = 323;
	set_htonll(&min, min);
	set_htonll(&max, max);
	set_qce(cp, page, 1, sizeof(min), &min, sizeof(max), &max);
	qll += (4+4+4+2+sizeof(min)+2+sizeof(max));
	cp += (4+4+4+2+sizeof(min)+2+sizeof(max));

	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);

	idlist[0] = oid+3; 
	idlist[1] = oid+6; 
	check_results(matches, matchlen, idlist, 2);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/* run intersection of 2 query criteria */
	qll = 0;

	/* first query */
	min = 4, max = 100;
	set_htonll(&min, min);
	set_htonll(&max, max);
	memset(buf, 0, 1024);
	cp = buf;
	cp[0] = 0x1; /* INTERSECTION */
	set_qce(&cp[4], page, 1, sizeof(min), &min, sizeof(max), &max);
	qll += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));
	cp += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));

	/* second query */
	min = 10, max = 400;
	set_htonll(&min, min);
	set_htonll(&max, max);
	set_qce(cp, page, 2, sizeof(min), &min, sizeof(max), &max);
	qll += (4+4+4+2+sizeof(min)+2+sizeof(max));
	cp += (4+4+4+2+sizeof(min)+2+sizeof(max));

	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);

	idlist[0] = oid+1; 
	idlist[1] = oid+4; 
	check_results(matches, matchlen, idlist, 2);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/* run union of 3 query criteria, with missing min/max */
	qll = 0;

	/* first query */
	min = 130, max = 130;
	set_htonll(&min, min);
	set_htonll(&max, max);
	memset(buf, 0, 1024);
	cp = buf;
	cp[0] = 0x0; /* UNION */
	set_qce(&cp[4], page, 2, sizeof(min), &min, sizeof(max), &max);
	qll += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));
	cp += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));

	/* second query */
	min = 150;
	set_htonll(&min, min);
	set_qce(cp, page, 1, sizeof(min), &min, 0, NULL);
	qll += (4+4+4+2+sizeof(min)+2+0);
	cp += (4+4+4+2+sizeof(min)+2+0);

	/* third query */
	max = 10;
	set_htonll(&max, max);
	set_qce(cp, page, 1, 0, NULL, sizeof(max), &max);
	qll += (4+4+4+2+0+2+sizeof(max));
	cp += (4+4+4+2+0+2+sizeof(max));

	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);

	idlist[3] = oid;
	idlist[4] = oid+1;
	idlist[5] = oid+6;
	idlist[2] = oid+9;
	check_results(matches, matchlen, idlist, 4);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/* set some attributes with text values */
	set_attr_val(osd, pid, oid,   page, 1, "hello", 6);
	set_attr_val(osd, pid, oid+1, page, 1, "cat", 4);
	set_attr_int(osd, pid, oid+1, page, 2, 130);
	set_attr_int(osd, pid, oid+2, page, 1, 20);
	set_attr_val(osd, pid, oid+3, page, 1, "zebra", 6);
	set_attr_int(osd, pid, oid+4, page, 1, 59);
	set_attr_int(osd, pid, oid+4, page, 2, 37);
	set_attr_int(osd, pid, oid+5, page, 1, 75);
	set_attr_val(osd, pid, oid+6, page, 1, "keema", 6);
	set_attr_int(osd, pid, oid+7, page, 1, 67);
	set_attr_int(osd, pid, oid+8, page, 1, 323);
	set_attr_int(osd, pid, oid+8, page, 2, 44);
	set_attr_int(osd, pid, oid+9, page, 1, 1);
	set_attr_val(osd, pid, oid+9, page, 2, "hotelling", 10);

	/* run queries on different datatypes, with diff min max lengths */
	qll = 0;

	/* first query */
	min = 41, max = 169;
	set_htonll(&min, min);
	set_htonll(&max, max);
	memset(buf, 0, 1024);
	cp = buf;
	cp[0] = 0x0; /* UNION */
	set_qce(&cp[4], page, 1, sizeof(min), &min, sizeof(max), &max);
	qll += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));
	cp += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max));

	/* second query */
	set_qce(cp, page, 1, 3, "ab", 5, "keta");
	qll += (4+4+4+2+2+2+5);
	cp += (4+4+4+2+2+2+5);

	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);
	idlist[3] = oid;
	idlist[4] = oid+1;
	idlist[0] = oid+4; 
	idlist[1] = oid+5; 
	idlist[5] = oid+6;
	idlist[2] = oid+7;
	check_results(matches, matchlen, idlist, 6);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/* run intersection of 3 query criteria, with missing min/max */
	qll = 0;

	/* first query */
	memset(buf, 0, 1024);
	cp = buf;
	cp[0] = 0x1; /* INTERSECTION */
	set_qce(&cp[4], page, 1, 2, "a", 3, "zz");
	qll += 4 + (4+4+4+2+2+2+3);
	cp += 4 + (4+4+4+2+2+2+3);

	/* second query */
	min = 140;
	set_htonll(&min, min);
	set_qce(cp, page, 1, sizeof(min), &min, 0, NULL);
	qll += (4+4+4+2+sizeof(min)+2+0);
	cp += (4+4+4+2+sizeof(min)+2+0);

	/* third query */
	set_qce(cp, page, 2, 0, NULL, 6, "alpha");
	qll += (4+4+4+2+0+2+6);
	cp += (4+4+4+2+0+2+6);

	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);
	idlist[0] = oid+1;
	check_results(matches, matchlen, idlist, 1);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/* run intersection of 2 query criteria with empty result */
	qll = 0;

	/* first query */
	memset(buf, 0, 1024);
	cp = buf;
	cp[0] = 0x1; /* INTERSECTION */
	set_qce(&cp[4], page, 1, 3, "aa", 4, "zzz");
	qll += 4 + (4+4+4+2+3+2+4);
	cp += 4 + (4+4+4+2+3+2+4);

	/* second query */
	min = 50;
	max = 80;
	set_htonll(&min, min);
	set_htonll(&max, max);
	set_qce(cp, page, 1, sizeof(min), &min, sizeof(max), &max);
	qll += (4+4+4+2+sizeof(min)+2+sizeof(max));
	cp += (4+4+4+2+sizeof(min)+2+sizeof(max));

	ret = osd_command_set_query(&cmd, pid, cid, qll, 4096);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, buf, qll, &matches,
				&matchlen, sense_out, &senselen_out);
	assert(ret == 0);
	check_results(matches, matchlen, idlist, 0);

	free(matches);
	matches = NULL;
	matchlen = 0;

	/*
	 * Cleanup.
	 */
	for (i=0; i<10; i++) {
		ret = osd_command_set_remove(&cmd, pid, oid + i);
		assert(ret == 0);
		ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
					&data_out_len, sense_out,
					&senselen_out);
		assert(ret == 0);
	}
	ret = osd_command_set_remove_collection(&cmd, pid, cid, 0);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);

	ret = osd_command_set_remove_partition(&cmd, pid);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);
}

struct test_attr {
	uint8_t type;
	uint64_t oid;
	uint32_t page;
	uint32_t number;
	uint64_t intval;
	uint16_t valen;
	const void *val;
}; 

static void ismember_attr(struct test_attr *attr, size_t sz, uint64_t oid,
			  uint32_t page, uint32_t number, uint64_t valen,
			  const void *val)
{
	size_t i = 0;
	for (i = 0; i < sz; i++) {
		if (attr[i].oid == oid && attr[i].page == page &&
		    attr[i].number == number) {
			assert(valen <= attr[i].valen);
			if (attr[i].type == 1) {
				if (valen == attr[i].valen)
					assert(attr[i].intval == get_ntohll(val));
			} else {
				assert(memcmp(attr[i].val, val, valen) == 0);
			}
			return;
		}
	}
	fprintf(stderr, "unknown attr: oid: %llu, page %u, number %u\n",
		llu(oid), page, number);
	assert(0); /* unknown attr */
}

static void test_oids_with_attr(struct osd_device *osd, uint64_t pid, 
				struct attribute_list *getattr, int numattr,
				uint64_t alloc_len, uint64_t exp_data_out_len,
				uint64_t exp_add_len, uint64_t exp_cont_id,
				uint8_t exp_odf, struct test_attr *attrs,
				size_t attrs_sz)
{
	int ret = 0;
	struct osd_command cmd;
	uint8_t *cp = NULL;
	uint32_t page = 0, number = 0;
	uint64_t data_in_len, data_out_len;
	const void *data_in;
	uint8_t *data_out = NULL;
	uint64_t oid = 0; 
	uint8_t sense_out[OSD_MAX_SENSE];
	uint16_t len = 0;
	int senselen_out;
	uint32_t attr_list_len = 0;

	/* execute list with attr, alloc length less than required */
	ret = osd_command_set_list(&cmd, pid, 0, alloc_len, 0, 1);
	assert(ret == 0);
	ret = osd_command_attr_build(&cmd, getattr, numattr);
	assert(ret == 0);
	data_in = cmd.outdata;
	data_in_len = cmd.outlen;
	ret = osdemu_cmd_submit(osd, cmd.cdb, data_in, data_in_len, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);
	cp = data_out;
	assert(data_out_len == exp_data_out_len);
	assert(get_ntohll(cp) == exp_add_len);
	cp += 8;
	assert(get_ntohll(cp) == exp_cont_id);
	cp += 8;
	assert(get_ntohl(cp) == 0);
	cp += 7;
	assert(cp[0] == exp_odf);
	cp += 1;
	oid = 0;
	attr_list_len = 0;
	len = 0;
	data_out_len -= 24;
	while (data_out_len > 0) {
		oid = get_ntohll(cp);
		cp += 12;
		attr_list_len = get_ntohl(cp);
		cp += 4;
		data_out_len -= 16;
		while (attr_list_len > 0) {
			page = get_ntohl(cp);
			cp += 4;
			number = get_ntohl(cp);
			cp += 4;
			len = get_ntohs(cp);
			cp += 2;
			attr_list_len -= (4+4+2);
			data_out_len -= (4+4+2);
			if (len > attr_list_len) {
				len = attr_list_len;
			}
			ismember_attr(attrs, attrs_sz, oid, page, number,
				      len, cp);
			cp += len;
			cp += (roundup8(2+len) - (2+len));
			data_out_len -= len;
			data_out_len -= (roundup8(2+len) - (2+len));
			attr_list_len -= len;
			attr_list_len -= (roundup8(2+len) - (2+len)); 
		}
	}
	free(data_out);
	data_out = NULL;
	osd_command_attr_free(&cmd);
}

void test_list(struct osd_device *osd)
{
	struct osd_command cmd;
	uint64_t pid = PARTITION_PID_LB;
	uint64_t cid = 0;
	uint64_t oid = 0; 
	uint8_t *data_out = NULL;
	uint8_t *cp;
	uint32_t page = 0, number = 0;
	uint64_t data_out_len;
	uint64_t idlist[64];
	uint8_t sense_out[OSD_MAX_SENSE];
	int senselen_out;
	int i, ret;

	/* create partition */
	ret = osd_command_set_create_partition(&cmd, pid);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);

	/* create collection */
	ret = osd_command_set_create_collection(&cmd, pid, cid);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);

	/* create 6 objects */
	ret = osd_command_set_create(&cmd, pid, 0, 6);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out, 
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);

	/* create another collection */
	ret = osd_command_set_create_collection(&cmd, pid, cid);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);

	/* create 4 objects */
	ret = osd_command_set_create(&cmd, pid, 0, 4);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out, 
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);

	/* set attributes on userobjects */
	page = USEROBJECT_PG + LUN_PG_LB;
	number = 1;
	oid = COLLECTION_OID_LB + 1;
	struct test_attr attrs[] = {
		{1, oid, page, number, 1, 8, NULL},
		{1, oid, page+1, number+1, 768, 8, NULL},
		{2, oid, page+2, number+2, 0, 5, "sudo"}, 
		{1, oid+1, page+1, number+1, 56, 8, NULL},
		{1, oid+1, page+2, number+2, 68, 8, NULL},
		{2, oid+2, page+2, number+2, 0, 9, "deadbeef"}, 
		{1, oid+3, page+3, number+3, 1, 8, NULL},
		{1, oid+3, page+1, number+1, 111, 8, NULL},
		{2, oid+3, page+4, number+4, 0, 5, "sudo"}, 
		{1, oid+3, page+2, number+2, 11, 8, NULL},
		{1, oid+3, page+5, number+5, 111111, 8, NULL},
		{2, oid+4, page+4, number+4, 0, 6, "milli"}, 
		{2, oid+4, page+5, number+5, 0, 10, "kilometer"},
		{2, oid+4, page+3, number+3, 0, 11, "hectameter"},
		{2, oid+5, page+1, number+1, 0, 12, "zzzzzzhhhhh"}, 
		{2, oid+5, page+2, number+2, 0, 2, "b"},
		{1, oid+5, page+3, number+3, 6, 8, NULL},
		{1, oid+7, page+1, number+1, 486, 8, NULL}, 
		{1, oid+7, page+4, number+4, 586, 8, NULL},
		{1, oid+7, page+2, number+2, 686, 8, NULL},
		{1, oid+8, page, number, 4, 8, NULL},
		{2, oid+9, page+1, number+1, 0, 14, "setting these"}, 
		{2, oid+9, page+2, number+2, 0, 11, "attributes"},
		{2, oid+9, page+3, number+3, 0, 8, "made me"},
		{2, oid+9, page+4, number+4, 0, 12, "mad! really"}, 
		{1, oid+10, page+1, number+1, 1234567890, 8, NULL},
		{2, oid+10, page, number, 0, 6, "DelTa"},
	};
	for (i = 0; i < ARRAY_SIZE(attrs); i++) {
		if (attrs[i].type == 1) {
			set_attr_int(osd, pid, attrs[i].oid, attrs[i].page,
				     attrs[i].number, attrs[i].intval);
		} else {
			set_attr_val(osd, pid, attrs[i].oid, attrs[i].page,
				     attrs[i].number, attrs[i].val,
				     attrs[i].valen);
		}
	}

	/* set some attributes on collections */
	page = COLLECTION_PG + LUN_PG_LB;
	cid = COLLECTION_OID_LB;
	set_attr_int(osd, pid, cid,   page, 1, 1);
	set_attr_int(osd, pid, cid+7, page, 2, 2);

	/* execute list command. get only oids first */
	ret = osd_command_set_list(&cmd, pid, 0, 4096, 0, 0);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);
	cp = data_out;
	assert(get_ntohll(cp) == 10*8+16);
	assert(data_out_len == 10*8+24);
	cp += 8;
	assert(get_ntohll(cp) == 0);
	cp += 8;
	assert(get_ntohl(cp) == 0);
	cp += 7;
	assert(cp[0] == (0x21 << 2));
	cp += 1;
	data_out_len -= 24;
	oid = COLLECTION_OID_LB + 1;
	for (i = 0; i < 6; i++)
		idlist[i] = oid + i;
	oid = COLLECTION_OID_LB + 1 + i + 1;
	for (i = 0; i < 4; i++)
		idlist[6+i] = oid + i;
	while (data_out_len > 0) {
		assert(ismember(get_ntohll(cp), idlist, 10));
		cp += 8;
		data_out_len -= 8;
	}
	free(data_out);
	data_out = NULL;
	osd_command_attr_free(&cmd);

	/* execute list command with less space */
	ret = osd_command_set_list(&cmd, pid, 0, 72, 0, 0);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);
	cp = data_out;
	assert(get_ntohll(cp) == 10*8+16);
	assert(data_out_len == 72);
	cp += 8;
	assert(get_ntohll(cp) == COLLECTION_OID_LB + 8);
	cp += 8;
	assert(get_ntohl(cp) == 0);
	cp += 7;
	assert(cp[0] == (0x21 << 2));
	cp += 1;
	data_out_len -= 24;
	oid = COLLECTION_OID_LB + 1;
	for (i = 0; i < 6; i++)
		idlist[i] = oid + i;
	for (i = 0; i < 4; i++)
		idlist[6+i] = 0;
	while (data_out_len > 0) {
		assert(ismember(get_ntohll(cp), idlist, 10));
		cp += 8;
		data_out_len -= 8;
	}
	free(data_out);
	data_out = NULL;
	osd_command_attr_free(&cmd);

	page = USEROBJECT_PG + LUN_PG_LB;
	number = 1;
	struct attribute_list getattr[] = {
		{ATTR_GET, page, number, NULL, 0, 0},
		{ATTR_GET, page+1, number+1, NULL, 0, 0},
		{ATTR_GET, page+2, number+2, NULL, 0, 0},
		{ATTR_GET, page+3, number+3, NULL, 0, 0},
		{ATTR_GET, page+4, number+4, NULL, 0, 0},
		{ATTR_GET, page+5, number+5, NULL, 0, 0},
	};

	/* execute list with attr */
	test_oids_with_attr(osd, pid, getattr, 6, 4096, 792, 784, 0, 
			    (0x22 << 2), attrs, ARRAY_SIZE(attrs));
	/* execute list with attr, alloc length less than required */
	test_oids_with_attr(osd, pid, getattr, 6, 200, 200, 784, 65539, 
			    (0x22 << 2), attrs, ARRAY_SIZE(attrs));
	/* execute list with attr, alloc length less than required */
	test_oids_with_attr(osd, pid, getattr, 6, 208, 208, 784, 65539, 
			    (0x22 << 2), attrs, ARRAY_SIZE(attrs));
	/* execute list with attr, alloc length less than required */
	test_oids_with_attr(osd, pid, getattr, 6, 216, 208, 784, 65539, 
			    (0x22 << 2), attrs, ARRAY_SIZE(attrs));
	/* execute list with attr, alloc length less than required */
	test_oids_with_attr(osd, pid, getattr, 6, 544, 536, 784, 65544, 
			    (0x22 << 2), attrs, ARRAY_SIZE(attrs));
	/* execute list with attr, alloc length less than required */
	test_oids_with_attr(osd, pid, getattr, 6, 688, 688, 784, 65546, 
			    (0x22 << 2), attrs, ARRAY_SIZE(attrs));
	/* execute list with attr, alloc length less than required */
	test_oids_with_attr(osd, pid, getattr, 6, 680, 680, 784, 65546, 
			    (0x22 << 2), attrs, ARRAY_SIZE(attrs));

	/* clean up */
	oid = USEROBJECT_OID_LB;
	for (i=0; i<12; i++) {
		if (i == 0 || i == 7)
			continue;
		ret = osd_command_set_remove(&cmd, pid, oid + i);
		assert(ret == 0);
		ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
					&data_out_len, sense_out,
					&senselen_out);
		assert(ret == 0);
	}
	cid = COLLECTION_OID_LB;
	ret = osd_command_set_remove_collection(&cmd, pid, cid, 0);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);
	cid = COLLECTION_OID_LB + 7;
	ret = osd_command_set_remove_collection(&cmd, pid, cid, 0);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);

	ret = osd_command_set_remove_partition(&cmd, pid);
	assert(ret == 0);
	ret = osdemu_cmd_submit(osd, cmd.cdb, NULL, 0, &data_out,
				&data_out_len, sense_out, &senselen_out);
	assert(ret == 0);
}

static void test_attr_vals(uint8_t *cp, struct attribute_list *attrs, 
			   size_t sz)
{
	size_t i = 0;
	uint32_t page = 0;
	uint32_t num = 0;
	uint16_t len = 0;
	uint32_t list_len = 0;

	assert((cp[0] & 0x0F) == 0x9);
	cp += 4;
	list_len = get_ntohl(cp);
	cp += 4;
	while (list_len > 0) {
		page = get_ntohl(cp);
		cp += 4;
		num = get_ntohl(cp);
		cp += 4;
		len = get_ntohs(cp);
		cp += 2;
		for (i = 0; i < sz; i++) {
			if (!(attrs[i].page==page && attrs[i].number==num)) 
				continue;

			assert(len == attrs[i].len);
			if (len == 8) {
				assert(get_ntohll(attrs[i].val) ==
				       get_ntohll(cp));
			} else if (len != 0) {
				assert(memcmp(attrs[i].val, cp, len) == 0);
			}
			break;
		}
		assert(i < sz);
		if (len == 0) {
			cp += (roundup8(10) - 10);
			list_len -= roundup8(4+4+2);
		} else {
			cp += len;
			cp += (roundup8(2+len) - (2+len));
			list_len -= roundup8(4+4+2+len);
		}
	}
	assert(list_len == 0);
}
Exemplo n.º 22
0
static void got_dehalfop(struct chanset_t *chan, char *nick, char *from,
                         char *who, struct userrec *opu)
{
  memberlist *m;
  char ch[sizeof chan->name];
  char s[UHOSTLEN], s1[UHOSTLEN];
  struct userrec *u;
  int had_halfop;

  m = ismember(chan, who);
  if (!m) {
    if (channel_pending(chan))
      return;
    putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who);
    chan->status |= CHAN_PEND;
    refresh_who_chan(chan->name);
    return;
  }

  strcpy(ch, chan->name);
  simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  simple_sprintf(s1, "%s!%s", nick, from);
  u = get_user_by_host(s);
  get_user_flagrec(u, &victim, chan->dname);

  had_halfop = chan_hasop(m);
  /* Flags need to be set correctly right from the beginning now, so that
   * add_mode() doesn't get irritated.
   */
  m->flags &= ~(CHANHALFOP | SENTDEHALFOP | FAKEHALFOP);
  check_tcl_mode(nick, from, opu, chan->dname, "-h", who);
  if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) ||
      !(m = ismember(chan, who)))
    return;
  /* Check comments in got_op()  (drummer) */
  m->flags &= ~WASHALFOP;

  if (channel_pending(chan))
    return;

  /* Dehalfop'd someone on my oplist? */
  if (HALFOP_CANDOMODE('h')) {
    int ok = 1;

    if (!glob_dehalfop(victim) && !chan_dehalfop(victim)) {
      if (channel_protecthalfops(chan) && (glob_master(victim) ||
          chan_master(victim) || glob_halfop(victim) || chan_halfop(victim)))
        ok = 0;
      else if (channel_protectfriends(chan) && (glob_friend(victim) ||
               chan_friend(victim)))
        ok = 0;
    }
    if ((reversing || !ok) && had_halfop && !match_my_nick(nick) &&
        rfc_casecmp(who, nick) && !match_my_nick(who) && !glob_master(user) &&
        !chan_master(user) && !glob_bot(user) && ((chan_halfop(victim) ||
        (glob_halfop(victim) && !chan_dehalfop(victim))) ||
        !channel_bitch(chan)))
      add_mode(chan, '+', 'h', who);
  }

  if (!nick[0])
    putlog(LOG_MODES, chan->dname, "TS resync (%s): %s deopped by %s",
           chan->dname, who, from);
  if (!(m->flags & (CHANVOICE | STOPWHO))) {
    chan->status |= CHAN_PEND;
    refresh_who_chan(chan->name);
    m->flags |= STOPWHO;
  }
}
Exemplo n.º 23
0
static void got_deop(struct chanset_t *chan, char *nick, char *from,
                     char *who, struct userrec *opu)
{
  memberlist *m;
  char ch[sizeof chan->name];
  char s[UHOSTLEN], s1[UHOSTLEN];
  struct userrec *u;
  int had_halfop;

  m = ismember(chan, who);
  if (!m) {
    if (channel_pending(chan))
      return;
    putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who);
    chan->status |= CHAN_PEND;
    refresh_who_chan(chan->name);
    return;
  }

  strcpy(ch, chan->name);
  simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  simple_sprintf(s1, "%s!%s", nick, from);
  u = get_user_by_host(s);
  get_user_flagrec(u, &victim, chan->dname);

  had_halfop = chan_hasop(m);
  /* Flags need to be set correctly right from the beginning now, so that
   * add_mode() doesn't get irritated.
   */
  m->flags &= ~(CHANOP | SENTDEOP | FAKEOP);
  check_tcl_mode(nick, from, opu, chan->dname, "-o", who);
  if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) ||
      !(m = ismember(chan, who)))
    return;
  m->flags &= ~WASOP;

  if (channel_pending(chan))
    return;

  if (HALFOP_CANDOMODE('o')) {
    int ok = 1;

    if (!glob_deop(victim) && !chan_deop(victim)) {
      if (channel_protectops(chan) && (glob_master(victim) ||
          chan_master(victim) || glob_op(victim) || chan_op(victim)))
        ok = 0;
      else if (channel_protectfriends(chan) && (glob_friend(victim) ||
               chan_friend(victim)))
        ok = 0;
    }
    if ((reversing || !ok) && had_halfop && !match_my_nick(nick) &&
        rfc_casecmp(who, nick) && !match_my_nick(who) && !glob_master(user) &&
        !chan_master(user) && !glob_bot(user) && ((chan_op(victim) ||
        (glob_op(victim) && !chan_deop(victim))) || !channel_bitch(chan)))
      add_mode(chan, '+', 'o', who);
  }

  if (!nick[0])
    putlog(LOG_MODES, chan->dname, "TS resync (%s): %s deopped by %s",
           chan->dname, who, from);

  /* Check for mass deop */
  if (nick[0])
    detect_chan_flood(nick, from, s1, chan, FLOOD_DEOP, who, 0);

  /* Having op hides your +v and +h status -- so now that someone's lost ops,
   * check to see if they have +v or +h
   */
  if (!(m->flags & (CHANVOICE | CHANHALFOP | STOPWHO))) {
    chan->status |= CHAN_PEND;
    refresh_who_chan(chan->name);
    m->flags |= STOPWHO;
  }

  /* Was the bot deopped? */
  if (match_my_nick(who)) {
    /* Cancel any pending kicks and modes */
    memberlist *m2;

    for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next)
      m2->flags &= ~(SENTKICK | SENTDEOP | SENTOP | SENTVOICE | SENTDEVOICE);

    check_tcl_need(chan->dname, "op");
    if (chan->need_op[0])
      do_tcl("need-op", chan->need_op);
    if (!nick[0])
      putlog(LOG_MODES, chan->dname, "TS resync deopped me on %s :(",
             chan->dname);
  }
  if (nick[0])
    maybe_revenge(chan, s1, s, REVENGE_DEOP);
}