예제 #1
0
void send_debug_packet_response(nabto_packet_header* header, uint32_t notification) 
{
    uint8_t* buf = nabtoCommunicationBuffer;
    uint8_t* ptr = nabtoCommunicationBuffer;
    uint8_t* end = nabtoCommunicationBuffer+nabtoCommunicationBufferSize;
    
    ptr = insert_header(ptr, header->nsi_cp, header->nsi_sp, U_DEBUG, true, header->seq, 0, NULL);
    
    if (ptr == NULL) {
        NABTO_LOG_ERROR(("Could not insert debug packet header"));
        return;
    }

    ptr = insert_notify_payload(ptr, end, NP_PAYLOAD_NOTIFY_DEBUG_OK);
    if (ptr == NULL) {
        NABTO_LOG_ERROR(("Could not insert notify payload"));
        return;
    }

    {
        uint16_t length = ptr - buf;
        insert_length(buf, length);
        send_to_basestation(buf, length, &nmc.context.gsp);
    }

}
예제 #2
0
bool nabto_fallback_connect_u_event(uint16_t packetLength, nabto_packet_header* hdr) {
    nabto_connect* con;
    uint8_t* startOfPayloads;
    uint8_t* endOfPayloads;
    uint8_t* noncePayloadStart;
    uint16_t noncePayloadLength;
    uint8_t type;
    uint8_t flags;
    uint8_t* ptr;
    bool isReliable;
    bool hasKeepAlive;

    con = nabto_find_connection(hdr->nsi_sp);
    if (con == 0) {
        NABTO_LOG_TRACE((PRInsi " No connection found.", MAKE_NSI_PRINTABLE(hdr->nsi_cp, hdr->nsi_sp, 0)));
        return false;
    }

    startOfPayloads = nabtoCommunicationBuffer + hdr->hlen;
    endOfPayloads = nabtoCommunicationBuffer + packetLength;

    if (!find_payload(startOfPayloads, endOfPayloads, NP_PAYLOAD_TYPE_NONCE, &noncePayloadStart, &noncePayloadLength)) {
        NABTO_LOG_ERROR((PRI_tcp_fb "No nonce payload in GW_CONN_U packet.", TCP_FB_ARGS(con)));
        return false;
    }

    if (noncePayloadLength < 2) {
        NABTO_LOG_ERROR((PRI_tcp_fb "The payload received is too small to contain both flags and type.", TCP_FB_ARGS(con)));
        return false;
    }

    ptr = noncePayloadStart + NP_PAYLOAD_HDR_BYTELENGTH;

    READ_U8(type, ptr);  ptr++;
    READ_U8(flags, ptr); ptr++;

    isReliable   = (flags & NP_GW_CONN_U_FLAG_RELIABLE) != 0;
    hasKeepAlive = (flags & NP_GW_CONN_U_FLAG_KEEP_ALIVE) != 0;

    con->tcpFallbackConnectionState = UTFS_READY_FOR_DATA;

    // If the connection is still resolving upgrade it to a fallback connection.
    if (isReliable) {
        con->fbConAttr |= CON_ATTR_NO_RETRANSMIT;
        NABTO_LOG_DEBUG((PRI_tcp_fb "connection needs no retransmition", TCP_FB_ARGS(con)));
    }

    if (!hasKeepAlive) {
        con->fbConAttr |= CON_ATTR_NO_KEEP_ALIVE;
        NABTO_LOG_DEBUG((PRI_tcp_fb "connection needs no keep alive", TCP_FB_ARGS(con)));
    } else {
        NABTO_LOG_DEBUG((PRI_tcp_fb "connection needs keep alive", TCP_FB_ARGS(con)));
    }
    
    return true;
}
예제 #3
0
bool unabto_buffer_test(void) {

    char * raw_test_string = "asjdhc#21?(!?(92814skzjbcasa";
    uint8_t data[7 + 2 + strlen(raw_test_string)];
    unabto_buffer buf, raw_string_buf;
    buffer_write_t w_buf;
    buffer_read_t r_buf;

    uint32_t t32;
    uint16_t t16;
    uint8_t  t8;
    uint8_t raw_string_data[strlen(raw_test_string) + 1];

    buffer_init(&raw_string_buf, (uint8_t*)raw_test_string, strlen(raw_test_string));
    
    buffer_init(&buf, data, sizeof(data));
    
    buffer_write_init(&w_buf, &buf);

    if (! (buffer_write_uint32(&w_buf, 0x12345678) &&
           buffer_write_uint16(&w_buf, 0x1234) &&
           buffer_write_uint8(&w_buf, 0x12) && 
           buffer_write_raw(&w_buf, &raw_string_buf) ) ) {
        NABTO_LOG_ERROR(("Buffer write test failed"));
        return false;
    }
    
    buffer_read_init(&r_buf, &buf);
    
    memset(raw_string_data, 0, sizeof(raw_string_data) + 1);
    buffer_init(&raw_string_buf, raw_string_data, sizeof(raw_string_data));
    bool t = false;    
    if (! ( buffer_read_uint32(&r_buf, &t32) && t32 == 0x12345678 &&
            buffer_read_uint16(&r_buf, &t16) && t16 == 0x1234 &&
            buffer_read_uint8(&r_buf, &t8)   && t8  == 0x12 && 
            (t = buffer_read_raw(&r_buf, &raw_string_buf)) && buffer_get_size(&raw_string_buf) == strlen(raw_test_string) &&
            0 == strncmp((char*)buffer_get_data(&raw_string_buf), raw_test_string, strlen(raw_test_string)) )) {
        NABTO_LOG_ERROR(("Failed read test failed"));
        return false;
    }

    if (buffer_read_uint32(&r_buf, &t32) ||
        buffer_read_uint16(&r_buf, &t16) ||
        buffer_read_uint8(&r_buf, &t8) ||
        buffer_read_raw(&w_buf, &raw_string_buf) ||
        buffer_write_uint32(&w_buf, 0x12345678) ||
        buffer_write_uint16(&w_buf, 0x1234) ||
        buffer_write_uint8(&w_buf, 0x12) || 
        buffer_write_raw(&w_buf, &raw_string_buf) ) {
        NABTO_LOG_ERROR(("Some function should have returned false but returned true"));
        return false;
    }

    return true;

}
bool connect_event(message_event* event, nabto_packet_header* hdr)
{
    nabto_endpoint* peer = &event->udpMessage.peer;
    bool isLocal = (event->udpMessage.socket == nmc.socketLocal);
    

    NABTO_LOG_TRACE(("U_CONNECT: Searching for hdr->nsi_cp=%" PRIu32 " (should not be found)", hdr->nsi_cp));
    if (nabto_find_connection(hdr->nsi_cp) == NULL) {
        uint32_t nsi;
        uint32_t ec = 0;
        nabto_connect* con = nabto_init_connection(hdr, &nsi, &ec, isLocal);
        if (con) {
            size_t olen;
            NABTO_LOG_TRACE(("Couldn't find connection (good!). Created a new connection (nsi=%" PRIu32 ") con->spnsi=%" PRIu32, nsi, con->spnsi));
            olen = mk_gsp_connect_rsp(nabtoCommunicationBuffer, hdr->seq, NOTIFY_CONNECT_OK, con->spnsi, hdr->nsi_cp, hdr->nsi_sp, isLocal);
            
            if (olen == 0) {
                NABTO_LOG_ERROR(("U_CONNECT out of resources in connect event."));
                nabto_release_connection(con); // no resources available
            } else {
                if (EP_EQUAL(*peer, nmc.context.gsp)) {
                    send_to_basestation(nabtoCommunicationBuffer, olen, peer);
                } else {
                    nabto_write(event->udpMessage.socket, nabtoCommunicationBuffer, olen, peer->addr, peer->port);
                }
                
                con->state = CS_CONNECTING;

                if (!con->noRendezvous) {
                    nabto_rendezvous_start(con);
                }
#if NABTO_ENABLE_TCP_FALLBACK
                if (con->hasTcpFallbackCapabilities) {
                    unabto_tcp_fallback_connect(con);
                }
#endif
                return true;
            }
        } else if (nsi && ec) {
            // build negative answer
            size_t olen = mk_gsp_connect_rsp(nabtoCommunicationBuffer, hdr->seq, ec, nsi, hdr->nsi_cp, hdr->nsi_sp, isLocal);
            NABTO_LOG_TRACE((PRInsi " Deny connection, result: %" PRIu32, MAKE_NSI_PRINTABLE(0, nsi, 0), ec));
            nabto_write(event->udpMessage.socket, nabtoCommunicationBuffer, olen, peer->addr, peer->port);
            return true;
        } else {
            NABTO_LOG_ERROR(("U_CONNECT was a malformed connect event."));
        }
    }
    return false;
}
예제 #5
0
bool hex_test(const char* string, uint8_t* expected, size_t expectedLength)
{
    uint8_t buffer[MAX_BUFFER_LENGTH];
    size_t readLength;
    if (unabto_read_hex(string, strlen(string), buffer, MAX_BUFFER_LENGTH, &readLength)) {
        if (expectedLength == readLength && memcmp(expected,buffer, expectedLength) == 0) {
            return true;
        } else {
            NABTO_LOG_ERROR(("invalid read hex in string %s at position %" PRIsize, string, readLength));
        }
    } else {
        NABTO_LOG_ERROR(("read hex for %s failed", string));
    }
    return false;
}
예제 #6
0
void tcp_provider_disconnect(tcp_socket* tcpSocket)
{
    closesocket(*tcpSocket);
    *tcpSocket = TCP_PROVIDER_INVALID_SOCKET;

    NABTO_LOG_ERROR(("TCP connection closed."));
}
예제 #7
0
void handle_stream_packet(nabto_connect* con, nabto_packet_header* hdr,
                          uint8_t* start, uint16_t dlen,
                          uint8_t* payloadsStart, uint8_t* payloadsEnd,
                          void* userData) {
    
    // read the window and sack payloads
    struct unabto_payload_packet window;

    uint8_t* sackStart = 0;
    uint16_t sackLength = 0;
         
    NABTO_NOT_USED(userData);

    if(!unabto_find_payload(payloadsStart, payloadsEnd, NP_PAYLOAD_TYPE_WINDOW, &window)) {
        NABTO_LOG_ERROR(("Stream %i, Packet has no WINDOW payload!", hdr->tag));
        return;
    }

    {
        struct unabto_payload_packet sack;
        if (unabto_find_payload(payloadsStart, payloadsEnd, NP_PAYLOAD_TYPE_SACK, &sack)) {
            sackStart = (uint8_t*)sack.dataBegin;
            sackLength = sack.dataLength;
        }
    }

    NABTO_LOG_DEBUG(("(.%i.) STREAM EVENT, dlen: %i", hdr->nsi_sp, dlen));
    nabtoSetFutureStamp(&con->stamp, con->timeOut);
    nabto_stream_event(con, hdr, (uint8_t*)(window.dataBegin - SIZE_PAYLOAD_HEADER), start, dlen, sackStart, sackLength);
}
void unabto_tcp_fallback_handle_write(nabto_connect* con) {
	ssize_t status;
    int dataToSend;
    unabto_tcp_fallback_connection* fbConn = &fbConns[nabto_connection_index(con)];
    UNABTO_ASSERT(fbConn->sendBufferSent <= fbConn->sendBufferLength); 
    dataToSend = fbConn->sendBufferLength - fbConn->sendBufferSent;
    
    status = send(fbConn->socket, fbConn->sendBuffer + fbConn->sendBufferSent, dataToSend, MSG_NOSIGNAL);
    if (status > 0) {
        fbConn->sendBufferSent += status;
    } else if (status < 0) {
        int err = errno;
        if ((err == EAGAIN) || err == EWOULDBLOCK) {
        } else {
            NABTO_LOG_ERROR((PRI_tcp_fb "Send of tcp packet failed", TCP_FB_ARGS(con)));
            close_tcp_socket(con);
            return; 
        }
    }

    if (fbConn->sendBufferSent > fbConn->sendBufferLength) {
        NABTO_LOG_FATAL(("fbConn->sendBufferSent(%" PRIsize ") > fbConn->sendBufferLength(%" PRIsize "), that should not be possible", fbConn->sendBufferSent, fbConn->sendBufferLength));
    }
    
    if (fbConn->sendBufferSent == fbConn->sendBufferLength) {
        fbConn->sendBufferLength = 0;
    }
}
bool convert_pattern_to_module_and_severity(const char* pattern, size_t patternLength, uint32_t* module, uint32_t* severity) {
    const char* dotIndex = strchr(pattern, '.');
    const char* patternEnd = pattern+patternLength;
    const char* moduleStart;
    const char* moduleEnd;
    const char* severityStart;
    const char* severityEnd;
    
    if (dotIndex == NULL) {
        NABTO_LOG_ERROR(("No . in log pattern"));
        return false;
    }

    moduleStart = pattern;
    moduleEnd = dotIndex;
    
    severityStart = dotIndex+1;
    severityEnd = patternEnd;

    if (!convert_module(moduleStart, moduleEnd, module)) {
        return false;
    }
    
    if (!convert_severity(severityStart, severityEnd, severity)) {
        return false;
    }

    return true;
}
예제 #10
0
bool poll_task_event_queue(void)
{
  OS_ERR osErr;
  OS_MSG_SIZE size;
  uint32_t event;
 
  event = (uint32_t)OSTaskQPend(0, OS_OPT_PEND_NON_BLOCKING, &size, NULL, &osErr);
  
  if(osErr == OS_ERR_PEND_WOULD_BLOCK)
  {
    return false;
  }
  
  if(osErr != OS_ERR_NONE)
  {
    NABTO_LOG_ERROR(("Error in receiver task: %i", osErr));
    return false;
  }
  
  NABTO_LOG_TRACE(("Received event: %u", event));
  
  if (event & EVENT_RECV_DATA)
  {
    uint8_t index = event & EVENT_MASK;
    
    if(sockets[index].isOpen)
    {
      OSSemPost(&sockets[index].receiverSemaphore, OS_OPT_POST_NO_SCHED, &osErr);
      if(osErr != OS_ERR_NONE)
      {
        NABTO_LOG_ERROR(("Unable to post on socket receive semaphore!"));
      }
      
      NABTO_LOG_TRACE(("Received packet on socket %u", index));
    }
    else
    {
      NABTO_LOG_TRACE(("Data on non-open socket."));
    }
  }
  else
  {
    NABTO_LOG_TRACE(("Dropped unexpected event."));
  }
  
  return true;
}
예제 #11
0
파일: main.c 프로젝트: nabto/unabto
/**
 *  main using gopt to check command line arguments
 *  -h for help
 */
