Exemple #1
0
static isc_result_t
configure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd,
		   isc_mem_t *mctx, ns_lwreslistenerlist_t *newlisteners)
{
	ns_lwreslistener_t *listener, *oldlistener = NULL;
	char socktext[ISC_SOCKADDR_FORMATSIZE];
	isc_result_t result;

	(void)find_listener(address, &oldlistener);
	listener = NULL;
	result = listener_create(mctx, lwresd, &listener);
	if (result != ISC_R_SUCCESS) {
		isc_sockaddr_format(address, socktext, sizeof(socktext));
		isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
			      "lwres failed to configure %s: %s",
			      socktext, isc_result_totext(result));
		return (result);
	}

	/*
	 * If there's already a listener, don't rebind the socket.
	 */
	if (oldlistener == NULL) {
		result = listener_bind(listener, address);
		if (result != ISC_R_SUCCESS) {
			ns_lwreslistener_detach(&listener);
			return (ISC_R_SUCCESS);
		}
	} else
		listener_copysock(oldlistener, listener);

	result = listener_startclients(listener);
	if (result != ISC_R_SUCCESS) {
		isc_sockaddr_format(address, socktext, sizeof(socktext));
		isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
			      "lwres: failed to start %s: %s", socktext,
			      isc_result_totext(result));
		ns_lwreslistener_detach(&listener);
		return (ISC_R_SUCCESS);
	}

	if (oldlistener != NULL) {
		/*
		 * Remove the old listener from the old list and shut it down.
		 */
		ISC_LIST_UNLINK(listeners, oldlistener, link);
		listener_shutdown(oldlistener);
		ns_lwreslistener_detach(&oldlistener);
	} else {
		isc_sockaddr_format(address, socktext, sizeof(socktext));
		isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
			      "lwres listening on %s", socktext);
	}

	ISC_LIST_APPEND(*newlisteners, listener, link);
	return (result);
}
Exemple #2
0
/*
 * 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, int family, int ssl)
{
	struct Listener *listener;
	struct rb_sockaddr_storage vaddr;

	/*
	 * if no port in conf line, don't bother
	 */
	if(port == 0)
		return;
	memset(&vaddr, 0, sizeof(vaddr));
	vaddr.ss_family = family;

	if(vhost_ip != NULL)
	{
		if(family == AF_INET)
		{
			if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in *)&vaddr)->sin_addr) <= 0)
				return;
		} 
#ifdef RB_IPV6
		else
		{
			if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in6 *)&vaddr)->sin6_addr) <= 0)
				return;
		
		}
#endif
	} else
	{
		switch(family)
		{
			case AF_INET:
				((struct sockaddr_in *)&vaddr)->sin_addr.s_addr = INADDR_ANY;
				break;
#ifdef RB_IPV6
			case AF_INET6:
				memcpy(&((struct sockaddr_in6 *)&vaddr)->sin6_addr, &in6addr_any, sizeof(struct in6_addr));
				break;
			default:
				return;
#endif
		} 
	}
	switch(family)
	{
		case AF_INET:
			SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in));
			((struct sockaddr_in *)&vaddr)->sin_port = htons(port);
			break;
#ifdef RB_IPV6
		case AF_INET6:
			SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in6));
			((struct sockaddr_in6 *)&vaddr)->sin6_port = htons(port);
			break;
