Example #1
0
/*
 * This is the new connection handler. This function is called by the
 * event handler when data is pending on the listening socket (conn_fd).
 * If space is available, an interactive data structure is initialized and
 * the connected is established.
 */
void new_conn_handler()
{

#ifdef IPV6
	struct sockaddr_in6 client;
#else
    struct sockaddr_in client;
#endif
    socklen_t client_len;
    struct hostent *c_hostent;
    int new_fd;
    int conn_index;

    client_len = sizeof(client);
    new_fd = accept(conn_fd, (struct sockaddr *) & client, &client_len);
    if (new_fd == -1) {
	socket_perror("new_conn_handler: accept", 0);
	return;
    }
    if (set_socket_nonblocking(new_fd, 1) == -1) {
	socket_perror("new_conn_handler: set_socket_nonblocking 1", 0);
	OS_socket_close(new_fd);
	return;
    }
    if (total_conns >= MAX_CONNS) {
	char *message = "no available slots -- closing connection.\n";

	fprintf(stderr, "new_conn_handler: no available connection slots.\n");
	OS_socket_write(new_fd, message, strlen(message));
	if (OS_socket_close(new_fd) == -1)
	    socket_perror("new_conn_handler: close", 0);
	return;
    }
    /* get some information about new connection */
    for (conn_index = 0; conn_index < MAX_CONNS; conn_index++) {
	if (all_conns[conn_index].state == CONN_CLOSED) {
	    DBG(("new_conn_handler: opening conn index %d", conn_index));
	    /* update global data for new fd */
	    all_conns[conn_index].fd = new_fd;
	    all_conns[conn_index].state = CONN_OPEN;
	    all_conns[conn_index].addr = client;

	    char portname[256];
	    if(getnameinfo(&client, sizeof(client), all_conns[conn_index].sname, SNAME_LEN, portname, 255, NI_NAMEREQD|NI_NUMERICHOST))
	    	strcpy(all_conns[conn_index].sname, "<unknown>");
	    total_conns++;
	    return;
	}
    }
    fprintf(stderr, "new_conn_handler: sanity check failed!\n");
}
Example #2
0
/*
 * This is the new connection handler. This function is called by the
 * event handler when data is pending on the listening socket (conn_fd).
 * If space is available, an interactive data structure is initialized and
 * the connected is established.
 */
