Ejemplo n.º 1
0
/** Initialize a UDP socket for upings.
 * @returns 0 on success, -1 on error.
 */
int uping_init(void)
{
  struct irc_sockaddr from;
  int fd;

  memcpy(&from, &VirtualHost_v4, sizeof(from));
  from.port = atoi(UDP_PORT);

  fd = os_socket(&from, SOCK_DGRAM, "IPv4 uping listener", AF_INET);
  if (fd < 0)
    return -1;
  if (!socket_add(&upingSock_v4, uping_echo_callback, 0, SS_DATAGRAM,
                  SOCK_EVENT_READABLE, fd)) {
    Debug((DEBUG_ERROR, "UPING: Unable to queue fd to event system"));
    close(fd);
    return -1;
  }

#ifdef AF_INET6
  memcpy(&from, &VirtualHost_v6, sizeof(from));
  from.port = atoi(UDP_PORT);

  fd = os_socket(&from, SOCK_DGRAM, "IPv6 uping listener", AF_INET6);
  if (fd < 0)
    return -1;
  if (!socket_add(&upingSock_v6, uping_echo_callback, 0, SS_DATAGRAM,
                  SOCK_EVENT_READABLE, fd)) {
    Debug((DEBUG_ERROR, "UPING: Unable to queue fd to event system"));
    close(fd);
    return -1;
  }
#endif

  return 0;
}
Ejemplo n.º 2
0
/** Start sending upings to a server.
 * @param[in] sptr Client requesting the upings.
 * @param[in] aconf ConfItem containing the address to ping.
 * @param[in] port Port number to ping.
 * @param[in] count Number of times to ping (should be at least 20).
 * @return Zero.
 */
int uping_server(struct Client* sptr, struct ConfItem* aconf, int port, int count)
{
  int fd;
  struct UPing* pptr;

  assert(0 != sptr);
  assert(0 != aconf);

  if (INADDR_NONE == aconf->ipnum.s_addr) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Host lookup failed for "
		  "%s", sptr, aconf->name);
    return 0;
  }

  if (IsUPing(sptr))
    uping_cancel(sptr, sptr);  /* Cancel previous ping request */

  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Unable to create udp "
		  "ping socket", sptr);
    return 0;
  }

  if (!os_set_nonblocking(fd)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't set fd non-"
		  "blocking", sptr);
    close(fd);
    return 0;
  }
  pptr = (struct UPing*) MyMalloc(sizeof(struct UPing));
  assert(0 != pptr);
  memset(pptr, 0, sizeof(struct UPing));

  if (!socket_add(&pptr->socket, uping_read_callback, (void*) pptr,
		  SS_DATAGRAM, SOCK_EVENT_READABLE, fd)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't queue fd for "
		  "reading", sptr);
    close(fd);
    MyFree(pptr);
    return 0;
  }

  pptr->fd                  = fd;
  pptr->sin.sin_port        = htons(port);
  pptr->sin.sin_addr.s_addr = aconf->ipnum.s_addr;
  pptr->sin.sin_family      = AF_INET;
  pptr->count               = IRCD_MIN(20, count);
  pptr->client              = sptr;
  pptr->index               = -1;
  pptr->freeable            = UPING_PENDING_SOCKET;
  strcpy(pptr->name, aconf->name);

  pptr->next = pingList;
  pingList   = pptr;

  SetUPing(sptr);
  uping_start(pptr);
  return 0;
}
Ejemplo n.º 3
0
/** Start sending upings to a server.
 * @param[in] sptr Client requesting the upings.
 * @param[in] aconf ConfItem containing the address to ping.
 * @param[in] port Port number to ping.
 * @param[in] count Number of times to ping (should be at least 20).
 * @return Zero.
 */
