Exemple #1
0
static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist)
{
	struct sockaddr_in sin;
	int sockfd;
	long flags;

	memset(&sin, 0, sizeof sin);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(listen_port);

	if (listen_addr) {
		/* Well, host better be an IP address here. */
		if (inet_pton(AF_INET, listen_addr, &sin.sin_addr.s_addr) <= 0)
			return 0;
	} else {
		sin.sin_addr.s_addr = htonl(INADDR_ANY);
	}

	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
		return 0;

	if (set_reuse_addr(sockfd)) {
		logerror("Could not set SO_REUSEADDR: %s", strerror(errno));
		close(sockfd);
		return 0;
	}

	set_keep_alive(sockfd);

	if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
		logerror("Could not bind to %s: %s",
			 ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)),
			 strerror(errno));
		close(sockfd);
		return 0;
	}

	if (listen(sockfd, 5) < 0) {
		logerror("Could not listen to %s: %s",
			 ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)),
			 strerror(errno));
		close(sockfd);
		return 0;
	}

	flags = fcntl(sockfd, F_GETFD, 0);
	if (flags >= 0)
		fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);

	ALLOC_GROW(socklist->list, socklist->nr + 1, socklist->alloc);
	socklist->list[socklist->nr++] = sockfd;
	return 1;
}
Exemple #2
0
static int execute(void)
{
	char *line = packet_buffer;
	int pktlen, len, i;
	char *addr = getenv("REMOTE_ADDR"), *port = getenv("REMOTE_PORT");
	struct hostinfo hi;

	hostinfo_init(&hi);

	if (addr)
		loginfo("Connection from %s:%s", addr, port);

	set_keep_alive(0);
	alarm(init_timeout ? init_timeout : timeout);
	pktlen = packet_read(0, NULL, NULL, packet_buffer, sizeof(packet_buffer), 0);
	alarm(0);

	len = strlen(line);
	if (pktlen != len)
		loginfo("Extended attributes (%d bytes) exist <%.*s>",
			(int) pktlen - len,
			(int) pktlen - len, line + len + 1);
	if (len && line[len-1] == '\n') {
		line[--len] = 0;
		pktlen--;
	}

	if (len != pktlen)
		parse_host_arg(&hi, line + len + 1, pktlen - len - 1);

	for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
		struct daemon_service *s = &(daemon_service[i]);
		const char *arg;

		if (skip_prefix(line, "git-", &arg) &&
		    skip_prefix(arg, s->name, &arg) &&
		    *arg++ == ' ') {
			/*
			 * Note: The directory here is probably context sensitive,
			 * and might depend on the actual service being performed.
			 */
			int rc = run_service(arg, s, &hi);
			hostinfo_clear(&hi);
			return rc;
		}
	}

	hostinfo_clear(&hi);
	logerror("Protocol error: '%s'", line);
	return -1;
}
Exemple #3
0
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
    int ret;
    int connfd = 0;

    while ((connfd = g_sys_accept(sockfd, addr, addrlen)) < 0)
    {
        if (EINTR == errno)
            continue;

        if (!fd_not_ready())
            return -1;

        ret = add_fd_event(sockfd, EVENT_READABLE, event_conn_callback, current_coro());
        if (ret)
            return -2;

        schedule_timeout(ACCEPT_TIMEOUT);
        del_fd_event(sockfd, EVENT_READABLE);
        if (is_wakeup_by_timeout())
        {
            errno = ETIME;
            return -3;
        }
    }

    ret = set_nonblock(connfd);
    if (ret)
    {
        close(connfd);
        return -4;
    }

    ret = enable_tcp_no_delay(connfd);
    if (ret)
    {
        close(connfd);
        return -5;
    }

    ret = set_keep_alive(connfd, KEEP_ALIVE);
    if (ret)
    {
        close(connfd);
        return -6;
    }

    return connfd;
}
Exemple #4
0
static int socket_set_options(int lsocket)
{
    struct linger l;
    int linger_timeout = 5;
    int yes = 1, no = 0;

#ifdef SO_REUSEPORT
    CP_SSO(lsocket, SOL_SOCKET, SO_REUSEPORT, yes);
#endif

#ifdef SO_REUSEADDR
    CP_SSO(lsocket, SOL_SOCKET, SO_REUSEADDR, yes);
#endif

    //XXX: use lignering socket ?
#if USE_LINGER
#ifdef SOL_SOCKET
    l.l_onoff = 1;
    l.l_linger = 30;
    CP_SSO(lsocket, SOL_SOCKET, SO_LINGER, l);
#endif
#ifdef TCP_LINGER2
    CP_SSO(lsocket, SOL_SOCKET, TCP_LINGER2, linger_timeout);
#endif
#endif

#if USE_TCP_KEEPALIVE
    set_keep_alive(lsocket, yes);
#endif

#if USE_TCP_NODELAY
    set_tcp_nodelay_option(lsocket, yes);
#endif

#if USE_TCP_NOPUSH
    set_tcp_nopush_option(lsocket, yes);
#endif

#ifdef TCP_QUICKACK
    CP_SSO(lsocket, IPPROTO_TCP, TCP_QUICKACK, yes);
#endif

#ifdef TCP_DEFER_ACCEPT
    CP_SSO(lsocket, IPPROTO_TCP, TCP_DEFER_ACCEPT, no);
#endif

    return CPO_OK;
}
Exemple #5
0
static int
connect_to(struct client* c, int ssh_id){
	if (c->cnt >= TOTAL_CONNECTION) {
		fprintf(stderr, "%s client max connection.....\n", get_time());
		return -1;
	}
	
	const char* ip;
	int port;
	if (ssh_id < 0) {
		if (c->free_connection > 0) return -1;

		struct timeval tv;
		gettimeofday(&tv, NULL);
		if (tv.tv_sec - c->time < FREE_CONNECT_TIME) {
			return -1;
		}else {
			c->time = tv.tv_sec;
		}

		ip = c->remote_ip;
		port = c->remote_port;
	} else {
		ip = "0.0.0.0";
		port = c->ssh_port;
	}

	int id;
	int idx;
	struct client_info* info;
	struct ring_buffer* rb;

	struct addrinfo hints;
	struct addrinfo* res = NULL;
	struct addrinfo* ai_ptr = NULL;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	char portstr[16];
	sprintf(portstr, "%d", port);
	int status = getaddrinfo(ip, portstr, &hints, &res);
	if (status != 0) {
		return -1;
	}

	int sock = -1;
	for (ai_ptr = res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
		sock = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
		if (sock < 0) {
			continue;
		}

		set_keep_alive(sock);
		sp_nonblocking(sock);
		status = connect(sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if (status != 0 && errno != EINPROGRESS) {
			close(sock);
			sock = -1;
			continue;
		}

		break;
	}

	if (sock < 0) {
		goto _failed;
	}

	id = get_id(c);
	assert(id != -1);

	idx = id % TOTAL_CONNECTION;
	info = &c->all_fds[idx];
	info->fd = sock;
	info->id = id;
	info->to_id = ssh_id;
	snprintf(info->client_ip, sizeof(info->client_ip), "%s:%d", ip, port);

	rb = alloc_ring_buffer(MAX_CLIENT_BUFFER);
	info->buffer = rb;

	c->all_ids[c->cnt++] = id;

	if (ssh_id < 0) {
		c->free_connection += 1;
	}

	if (status != 0) {
		//connect no block, need check after
		FD_SET(sock, &c->fd_wset);
		info->connect_type = SOCKET_CONNECTING;
	}else {
		//success
		FD_SET(sock, &c->fd_rset);
		info->connect_type = SOCKET_CONNECTED;

		struct sockaddr* addr = ai_ptr->ai_addr;
		void* sin_addr = (ai_ptr->ai_family == AF_INET) ? (void*)&((struct sockaddr_in*)addr)->sin_addr : (void*)&((struct sockaddr_in6*)addr)->sin6_addr;

		inet_ntop(ai_ptr->ai_family, sin_addr, info->client_ip, sizeof(info->client_ip));
		fprintf(stderr, "%s connected to %s. \n", get_time(), info->client_ip);
	}

	if (c->max_fd < sock + 1) {
		c->max_fd = sock + 1;
	}

	return id;

_failed:
	freeaddrinfo(res);
	return -1;
}
Exemple #6
0
static
struct conn_t *conn_new(struct sockaddr_in *raddr, struct sockaddr_in *laddr) {
    struct conn_t *c;
    int lsize, errnosave;
    struct sockaddr_in tmp;

    c = smalloc(sizeof(*c));
    memset(c, 0, sizeof(*c));
    c->state = CONN_NEW;
    INIT_LIST_HEAD(&c->reqs);

    if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
	errnosave = errno;
	syslog(LOG_ERR, "socket: %s", strerror(errno));
	free(c);
	errno = errnosave;
	return 0;
    }

    /* If this is not the first connection, do a non-blocking connect */
    if (!list_empty(&clist))
	set_non_block(c->fd);

    tmp = *laddr;		/* use a temp here because
				 * bindresvport writes it. */
    if (laddr->sin_port ||
	bindresvport(c->fd, &tmp) == -1) {
	    syslog(LOG_ERR, "bindresvport: %s (ignoring)", strerror(errno));
	    /* If we specified a port or failed to bind to a reserved
	     * port for some reason, try a normal bind. */
	    if (bind(c->fd, (struct sockaddr *) laddr, sizeof(*laddr)) == -1) {
		errnosave = errno;
		syslog(LOG_ERR, "bind(%s:%d): %s (ignoring)",
		       inet_ntoa(laddr->sin_addr), ntohs(laddr->sin_port),
		       strerror(errno));
		close(c->fd);
		free(c);
		errno = errnosave;
		return 0;
	    }
    }

    if (verbose)
	syslog(LOG_INFO, "Connecting to %s:%d...",
	       inet_ntoa(raddr->sin_addr), ntohs(raddr->sin_port));

    if (connect(c->fd, (struct sockaddr *) raddr, sizeof(*raddr)) == -1) {
	if (errno != EINPROGRESS) {
	    errnosave = errno;
	    syslog(LOG_ERR, "connect(%s:%d): %s",
		   inet_ntoa(raddr->sin_addr), ntohs(raddr->sin_port),
		   strerror(errno));
	    close(c->fd);
	    free(c);
	    errno = errnosave;
	    return 0;
	}
    }

    /* Make note of our local address */
    lsize = sizeof(c->laddr);
    getsockname(c->fd, (struct sockaddr *)&c->laddr, &lsize);
    c->raddr = *raddr;

    /* Prime output buffer with version information and cookie */
    conn_send_version(c);

    set_keep_alive(c->fd);
    set_no_delay(c->fd);
    set_non_block(c->fd);

    /* Append to list of connections */
    list_add_tail(&c->list, &clist);
    return c;
}
Exemple #7
0
static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist)
{
	int socknum = 0;
	char pbuf[NI_MAXSERV];
	struct addrinfo hints, *ai0, *ai;
	int gai;
	long flags;

	xsnprintf(pbuf, sizeof(pbuf), "%d", listen_port);
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

	gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
	if (gai) {
		logerror("getaddrinfo() for %s failed: %s", listen_addr, gai_strerror(gai));
		return 0;
	}

	for (ai = ai0; ai; ai = ai->ai_next) {
		int sockfd;

		sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if (sockfd < 0)
			continue;
		if (sockfd >= FD_SETSIZE) {
			logerror("Socket descriptor too large");
			close(sockfd);
			continue;
		}

#ifdef IPV6_V6ONLY
		if (ai->ai_family == AF_INET6) {
			int on = 1;
			setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
				   &on, sizeof(on));
			/* Note: error is not fatal */
		}
#endif

		if (set_reuse_addr(sockfd)) {
			logerror("Could not set SO_REUSEADDR: %s", strerror(errno));
			close(sockfd);
			continue;
		}

		set_keep_alive(sockfd);

		if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
			logerror("Could not bind to %s: %s",
				 ip2str(ai->ai_family, ai->ai_addr, ai->ai_addrlen),
				 strerror(errno));
			close(sockfd);
			continue;	/* not fatal */
		}
		if (listen(sockfd, 5) < 0) {
			logerror("Could not listen to %s: %s",
				 ip2str(ai->ai_family, ai->ai_addr, ai->ai_addrlen),
				 strerror(errno));
			close(sockfd);
			continue;	/* not fatal */
		}

		flags = fcntl(sockfd, F_GETFD, 0);
		if (flags >= 0)
			fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);

		ALLOC_GROW(socklist->list, socklist->nr + 1, socklist->alloc);
		socklist->list[socklist->nr++] = sockfd;
		socknum++;
	}

	freeaddrinfo(ai0);

	return socknum;
}
Exemple #8
0
int
reqs_proc(struct conn_t *conn)
{
    struct vhost_t *vhost;
    struct uhook_t *uhook;
    struct reqs_t *reqs;
    reqs = reqs_new(conn);
    if (!reqs) {
        return 0;
    }

    /* reqs parse */
    if (!reqs_parse(reqs)) {
        conn->keep_alive = 0;
        reqs_throw_status(reqs, 400, ""); /* "400 Bad Request" */
        chtd_log(reqs->htdx, "reqs_parse() failed!");
        reqs->htdx->nBadReqs++;
        reqs_del(reqs);
        return 1;
    }

    reqs->wker->nReqs++;

    set_keep_alive(reqs, 1);

    /* match uhook */
    uhook = chtd_uhook_match(reqs);
    if (uhook) {
        if (uhook->func(reqs)) {
            if (reqs->rp_header_sent == 0) {
                reqs_throw_status(reqs, 400, ""); /* "400 Bad Request" */
            }
            if (reqs->post_read_flag == 0) {
                reqs_skip_post(reqs);
            }
            reqs_del(reqs);
            return 1;
        }
    }

    /* match vhost */
    vhost = chtd_vhost_match(reqs);
    if (vhost) {
        if (vhost_proc(reqs, vhost)) {
            if (reqs->post_read_flag == 0) {
                reqs_skip_post(reqs);
            }
            reqs_del(reqs);
            return 1;
        }
    }

    /* Bad Request */
    set_keep_alive(reqs, 0);
    reqs_throw_status(reqs, 400, ""); /* "400 Bad Request" */
    chtd_log(reqs->htdx, "Got a bad request.");
    pthread_mutex_lock(&reqs->htdx->mutex);
    reqs->htdx->nBadReqs++;
    pthread_mutex_unlock(&reqs->htdx->mutex);

    reqs_del(reqs);
    return 1;
}