Exemple #1
0
/*
 * Handles a message received from the UDP tunnel. Returns 0 if successful, -1
 * on some error it handled, or -2 if the client is to disconnect.
 */
int handle_message(client_t *c, uint16_t id, uint8_t msg_type,
                   char *data, int data_len)
{
    int ret = 0;
    char addrstr[ADDRSTRLEN];
    
    switch(msg_type)
    {
        case MSG_TYPE_GOODBYE:
            ret = -2;
            break;
            
        case MSG_TYPE_HELLOACK:
            client_got_helloack(c);
            CLIENT_ID(c) = id;
            ret = client_send_helloack(c, ntohs(*((uint16_t *)data)));

            if(debug_level >= DEBUG_LEVEL1)
            {
                sock_get_str(c->tcp_sock, addrstr, sizeof(addrstr));
                printf("New connection(%d): tcp://%s", CLIENT_ID(c), addrstr);
                sock_get_str(c->udp_sock, addrstr, sizeof(addrstr));
                printf(" -> udp://%s\n", addrstr);
            }
            break;
            
        case MSG_TYPE_DATA0:
        case MSG_TYPE_DATA1:
            ret = client_got_udp_data(c, data, data_len, msg_type);
            if(ret == 0)
                ret = client_send_tcp_data(c);
            break;
            
        case MSG_TYPE_ACK0:
        case MSG_TYPE_ACK1:
            ret = client_got_ack(c, msg_type);
            break;
            
        default:
            ret = -1;
            break;
    }

    return ret;
}
Exemple #2
0
/*
 * Handles the message received from the UDP tunnel. Returns 0 for success, -1
 * for some error that it handled, and -2 if the connection should be
 * disconnected.
 */
int handle_message(uint16_t id, uint8_t msg_type, char *data, int data_len,
                   socket_t *from, list_t *clients, fd_set *client_fds,
                   list_t *allowed_destinations, char *port_str)
{
    client_t *c = NULL;
    client_t *c2 = NULL;
    socket_t *tcp_sock = NULL;
    int ret = 0;
    
    if(id != 0)
    {
        c = list_get(clients, &id);
        if(!c)
            return -1;
    }

    if(id == 0 && msg_type != MSG_TYPE_HELLO)
        return -2;
    
    switch(msg_type)
    {
        case MSG_TYPE_GOODBYE:
            ret = -2;
            break;
            
        /* Data in the hello message will be like "hostname port", possibly
           without the null terminator. This will look for the space and
           parse out the hostname or ip address and port number */
        case MSG_TYPE_HELLO:
        {
            int i;
            char port[6]; /* need this so port str can have null term. */
            char addrstr[ADDRSTRLEN];
            uint16_t req_id;
            
            if(id != 0)
                break;

            req_id = ntohs(*((uint16_t*)data));
            data += sizeof(uint16_t);
            data_len -= sizeof(uint16_t);
            
            /* look for the space separating the host and port */
            for(i = 0; i < data_len; i++)
                if(data[i] == ' ')
                    break;
            if(i == data_len)
                break;

            /* null terminate the host and get the port number to the string */
            data[i++] = 0;
            strncpy(port, data+i, data_len-i);
            port[data_len-i] = 0;

            if (!destination_allowed(allowed_destinations, data, port))
            {
                if (debug_level >= DEBUG_LEVEL1)
                    printf("Connection to %s:%s denied\n", data, port);
                msg_send_msg(from, next_client_id, MSG_TYPE_GOODBYE, NULL, 0);
                return -2;
            }
            
            /* Create an unconnected TCP socket for the remote host, the
               client itself, add it to the list of clients */
            tcp_sock = sock_create(data, port, ipver, SOCK_TYPE_TCP, 0, 0);
            ERROR_GOTO(tcp_sock == NULL, "Error creating tcp socket", error);

            c = client_create(next_client_id++, tcp_sock, from, 0);
            sock_free(tcp_sock);
            ERROR_GOTO(c == NULL, "Error creating client", error);

            c2 = list_add(clients, c);
            ERROR_GOTO(c2 == NULL, "Error adding client to list", error);

            if(debug_level >= DEBUG_LEVEL1)
            {
                sock_get_str(c2->udp_sock, addrstr, sizeof(addrstr));
                printf("New connection(%d): udp://%s", CLIENT_ID(c2), addrstr);
                sock_get_str(c2->tcp_sock, addrstr, sizeof(addrstr));
                printf(" -> tcp://%s\n", addrstr);
            }
            
            /* Send the Hello ACK message if created client successfully */
            client_send_helloack(c2, req_id);
            client_reset_keepalive(c2);
            client_free(c);
            
            break;
        }

        /* Can connect to TCP connection once received the Hello ACK */
        case MSG_TYPE_HELLOACK:
            client_got_helloack(c);
            client_connect_tcp(c, port_str);
            client_add_tcp_fd_to_set(c, client_fds);
            break;

        /* Resets the timeout of the client's keep alive time */
        case MSG_TYPE_KEEPALIVE:
            client_reset_keepalive(c);
            break;

        /* Receives the data it got from the UDP tunnel and sends it to the
           TCP connection. */
        case MSG_TYPE_DATA0:
        case MSG_TYPE_DATA1:
            ret = client_got_udp_data(c, data, data_len, msg_type);
            if(ret == 0)
                ret = client_send_tcp_data(c);
            break;

        /* Receives the ACK from the UDP tunnel to set the internal client
           state. */
        case MSG_TYPE_ACK0:
        case MSG_TYPE_ACK1:
            client_got_ack(c, msg_type);
            break;

        default:
            ret = -1;
    }

    return ret;

  error:
    return -1;
}