#endif
		default:
			break;
	}
	if((listener = find_listener(&vaddr)))
	{
		if(listener->F != NULL)
			return;
	}
	else
	{
		listener = make_listener(&vaddr);
		listener->next = ListenerPollList;
		ListenerPollList = listener;
	}

	listener->F = NULL;
	listener->ssl = ssl;

	if(inetport(listener))
		listener->active = 1;
	else
		close_listener(listener);
}
Exemple #3
0
static int
answer_to_connection(void *cls, struct MHD_Connection *connection,
    const char *url, const char *method,
    const char *version, const char *upload_data,
    size_t * upload_data_size, void **con_cls)
{
	struct agent_core_t *core = (struct agent_core_t *)cls;
	struct http_priv_t *http;
	struct http_request request;
	struct connection_info_struct *con_info;

	(void)version;

	GET_PRIV(core, http);

	if (*con_cls == NULL) {
		ALLOC_OBJ(con_info);
		*con_cls = con_info;
		return (MHD_YES);
	}
	con_info = *con_cls;
	assert(core->config->userpass);

	log_request(connection, http, method, url);

	if (!strcmp(method, "OPTIONS")) {
		/* We need this for preflight requests (CORS). */
		return (http_reply(connection, 200, NULL));
	} else if (!strcmp(method, "GET") || !strcmp(method, "HEAD") ||
	    !strcmp(method, "DELETE")) {
		if (check_auth(connection, core, con_info))
			return (MHD_YES);
		if (!strcmp(method, "DELETE"))
			request.method = M_DELETE;
		else
			request.method = M_GET;
		request.connection = connection;
		request.url = url;
		request.ndata = 0;
		if (find_listener(&request, http))
			return (MHD_YES);
	} else if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {
		if (*upload_data_size != 0) {
			if (*upload_data_size + con_info->progress >=
			    RCV_BUFFER) {
				warnlog(http->logger,
				    "Client input exceeded buffer size "
				    "of %u bytes. Dropping client.",
				    RCV_BUFFER);
				return (MHD_NO);
			}
			memcpy(con_info->answerstring + con_info->progress,
			    upload_data, *upload_data_size);
			con_info->progress += *upload_data_size;
			*upload_data_size = 0;
			return (MHD_YES);
		} else if ((char *)con_info->answerstring != NULL) {
			if (check_auth(connection, core, con_info))
				return (MHD_YES);
			if (!strcmp(method, "POST"))
				request.method = M_POST;
			else
				request.method = M_PUT;
			request.connection = connection;
			request.url = url;
			request.ndata = con_info->progress;
			request.data = con_info->answerstring;
			/*
			 * FIXME
			 */
			((char *)request.data)[con_info->progress] = '\0';
			if (find_listener(&request, http))
				return (MHD_YES);
		}
	}
	if (request.method == M_GET && !strcmp(url, "/")) {
		if (http->help_page == NULL)
			http->help_page = make_help(http);
		assert(http->help_page);
		return (http_reply(connection, 200, http->help_page));
	}

	return (http_reply(connection, 500, "Failed"));
}
Exemple #4
0
static int answer_to_connection (void *cls, struct MHD_Connection *connection,
                      const char *url, const char *method,
                      const char *version, const char *upload_data,
                      size_t *upload_data_size, void **con_cls)
{
	struct agent_core_t *core = (struct agent_core_t *)cls;
	struct http_priv_t *http;
	struct agent_plugin_t *plug;
	struct http_request request;
	struct connection_info_struct *con_info = NULL;
	int ret;

	(void)version;
	plug = plugin_find(core,"http");
	http = (struct http_priv_t *) plug->data;
	assert(plug);
	assert(http);


	if (NULL == *con_cls) {
		con_info = malloc (sizeof (struct connection_info_struct));
		assert(con_info);
		con_info->answerstring[0] = '\0';
		con_info->progress = 0;
		con_info->authed = 0;
		*con_cls = con_info;
		return MHD_YES;
	}
	con_info = *con_cls;
	assert(core->config->userpass);

	log_request(connection, http, method, url);

	if (0 == strcmp (method, "GET") || !strcmp(method, "HEAD") || !strcmp(method,"DELETE")) {
		ret = check_auth(connection, core, con_info);
		if (ret == 1)
			return MHD_YES;
		if (!strcmp(method,"DELETE")) {
			request.method = M_DELETE;
		} else {
			request.method = M_GET;
		}
		request.connection = connection;
		request.url = url;
		request.ndata = 0;
		if (find_listener(&request, http))
			return MHD_YES;
	}


	if (!strcmp(method, "POST") || !strcmp(method, "PUT")) {

		if (*upload_data_size != 0) {
			if (*upload_data_size + con_info->progress >= RCV_BUFFER) {
				warnlog(http->logger, "Client input exceeded buffer size of %u bytes. Dropping client.", RCV_BUFFER);

				 return MHD_NO;
			}
			memcpy(con_info->answerstring + con_info->progress,
				upload_data, *upload_data_size);
			con_info->progress += *upload_data_size;
			*upload_data_size = 0;

			return MHD_YES;
		} else if (NULL != con_info->answerstring){
			ret = check_auth(connection, core, con_info);
			if (ret == 1)
				return MHD_YES;
			if (!strcmp(method,"POST")) {
				request.method = M_POST;
			} else {
				request.method = M_PUT;
			}
			request.connection = connection;
			request.url = url;
			request.ndata = con_info->progress;
			request.data = con_info->answerstring;
			/*
			 * FIXME
			 */
			((char *)request.data)[con_info->progress] = '\0';
			if (find_listener(&request, http))
				return MHD_YES;
		}
	}
	if (request.method == M_GET && !strcmp(url, "/")) {
		if (http->help_page == NULL)
			http->help_page = make_help(http);
		assert (http->help_page);
		return send_response_ok(connection, http->help_page);
	}


	return send_response_fail (connection, "Failed\n");
}
Exemple #5
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);
}
Exemple #6
0
/*
 * 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"
 * options - listener options
 * cp - listener default code page
 */
void add_listener(int port, const char* vhost_ip, char* options, char* cp)
{
  struct Listener* listener;
  struct IN_ADDR   vaddr;

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

#ifdef IPV6
  vaddr = INADDRANY;
#else
   vaddr.s_addr = INADDRANY;
#endif

  if (vhost_ip) {
#ifdef IPV6
     if(inetpton(AFINET, vhost_ip, &vaddr) == 0)
       return;
#else
      vaddr.s_addr = inet_addr(vhost_ip);
      if (INADDR_NONE == vaddr.s_addr)
        return;
#endif
  }

  if ((listener = find_listener(port, vaddr))) {
    listener->active = 1;
    return;
  }
  
  if(options && *options)
    irclog(L_NOTICE,"Adding listener for %s, port %d Options:%s",
  	vhost_ip ? vhost_ip : "ANY", port, options );
  else
    irclog(L_NOTICE,"Adding listener for %s, port %d",
  	vhost_ip ? vhost_ip : "ANY", port);
  	
  listener = make_listener(port, vaddr);
  if(options)
  {
    while(*options)
      {
        switch(*options)
          {
            case 's' : 
#ifdef HAVE_SSL            
            if(no_ssl)
              irclog(L_WARN,"ignoring port with 's' option!");
            else
              listener->options |= LST_SSL; 
#else
              irclog(L_WARN,"ircd compiled without SSL support, ignoring port with 's' option!");
#endif              
              break;
            case 'S' : listener->options |= LST_SERVER; break;
            case 'W' : listener->options |= LST_WEBCHAT; break;
            case 'J' : listener->options |= LST_JAVACR; break;
            case 'n' : listener->options |= LST_NOSPOOF; break;
          }
        ++options;          
      }
  }
  
  if(cp && cp[0])
    {
       listener->codepage = codepage_find(cp); 
       if(listener->codepage==-1)
         irclog(L_WARN,"Codepage %s defined on P:line was not loaded!", cp);
    }
  else
     listener->codepage=-1;
     
  if (inetport(listener)) {
    listener->active = 1;
    listener->next   = ListenerPollList;
    ListenerPollList = listener; 
  }
  else
    free_listener(listener);
}