예제 #1
0
파일: uping.c 프로젝트: Compy/Undernet-IRCU
/** Clean up a UPing structure, reporting results to the requester.
 * @param[in,out] pptr UPing results.
 */
void uping_end(struct UPing* pptr)
{
  Debug((DEBUG_DEBUG, "uping_end: %p", pptr));

  if (pptr->client) {
    if (pptr->lastsent) {
      if (0 < pptr->received) {
	sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING %s%s",
		      pptr->client, pptr->name, pptr->buf);
	sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING Stats: "
		      "sent %d recvd %d ; min/avg/max = %u/%u/%u ms",
		      pptr->client, pptr->sent, pptr->received, pptr->ms_min,
		      (2 * pptr->ms_ave) / (2 * pptr->received), pptr->ms_max);
      } else
	sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: no response "
		      "from %s within %d seconds", pptr->client, pptr->name,
		      UPINGTIMEOUT);
    } else
      sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: Could not "
		    "start ping to %s", pptr->client, pptr->name);
  }

  close(pptr->fd);
  pptr->fd = -1;
  uping_erase(pptr);
  if (pptr->client)
    ClearUPing(pptr->client);
  if (pptr->freeable & UPING_PENDING_SOCKET)
    socket_del(&pptr->socket);
  if (pptr->freeable & UPING_PENDING_SENDER)
    timer_del(&pptr->sender);
  if (pptr->freeable & UPING_PENDING_KILLER)
    timer_del(&pptr->killer);
}
예제 #2
0
/*
 * authsenderr - handle auth send errors
 */
static void auth_error(struct AuthRequest* auth, int kill)
{
  ++ServerStats->is_abad;

  assert(0 != auth);
  close(auth->fd);
  auth->fd = -1;
  socket_del(&auth->socket);

  if (IsUserPort(auth->client))
    sendheader(auth->client, REPORT_FAIL_ID);

  if (kill) {
    /*
     * we can't read the client info from the client socket,
     * close the client connection and free the client
     * Need to do this before we ClearAuth(auth) so we know
     * which list to remove the query from. --Bleep
     */
    auth_kill_client(auth);
    return;
  }

  ClearAuth(auth);
  unlink_auth_request(auth, &AuthPollList);

  if (IsDNSPending(auth))
    link_auth_request(auth, &AuthIncompleteList);
  else {
    release_auth_client(auth->client);
    free_auth_request(auth);
  }
}
예제 #3
0
/*
 * destroy_auth_request - stop an auth request completely
 */
void destroy_auth_request(struct AuthRequest* auth, int send_reports)
{
  struct AuthRequest** authList;

  if (IsDoingAuth(auth)) {
    authList = &AuthPollList;
    if (-1 < auth->fd) {
      close(auth->fd);
      auth->fd = -1;
      socket_del(&auth->socket);
    }

    if (send_reports && IsUserPort(auth->client))
      sendheader(auth->client, REPORT_FAIL_ID);
  } else
    authList = &AuthIncompleteList;

  if (IsDNSPending(auth)) {
    delete_resolver_queries(auth);
    if (send_reports && IsUserPort(auth->client))
      sendheader(auth->client, REPORT_FAIL_DNS);
  }

  if (send_reports) {
    log_write(LS_RESOLVER, L_INFO, 0, "DNS/AUTH timeout %s",
	      get_client_name(auth->client, HIDE_IP));
    release_auth_client(auth->client);
  }

  unlink_auth_request(auth, authList);
  free_auth_request(auth);
}
예제 #4
0
/*
 * free_auth_request - cleanup auth request allocations
 */
void free_auth_request(struct AuthRequest* auth)
{
  if (-1 < auth->fd) {
    close(auth->fd);
    Debug((DEBUG_LIST, "Deleting auth socket for %p", auth->client));
    socket_del(&auth->socket);
  }
  Debug((DEBUG_LIST, "Deleting auth timeout timer for %p", auth->client));
  timer_del(&auth->timeout);
}
예제 #5
0
/*
 * read_auth_reply - read the reply (if any) from the ident server 
 * we connected to.
 * We only give it one shot, if the reply isn't good the first time
 * fail the authentication entirely. --Bleep
 */