void new_conn_handler()
{
    struct sockaddr_in client;
    int client_len;
    struct hostent *c_hostent;
    int new_fd;
    int conn_index;

    client_len = sizeof(client);
    new_fd = accept(conn_fd, (struct sockaddr *) & client, (int *) &client_len);
    if (new_fd == -1) {
	socket_perror("new_conn_handler: accept", 0);
	return;
    }
    if (set_socket_nonblocking(new_fd, 1) == -1) {
	socket_perror("new_conn_handler: set_socket_nonblocking 1", 0);
	OS_socket_close(new_fd);
	return;
    }
    if (total_conns >= MAX_CONNS) {
	char *message = "no available slots -- closing connection.\n";

	fprintf(stderr, "new_conn_handler: no available connection slots.\n");
	OS_socket_write(new_fd, message, strlen(message));
	if (OS_socket_close(new_fd) == -1)
	    socket_perror("new_conn_handler: close", 0);
	return;
    }
    /* get some information about new connection */
    c_hostent = gethostbyaddr((char *) &client.sin_addr.s_addr,
			      sizeof(client.sin_addr.s_addr), AF_INET);
    for (conn_index = 0; conn_index < MAX_CONNS; conn_index++) {
	if (all_conns[conn_index].state == CONN_CLOSED) {
	    DBG(("new_conn_handler: opening conn index %d", conn_index));
	    /* update global data for new fd */
	    all_conns[conn_index].fd = new_fd;
	    all_conns[conn_index].state = CONN_OPEN;
	    all_conns[conn_index].addr = client;
	    if (c_hostent)
		strcpy(all_conns[conn_index].sname, c_hostent->h_name);
	    else
		strcpy(all_conns[conn_index].sname, "<unknown>");
	    total_conns++;
	    return;
	}
    }
    fprintf(stderr, "new_conn_handler: sanity check failed!\n");
}
Example #3
0
int main (void) {
    socket_t *sock;
    ssize_t bytes;
    struct sockaddr_in address;


    if(NULL == (sock = socket_new(AF_INET, SOCK_STREAM, IPPROTO_IP)) ) {
        socket_perror();
        exit(1);
    }

    address.sin_family = AF_INET;
    address.sin_port = htons(8585);

    inet_aton("127.0.0.1", &address.sin_addr);

    if(!socket_connect(sock,
                       (struct sockaddr*)&address, (socklen_t)sizeof(address)) ) {
        socket_perror();
        exit(1);
    }

    if(!socket_isconnected(sock)) {
        socket_perror();
        puts("not connected!");
    }

    if(!socket_send(sock,"this is a test 1", 17, MSG_NOFLAGS, &bytes) ) {
        socket_perror();
        exit(1);
    }

    if(!socket_close(sock) ) {
        socket_perror();
        exit(1);
    }

    return 0;
}
Example #4
0
static int socket_write(struct imap_socket *sock, const char *buf, int len)
{
	int n;
#ifndef NO_OPENSSL
	if (sock->ssl)
		n = SSL_write(sock->ssl, buf, len);
	else
#endif
		n = write_in_full(sock->fd[1], buf, len);
	if (n != len) {
		socket_perror("write", sock, n);
		close(sock->fd[0]);
		close(sock->fd[1]);
		sock->fd[0] = sock->fd[1] = -1;
	}
	return n;
}
Example #5
0
static int socket_read(struct imap_socket *sock, char *buf, int len)
{
	ssize_t n;
#ifndef NO_OPENSSL
	if (sock->ssl)
		n = SSL_read(sock->ssl, buf, len);
	else
#endif
		n = xread(sock->fd[0], buf, len);
	if (n <= 0) {
		socket_perror("read", sock, n);
		close(sock->fd[0]);
		close(sock->fd[1]);
		sock->fd[0] = sock->fd[1] = -1;
	}
	return n;
}
Example #6
0
void terminate (int conn_index)
{
    if (conn_index < 0 || conn_index >= MAX_CONNS) {
	fprintf(stderr, "terminate: conn_index %d out of range.\n", conn_index);
	return;
    }
    if (all_conns[conn_index].state == CONN_CLOSED) {
	fprintf(stderr, "terminate: connection %d already closed.\n", conn_index);
	return;
    }
    DBG(("terminating connection %d", conn_index));

    if (OS_socket_close(all_conns[conn_index].fd) == -1) {
	socket_perror("terminate: close", 0);
	return;
    }
    all_conns[conn_index].state = CONN_CLOSED;
    total_conns--;
}
Example #7
0
/*
 * Initialize connection socket.
 */
