Ejemplo n.º 1
0
int
match_cidr(const char *s1, const char *s2)
{
  struct irc_inaddr ipaddr, maskaddr;
  char mask[BUFSIZE];
  char address[NICKLEN + USERLEN + HOSTLEN + 6];
  char *ipmask;
  char *ip;
  char *len;
  int cidrlen, aftype;

  strcpy(mask, s1);
  strcpy(address, s2);
  
  ipmask = strrchr(mask, '@');
  if(ipmask == NULL)
    return 0;
  
  *ipmask++ = '\0';
  
  ip = strrchr(address, '@');
  if(ip == NULL)
    return 0;
  *ip++ = '\0';
  
  
  len = strrchr(ipmask, '/');
  if(len == NULL)
    return 0;
  
  *len++ = '\0';
  
  cidrlen = atoi(len);
  if(cidrlen == 0) 
    return 0;
  
#ifdef IPV6
  if(strchr(ip, ':') && strchr(ipmask, ':'))
    aftype = AF_INET6;
  else
#endif
  if(!strchr(ip, ':') && !strchr(ipmask, ':'))
    aftype = AF_INET;
  else
    return 0;
  
  inetpton(aftype, ip, &ipaddr);
  inetpton(aftype, ipmask, &maskaddr);
  if(comp_with_mask(&IN_ADDR(ipaddr), &IN_ADDR(maskaddr), cidrlen) && match(mask, address))
    return 1;
  else
    return 0;
}
Ejemplo n.º 2
0
int			connect_to_server(t_graphic *c)
{
  c->server.sin_family = AF_INET;
  c->server.sin_port = htons(c->port);
  if (((c->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 &&
       my_perror(SYSCALL("socket"), FAILURE) == FAILURE) ||
      (inet_aton(c->ip, IN_ADDR(&c->server.sin_addr.s_addr)) == -1 &&
       my_perror(SYSCALL("inet_aton"), FAILURE) == FAILURE) ||
      (connect(c->socket, C_SOCKADDR(&c->server), sizeof(c->server)) == -1 &&
       my_perror(SYSCALL("connect"), FAILURE) == FAILURE))
    return (close_graphic(c, FAILURE));
  printf("Graphic trying to connect\n");
  return (check_fds(c));
}
Ejemplo n.º 3
0
int     dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr *sa,
		             SOCKADDR_SIZE *sa_length)
{
    SOCKADDR_SIZE sock_addr_len;

    if (rr->type == T_A) {
	if (rr->data_len != sizeof(SOCK_ADDR_IN_ADDR(sa))) {
	    errno = EINVAL;
	    return (-1);
	} else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN_PTR(sa))) > *sa_length) {
	    errno = ENOSPC;
	    return (-1);
	} else {
	    memset((void *) SOCK_ADDR_IN_PTR(sa), 0, sock_addr_len);
	    SOCK_ADDR_IN_FAMILY(sa) = AF_INET;
	    SOCK_ADDR_IN_PORT(sa) = port;
	    SOCK_ADDR_IN_ADDR(sa) = IN_ADDR(rr->data);
#ifdef HAS_SA_LEN
	    sa->sa_len = sock_addr_len;
#endif
	    *sa_length = sock_addr_len;
	    return (0);
	}
#ifdef HAS_IPV6
    } else if (rr->type == T_AAAA) {
	if (rr->data_len != sizeof(SOCK_ADDR_IN6_ADDR(sa))) {
	    errno = EINVAL;
	    return (-1);
	} else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN6_PTR(sa))) > *sa_length) {
	    errno = ENOSPC;
	    return (-1);
	} else {
	    memset((void *) SOCK_ADDR_IN6_PTR(sa), 0, sock_addr_len);
	    SOCK_ADDR_IN6_FAMILY(sa) = AF_INET6;
	    SOCK_ADDR_IN6_PORT(sa) = port;
	    SOCK_ADDR_IN6_ADDR(sa) = IN6_ADDR(rr->data);
#ifdef HAS_SA_LEN
	    sa->sa_len = sock_addr_len;
#endif
	    *sa_length = sock_addr_len;
	    return (0);
	}