int main(int argc, char* argv[])
{
    // Set nabto to default values

    nabto_main_setup* nms = unabto_init_context();

    // Overwrite default values with command line args
    if (!check_args(argc, argv, nms)) {
        return 1;
    }
    NABTO_LOG_INFO(("Identity: '%s'", nms->id));
    NABTO_LOG_INFO(("Program Release %i.%i", RELEASE_MAJOR, RELEASE_MINOR));
    NABTO_LOG_INFO(("Buffer size: %i", nms->bufsize));

    // Initialize nabto
    if (!unabto_init()) {
        NABTO_LOG_FATAL(("Failed at nabto_main_init"));
    }

    nabto_stamp_t attachExpireStamp;
    // 20 seconds
    nabtoSetFutureStamp(&attachExpireStamp, 1000*20);
        
    // The main loop gives nabto a tick from time to time.
    // Everything else is taken care of behind the scenes.
    while (true) {
        unabto_tick();
        nabto_yield(10);
        if (nabtoIsStampPassed(&attachExpireStamp)) {
            NABTO_LOG_ERROR(("Attach took too long."));
            exit(4);
        }
        if (unabto_is_connected_to_gsp()) {
            NABTO_LOG_INFO(("Successfully attached to the gsp, now exiting."));
            exit(0);
        }
    }

    NABTO_LOG_ERROR(("we should not end here"));
    exit(5);
    
    unabto_close();
    return 0;
}
void rendezvous_time_event(nabto_connect* con) 
{
    nabto_rendezvous_connect_state* rcs = &con->rendezvousConnectState;
    if (rcs->state == RS_CONNECTING) {
        if (nabtoIsStampPassed(&rcs->timestamp)) 
        {
            send_rendezvous_to_all(con);
        }

#if NABTO_ENABLE_EXTENDED_RENDEZVOUS_MULTIPLE_SOCKETS         
        if (rcs->openManySockets &&
            nabtoIsStampPassed(&rcs->openManySocketsStamp))
        {
            if (rcs->socketsOpened < NABTO_EXTENDED_RENDEZVOUS_MAX_SOCKETS) {
                nabto_socket_t* candidate = &rcs->sockets[rcs->socketsOpened];
                uint16_t localport = 0;
                if(nabto_init_socket(0,&localport, candidate)) {
                    rcs->socketsOpened++;
                    send_rendezvous_socket(*candidate, con, 0, &con->cp.globalEndpoint, 0);
                } else {
                    NABTO_LOG_ERROR(("Could not open socket."));
                    
                }
                nabtoSetFutureStamp(&con->rendezvousConnectState.openManySocketsStamp, 20);
            } else {
                rcs->openManySockets = false;
            }
        }
#endif

        if (rcs->openManyPorts &&
            nabtoIsStampPassed(&rcs->openManyPortsStamp))
        {
            int i;
            for (i = 0; i < 10; i++) {
                nabto_endpoint newEp;
                uint16_t newPort;
                nabto_random((uint8_t*)&newPort, sizeof(uint16_t));
                
                newEp.addr = con->cp.globalEndpoint.addr;
                newEp.port = 1024+(newPort%64500);
                
                send_rendezvous(con, 0, &newEp, 0);
                rcs->portsOpened++;
            }
            nabtoSetFutureStamp(&rcs->openManyPortsStamp, 50);
        }

        if(nabtoIsStampPassed(&rcs->timeout)) {
#if NABTO_ENABLE_EXTENDED_RENDEZVOUS_MULTIPLE_SOCKETS
            NABTO_LOG_INFO(("Rendezvous timeout. Sockets opened %i", rcs->socketsOpened));
#endif
            nabto_rendezvous_stop(con);
        }
    }
} 
예제 #13
0
bool tcp_provider_connect(tcp_socket* tcpSocket, text host, uint16_t port)
{
    struct sockaddr_in sa;
    
    *tcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(*tcpSocket == TCP_PROVIDER_INVALID_SOCKET)
    {
        NABTO_LOG_ERROR(("Unable to connect to TCP relay service!"));
        return false;
    }
    
    {
        uint32_t hostIp = resolve_host_name(host);
        
        if(hostIp == 0)
        {
            NABTO_LOG_ERROR(("Unable to resolve host!"));
            return false;
        }

        sa.sin_family = AF_INET;
        sa.sin_addr.s_addr = htonl(hostIp);
        sa.sin_port = htons(port);
        if(connect(*tcpSocket, (struct sockaddr*)&sa, sizeof(sa)))
        {
            closesocket(*tcpSocket);
            *tcpSocket = TCP_PROVIDER_INVALID_SOCKET;

            NABTO_LOG_ERROR(("Unable to connect to host!"));

            return false;
        }
    }
    
    { // If iMode!=0, non-blocking mode is enabled.
        u_long iMode = 1;
	    ioctlsocket(*tcpSocket, FIONBIO, &iMode);
    }
    
    NABTO_LOG_TRACE(("Connection to TCP relay service established."));

    return true;
}
bool unabto_tcp_fallback_event(nabto_connect* con) {
    if (con->tcpFallbackConnectionState == UTFS_CONNECTED) {
        uint8_t handshakePacket[1500];
        size_t handshakePacketLength;
        if (!build_handshake_packet(con, handshakePacket, 1500, &handshakePacketLength)) {
            NABTO_LOG_ERROR((PRI_tcp_fb "Could not create handshake packet.", TCP_FB_ARGS(con)));
            unabto_tcp_fallback_close(con);
            return false;
        }

        if (unabto_tcp_fallback_write(con, handshakePacket, handshakePacketLength) != UTFE_OK) {
            NABTO_LOG_ERROR((PRI_tcp_fb "Could not send handshake packet.", TCP_FB_ARGS(con)));
            return false;
        }
        con->tcpFallbackConnectionState = UTFS_HANDSHAKE_SENT;
        return true;
    }
    return false;
}
예제 #15
0
bool negative_hex_test(const char* string) {
    uint8_t buffer[MAX_BUFFER_LENGTH];
    size_t readLength;
    if (unabto_read_hex(string, strlen(string), buffer, MAX_BUFFER_LENGTH, &readLength)) {
        NABTO_LOG_ERROR(("didn't expect to be able to read hex from %s", string));
        return false;
    } else {
        return true;
    }
}
예제 #16
0
bool handle_debug_packet(message_event* event, nabto_packet_header* header) {
    
    uint8_t* buf = nabtoCommunicationBuffer;
    uint8_t* end = nabtoCommunicationBuffer+nabtoCommunicationBufferSize;
    struct unabto_payload_crypto crypto;

    buf += header->hlen;

    {
        struct unabto_payload_packet payload;
        if (!unabto_find_payload(buf, end, NP_PAYLOAD_TYPE_CRYPTO, &payload)) {
            NABTO_LOG_ERROR(("No crypto payload in debug packet."));
            return false;
        }

        if (!unabto_payload_read_crypto(&payload, &crypto)) {
            NABTO_LOG_ERROR(("Crypto packet too short."));
            return false;
        }
    }
    {
        uint16_t verifSize;
        if (!unabto_verify_integrity(nmc.context.cryptoConnect, crypto.code, nabtoCommunicationBuffer, header->len, &verifSize)) {
            NABTO_LOG_DEBUG(("U_DEBUG Integrity verification failed"));
            return false;
        }
    }

    {
        struct unabto_payload_packet payload;
        if (!unabto_find_payload(buf, end, NP_PAYLOAD_TYPE_SYSLOG_CONFIG, &payload)) {
            NABTO_LOG_ERROR(("No syslog config packet which is the only one understand at the moment."));
            return false;
        }
        
        if (!handle_syslog_config(&payload)) {
            return false;
        }
    }

    return true;
}
예제 #17
0
ssize_t nabto_read(nabto_socket_t socket, uint8_t* buffer, size_t length, uint32_t* address, uint16_t* port)
{
  OS_ERR osErr;
  uint8_t* receiveBuffer;
  uint16_t receiveBufferLength;
  RAK_SOCKET_ADDR socketInfo;
 
  if(socket > NUMBER_OF_SOCKETS)
  {
    NABTO_LOG_FATAL(("Read on invalid socket!"));
    return 0;
  }
  
  if(sockets[socket].isOpen == false)
  {
    NABTO_LOG_ERROR(("Read on closed socket!"));
    return 0;
  }
  
  while(poll_task_event_queue());
  
  OSSemPend(&sockets[socket].receiverSemaphore, 0, OS_OPT_PEND_NON_BLOCKING, NULL, &osErr);
  if(osErr != OS_ERR_NONE)
  {
    return 0;
  }
  
  NABTO_LOG_TRACE(("nabto_read=%u receiving...", socket));
  
  if (RAK_RecvData(socket, &receiveBuffer, &receiveBufferLength) != RAK_OK)
  {
    return 0;
  }
  
  if(receiveBufferLength > length)
  {
    NABTO_LOG_TRACE(("nabto_read=%u oversize frame", socket));
    RAK_RecvFree(buffer);
    return 0;
  }
  
  memcpy(buffer, receiveBuffer, receiveBufferLength);
  
  RAK_RecvFree(receiveBuffer);

  RAK_GetSocketInfo(socket, &socketInfo);

  *address = socketInfo.dest_addr;
  *port = socketInfo.dest_port;
  
  NABTO_LOG_TRACE(("Received UDP packet from " PRI_IP ":%u length=%u", PRI_IP_FORMAT(*address), *port, receiveBufferLength));
  
  return receiveBufferLength;
}
예제 #18
0
/**
 * utility function for either sending +ok\n or -error message\n in
 * case of either success or failure.  see spec in
 * https://www.rfc-editor.org/rfc/rfc1078.txt instead of CRLF only LF
 * is used.
 */
