예제 #1
0
void del_ban(const char * addr)
{
    netban_vector::iterator it;

    if(find_ban(addr, &it))
    {
        netbans.erase(it);
        std::cout << "removed " << it->to_string() << " (hits: " << it->hits_value() << ") from network bans" << std::endl;
    }
}
예제 #2
0
void add_ban(const char * addr, bool persist, const char * reason)
{
    netban nb(addr, persist);

    if(nb.is_valid())
    {
        if(find_ban(nb)) return;

        nb.set_reason(reason);
        netbans.push_back(nb);
    }
}
예제 #3
0
void merge_pushed_bans()
{
    if(stack.empty()) return;

    netban_vector oldbans = stack.front();

    for(netban_vector::reverse_iterator it = oldbans.rbegin(); it != oldbans.rend(); ++it)
    {
        netban *newban = find_ban(*it);

        if(newban || it->persist_value())
        {
            if(newban) *newban = *it; // update hits
            else netbans.push_back(*it); // re-add persist ban

            oldbans.erase(it.base());
        }
    }

    for(netban_vector::iterator it = oldbans.begin(); it != oldbans.end(); ++it)
    {
        std::cout << "removed " << it->to_string() << " (hits: " << it->hits_value() << ") from network bans" << std::endl;
    }
}
예제 #4
0
/** Handle a JOIN message from a client connection.
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel *chptr;
  struct JoinBuf join;
  struct JoinBuf create;
  struct Gline *gline;
  char *p = 0;
  char *chanlist;
  char *name;
  char *keys;

  if (parc < 2 || *parv[1] == '\0')
    return need_more_params(sptr, "JOIN");

  joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
  joinbuf_init(&create, sptr, cptr, JOINBUF_TYPE_CREATE, 0, TStime());

  chanlist = last0(cptr, sptr, parv[1]); /* find last "JOIN 0" */

  keys = parv[2]; /* remember where keys are */

  for (name = ircd_strtok(&p, chanlist, ","); name;
       name = ircd_strtok(&p, 0, ",")) {
    char *key = 0;

    /* If we have any more keys, take the first for this channel. */
    if (!BadPtr(keys)
        && (keys = strchr(key = keys, ',')))
      *keys++ = '\0';

    /* Empty keys are the same as no keys. */
    if (key && !key[0])
      key = 0;

    if (!IsChannelName(name) || !strIsIrcCh(name))
    {
      /* bad channel name */
      send_reply(sptr, ERR_NOSUCHCHANNEL, name);
      continue;
    }

    if (cli_user(sptr)->joined >= feature_int(FEAT_MAXCHANNELSPERUSER)
	&& !HasPriv(sptr, PRIV_CHAN_LIMIT)) {
      send_reply(sptr, ERR_TOOMANYCHANNELS, name);
      break; /* no point processing the other channels */
    }

    /* BADCHANed channel */
    if ((gline = gline_find(name, GLINE_BADCHAN | GLINE_EXACT)) &&
	GlineIsActive(gline) && !IsAnOper(sptr)) {
      send_reply(sptr, ERR_BANNEDFROMCHAN, name);
      continue;
    }

    if (!(chptr = FindChannel(name))) {
      if (((name[0] == '&') && !feature_bool(FEAT_LOCAL_CHANNELS))
          || strlen(name) > IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN))) {
        send_reply(sptr, ERR_NOSUCHCHANNEL, name);
        continue;
      }

      if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
        continue;

      /* Try to add the new channel as a recent target for the user. */
      if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
        chptr->members = 0;
        destruct_channel(chptr);
        continue;
      }

      joinbuf_join(&create, chptr, CHFL_CHANOP | CHFL_CHANNEL_MANAGER);
    } else if (find_member_link(chptr, sptr)) {
      continue; /* already on channel */
    } else if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
      continue;
    } else {
      int flags = CHFL_DEOPPED;
      int err = 0;

      /* Check Apass/Upass -- since we only ever look at a single
       * "key" per channel now, this hampers brute force attacks. */
      if (key && !strcmp(key, chptr->mode.apass))
        flags = CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
      else if (key && !strcmp(key, chptr->mode.upass))
        flags = CHFL_CHANOP;
      else if (chptr->users == 0 && !chptr->mode.apass[0]) {
        /* Joining a zombie channel (zannel): give ops and increment TS. */
        flags = CHFL_CHANOP;
        chptr->creationtime++;
      } else if (IsInvited(sptr, chptr)) {
        /* Invites bypass these other checks. */
      } else if (chptr->mode.mode & MODE_INVITEONLY)
        err = ERR_INVITEONLYCHAN;
      else if (chptr->mode.limit && (chptr->users >= chptr->mode.limit))
        err = ERR_CHANNELISFULL;
      else if ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(sptr))
        err = ERR_NEEDREGGEDNICK;
      else if (find_ban(sptr, chptr->banlist))
        err = ERR_BANNEDFROMCHAN;
      else if (*chptr->mode.key && (!key || strcmp(key, chptr->mode.key)))
        err = ERR_BADCHANNELKEY;

      /* An oper with WALK_LCHAN privilege can join a local channel
       * he otherwise could not join by using "OVERRIDE" as the key.
       * This will generate a HACK(4) notice, but fails if the oper
       * could normally join the channel. */
      if (IsLocalChannel(chptr->chname)
          && HasPriv(sptr, PRIV_WALK_LCHAN)
          && !(flags & CHFL_CHANOP)
          && key && !strcmp(key, "OVERRIDE"))
      {
        switch (err) {
        case 0:
          if (strcmp(chptr->mode.key, "OVERRIDE")
              && strcmp(chptr->mode.apass, "OVERRIDE")
              && strcmp(chptr->mode.upass, "OVERRIDE")) {
            send_reply(sptr, ERR_DONTCHEAT, chptr->chname);
            continue;
          }
          break;
        case ERR_INVITEONLYCHAN: err = 'i'; break;
        case ERR_CHANNELISFULL:  err = 'l'; break;
        case ERR_BANNEDFROMCHAN: err = 'b'; break;
        case ERR_BADCHANNELKEY:  err = 'k'; break;
        case ERR_NEEDREGGEDNICK: err = 'r'; break;
        default: err = '?'; break;
        }
        /* send accountability notice */
        if (err)
          sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
                               "(overriding +%c)", sptr, chptr, err);
        err = 0;
      }

      /* Is there some reason the user may not join? */
      if (err) {
        switch(err) {
          case ERR_NEEDREGGEDNICK:
            send_reply(sptr, 
                       ERR_NEEDREGGEDNICK, 
                       chptr->chname, 
                       feature_str(FEAT_URLREG));            
            break;
          default:
            send_reply(sptr, err, chptr->chname);
            break;
        }
        continue;
      }

      joinbuf_join(&join, chptr, flags);
      if (flags & CHFL_CHANOP) {
        struct ModeBuf mbuf;
	/* Always let the server op him: this is needed on a net with older servers
	   because they 'destruct' channels immediately when they become empty without
	   sending out a DESTRUCT message. As a result, they would always bounce a mode
	   (as HACK(2)) when the user ops himself.
           (There is also no particularly good reason to have the user op himself.)
        */
	modebuf_init(&mbuf, &me, cptr, chptr, MODEBUF_DEST_SERVER);
	modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr,
                            chptr->mode.apass[0] ? ((flags & CHFL_CHANNEL_MANAGER) ? 0 : 1) : MAXOPLEVEL);
	modebuf_flush(&mbuf);
      }
    }

    del_invite(sptr, chptr);

    if (chptr->topic[0]) {
      send_reply(sptr, RPL_TOPIC, chptr->chname, chptr->topic);
      send_reply(sptr, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
		 chptr->topic_time);
    }

    do_names(sptr, chptr, NAMES_ALL|NAMES_EON); /* send /names list */
  }

  joinbuf_flush(&join); /* must be first, if there's a JOIN 0 */
  joinbuf_flush(&create);

  return 0;
}
예제 #5
0
파일: m_join.c 프로젝트: evilnet/nefarious2
void do_join(struct Client *cptr, struct Client *sptr, struct JoinBuf *join,
             struct JoinBuf *create, char *chan, char *key, int level)
{
  struct Channel *chptr;
  struct Gline *gline;