int uping_server(struct Client* sptr, struct ConfItem* aconf, int port, int count)
{
  int fd;
  int family = 0;
  struct UPing* pptr;
  struct irc_sockaddr *local;

  assert(0 != sptr);
  assert(0 != aconf);

  if (!irc_in_addr_valid(&aconf->address.addr)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Host lookup failed for "
		  "%s", sptr, aconf->name);
    return 0;
  }

  if (IsUPing(sptr))
    uping_cancel(sptr, sptr);  /* Cancel previous ping request */

  if (irc_in_addr_is_ipv4(&aconf->address.addr)) {
    local = &VirtualHost_v4;
    family = AF_INET;
  } else {
    local = &VirtualHost_v6;
  }
  fd = os_socket(local, SOCK_DGRAM, "Outbound uping socket", family);
  if (fd < 0)
    return 0;

  pptr = (struct UPing*) MyMalloc(sizeof(struct UPing));
  assert(0 != pptr);
  memset(pptr, 0, sizeof(struct UPing));

  if (!socket_add(&pptr->socket, uping_read_callback, (void*) pptr,
		  SS_DATAGRAM, SOCK_EVENT_READABLE, fd)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't queue fd for "
		  "reading", sptr);
    close(fd);
    MyFree(pptr);
    return 0;
  }

  pptr->fd                  = fd;
  memcpy(&pptr->addr.addr, &aconf->address.addr, sizeof(pptr->addr.addr));
  pptr->addr.port           = port;
  pptr->count               = IRCD_MIN(20, count);
  pptr->client              = sptr;
  pptr->freeable            = UPING_PENDING_SOCKET;
  strcpy(pptr->name, aconf->name);

  pptr->next = pingList;
  pingList   = pptr;

  SetUPing(sptr);
  uping_start(pptr);
  return 0;
}
Ejemplo n.º 4
0
/** Start (or re-start) resolver.
 * This means read resolv.conf, initialize the list of pending
 * requests, open the resolver socket and initialize its timeout.
 */