void init_conn_sock (int port_num, char * ipaddress)
{
#ifdef IPV6
	struct sockaddr_in6 sin;
#else
    struct sockaddr_in sin;
#endif
    socklen_t sin_len;
    int optval;
#ifdef WINSOCK
    WSADATA WSAData;

    WSAStartup(MAKEWORD(1,1), &WSAData);
    atexit(cleanup_sockets);
#endif

    /*
     * create socket of proper type.
     */
#ifdef IPV6
    if ((conn_fd = socket(AF_INET6, SOCK_STREAM, 0)) == INVALID_SOCKET) {
#else
    if ((conn_fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
#endif
	socket_perror("init_conn_sock: socket", 0);
	exit(1);
    }
    /*
     * enable local address reuse.
     */
    optval = 1;
    if (setsockopt(conn_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval,
		   sizeof(optval)) == -1) {
	socket_perror("init_conn_sock: setsockopt", 0);
	exit(2);
    }
    /*
     * fill in socket address information.
     */
#ifdef IPV6
    sin.sin6_family = AF_INET6;
    if(ipaddress)
       	inet_pton(AF_INET6, ipaddress, &(sin.sin6_addr));
    else
       	sin.sin6_addr = in6addr_any;
    sin.sin6_port = htons((u_short) port_num);
#else
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = (ipaddress ? inet_addr(ipaddress) : INADDR_ANY);
    sin.sin_port = htons((u_short) port_num);
#endif
    /*
     * bind name to socket.
     */
    if (bind(conn_fd, (struct sockaddr *) & sin, sizeof(sin)) == -1) {
	socket_perror("init_conn_sock: bind", 0);
	exit(3);
    }
    /*
     * get socket name.
     */
    sin_len = sizeof(sin);
    if (getsockname(conn_fd, (struct sockaddr *) & sin, &sin_len) == -1) {
	socket_perror("init_conn_sock: getsockname", 0);
	exit(4);
    }
    /*
     * register signal handler for SIGPIPE.
     */
#if defined(SIGPIPE) && defined(SIGNAL_ERROR)/* windows has no SIGPIPE */
    if (signal(SIGPIPE, sigpipe_handler) == SIGNAL_ERROR) {
	socket_perror("init_conn_sock: signal SIGPIPE", 0);
	exit(5);
    }
#endif
    /*
     * set socket non-blocking
     */
    if (set_socket_nonblocking(conn_fd, 1) == -1) {
	socket_perror("init_conn_sock: set_socket_nonblocking 1", 0);
	exit(8);
    }
    /*
     * listen on socket for connections.
     */
    if (listen(conn_fd, 128) == -1) {
	socket_perror("init_conn_sock: listen", 0);
	exit(10);
    }
    DBG(("listening for connections on port %d", port_num));
}

/*
 * SIGPIPE handler -- does very little for now.
 */
#ifdef SIGNAL_FUNC_TAKES_INT
void sigpipe_handler (int sig)
{
#else
void sigpipe_handler()
{
#endif
    fprintf(stderr, "SIGPIPE received.\n");
}
Example #8
0
void conn_data_handler (int fd)
{
    int conn_index;
    int buf_index;
    int num_bytes;
    int msgtype;
    int leftover;
    char *buf;
    int res, msglen, expecting;
    long unread_bytes;

    if ((conn_index = index_by_fd(fd)) == -1) {
	fprintf(stderr, "conn_data_handler: invalid fd.\n");
	return;
    }
    DBG(("conn_data_handler: read on fd %d", fd));

    /* append new data to end of leftover data (if any) */
    leftover = all_conns[conn_index].leftover;
    buf = (char *) &all_conns[conn_index].buf[0];
    num_bytes = OS_socket_read(fd, buf + leftover, (IN_BUF_SIZE - 1) - leftover);

    switch (num_bytes) {
    case -1:
	switch (socket_errno) {
	case EWOULDBLOCK:
	    DBG(("conn_data_handler: read on fd %d: Operation would block.",
			fd));
	    break;
	default:
	    socket_perror("conn_data_handler: read", 0);
	    terminate(conn_index);
	    break;
	}
	break;
    case 0:
	if (all_conns[conn_index].state == CONN_CLOSED)
	    fprintf(stderr, "get_user_data: tried to read from closed fd.\n");
	terminate(conn_index);
	break;
    default:
	DBG(("conn_data_handler: read %d bytes on fd %d", num_bytes, fd));
	num_bytes += leftover;
	buf_index = 0;
	expecting = 0;
	while (num_bytes > sizeof(int) && buf_index < (IN_BUF_SIZE - 1)) {
	    /* get message type */
	    memcpy((char *) &msgtype, (char *) &buf[buf_index], sizeof(int));
	    DBG(("conn_data_handler: message type: %d", msgtype));

	    if (msgtype == NAMEBYIP) {
		if (buf[buf_index + sizeof(int)] == '\0') {
		    /* no data here...resync */
		    buf_index++;
		    num_bytes--;
		    continue;
		}
		if (expecting && num_bytes < expecting) {
		    /*
		     * message truncated...back up to DATALEN message; exit
		     * loop...and try again later
		     */
		    buf_index -= (sizeof(int) + sizeof(int));
		    num_bytes += (sizeof(int) + sizeof(int));
		    break;
		}
		res = name_by_ip(conn_index, &buf[buf_index]);
	    } else if (msgtype == IPBYNAME) {
		if (buf[buf_index + sizeof(int)] == '\0') {
		    /* no data here...resync */
		    buf_index++;
		    num_bytes--;
		    continue;
		}
		if (expecting && num_bytes < expecting) {
		    /*
		     * message truncated...back up to DATALEN message; exit
		     * loop...and try again later
		     */
		    buf_index -= (sizeof(int) + sizeof(int));
		    num_bytes += (sizeof(int) + sizeof(int));
		    break;
		}
		res = ip_by_name(conn_index, &buf[buf_index]);
	    } else if (msgtype == DATALEN) {
		if (num_bytes > (sizeof(int) + sizeof(int))) {
		    memcpy((char *) &expecting, (char *) &buf[buf_index + sizeof(int)], sizeof(int));
		    /*
		     * advance to next message
		     */
		    buf_index += (sizeof(int) + sizeof(int));
		    num_bytes -= (sizeof(int) + sizeof(int));
		    if (expecting > IN_BUF_SIZE || expecting <= 0) {
			fprintf(stderr, "conn_data_handler: bad data length %d\n", expecting);
			expecting = 0;
		    }
		    continue;
		} else {
		    /*
		     * not enough bytes...assume truncated; exit loop...we'll
		     * handle this message later
		     */
		    break;
		}
	    } else {
		fprintf(stderr, "conn_data_handler: unknown message type %08x\n", msgtype);
		/* advance through buffer */
		buf_index++;
		num_bytes--;
		continue;
	    }

	    msglen = (int) (sizeof(int) + strlen(&buf[buf_index + sizeof(int)]) +1);
	    if (res) {
		/*
		 * ok...advance to next message
		 */
		buf_index += msglen;
		num_bytes -= msglen;
	    } else if (msglen < num_bytes || (expecting && expecting == msglen)) {
		/*
		 * failed...
		 */

		/*
		 * this was a complete message...advance to the next one
		 */
		msglen = (int) (sizeof(int) + strlen(&buf[buf_index + sizeof(int)]) +1);
		buf_index += msglen;
		num_bytes -= msglen;
		expecting = 0;
	    }
	    else if (!OS_socket_ioctl(fd, FIONREAD, &unread_bytes) &&
		     unread_bytes > 0) {
		/*
		 * msglen == num_bytes could be a complete message... if
		 * there's unread data we'll assume it was truncated
		 */
		break;
	    } else {
		/*
		 * nothing more?  then discard message (it was the last one)
		 */
		buf_index = 0;
		num_bytes = 0;
		break;
	    }
	}

	/* keep track of leftover buffer contents */
	if (num_bytes && buf_index)
	    memmove(buf, &buf[buf_index], num_bytes);
	buf[num_bytes] = '\0';
	all_conns[conn_index].leftover = num_bytes;

	break;
    }
}
Example #9
0
/*
 * Create an LPC efun socket
 */
int socket_create (enum socket_mode mode, svalue_t * read_callback, svalue_t * close_callback)
{
    int type, i, fd, optval;
#ifndef NO_BUFFER_TYPE
    int binary = 0;

    if (mode == STREAM_BINARY) {
        binary = 1;
        mode = STREAM;
    } else if (mode == DATAGRAM_BINARY) {
        binary = 1;
        mode = DATAGRAM;
    }
#endif
    switch (mode) {

        case MUD:
        case STREAM:
            type = SOCK_STREAM;
            break;
        case DATAGRAM:
            type = SOCK_DGRAM;
            break;

        default:
            return EEMODENOTSUPP;
    }

    i = find_new_socket();
    if (i >= 0) {
#ifdef IPV6
        fd = socket(PF_INET6, type, 0);
#else
        fd = socket(PF_INET, type, 0);
#endif
        if (fd == INVALID_SOCKET) {
            socket_perror("socket_create: socket", 0);
            return EESOCKET;
        }
        optval = 1;
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval,
                    sizeof(optval)) == -1) {
            socket_perror("socket_create: setsockopt", 0);
            OS_socket_close(fd);
            return EESETSOCKOPT;
        }
        if (set_socket_nonblocking(fd, 1) == -1) {
            socket_perror("socket_create: set_socket_nonblocking", 0);
            OS_socket_close(fd);
            return EENONBLOCK;
        }
        lpc_socks[i].fd = fd;
        lpc_socks[i].flags = S_HEADER;

        if (type == SOCK_DGRAM) close_callback = 0;
        set_read_callback(i, read_callback);
        set_write_callback(i, 0);
        set_close_callback(i, close_callback);

#ifndef NO_BUFFER_TYPE
        if (binary) {
            lpc_socks[i].flags |= S_BINARY;
        }
#endif
        lpc_socks[i].mode = mode;
        lpc_socks[i].state = STATE_UNBOUND;
        memset((char *) &lpc_socks[i].l_addr, 0, sizeof(lpc_socks[i].l_addr));
        memset((char *) &lpc_socks[i].r_addr, 0, sizeof(lpc_socks[i].r_addr));
        lpc_socks[i].owner_ob = current_object;
        lpc_socks[i].release_ob = NULL;
        lpc_socks[i].r_buf = NULL;
        lpc_socks[i].r_off = 0;
        lpc_socks[i].r_len = 0;
        lpc_socks[i].w_buf = NULL;
        lpc_socks[i].w_off = 0;
        lpc_socks[i].w_len = 0;

        current_object->flags |= O_EFUN_SOCKET;

        debug(sockets, ("socket_create: created socket %d mode %d fd %d\n",
                    i, mode, fd));
    }

    return i;
}
Example #10
0
static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
	const SSL_METHOD *meth;
#else
	SSL_METHOD *meth;
#endif
	SSL_CTX *ctx;
	int ret;
	X509 *cert;

	SSL_library_init();
	SSL_load_error_strings();

	meth = SSLv23_method();
	if (!meth) {
		ssl_socket_perror("SSLv23_method");
		return -1;
	}

	ctx = SSL_CTX_new(meth);
	if (!ctx) {
		ssl_socket_perror("SSL_CTX_new");
		return -1;
	}

	if (use_tls_only)
		SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

	if (verify)
		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

	if (!SSL_CTX_set_default_verify_paths(ctx)) {
		ssl_socket_perror("SSL_CTX_set_default_verify_paths");
		return -1;
	}
	sock->ssl = SSL_new(ctx);
	if (!sock->ssl) {
		ssl_socket_perror("SSL_new");
		return -1;
	}
	if (!SSL_set_rfd(sock->ssl, sock->fd[0])) {
		ssl_socket_perror("SSL_set_rfd");
		return -1;
	}
	if (!SSL_set_wfd(sock->ssl, sock->fd[1])) {
		ssl_socket_perror("SSL_set_wfd");
		return -1;
	}

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
	/*
	 * SNI (RFC4366)
	 * OpenSSL does not document this function, but the implementation
	 * returns 1 on success, 0 on failure after calling SSLerr().
	 */
	ret = SSL_set_tlsext_host_name(sock->ssl, server.host);
	if (ret != 1)
		warning("SSL_set_tlsext_host_name(%s) failed.", server.host);
#endif

	ret = SSL_connect(sock->ssl);
	if (ret <= 0) {
		socket_perror("SSL_connect", sock, ret);
		return -1;
	}

	if (verify) {
		/* make sure the hostname matches that of the certificate */
		cert = SSL_get_peer_certificate(sock->ssl);
		if (!cert)
			return error("unable to get peer certificate.");
		if (verify_hostname(cert, server.host) < 0)
			return -1;
	}

	return 0;
}