#endif
    } else {
	errno = EAFNOSUPPORT;
	return (-1);
    }
}
Ejemplo n.º 4
0
static struct Listener* 
make_listener(int port, struct irc_inaddr *addr)
{
  struct Listener* listener =
    (struct Listener*) MyMalloc(sizeof(struct Listener));
  assert(0 != listener);
  
  listener->name        = me.name;
  listener->fd          = -1;
  copy_s_addr(IN_ADDR(listener->addr),PIN_ADDR(addr));

  listener->port        = port;

  listener->next = NULL;
  return listener;
}
Ejemplo n.º 5
0
static void 
accept_connection(int pfd, void *data)
{
  static time_t      last_oper_notice = 0;

  struct irc_sockaddr sai;
  struct irc_inaddr addr;
  int                fd;
  int pe;
  struct Listener *  listener = data;

  assert(listener != NULL);
  if(listener == NULL)
    return;
  /*
   * There may be many reasons for error return, but
   * in otherwise correctly working environment the
   * probable cause is running out of file descriptors
   * (EMFILE, ENFILE or others?). The man pages for
   * accept don't seem to list these as possible,
   * although it's obvious that it may happen here.
   * Thus no specific errors are tested at this
   * point, just assume that connections cannot
   * be accepted until some old is closed first.
   */

  fd = comm_accept(listener->fd, &sai);

  copy_s_addr(IN_ADDR(addr), S_ADDR(sai));

#ifdef IPV6
  if((IN6_IS_ADDR_V4MAPPED(&IN_ADDR2(addr))) ||
  	(IN6_IS_ADDR_V4COMPAT(&IN_ADDR2(addr))))
  {
    memmove(&addr.sins.sin.s_addr, addr.sins.sin6.s6_addr+12,
            sizeof(struct in_addr));

    sai.sins.sin.sin_family = AF_INET;
  }
#endif

  if (fd < 0)
    {
      /* Re-register a new IO request for the next accept .. */
      comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
                     accept_connection, listener, 0);
      return;
    }
  /*
   * check for connection limit
   */
  if ((MAXCONNECTIONS - 10) < fd)
    {
      ++ServerStats->is_ref;
      /*
       * slow down the whining to opers bit
       */
      if((last_oper_notice + 20) <= CurrentTime)
	{
	  sendto_realops_flags(UMODE_ALL, L_ALL,"All connections in use. (%s)",
			       get_listener_name(listener));
	  last_oper_notice = CurrentTime;
	}

      send(fd, "ERROR :All connections in use\r\n", 32, 0);
      fd_close(fd);
      /* Re-register a new IO request for the next accept .. */
      comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
                     accept_connection, listener, 0);
      return;
    }

  /* Do an initial check we aren't connecting too fast or with too many
   * from this IP... */
  if ((pe = conf_connect_allowed(&addr, sai.sins.sin.sin_family)) != 0)
  {
    ServerStats->is_ref++;

    /* XXX - this can only be BANNED_CLIENT? */
    switch (pe)
    {
      case BANNED_CLIENT:
        send(fd, DLINE_WARNING, sizeof(DLINE_WARNING)-1, 0);
        break;
    }

    fd_close(fd);

    /* Re-register a new IO request for the next accept .. */
    comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
                   accept_connection, listener, 0);
    return;
  }

  ServerStats->is_ac++;

  add_connection(listener, fd);

  /* Re-register a new IO request for the next accept .. */
  comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
    accept_connection, listener, 0);
}
Ejemplo n.º 6
0
static int 
inetport(struct Listener* listener)
{
  struct irc_sockaddr lsin;
  int                fd;
  int                opt = 1;

  /*
   * At first, open a new socket
   */
  fd = comm_open(DEF_FAM, SOCK_STREAM, 0, "Listener socket");

#ifdef IPV6
  if (!IN6_ARE_ADDR_EQUAL((struct in6_addr *)&listener->addr, &in6addr_any))
  {
#else
  if (INADDR_ANY != listener->addr.sins.sin.s_addr)
  {
#endif
    inetntop(DEF_FAM, &IN_ADDR(listener->addr), listener->vhost, HOSTLEN);
    listener->name = listener->vhost;
  }

  if (fd == -1)
  {
    report_error(L_ALL, "opening listener socket %s:%s",
                 get_listener_name(listener), errno);
    return 0;
  }
  else if ((HARD_FDLIMIT - 10) < fd)
  {
    report_error(L_ALL, "no more connections left for listener %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }
  /*
   * XXX - we don't want to do all this crap for a listener
   * set_sock_opts(listener);
   */
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt)))
  {
    report_error(L_ALL, "setting SO_REUSEADDR for listener %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  /*
   * Bind a port to listen for new connections if port is non-null,
   * else assume it is already open and try get something from it.
   */
  memset(&lsin, 0, sizeof(struct irc_sockaddr));
  S_FAM(lsin) = DEF_FAM;
  copy_s_addr(S_ADDR(lsin), IN_ADDR(listener->addr));
  S_PORT(lsin) = htons(listener->port);


  if (bind(fd, (struct sockaddr*) &SOCKADDR(lsin),
      sizeof(struct irc_sockaddr)))
  {
    report_error(L_ALL, "binding listener socket %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  if (listen(fd, HYBRID_SOMAXCONN)) {
    report_error(L_ALL, "listen failed for %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  /*
   * XXX - this should always work, performance will suck if it doesn't
   */
  if (!set_non_blocking(fd))
    report_error(L_ALL, NONB_ERROR_MSG, get_listener_name(listener), errno);

  listener->fd = fd;

  /* Listen completion events are READ events .. */

  accept_connection(fd, listener);
  return 1;
}

static struct Listener* 
find_listener(int port, struct irc_inaddr *addr)
{
  struct Listener* listener = NULL;
  struct Listener* last_closed = NULL;

  for (listener = ListenerPollList; listener; listener = listener->next)
  {

    if ( (port == listener->port) &&
         (!memcmp(&PIN_ADDR(addr),
                 &IN_ADDR(listener->addr),
                 sizeof(struct irc_inaddr))))
    {
      /* Try to return an open listener, otherwise reuse a closed one */
      if (listener->fd == -1)
        last_closed = listener;
      else
        return listener;
    }
  }
  return last_closed;
}


/*
 * add_listener- create a new listener
 * port - the port number to listen on
 * vhost_ip - if non-null must contain a valid IP address string in
 * the format "255.255.255.255"
 */
void 
add_listener(int port, const char* vhost_ip)
{
  struct Listener* listener;
  struct irc_inaddr   vaddr;

  /*
   * if no port in conf line, don't bother
   */
  if (port == 0)
    return;

#ifdef IPV6
  copy_s_addr(IN_ADDR(vaddr), &in6addr_any);
#else
  copy_s_addr(IN_ADDR(vaddr), INADDR_ANY);
#endif

  if (vhost_ip)
  {
    if(inetpton(DEF_FAM, vhost_ip, &IN_ADDR(vaddr)) <= 0)
      return;
  }

  if ((listener = find_listener(port, &vaddr)))
  {
    if (listener->fd > -1)
      return;
  }
  else
  {
    listener = make_listener(port, &vaddr);
    listener->next = ListenerPollList;
    ListenerPollList = listener;
  }

  listener->fd = -1;

  if (inetport(listener))
    listener->active = 1;
  else
    close_listener(listener);
}

/*
 * close_listener - close a single listener
 */
void close_listener(struct Listener* listener)
{
  assert(listener != NULL);
  if(listener == NULL)
    return;
  if (listener->fd >= 0)
  {
    fd_close(listener->fd);
    listener->fd = -1;
  }

  listener->active = 0;

  if (listener->ref_count)
    return;

  free_listener(listener);
}