void
restart_resolver(void)
{
  int need_v4;
  int need_v6;
  int ns;

  irc_res_init();

  if (!request_list.next)
    request_list.next = request_list.prev = &request_list;

  /* Check which address family (or families) our nameservers use. */
  for (need_v4 = need_v6 = ns = 0; ns < irc_nscount; ns++)
  {
    if (irc_in_addr_is_ipv4(&irc_nsaddr_list[ns].addr))
      need_v4 = 1;
    else
      need_v6 = 1;
  }

  /* If we need an IPv4 socket, and don't have one, open it. */
  if (need_v4 && !s_active(&res_socket_v4))
  {
    int fd = os_socket(&VirtualHost_dns_v4, SOCK_DGRAM, "Resolver UDPv4 socket", AF_INET);
    if (fd >= 0)
      socket_add(&res_socket_v4, res_readreply, NULL,
                 SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
  }

#ifdef AF_INET6
  /* If we need an IPv6 socket, and don't have one, open it. */
  if (need_v6 && !s_active(&res_socket_v6))
  {
    int fd = os_socket(&VirtualHost_dns_v6, SOCK_DGRAM, "Resolver UDPv6 socket", AF_INET6);
    if (fd >= 0)
      socket_add(&res_socket_v6, res_readreply, NULL,
                 SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
  }
#endif

  if (s_active(&res_socket_v4) || s_active(&res_socket_v6))
    timer_init(&res_timeout);
}
Ejemplo n.º 5
0
/*
 * @returns 0 on success, -1 on error.
 */
int uping_init(void)
{
  struct sockaddr_in from = { 0 };
  int fd;

  memset(&from, 0, sizeof(from));
  from.sin_addr = VirtualHost.sin_addr;
  from.sin_port = htons(atoi(UDP_PORT));
  from.sin_family = AF_INET;

  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    Debug((DEBUG_ERROR, "UPING: UDP listener socket call failed: %s", 
           (strerror(errno)) ? strerror(errno) : "Unknown error"));
    return -1;
  }
  if (!os_set_reuseaddr(fd)) {
    log_write(LS_SOCKET, L_ERROR, 0,
	      "UPING: set reuseaddr on UDP listener failed: %m (fd %d)", fd);
    Debug((DEBUG_ERROR, "UPING: set reuseaddr on UDP listener failed: %s",
           (strerror(errno)) ? strerror(errno) : "Unknown error"));
    close(fd);
    return -1;
  }
  if (bind(fd, (struct sockaddr*) &from, sizeof(from)) == -1) {
    log_write(LS_SOCKET, L_ERROR, 0,
	      "UPING: bind on UDP listener (%d fd %d) failed: %m",
	      htons(from.sin_port), fd);
    Debug((DEBUG_ERROR, "UPING: bind on UDP listener failed : %s",
           (strerror(errno)) ? strerror(errno) : "Unknown error"));
    close(fd);
    return -1;
  }
  if (!os_set_nonblocking(fd)) {
    Debug((DEBUG_ERROR, "UPING: set non-blocking: %s",
           (strerror(errno)) ? strerror(errno) : "Unknown error"));
    close(fd);
    return -1;
  }
  if (!socket_add(&upingSock, uping_echo_callback, 0, SS_DATAGRAM,
		  SOCK_EVENT_READABLE, fd)) {
    Debug((DEBUG_ERROR, "UPING: Unable to queue fd to event system"));
    close(fd);
    return -1;
  }
  UPingFileDescriptor = fd;
  return fd;
}
Ejemplo n.º 6
0
    helper(const struct arguments &args)
        : recoder_stack(args),
          m_frame(frame_len()),
          m_packet_hdr(&m_frame[0]),
          m_payload_hdr(&m_frame[packet_hdr_len()]),
          m_payload_data(&m_frame[header_len()]),
          m_threshold(budgets::helper_threshold(args.symbols, args.e1/100.0,
                                                args.e2/100.0, args.e3/100.0)),
          m_budget_max(budgets::helper_budget(args.symbols, args.e1/100.0,
                                              args.e2/100.0, args.e3/100.0)),
          m_credits(budgets::helper_credits(args.symbols, args.e1/100.0,
                                            args.e2/100.0, args.e3/100.0))
    {
        auto r = std::bind(&helper::recv_packet, this, std::placeholders::_1);

        m_sock = socket_add(args.interface, r);

        std::cout << "credits:   " << m_credits << std::endl;
        std::cout << "budget:    " << m_budget_max << std::endl;
        std::cout << "threshold: " << m_threshold << std::endl;

        start();
    }
Ejemplo n.º 7
0
/*
 * start_auth_query - Flag the client to show that an attempt to 
 * contact the ident server on the client's host.  The connect and
 * subsequently the socket are all put into 'non-blocking' mode.  
 * Should the connect or any later phase of the identifing process fail,
 * it is aborted and the user is given a username of "unknown".
 */
static int start_auth_query(struct AuthRequest* auth)
{
  struct sockaddr_in remote_addr;
  struct sockaddr_in local_addr;
  int                fd;
  IOResult           result;

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

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    ++ServerStats->is_abad;
    return 0;
  }
  if ((MAXCONNECTIONS - 10) < fd) {
    close(fd);
    return 0;
  }
  if (!os_set_nonblocking(fd)) {
    close(fd);
    return 0;
  }
  if (IsUserPort(auth->client))
    sendheader(auth->client, REPORT_DO_ID);
  /* 
   * get the local address of the client and bind to that to
   * make the auth request.  This used to be done only for
   * ifdef VIRTTUAL_HOST, but needs to be done for all clients
   * since the ident request must originate from that same address--
   * and machines with multiple IP addresses are common now
   */
  memset(&local_addr, 0, sizeof(struct sockaddr_in));
  os_get_sockname(cli_fd(auth->client), &local_addr);
  local_addr.sin_port = htons(0);

  if (bind(fd, (struct sockaddr*) &local_addr, sizeof(struct sockaddr_in))) {
    close(fd);
    return 0;
  }

  remote_addr.sin_addr.s_addr = (cli_ip(auth->client)).s_addr;
  remote_addr.sin_port = htons(113);
  remote_addr.sin_family = AF_INET;

  if ((result = os_connect_nonb(fd, &remote_addr)) == IO_FAILURE ||
      !socket_add(&auth->socket, auth_sock_callback, (void*) auth,
		  result == IO_SUCCESS ? SS_CONNECTED : SS_CONNECTING,
		  SOCK_EVENT_READABLE, fd)) {
    ServerStats->is_abad++;
    /*
     * No error report from this...
     */
    close(fd);
    if (IsUserPort(auth->client))
      sendheader(auth->client, REPORT_FAIL_ID);
    return 0;
  }

  auth->flags |= AM_SOCKET;
  auth->fd = fd;

  SetAuthConnect(auth);
  if (result == IO_SUCCESS)
    send_auth_query(auth); /* this does a SetAuthPending(auth) for us */

  return 1;
}
Ejemplo n.º 8
0
void add_connection(struct Listener* listener, int fd, void *ssl) {
#else
void add_connection(struct Listener* listener, int fd) {
#endif
  struct irc_sockaddr addr;
  struct Client      *new_client;
  time_t             next_target = 0;
#if defined(USE_SSL)
  char *sslfp;
#endif

  const char* const throttle_message =
         "ERROR :Your host is trying to (re)connect too fast -- throttled\r\n";
       /* 12345678901234567890123456789012345679012345678901234567890123456 */
  const char* const register_message =
         "ERROR :Unable to complete your registration\r\n";

  assert(0 != listener);

  /*
   * Removed preliminary access check. Full check is performed in m_server and
   * m_user instead. Also connection time out help to get rid of unwanted
   * connections.
   */
  if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) {
    ++ServerStats->is_ref;
#if defined(USE_SSL)
    ssl_murder(ssl, fd, NULL);
#else
    close(fd);
#endif
    return;
  }
  /*
   * Disable IP (*not* TCP) options.  In particular, this makes it impossible
   * to use source routing to connect to the server.  If we didn't do this
   * (and if intermediate networks didn't drop source-routed packets), an
   * attacker could successfully IP spoof us...and even return the anti-spoof
   * ping, because the options would cause the packet to be routed back to
   * the spoofer's machine.  When we disable the IP options, we delete the
   * source route, and the normal routing takes over.
   */
  os_disable_options(fd);

  if (listener_server(listener))
  {
    new_client = make_client(0, STAT_UNKNOWN_SERVER);
  }
  else
  {
    /*
     * Add this local client to the IPcheck registry.
     *
     * If they're throttled, murder them, but tell them why first.
     */
    if (!IPcheck_local_connect(&addr.addr, &next_target))
    {
      ++ServerStats->is_ref;
#if defined(USE_SSL)
      ssl_murder(ssl, fd, throttle_message);
#else
      write(fd, throttle_message, strlen(throttle_message));
      close(fd);
#endif
      return;
    }
    new_client = make_client(0, STAT_UNKNOWN_USER);
    SetIPChecked(new_client);
  }

  /*
   * Copy ascii address to 'sockhost' just in case. Then we have something
   * valid to put into error messages...
   */
  ircd_ntoa_r(cli_sock_ip(new_client), &addr.addr);
  strcpy(cli_sockhost(new_client), cli_sock_ip(new_client));
  memcpy(&cli_ip(new_client), &addr.addr, sizeof(cli_ip(new_client)));

  if (next_target)
    cli_nexttarget(new_client) = next_target;

  cli_fd(new_client) = fd;
  if (!socket_add(&(cli_socket(new_client)), client_sock_callback,
		  (void*) cli_connect(new_client), SS_CONNECTED, 0, fd)) {
    ++ServerStats->is_ref;
#if defined(USE_SSL)
    ssl_murder(ssl, fd, register_message);
#else
    write(fd, register_message, strlen(register_message));
    close(fd);
#endif
    cli_fd(new_client) = -1;
    return;
  }
#if defined(USE_SSL)
  if (ssl) {
    cli_socket(new_client).s_ssl = ssl;
    sslfp = ssl_get_fingerprint(ssl);
    if (sslfp)
      ircd_strncpy(cli_sslclifp(new_client), sslfp, BUFSIZE+1);
  }
#endif
  cli_freeflag(new_client) |= FREEFLAG_SOCKET;
  cli_listener(new_client) = listener;
  ++listener->ref_count;

  Count_newunknown(UserStats);
  /* if we've made it this far we can put the client on the auth query pile */
  start_auth(new_client);
}