  /* BADCHANed channel */
  if ((gline = gline_find(chan, GLINE_BADCHAN | GLINE_EXACT)) &&
      GlineIsActive(gline) && !IsAnOper(sptr)) {
    send_reply(sptr, ERR_BANNEDFROMCHAN, chan);
    return;
  }

  /* Bouncy +L joins */
  if (level > feature_int(FEAT_MAX_BOUNCE)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Couldn't join %s ! - Redirection (+L) setting was too bouncy", sptr, chan);
    return;
  }

  if (!(chptr = FindChannel(chan))) {
    if (((chan[0] == '&') && !feature_bool(FEAT_LOCAL_CHANNELS))
        || strlen(chan) > IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN))) {
      send_reply(sptr, ERR_NOSUCHCHANNEL, chan);
      return;
    }

    if (feature_bool(FEAT_CHANNEL_CREATE_IRCOPONLY) && !IsAnOper(sptr) && !IsChannelService(sptr)) {
      send_reply(sptr, ERR_NOSUCHCHANNEL, chan);
      return;
    }

    if (!(chptr = get_channel(sptr, chan, CGT_CREATE)))
      return;

    /* Try to add the new channel as a recent target for the user. */
    if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
      chptr->members = 0;
      destruct_channel(chptr);
      return;
    }

    joinbuf_join(create, chptr, CHFL_CHANOP | CHFL_CHANNEL_MANAGER);
  } else if (find_member_link(chptr, sptr)) {
    return; /* already on channel */
  } else if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
    return;
  } else {
    int flags = CHFL_DEOPPED;
    int err = 0;
    int excepted = 0;
    int exceptkli = 0;
    struct Ban *ban = NULL;

    if (*chptr->mode.redir && (*chptr->mode.redir != '\0')) {
      if (chptr->users >= chptr->mode.limit) {
        if (IsNoLink(sptr))
          send_reply(sptr, ERR_LINKCHAN, chptr->chname, chptr->mode.redir);
        else if (!IsChannelName(chptr->mode.redir) || !strIsIrcCh(chptr->mode.redir))
          send_reply(sptr, ERR_NOSUCHCHANNEL, chptr->mode.redir);
        else {
          send_reply(sptr, ERR_LINKSET, chptr->chname, chptr->chname, chptr->mode.redir);
          do_join(cptr, sptr, join, create, chptr->mode.redir, key, level+1);
        }
        return;
      }
    }

    if (find_ban(sptr, chptr->exceptlist, EBAN_EXCEPTLIST, 0)) {
      if (feature_bool(FEAT_CHMODE_e_CHMODEEXCEPTION))
        exceptkli = 1;
      excepted = 1;
    }

    /* Check Apass/Upass -- since we only ever look at a single
     * "key" per channel now, this hampers brute force attacks. */
    if (feature_bool(FEAT_CHMODE_Z_STRICT) && (chptr->mode.exmode & EXMODE_SSLONLY) && !IsSSL(sptr))
      err = ERR_SSLONLYCHAN;
    else if (key && !strcmp(key, chptr->mode.apass))
      flags = CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
    else if (key && !strcmp(key, chptr->mode.upass))
      flags = CHFL_CHANOP;
    else if (chptr->users == 0 && !chptr->mode.apass[0] && !(chptr->mode.exmode & EXMODE_PERSIST)) {
      /* Joining a zombie channel (zannel): give ops and increment TS. */
      flags = CHFL_CHANOP;
      chptr->creationtime++;
    } else if (IsXtraOp(sptr)) {
      /* XtraOp bypasses all other checks. */
    } else if ((chptr->mode.exmode & EXMODE_SSLONLY) && !IsSSL(sptr))
      err = ERR_SSLONLYCHAN;
    else if (IsInvited(sptr, chptr)) {
      /* Invites bypass these other checks. */
    } else if (*chptr->mode.key && (!key || strcmp(key, chptr->mode.key)) && !exceptkli)
      err = ERR_BADCHANNELKEY;
    else if (*chptr->mode.key && feature_bool(FEAT_FLEXIBLEKEYS) && (key && !strcmp(key, chptr->mode.key))) {
      /* Assume key checked by previous condition was found to be correct
         and allow join because FEAT_FLEXIBLEKEYS was enabled */
    } else if ((chptr->mode.mode & MODE_INVITEONLY) && !exceptkli)
      err = ERR_INVITEONLYCHAN;
    else if (chptr->mode.limit && (chptr->users >= chptr->mode.limit) && !exceptkli)
      err = ERR_CHANNELISFULL;
    else if ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(sptr))
      err = ERR_NEEDREGGEDNICK;
    else if ((chptr->mode.exmode & EXMODE_ADMINONLY) && !IsAdmin(sptr))
      err = ERR_ADMINONLYCHAN;
    else if ((chptr->mode.exmode & EXMODE_OPERONLY) && !IsAnOper(sptr))
      err = ERR_OPERONLYCHAN;
    else if ((ban = find_ban(sptr, chptr->banlist, EBAN_NONE, 0)) && !excepted)
      err = ERR_BANNEDFROMCHAN;

    /* An oper with WALK_LCHAN privilege can join a local channel
     * he otherwise could not join by using "OVERRIDE" as the key.
     * This will generate a HACK(4) notice, but fails if the oper
     * could normally join the channel. */
    if (IsLocalChannel(chptr->chname)
        && HasPriv(sptr, PRIV_WALK_LCHAN)
        && !(flags & CHFL_CHANOP)
        && key && !strcmp(key, "OVERRIDE"))
    {
      switch (err) {
      case 0:
        if (strcmp(chptr->mode.key, "OVERRIDE")
            && strcmp(chptr->mode.apass, "OVERRIDE")
            && strcmp(chptr->mode.upass, "OVERRIDE")) {
          send_reply(sptr, ERR_DONTCHEAT, chptr->chname);
          return;
        }
        break;
      case ERR_INVITEONLYCHAN: err = 'i'; break;
      case ERR_CHANNELISFULL:  err = 'l'; break;
      case ERR_BANNEDFROMCHAN: err = 'b'; break;
      case ERR_BADCHANNELKEY:  err = 'k'; break;
      case ERR_NEEDREGGEDNICK: err = 'r'; break;
      case ERR_ADMINONLYCHAN:  err = 'a'; break;
      case ERR_OPERONLYCHAN:   err = 'O'; break;
      case ERR_SSLONLYCHAN:    err = 'Z'; break;
      default: err = '?'; break;
      }
      /* send accountability notice */
      if (err)
        sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
                             "(overriding +%c)", sptr, chptr, err);
      err = 0;
    }

    /* Is there some reason the user may not join? */
    if (err) {
      switch(err) {
        case ERR_NEEDREGGEDNICK:
          send_reply(sptr,
                     ERR_NEEDREGGEDNICK,
                     chptr->chname,
                     feature_str(FEAT_URLREG));
          break;
        default:
          send_reply(sptr, err, chptr->chname);
          break;
      }
      return;
    }

    joinbuf_join(join, chptr, flags);
    if (flags & CHFL_CHANOP) {
      struct ModeBuf mbuf;
      /* Always let the server op him: this is needed on a net with older servers
         because they 'destruct' channels immediately when they become empty without
         sending out a DESTRUCT message. As a result, they would always bounce a mode
         (as HACK(2)) when the user ops himself.
         (There is also no particularly good reason to have the user op himself.)
      */
      modebuf_init(&mbuf, &me, cptr, chptr, MODEBUF_DEST_SERVER);
      modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr,
                          chptr->mode.apass[0] ? ((flags & CHFL_CHANNEL_MANAGER) ? 0 : 1) : MAXOPLEVEL);
      modebuf_flush(&mbuf);
    }
  }

  del_invite(sptr, chptr);

  if (chptr->topic[0]) {
    send_reply(sptr, RPL_TOPIC, chptr->chname, chptr->topic);
    send_reply(sptr, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
               chptr->topic_time);
  }

  do_names(sptr, chptr, NAMES_ALL|NAMES_EON); /* send /names list */
}
예제 #6
0
void read_message(void *arg)
{
    int fd = *((int *)arg);
    int to_fd;
    int count;
    int result;  
    int temp;

    struct message msg;
    struct online *p;
    struct online *q;
    struct online *m;

    while(1)
    {
         if((count = read(fd,&msg,sizeof(msg))) != 0)  //读取客户端传来的信息
	 {
             //printf("aaaaaaaaaaaaa%d\n",msg.action);
	     if(msg.action == log)
	     {
	         p = (struct online*)malloc(sizeof(struct online));
		 p->fd = fd;
		 p->ID = msg.ID;
		 strcpy(p->passwd,msg.passwd);
		
		 if(find_id(msg.ID) == 0)       //找到已经登录的ID号,返回have_log,防止重复登录
		 {
		     msg.action = have_log;

		     write(fd,&msg,sizeof(msg));
		 }
                 else
		 {
	             result = server_log(p);  //去数据库中核实登录信息和注册信息是否一致
                 
                 //printf("bbbbbbbbbbbbb%d\n",result);

                     strcpy(msg.name,p->name);

		     if(result == log_ok)
		     {
		         msg.action = log_ok;

		         insert_online(p);    //登录成功后,插入链表,用来显示在线的用户

		         write(fd,&msg,sizeof(msg));

		         sleep(8);

		         read_unlog_msg(msg.name,fd);    //读保存在服务器里的离线消息
		     }

		     if(result == admin_log_ok)
		     {
		         msg.action = admin_log_ok;

		         insert_online(p);
		         write(fd,&msg,sizeof(msg));

		         sleep(8);
		     
		         read_unlog_msg(msg.name,fd);
		     }

		 
		 
		     if(result == passwd_error)
		     {
		         msg.action = passwd_error;
       		         write(fd,&msg,sizeof(msg));
		     }
		     
		     if(result == ID_error)
		     {
		         msg.action = ID_error;
	                 write(fd,&msg,sizeof(msg));
		     }
		 
                 }
             }

	     if(msg.action == reg)
	     {
	         p = (struct online*)malloc(sizeof(struct online)); //给结构体p分配空间

                 p->fd = fd;                                        //为写入数据库作准备
		 strcpy(p->name,msg.name);
		 strcpy(p->passwd,msg.passwd);

		 //result = insert_online(p);

		 //if(result == insert_ok)
                 srand(time(0));  //防止随机数重复
		 temp = rand();   //生成随机数
		 p->ID = temp;
		 msg.ID = p->ID;         //返回给客户端的ID和reg_ok
		 msg.action = reg_ok;    //通知客户端“注册成功”的标志
            
		 my_sqlite(p);         //注册时的信息写入数据库
		 write(fd,&msg,sizeof(msg));//把生成的id号传给客户端
	     }

	     if(msg.action == say)
	     {
                 if(find_ban(fd) == ban)
		 {
		     msg.action = ban;
		     write(fd,&msg,sizeof(msg));

		     msg.action = -2;                  //防止和谁聊天,谁被禁言
		 }
	        
		 else
		 {
	             to_fd = find_fd(msg.toname);//聊天通过寻找对方的fd,找不到返回-1,找到返回对方的fd
		 
		     if(to_fd == -1)
		     {
		         msg.action = to_fd;

                         reserve_unlog_msg(&msg);

			 reserve_chat_msg(&msg);

		         write(fd,&msg,sizeof(msg));//没找到客户2,就返回客户1的fd
		     }
		     else
		     {
		         
			 reserve_chat_msg(&msg);
			 
			 write(to_fd,&msg,sizeof(msg));//找到了客户2,就返回客户2的fd
		     }
		 }
	     }
	     
	     if(msg.action == say_all)
	     {
                 if(find_ban(fd) == ban)
		 {
		     msg.action = ban;
		     write(fd,&msg,sizeof(msg));

		     msg.action = -2;
		 }
	         else
		 {
	             struct online *temp = head;     //遍历链表,传送每一个fd
		 
	             reserve_chat_msg(&msg);
		     
		     while(temp != NULL)
		     {    
			 write(temp->fd,&msg,sizeof(msg));
		         temp = temp->next;
		     }
		 }
	     }

	     if(msg.action == send_face)
	     {
                 if(find_ban(fd) == ban)
		 {
		     msg.action = ban;
		     write(fd,&msg,sizeof(msg));

		     msg.action = -2;                  //防止和谁聊天,谁被禁言
		 }
		 else
		 {
                     to_fd = find_fd(msg.toname);
		 
		     if(to_fd == -1)
		     {
		         msg.action = to_fd;        

		         write(fd,&msg,sizeof(msg));
		     }
		     else
		     {   
			 write(to_fd,&msg,sizeof(msg));
		     }
		 }
	     }

	     if(msg.action == change)
	     {   
	         struct online *temp = head;           //通过查找ID,替换昵称和密码
	         
		 q = (struct online*)malloc(sizeof(struct online));
		 
		 while(temp->fd == fd)
		 {   
		     q->ID = msg.ID;
		     strcpy(q->passwd,msg.passwd);
		     strcpy(q->name,msg.name);

		     //printf("aaaaaaaaaa%ldaaaaaaa%saaaaaaa%s\n",q->ID,q->passwd,q->name);
		 
	             result = server_change(q);
                      
                     //printf("cccccccccccccccckui zi shi sha bi!\n");

		     if(result == change_ok)
		     {
		         msg.action = change_ok;
                         write(fd,&msg,sizeof(msg));
			 break;
		     }

		     else
		     {
		         msg.action = change_error;
		         write(fd,&msg,sizeof(msg));
			 break;
		     }

		     temp = temp->next;
		 }
	     }

	     if(msg.action == show)
	     {      
	         struct online *temp = head;     //遍历链表,传送每一个fd
		 while(temp != NULL)
		 {
		     msg.ID = temp->ID;             //错误:这两句话要加,不然信息是同一个人的
		     my_strcpy(msg.name,temp->name);
		     write(fd,&msg,sizeof(msg)); //错误:这里是fd,是在发过来的客户的界面显示
		     temp = temp->next;
		 }
	     }

	     if(msg.action == quit)
	     {
		 //printf("aaaaaaaaaaaaa%ld\n",msg.ID);
	         m = (struct online*)malloc(sizeof(struct online));
		 m->fd = fd;
		 //m->ID = msg.ID;
		 //my_strcpy(m->passwd,msg.passwd);
		 //my_strcpy(m->name,msg.name);
		 
		 //printf("aaaaaaaaaaaaa%ld\n",msg.ID);

	         delete_online(m);      //链表中不显示该用户
		 
		 msg.action = quit_ok;
		 
		 write(fd,&msg,sizeof(msg));

                 /*
		 if(result == delete_error)
		 {
		     msg.action = quit_error;
		     write(fd,&msg,sizeof(msg));
		 }
		 */
	     }

	     if(msg.action == kick)
	     {	
		 to_fd = find_fd(msg.toname);
	         //fd = find_fd(msg.name);
                 if(to_fd == -1 || my_strcmp(msg.name,msg.toname) == 0)
		 {
		     msg.action = -1;

		     write(fd,&msg,sizeof(msg));
		 }
		 
		 else
		 {
		     m = (struct online*)malloc(sizeof(struct online));
		 
		     m->fd = to_fd;
	         
		     delete_online(m);      //链表中不显示该用户
		 
		     msg.action = kick_ok;
		  
		     write(fd,&msg,sizeof(msg));
		 
		     write(to_fd,&msg,sizeof(msg));
		 }
	     }

             if(msg.action == ban)
	     {
	         //printf("nnnnnnn%s\n",msg.toname);

	         to_fd = find_fd(msg.toname);

		 struct online *temp;
		 struct online *str = head;

		 temp = (struct online*)malloc(sizeof(struct online));

		 while(str != NULL)
		 {
                     msg.action = ban_tell_all;  //不能写在后面,找到了就要发过去

                     write(str->fd,&msg,sizeof(msg));

		     if(str->fd == to_fd)
		     {
		         temp->fd = to_fd;
			 temp->ID = str->ID;
			 my_strcpy(temp->name,str->name);

			 //insert_online(temp);   错误:不能插入head中,那是显示在线链表的
			 insert_ban(temp);   //建立一个禁言链表
		     }
		     
		     str = str->next;        
		 }
	     }

	     if(msg.action == solve_ban)
	     {
	        
		 to_fd = find_fd(msg.toname);

	     
		 if((find_ban(to_fd)) == -1)
		 {
	        //printf("aaaaaaaaaaaaaaaaaa\n"); 
		     msg.action = solve_error;

		     write(fd,&msg,sizeof(msg));
	        //printf("aaaaaaaaaaaaaaaaaa\n"); 
		 }
	         
		 else
		 {
		     m = (struct online*)malloc(sizeof(struct online));
		 
		     m->fd = to_fd;
	         
		     delete_ban(m);  //删除禁言链表中该用户名字

		     msg.action = solve_ban;

		     struct online *temp = head;

		     while(temp != NULL)          //通知所有人,该用户被解禁了
                     {
		         write(temp->fd,&msg,sizeof(msg));
		         temp = temp->next;
		     }
		 }
	     }

	     if(msg.action == see_record)
	     {

	         //printf("cccccccccccccccccccccccccc\n");
		 read_chat_msg(msg.name,fd);

		 write(fd,&msg,sizeof(msg));
	     }
	 }

	 else              //客户端ctrl+c之后,将在线的用户删除掉,show的时候少掉这个异常退出的用户
	 {
             struct online *m = (struct online*)malloc(sizeof(struct online));
		 
	     m->fd = fd;
	         
	     delete_online(m);   
	 }
    }
}