bool tunnel_send_init_message(tunnel* tunnel, const char* msg)
{
    unabto_stream_hint hint;
    size_t written;
    size_t writeLength = strlen(msg);
    written = unabto_stream_write(tunnel->stream, (uint8_t*)msg, writeLength, &hint);
    if (written != writeLength) {
        NABTO_LOG_ERROR(("we should at a minimum be able to send this simple message, we will probably just goive up..."));
        return false;
    }
    return true;
}
예제 #19
0
bool handle_syslog_config(struct unabto_payload_packet* payload) {
#if NABTO_ENABLE_DEBUG_SYSLOG_CONFIG
    uint8_t flags;
    uint8_t facility;
    uint16_t port;
    uint32_t ip;
    uint32_t expire;
    uint8_t* pattern;
    uint16_t patternLength;
    bool enabled;
    const uint8_t* ptr;
    if (payload->length < (NP_PAYLOAD_SYSLOG_CONFIG_SIZE_WO_STRINGS + 2)) {
        NABTO_LOG_ERROR(("Syslog config packet too short"));
        return false;
    }

    ptr = payload->dataBegin;

    READ_FORWARD_U8(flags, ptr);
    READ_FORWARD_U8(facility, ptr);
    READ_FORWARD_U16(port, ptr);
    READ_FORWARD_U32(ip, ptr);
    READ_FORWARD_U32(expire, ptr);
    READ_FORWARD_U16(patternLength, ptr);
    pattern = (uint8_t*)ptr;
    
    if (payload->length < (NP_PAYLOAD_SYSLOG_CONFIG_SIZE_WO_STRINGS + 2 + patternLength)) {
        NABTO_LOG_ERROR(("syslog packet log settings string too long"));
        return false;
    }

    enabled = flags & NP_PAYLOAD_SYSLOG_FLAG_ENABLE;

    return unabto_debug_syslog_config(enabled, facility, ip, port, expire, pattern, patternLength);
#else
    return false;
#endif
}
예제 #20
0
void unabto_tunnel_read_command(tunnel* tunnel, tunnel_event_source event_source)
{
    const uint8_t* buf;
    unabto_stream_hint hint;
    size_t readen;
    if (tunnel->state != TS_READ_COMMAND) {
        return;
    }
    readen = unabto_stream_read(tunnel->stream, &buf, &hint);
    if (hint != UNABTO_STREAM_HINT_OK) {
        tunnel->state = TS_CLOSING;
    } else {
        if (readen > 0) {
            size_t i;
            for (i = 0; i < readen; i++) {
                if (buf[i] == '\n') {
                    tunnel->state = TS_PARSE_COMMAND;
                } else {
                    tunnel->staticMemory->command[tunnel->commandLength] = buf[i];
                    tunnel->commandLength++;
                }

                if (tunnel->commandLength > MAX_COMMAND_LENGTH) {
                    NABTO_LOG_ERROR(("Tunnel command too long"));
                    tunnel->state = TS_CLOSING;
                }
            }

            unabto_stream_ack(tunnel->stream, buf, i, &hint);

            if (hint != UNABTO_STREAM_HINT_OK) {
                NABTO_LOG_ERROR(("Failed to ack on stream."));
                tunnel->state = TS_CLOSING;
            }
        }
    }
}
예제 #21
0
static void unabto_tcp_fallback_close_socket(unabto_tcp_fallback_connection* fbConn)
{
    if (fbConn->socket == INVALID_SOCKET) {
        NABTO_LOG_ERROR(("trying to close invalid socket"));
    } else {
#if NABTO_ENABLE_EPOLL
        {
            struct epoll_event ev;
            memset(&ev, 0, sizeof(struct epoll_event));
            epoll_ctl(unabto_epoll_fd, EPOLL_CTL_DEL, fbConn->socket, &ev);
        }
#endif
        closesocket(fbConn->socket);
        fbConn->socket = INVALID_SOCKET;
    }
}
예제 #22
0
bool unabto_tcp_fallback_handle_write(nabto_connect* con) {
    ssize_t status;
    int dataToSend;
    bool canMaybeSendMoreData = false;
    unabto_tcp_fallback_connection* fbConn = &fbConns[nabto_connection_index(con)];
    UNABTO_ASSERT(fbConn->sendBufferSent <= fbConn->sendBufferLength); 
    dataToSend = fbConn->sendBufferLength - fbConn->sendBufferSent;

    if (dataToSend == 0) {
        return false;
    }
    
    NABTO_LOG_TRACE(("data to send %i, sendBufferLength %i, sendBufferSent %i", dataToSend, fbConn->sendBufferLength, fbConn->sendBufferSent));
    
    status = send(fbConn->socket, fbConn->sendBuffer + fbConn->sendBufferSent, dataToSend, MSG_NOSIGNAL);
    NABTO_LOG_TRACE(("tcp send status: %i", status));
    if (status > 0) {
        fbConn->sendBufferSent += status;
        canMaybeSendMoreData = true;
    } else if (status < 0) {
        int err = errno;
        if ((err == EAGAIN) || err == EWOULDBLOCK) {
            canMaybeSendMoreData = false;
        } else {
            NABTO_LOG_ERROR((PRI_tcp_fb "Send of tcp packet failed", TCP_FB_ARGS(con)));
            close_tcp_socket(con);
            canMaybeSendMoreData = false;
            return canMaybeSendMoreData; 
        }
    }

    if (fbConn->sendBufferSent > fbConn->sendBufferLength) {
        NABTO_LOG_FATAL(("fbConn->sendBufferSent(%" PRIsize ") > fbConn->sendBufferLength(%" PRIsize "), that should not be possible", fbConn->sendBufferSent, fbConn->sendBufferLength));
    }
    
    if (fbConn->sendBufferSent == fbConn->sendBufferLength) {
        fbConn->sendBufferLength = 0;
        fbConn->sendBufferSent = 0;
        canMaybeSendMoreData = false;
    }

    NABTO_LOG_TRACE(("state after send, sendBufferLength %i, sendBufferSent %i", fbConn->sendBufferLength, fbConn->sendBufferSent));
    
    return canMaybeSendMoreData;
}
예제 #23
0
/* Reconstruct nabto header with crypto payload header. */
uint8_t* reconstruct_header(uint8_t* buf, const nabto_packet_header * hdr)
{
    uint8_t* ptr;

    // insert copy of request header (Length will be inserted later)

    ptr = buf;

    /* Write fixed part of packet header */
    WRITE_U32(ptr, hdr->nsi_cp);      ptr += 4;
    WRITE_U32(ptr, hdr->nsi_sp);      ptr += 4;
    WRITE_U8(ptr,  hdr->type);        ptr += 1;
    WRITE_U8(ptr,  hdr->version);     ptr += 1;
    WRITE_U8(ptr,  hdr->rsvd);        ptr += 1;
    WRITE_U8(ptr,  hdr->flags | NP_PACKET_HDR_FLAG_RESPONSE); ptr += 1;
    WRITE_U16(ptr, hdr->seq);         ptr += 2;
    /*WRITE_U16(ptr, len);*/          ptr += 2; /* Length to be packed later */

    /* Write NSI.co to packet header (optional) */
    if (hdr->flags & NP_PACKET_HDR_FLAG_NSI_CO) {
        memcpy(ptr, (const void*) hdr->nsi_co, 8);  ptr += 8;
    }

    /* Write tag to packet header (optional) */
    if (hdr->flags & NP_PACKET_HDR_FLAG_TAG) {
        WRITE_U16(ptr, hdr->tag);     ptr += 2;
    }

    {
        ptrdiff_t diff = ptr - buf;
        if (hdr->hlen != (uint16_t)(diff)) {
            NABTO_LOG_ERROR(("header length mismatch: %" PRIu16 " != %" PRIptrdiff " !!!!!!!!!!!!!!!!!!!", hdr->hlen, diff));
            return NULL;
        }
    }

    // insert crypto header (len and code will be inserted later)
    WRITE_U8(ptr, NP_PAYLOAD_TYPE_CRYPTO);                    ptr += 1;
    WRITE_U8(ptr, NP_PAYLOAD_HDR_FLAG_NONE);                /*ptr += 1;
    WRITE_U16(ptr, len);                                      ptr += 2;
    WRITE_U16(ptr, code);                                     ptr += 2;*/
    /* len and code is patched by unabto_encrypt() */         ptr += 5;

    return ptr; /* return end of packet (so far) */
}
예제 #24
0
bool modbus_rtu_master_transfer_message(modbus_message* message)
{
    modbus* bus;

    if(message->bus >= MODBUS_NUMBER_OF_BUSSES) // invalid bus
    {
        NABTO_LOG_TRACE(("Attempted to enqueue a message on an invalid bus (query=%u)!", (int)message));
        return false;
    }
    
    bus = &busses[message->bus];

    if((message->frameSize + 2) > MODBUS_MAXIMUM_FRAME_SIZE) // not enough space to add CRC
    {
        NABTO_LOG_TRACE(("Attempted to enqueue an oversize message (bus=%u, query=%u)!", (int)bus->identifier, (int)message));
        return false;
    }

    // add CRC
    message->frameSize += 2;
    modbus_rtu_crc_update_crc_field(message->frame, message->frameSize);

    if(list_append(&bus->messageQueue, message)) // add to the end of the transfer queue
    {
        message->state = MODBUS_MESSAGE_STATE_QUEUED;
        NABTO_LOG_TRACE(("Query has been queued (bus=%u, query=%u, length=%u).", bus->identifier, (int)message, (int)message->frameSize));

        // eager tick when queue was empty
        if(list_count(&bus->messageQueue) == 1)
        {
            NABTO_LOG_TRACE(("Performing eager tick as message queue was empty (bus=%u).", bus->identifier));
            modbus_rtu_master_tick();
        }

        return true;
    }
    else
    {
        NABTO_LOG_ERROR(("Unable to enqueued query (bus=%u, query=%u, length=%u)!", bus->identifier, (int)message, (int)message->frameSize));
        return false;
    }
}
예제 #25
0
ssize_t nabto_write(nabto_socket_t socket, const uint8_t* buffer, size_t length, uint32_t address, uint16_t port)
{
  int32_t result;
  
  if(length > SEND_BUFFER_SIZE)
  {
    return 0;
  }
  
  memcpy(sendBuffer, buffer, length);
  
  result = RAK_SendData(socket, sendBuffer, length, address, port);
  
  if(result != RAK_OK)
  {
    NABTO_LOG_ERROR(("RAK_SendData failed: %i", result));
    return 0;
  }
  
  NABTO_LOG_TRACE(("Sent UDP packet to " PRI_IP ":%u length=%u", PRI_IP_FORMAT(address), port, length));
  
  return length;
}
bool nabto_connect_event(message_event* event, nabto_packet_header* hdr)
{
    /**
     * We can get here if we got either a connect request or
     * if the connect request is a rendezvous event.
     *
     * If the first payload is an endpoint it's a rendezvous event.
     * If the request is a request for a new connection the first payload will be an IPX payload.
     */
    uint8_t type = 0;

    nabto_rd_payload(nabtoCommunicationBuffer+hdr->hlen, nabtoCommunicationBuffer + hdr->len, &type);

    if (type == NP_PAYLOAD_TYPE_EP) {
        return rendezvous_event(event, hdr);
    } 
    
    if (type == NP_PAYLOAD_TYPE_IPX) {
        return connect_event(event, hdr);
    }
    
    NABTO_LOG_ERROR(("U_CONNECT was neither a rendezvous nor a connect event."));
    return false;
}
static void send_rendezvous_socket(nabto_socket_t socket, nabto_connect* con, uint16_t seq, nabto_endpoint* dest, nabto_endpoint *myAddress)
{
    uint8_t* ptr;
    uint8_t* buf = nabtoCommunicationBuffer;

    ptr = insert_header(buf, 0, con->spnsi, U_CONNECT, false, seq, 0, 0);
    ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6);
    WRITE_U32(ptr, dest->addr); ptr += 4;
    WRITE_U16(ptr, dest->port); ptr += 2;
    if (seq > 0) {
        if (!myAddress) {
            NABTO_LOG_ERROR(("Send rendezvous called with an invalid address"));
            return;
        } else {
            ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6);
            WRITE_U32(ptr, myAddress->addr); ptr += 4;
            WRITE_U16(ptr, myAddress->port); ptr += 2;
        }
    }
    {
        size_t len = ptr - buf;

        insert_length(buf, len);

        if (seq) {
            NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=%" PRIu16 "  " PRIep, MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest), seq, MAKE_EP_PRINTABLE(*myAddress)));
        } else {
            NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=0", MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest)));
        }
        if (dest->addr != 0 && dest->port != 0) {
            nabto_write(socket, buf, len, dest->addr, dest->port);
        } else {
            NABTO_LOG_TRACE(("invalid rendezvous packet thrown away"));
        }
    }
}
bool verify_connection_encryption(nabto_connect* con) {

    // Local connections can use whatever crypto they like.
    if (con->isLocal) {
        return true;
    } 
    
    // If we don't want encryption it's ok.
    if (!nmc.nabtoMainSetup.secureData) {
        return true;
    }

    // If secure data is chosen and the connection isn't local.
    // The encryption for the new connection should match the crypto suite
    // set in the setup.
    if (nmc.nabtoMainSetup.secureData && !con->isLocal) {
        if (con->cryptoctx.code == nmc.nabtoMainSetup.cryptoSuite) {
            return true;
        }
    }

    NABTO_LOG_ERROR(("The connection's encryption capabilities doesn't match the expected capabilities"));
    return false;
}
void unabto_tcp_fallback_read_packet(nabto_connect* con) {
    unabto_tcp_fallback_connection* fbConn = &fbConns[nabto_connection_index(con)];
    while(true) {
        if (fbConn->recvBufferLength < 16) {
            int status = recv(fbConn->socket, fbConn->recvBuffer + fbConn->recvBufferLength, 16-fbConn->recvBufferLength, 0);
            int err = errno;
            if (status < 0) {
                if ((err == EAGAIN) || err == EWOULDBLOCK) {
                    return;
                } else {
                    NABTO_LOG_ERROR((PRI_tcp_fb "unabto_tcp_fallback_read_single_packet failed", TCP_FB_ARGS(con)));
                    unabto_tcp_fallback_close(con);
                    return;
                }
            } else if (status == 0) {
                NABTO_LOG_INFO((PRI_tcp_fb "TCP fallback connection closed by peer", TCP_FB_ARGS(con)));
                unabto_tcp_fallback_close(con);
                return;
            } else {
                fbConn->recvBufferLength+=status;
            }
        }

        if (fbConn->recvBufferLength >= 16) {
            uint16_t packetLength;
            int status;
            int err;
            READ_U16(packetLength, fbConn->recvBuffer+14);
            
            status = recv(fbConn->socket, fbConn->recvBuffer + fbConn->recvBufferLength, packetLength - fbConn->recvBufferLength, 0);
            err = errno;
            if (status < 0) {
                if ((err == EAGAIN) || err == EWOULDBLOCK) {
                    return;
                } else {
                    NABTO_LOG_ERROR((PRI_tcp_fb "Tcp read failed", TCP_FB_ARGS(con)));
                    unabto_tcp_fallback_close(con);
                    return;
                }
            } else if (status == 0) {
                NABTO_LOG_INFO((PRI_tcp_fb "TCP fallback connection closed by peer", TCP_FB_ARGS(con)));
                unabto_tcp_fallback_close(con);
                return;
            } else {
                fbConn->recvBufferLength += status;
            }
            
            if (fbConn->recvBufferLength == packetLength) {
                message_event event;
                event.type = MT_TCP_FALLBACK;
                
                memcpy(nabtoCommunicationBuffer, fbConn->recvBuffer, fbConn->recvBufferLength);
                
                NABTO_LOG_TRACE((PRI_tcp_fb "Received fallback packet length %" PRIsize, TCP_FB_ARGS(con), fbConn->recvBufferLength));
                
                nabto_message_event(&event, fbConn->recvBufferLength);
                NABTO_LOG_TRACE((PRI_tcp_fb "fallback packet done\n==================================================", TCP_FB_ARGS(con)));
                
                fbConn->recvBufferLength = 0;
            }
        }
    }
}
bool unabto_tcp_fallback_connect(nabto_connect* con) {
    unabto_tcp_fallback_connection* fbConn = &fbConns[nabto_connection_index(con)];
    int status;
    int flags;

    fbConn->socket = socket(AF_INET, SOCK_STREAM, 0);
    if (fbConn->socket < 0) {
        NABTO_LOG_ERROR((PRI_tcp_fb "Could not create socket for tcp fallback.", TCP_FB_ARGS(con)));
        return false;
    }

    flags = 1;
    if (setsockopt(fbConn->socket, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof(int)) != 0) {
        NABTO_LOG_ERROR(("Could not set socket option TCP_NODELAY"));
    }




#ifndef WIN32
    flags = fcntl(fbConn->socket, F_GETFL, 0);
    if (flags < 0) {
        NABTO_LOG_ERROR((PRI_tcp_fb "fcntl fail", TCP_FB_ARGS(con))); 
        closesocket(fbConn->socket);
        fbConn->socket = INVALID_SOCKET;
        con->tcpFallbackConnectionState = UTFS_CLOSED;
        return false;
    }
    if (fcntl(fbConn->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
        NABTO_LOG_ERROR((PRI_tcp_fb "fcntl fail", TCP_FB_ARGS(con)));        
        closesocket(fbConn->socket);
        fbConn->socket = INVALID_SOCKET;
        con->tcpFallbackConnectionState = UTFS_CLOSED;
        return false;
    }

    flags = 1;
    if(setsockopt(fbConn->socket, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags)) < 0) {
        NABTO_LOG_ERROR(("could not enable KEEPALIVE"));
    }
#ifndef __MACH__
    flags = 9;
    if(setsockopt(fbConn->socket, SOL_TCP, TCP_KEEPCNT, &flags, sizeof(flags)) < 0) {
        NABTO_LOG_ERROR(("could not set TCP_KEEPCNT"));
    }

    flags = 60;
    if(setsockopt(fbConn->socket, SOL_TCP, TCP_KEEPIDLE, &flags, sizeof(flags)) < 0) {
        NABTO_LOG_ERROR(("could not set TCP_KEEPIDLE"));
    }
    
    flags = 60;
    if(setsockopt(fbConn->socket, SOL_TCP, TCP_KEEPINTVL, &flags, sizeof(flags)) < 0) {
        NABTO_LOG_ERROR(("could not set TCP KEEPINTVL"));
    }
#else
    flags = 60;
    if(setsockopt(fbConn->socket, IPPROTO_TCP, TCP_KEEPALIVE, &flags, sizeof(flags)) < 0) {
        NABTO_LOG_ERROR(("could not set TCP_KEEPCNT"));
    }
#endif
    
#endif

    memset(&fbConn->fbHost,0,sizeof(struct sockaddr_in));
    fbConn->fbHost.sin_family = AF_INET;
    fbConn->fbHost.sin_addr.s_addr = htonl(con->fallbackHost.addr);
    fbConn->fbHost.sin_port = htons(con->fallbackHost.port);
    
    NABTO_LOG_INFO((PRI_tcp_fb "Ep. " PRIep, TCP_FB_ARGS(con), MAKE_EP_PRINTABLE(con->fallbackHost)));


    status = connect(fbConn->socket, (struct sockaddr*)&fbConn->fbHost, sizeof(struct sockaddr_in));
   
    if (status == 0) {
        con->tcpFallbackConnectionState = UTFS_CONNECTED;
    } else {
        int err = errno;
        // err is two on windows.
        if (err == EINPROGRESS) {
            con->tcpFallbackConnectionState = UTFS_CONNECTING;
        } else {
            NABTO_LOG_ERROR((PRI_tcp_fb "Could not connect to fallback tcp endpoint. %s", TCP_FB_ARGS(con), strerror(errno)));
            closesocket(fbConn->socket);
            fbConn->socket = INVALID_SOCKET;
            con->tcpFallbackConnectionState = UTFS_CLOSED;    
            return false;
        }
    }

#ifdef WIN32
    flags = 1;
    if (ioctlsocket(fbConn->socket, FIONBIO, &flags) != 0) {
        NABTO_LOG_ERROR((PRI_tcp_fb "ioctlsocket fail", TCP_FB_ARGS(con)));        
        closesocket(fbConn->socket);
        fbConn->socket = INVALID_SOCKET;
        con->tcpFallbackConnectionState = UTFS_CLOSED;
        return false;
    }
#endif

    return true;
}