/** Determines whether to tell the events engine we're interested in
 * writable events.
 * @param cptr Client for which to decide this.
 */
void update_write(struct Client* cptr)
{
  /* If there are messages that need to be sent along, or if the client
   * is in the middle of a /list, then we need to tell the engine that
   * we're interested in writable events--otherwise, we need to drop
   * that interest.
   */
  socket_events(&(cli_socket(cptr)),
		((MsgQLength(&cli_sendQ(cptr)) || cli_listing(cptr)) ?
		 SOCK_ACTION_ADD : SOCK_ACTION_DEL) | SOCK_EVENT_WRITABLE);
}
Ejemplo n.º 9
0
/** Set up address and port and make a connection.
 * @param aconf Provides the connection information.
 * @param cptr Client structure for the peer.
 * @return Non-zero on success; zero on failure.
 */
static int connect_inet(struct ConfItem* aconf, struct Client* cptr)
{
  const struct irc_sockaddr *local;
  IOResult result;
  int family = 0;

  assert(0 != aconf);
  assert(0 != cptr);
  /*
   * Might as well get sockhost from here, the connection is attempted
   * with it so if it fails its useless.
   */
  if (irc_in_addr_valid(&aconf->origin.addr))
    local = &aconf->origin;
  else if (irc_in_addr_is_ipv4(&aconf->address.addr)) {
    local = &VirtualHost_v4;
    family = AF_INET;
  } else
    local = &VirtualHost_v6;
  cli_fd(cptr) = os_socket(local, SOCK_STREAM, cli_name(cptr), family);
  if (cli_fd(cptr) < 0)
    return 0;

  /*
   * save connection info in client
   */
  memcpy(&cli_ip(cptr), &aconf->address.addr, sizeof(cli_ip(cptr)));
  ircd_ntoa_r(cli_sock_ip(cptr), &cli_ip(cptr));
  /*
   * we want a big buffer for server connections
   */
  if (!os_set_sockbufs(cli_fd(cptr), feature_int(FEAT_SOCKSENDBUF), feature_int(FEAT_SOCKRECVBUF))) {
    cli_error(cptr) = errno;
    report_error(SETBUFS_ERROR_MSG, cli_name(cptr), errno);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  /*
   * Set the TOS bits - this is nonfatal if it doesn't stick.
   */
  if (!os_set_tos(cli_fd(cptr), feature_int(FEAT_TOS_SERVER))) {
    report_error(TOS_ERROR_MSG, cli_name(cptr), errno);
  }
  if ((result = os_connect_nonb(cli_fd(cptr), &aconf->address)) == IO_FAILURE) {
    cli_error(cptr) = errno;
    report_error(CONNECT_ERROR_MSG, cli_name(cptr), errno);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  if (!socket_add(&(cli_socket(cptr)), client_sock_callback,
		  (void*) cli_connect(cptr),
		  (result == IO_SUCCESS) ? SS_CONNECTED : SS_CONNECTING,
		  SOCK_EVENT_READABLE, cli_fd(cptr))) {
    cli_error(cptr) = ENFILE;
    report_error(REGISTER_ERROR_MSG, cli_name(cptr), ENFILE);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  cli_freeflag(cptr) |= FREEFLAG_SOCKET;
  return 1;
}
Ejemplo n.º 10
0
/** Creates a client which has just connected to us on the given fd.
 * The sockhost field is initialized with the ip# of the host.
 * The client is not added to the linked list of clients, it is
 * passed off to the auth handler for dns and ident queries.
 * @param listener Listening socket that received the connection.
 * @param fd File descriptor of new connection.
 */
void add_connection(struct Listener* listener, int fd) {
  struct irc_sockaddr addr;
  struct Client      *new_client;
  time_t             next_target = 0;

  const char* const throttle_message =
         "ERROR :Your host is trying to (re)connect too fast -- throttled\r\n";
       /* 12345678901234567890123456789012345679012345678901234567890123456 */
  const char* const register_message =
         "ERROR :Unable to complete your registration\r\n";

  assert(0 != listener);

  /*
   * Removed preliminary access check. Full check is performed in m_server and
   * m_user instead. Also connection time out help to get rid of unwanted
   * connections.
   */
  if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) {
    ++ServerStats->is_ref;
    close(fd);
    return;
  }
  /*
   * Disable IP (*not* TCP) options.  In particular, this makes it impossible
   * to use source routing to connect to the server.  If we didn't do this
   * (and if intermediate networks didn't drop source-routed packets), an
   * attacker could successfully IP spoof us...and even return the anti-spoof
   * ping, because the options would cause the packet to be routed back to
   * the spoofer's machine.  When we disable the IP options, we delete the
   * source route, and the normal routing takes over.
   */
  os_disable_options(fd);

  if (listener_server(listener))
  {
    new_client = make_client(0, STAT_UNKNOWN_SERVER);
  }
  else
  {
    /*
     * Add this local client to the IPcheck registry.
     *
     * If they're throttled, murder them, but tell them why first.
     */
    if (!IPcheck_local_connect(&addr.addr, &next_target))
    {
      ++ServerStats->is_ref;
      write(fd, throttle_message, strlen(throttle_message));
      close(fd);
      return;
    }
    new_client = make_client(0, STAT_UNKNOWN_USER);
    SetIPChecked(new_client);
  }

  /*
   * Copy ascii address to 'sockhost' just in case. Then we have something
   * valid to put into error messages...
   */
  ircd_ntoa_r(cli_sock_ip(new_client), &addr.addr);
  strcpy(cli_sockhost(new_client), cli_sock_ip(new_client));
  memcpy(&cli_ip(new_client), &addr.addr, sizeof(cli_ip(new_client)));

  if (next_target)
    cli_nexttarget(new_client) = next_target;

  cli_fd(new_client) = fd;
  if (!socket_add(&(cli_socket(new_client)), client_sock_callback,
		  (void*) cli_connect(new_client), SS_CONNECTED, 0, fd)) {
    ++ServerStats->is_ref;
    write(fd, register_message, strlen(register_message));
    close(fd);
    cli_fd(new_client) = -1;
    return;
  }
  cli_freeflag(new_client) |= FREEFLAG_SOCKET;
  cli_listener(new_client) = listener;
  ++listener->ref_count;

  Count_newunknown(UserStats);
  /* if we've made it this far we can put the client on the auth query pile */
  start_auth(new_client);
}