void read_auth_reply(struct AuthRequest* auth)
{
  char*        username = 0;
  unsigned int len;
  /*
   * rfc1453 sez we MUST accept 512 bytes
   */
  char   buf[BUFSIZE + 1];

  assert(0 != auth);
  assert(0 != auth->client);
  assert(auth == cli_auth(auth->client));

  if (IO_SUCCESS == os_recv_nonb(auth->fd, buf, BUFSIZE, &len)) {
    buf[len] = '\0';
    Debug((DEBUG_LIST, "Auth %p [%p] reply: %s", auth, &auth->socket, buf));
    username = check_ident_reply(buf);
    Debug((DEBUG_LIST, "Username: %s", username));
  }

  close(auth->fd);
  auth->fd = -1;
  Debug((DEBUG_LIST, "Deleting auth [%p] socket %p", auth, &auth->socket));
  socket_del(&auth->socket);
  ClearAuth(auth);
  
  if (!EmptyString(username)) {
    ircd_strncpy(cli_username(auth->client), username, USERLEN);
    /*
     * Not needed, struct is zeroed by memset
     * auth->client->username[USERLEN] = '\0';
     */
    SetGotId(auth->client);
    ++ServerStats->is_asuc;
    if (IsUserPort(auth->client))
      sendheader(auth->client, REPORT_FIN_ID);
  }
  else {
    ++ServerStats->is_abad;
  }
  unlink_auth_request(auth, &AuthPollList);

  if (IsDNSPending(auth))
    link_auth_request(auth, &AuthIncompleteList);
  else {
    release_auth_client(auth->client);
    free_auth_request(auth);
  }
}
예제 #6
0
파일: list.c 프로젝트: NX-Andro/nefarious
/** Release a Client.
 * In addition to the cleanup done by dealloc_client(), this will free
 * any pending auth request, free the connection for local clients,
 * and delete the processing timer for the client.
 * @param[in] cptr Client to free.
 */
void free_client(struct Client* cptr)
{
  if (!cptr)
    return;
  /*
   * forget to remove the client from the hash table?
   */
  assert(cli_verify(cptr));
  assert(cli_hnext(cptr) == cptr);
  /* or from linked list? */
  assert(cli_next(cptr) == 0);
  assert(cli_prev(cptr) == 0);

  Debug((DEBUG_LIST, "Freeing client %s [%p], connection %p", cli_name(cptr),
	 cptr, cli_connect(cptr)));

  if (cli_auth(cptr))
    destroy_auth_request(cli_auth(cptr), 0);

  /* Make sure we didn't magically get re-added to the list */
  assert(cli_next(cptr) == 0);
  assert(cli_prev(cptr) == 0);

  if (cli_from(cptr) == cptr) { /* in other words, we're local */
    cli_from(cptr) = 0;
    /* timer must be marked as not active */
    if (!cli_freeflag(cptr) && !t_active(&(cli_proc(cptr))))
      dealloc_connection(cli_connect(cptr)); /* connection not open anymore */
    else {
      if (-1 < cli_fd(cptr) && cli_freeflag(cptr) & FREEFLAG_SOCKET)
	socket_del(&(cli_socket(cptr))); /* queue a socket delete */
      if (cli_freeflag(cptr) & FREEFLAG_TIMER)
	timer_del(&(cli_proc(cptr))); /* queue a timer delete */
    }
  }

  cli_connect(cptr) = 0;

  dealloc_client(cptr); /* actually destroy the client */
}
예제 #7
0
파일: s_bsd.c 프로젝트: mojadita/ircd
/** Attempt to send a sequence of bytes to the connection.
 * As a side effect, updates \a cptr's FLAG_BLOCKED setting
 * and sendB/sendK fields.
 * @param cptr Client that should receive data.
 * @param buf Message buffer to send to client.
 * @return Negative on connection-fatal error; otherwise
 *  number of bytes sent.
 */
unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf)
{
  unsigned int bytes_written = 0;
  unsigned int bytes_count = 0;
  assert(0 != cptr);

#if defined(USE_SSL)
  switch (client_sendv(cptr, buf, &bytes_count, &bytes_written)) {
#else
  switch (os_sendv_nonb(cli_fd(cptr), buf, &bytes_count, &bytes_written)) {
#endif
  case IO_SUCCESS:
    ClrFlag(cptr, FLAG_BLOCKED);

    cli_sendB(cptr) += bytes_written;
    cli_sendB(&me)  += bytes_written;
    /* A partial write implies that future writes will block. */
    if (bytes_written < bytes_count)
      SetFlag(cptr, FLAG_BLOCKED);
    break;
  case IO_BLOCKED:
    SetFlag(cptr, FLAG_BLOCKED);
    break;
  case IO_FAILURE:
    cli_error(cptr) = errno;
    SetFlag(cptr, FLAG_DEADSOCKET);
    break;
  }
  return bytes_written;
}

/** Complete non-blocking connect()-sequence. Check access and
 * terminate connection, if trouble detected.
 * @param cptr Client to which we have connected, with all ConfItem structs attached.
 * @return Zero on failure (caller should exit_client()), non-zero on success.
 */
static int completed_connection(struct Client* cptr)
{
  struct ConfItem *aconf;
  time_t newts;
  struct Client *acptr;
  int i;
#if defined(USE_SSL)
  char *sslfp;
  int r;
#endif

  assert(0 != cptr);

  /*
   * get the socket status from the fd first to check if
   * connection actually succeeded
   */
  if ((cli_error(cptr) = os_get_sockerr(cli_fd(cptr)))) {
    const char* msg = strerror(cli_error(cptr));
    if (!msg)
      msg = "Unknown error";
    sendto_opmask(0, SNO_OLDSNO, "Connection failed to %s: %s",
                  cli_name(cptr), msg);
    return 0;
  }
  if (!(aconf = find_conf_byname(cli_confs(cptr), cli_name(cptr), CONF_SERVER))) {
    sendto_opmask(0, SNO_OLDSNO, "Lost Server Line for %s", cli_name(cptr));
    return 0;
  }

#if defined(USE_SSL)
  if (aconf->flags & CONF_SSL) {
    r = ssl_connect(&(cli_socket(cptr)));
    if (r == -1) {
      sendto_opmask(0, SNO_OLDSNO, "Connection failed to %s: SSL error",
                    cli_name(cptr));
      return 0;
    } else if (r == 0)
      return 1;
    sslfp = ssl_get_fingerprint(cli_socket(cptr).s_ssl);
    if (sslfp)
      ircd_strncpy(cli_sslclifp(cptr), sslfp, BUFSIZE+1);
    SetSSL(cptr);
  }
#endif

  if (s_state(&(cli_socket(cptr))) == SS_CONNECTING)
    socket_state(&(cli_socket(cptr)), SS_CONNECTED);

  if (!EmptyString(aconf->passwd))
    sendrawto_one(cptr, MSG_PASS " :%s", aconf->passwd);

  /*
   * Create a unique timestamp
   */
  newts = TStime();
  for (i = HighestFd; i > -1; --i) {
    if ((acptr = LocalClientArray[i]) &&
        (IsServer(acptr) || IsHandshake(acptr))) {
      if (cli_serv(acptr)->timestamp >= newts)
        newts = cli_serv(acptr)->timestamp + 1;
    }
  }
  assert(0 != cli_serv(cptr));

  cli_serv(cptr)->timestamp = newts;
  SetHandshake(cptr);
  /*
   * Make us timeout after twice the timeout for DNS look ups
   */
  cli_lasttime(cptr) = CurrentTime;
  ClearPingSent(cptr);

/* TODO: NEGOCIACION
  envia_config_req(cptr);
*/

  sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6 :%s",
                cli_name(&me), cli_serv(&me)->timestamp, newts,
		MAJOR_PROTOCOL, NumServCap(&me),
		feature_bool(FEAT_HUB) ? "h" : "", cli_info(&me));

#if defined(DDB)
  ddb_burst(cptr);
#endif

  return (IsDead(cptr)) ? 0 : 1;
}

/** Close the physical connection.  Side effects: MyConnect(cptr)
 * becomes false and cptr->from becomes NULL.
 * @param cptr Client to disconnect.
 */
void close_connection(struct Client *cptr)
{
  struct ConfItem* aconf;

  if (IsServer(cptr)) {
    ServerStats->is_sv++;
    ServerStats->is_sbs += cli_sendB(cptr);
    ServerStats->is_sbr += cli_receiveB(cptr);
    ServerStats->is_sti += CurrentTime - cli_firsttime(cptr);
    /*
     * If the connection has been up for a long amount of time, schedule
     * a 'quick' reconnect, else reset the next-connect cycle.
     */
    if ((aconf = find_conf_exact(cli_name(cptr), cptr, CONF_SERVER))) {
      /*
       * Reschedule a faster reconnect, if this was a automatically
       * connected configuration entry. (Note that if we have had
       * a rehash in between, the status has been changed to
       * CONF_ILLEGAL). But only do this if it was a "good" link.
       */
      aconf->hold = CurrentTime;
      aconf->hold += ((aconf->hold - cli_since(cptr) >
		       feature_int(FEAT_HANGONGOODLINK)) ?
		      feature_int(FEAT_HANGONRETRYDELAY) : ConfConFreq(aconf));
/*        if (nextconnect > aconf->hold) */
/*          nextconnect = aconf->hold; */
    }
  }
  else if (IsUser(cptr)) {
    ServerStats->is_cl++;
    ServerStats->is_cbs += cli_sendB(cptr);
    ServerStats->is_cbr += cli_receiveB(cptr);
    ServerStats->is_cti += CurrentTime - cli_firsttime(cptr);
  }
  else
    ServerStats->is_ni++;

#if defined(USE_ZLIB)
  /*
   * Siempre es una conexion nuestra
   */
  if (cli_connect(cptr)->zlib_negociation & ZLIB_IN) {
    inflateEnd(cli_connect(cptr)->comp_in);
    MyFree(cli_connect(cptr)->comp_in);
  }
  if (cli_connect(cptr)->zlib_negociation & ZLIB_OUT) {
    deflateEnd(cli_connect(cptr)->comp_out);
    MyFree(cli_connect(cptr)->comp_out);
  }
#endif

  if (-1 < cli_fd(cptr)) {
    flush_connections(cptr);
    LocalClientArray[cli_fd(cptr)] = 0;
    close(cli_fd(cptr));
    socket_del(&(cli_socket(cptr))); /* queue a socket delete */
    cli_fd(cptr) = -1;
    cli_freeflag(cptr) &= ~FREEFLAG_SOCKET;
  }
  SetFlag(cptr, FLAG_DEADSOCKET);

  MsgQClear(&(cli_sendQ(cptr)));
  client_drop_sendq(cli_connect(cptr));
  DBufClear(&(cli_recvQ(cptr)));
  memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr)));
  set_snomask(cptr, 0, SNO_SET);

  det_confs_butmask(cptr, 0);

  if (cli_listener(cptr)) {
    release_listener(cli_listener(cptr));
    cli_listener(cptr) = 0;
  }

  for ( ; HighestFd > 0; --HighestFd) {
    if (LocalClientArray[HighestFd])
      break;
  }
}

/** Close all unregistered connections.
 * @param source Oper who requested the close.
 * @return Number of closed connections.
 */
int net_close_unregistered_connections(struct Client* source)
{
  int            i;
  struct Client* cptr;
  int            count = 0;
  assert(0 != source);

  for (i = HighestFd; i > 0; --i) {
    if ((cptr = LocalClientArray[i]) && !IsRegistered(cptr)) {
      send_reply(source, RPL_CLOSING, get_client_name(source, HIDE_IP));
      exit_client(source, cptr, &me, "Oper Closing");
      ++count;
    }
  }
  return count;
}
예제 #8
0
파일: s_bsd.c 프로젝트: Niichan/snircd
/** Close the physical connection.  Side effects: MyConnect(cptr)
 * becomes false and cptr->from becomes NULL.
 * @param cptr Client to disconnect.
 */
void close_connection(struct Client *cptr)
{
  struct ConfItem* aconf;

  if (IsServer(cptr)) {
    ServerStats->is_sv++;
    ServerStats->is_sbs += cli_sendB(cptr);
    ServerStats->is_sbr += cli_receiveB(cptr);
    ServerStats->is_sti += CurrentTime - cli_firsttime(cptr);
    /*
     * If the connection has been up for a long amount of time, schedule
     * a 'quick' reconnect, else reset the next-connect cycle.
     */
    if ((aconf = find_conf_exact(cli_name(cptr), cptr, CONF_SERVER))) {
      /*
       * Reschedule a faster reconnect, if this was a automatically
       * connected configuration entry. (Note that if we have had
       * a rehash in between, the status has been changed to
       * CONF_ILLEGAL). But only do this if it was a "good" link.
       */
      aconf->hold = CurrentTime;
      aconf->hold += ((aconf->hold - cli_since(cptr) >
		       feature_int(FEAT_HANGONGOODLINK)) ?
		      feature_int(FEAT_HANGONRETRYDELAY) : ConfConFreq(aconf));
/*        if (nextconnect > aconf->hold) */
/*          nextconnect = aconf->hold; */
    }
  }
  else if (IsUser(cptr)) {
    ServerStats->is_cl++;
    ServerStats->is_cbs += cli_sendB(cptr);
    ServerStats->is_cbr += cli_receiveB(cptr);
    ServerStats->is_cti += CurrentTime - cli_firsttime(cptr);
  }
  else
    ServerStats->is_ni++;

  if (-1 < cli_fd(cptr)) {
    flush_connections(cptr);
    LocalClientArray[cli_fd(cptr)] = 0;
    close(cli_fd(cptr));
    socket_del(&(cli_socket(cptr))); /* queue a socket delete */
    cli_fd(cptr) = -1;
  }
  SetFlag(cptr, FLAG_DEADSOCKET);

  MsgQClear(&(cli_sendQ(cptr)));
  client_drop_sendq(cli_connect(cptr));
  DBufClear(&(cli_recvQ(cptr)));
  memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr)));
  set_snomask(cptr, 0, SNO_SET);

  det_confs_butmask(cptr, 0);

  if (cli_listener(cptr)) {
    release_listener(cli_listener(cptr));
    cli_listener(cptr) = 0;
  }

  for ( ; HighestFd > 0; --HighestFd) {
    if (LocalClientArray[HighestFd])
      break;
  }
}