Beispiel #1
0
int csp_route_work(uint32_t timeout) {

	csp_qfifo_t input;
	csp_packet_t * packet;
	csp_conn_t * conn;
	csp_socket_t * socket;

#ifdef CSP_USE_RDP
	/* Check connection timeouts (currently only for RDP) */
	csp_conn_check_timeouts();
#endif

	/* Get next packet to route */
	if (csp_qfifo_read(&input) != CSP_ERR_NONE)
		return -1;

	packet = input.packet;

	csp_log_packet("INP: S %u, D %u, Dp %u, Sp %u, Pr %u, Fl 0x%02X, Sz %"PRIu16" VIA: %s",
			packet->id.src, packet->id.dst, packet->id.dport,
			packet->id.sport, packet->id.pri, packet->id.flags, packet->length, input.interface->name);

	/* Here there be promiscuous mode */
#ifdef CSP_USE_PROMISC
	csp_promisc_add(packet);
#endif

#ifdef CSP_USE_DEDUP
	/* Check for duplicates */
	if (csp_dedup_is_duplicate(packet)) {
		/* Discard packet */
		csp_log_packet("Duplicate packet discarded");
		csp_buffer_free(packet);
		return 0;
	}
#endif

	/* If the message is not to me, route the message to the correct interface */
	if ((packet->id.dst != csp_get_address()) && (packet->id.dst != CSP_BROADCAST_ADDR)) {

		/* Find the destination interface */
		csp_iface_t * dstif = csp_rtable_find_iface(packet->id.dst);

		/* If the message resolves to the input interface, don't loop it back out */
		if ((dstif == NULL) || ((dstif == input.interface) && (input.interface->split_horizon_off == 0))) {
			csp_buffer_free(packet);
			return 0;
		}

		/* Otherwise, actually send the message */
		if (csp_send_direct(packet->id, packet, dstif, 0) != CSP_ERR_NONE) {
			csp_log_warn("Router failed to send");
			csp_buffer_free(packet);
		}

		/* Next message, please */
		return 0;
	}

	/* Discard packets with unsupported options */
	if (csp_route_check_options(input.interface, packet) != CSP_ERR_NONE) {
		csp_buffer_free(packet);
		return 0;
	}

	/* The message is to me, search for incoming socket */
	socket = csp_port_get_socket(packet->id.dport);

	/* If the socket is connection-less, deliver now */
	if (socket && (socket->opts & CSP_SO_CONN_LESS)) {
		if (csp_route_security_check(socket->opts, input.interface, packet) < 0) {
			csp_buffer_free(packet);
			return 0;
		}
		if (csp_queue_enqueue(socket->socket, &packet, 0) != CSP_QUEUE_OK) {
			csp_log_error("Conn-less socket queue full");
			csp_buffer_free(packet);
			return 0;
		}
		return 0;
	}

	/* Search for an existing connection */
	conn = csp_conn_find(packet->id.ext, CSP_ID_CONN_MASK);

	/* If this is an incoming packet on a new connection */
	if (conn == NULL) {

		/* Reject packet if no matching socket is found */
		if (!socket) {
			csp_buffer_free(packet);
			return 0;
		}

		/* Run security check on incoming packet */
		if (csp_route_security_check(socket->opts, input.interface, packet) < 0) {
			csp_buffer_free(packet);
			return 0;
		}

		/* New incoming connection accepted */
		csp_id_t idout;
		idout.pri   = packet->id.pri;
		idout.src   = csp_get_address();

		idout.dst   = packet->id.src;
		idout.dport = packet->id.sport;
		idout.sport = packet->id.dport;
		idout.flags = packet->id.flags;

		/* Create connection */
		conn = csp_conn_new(packet->id, idout);

		if (!conn) {
			csp_log_error("No more connections available");
			csp_buffer_free(packet);
			return 0;
		}

		/* Store the socket queue and options */
		conn->socket = socket->socket;
		conn->opts = socket->opts;

	/* Packet to existing connection */
	} else {

		/* Run security check on incoming packet */
		if (csp_route_security_check(conn->opts, input.interface, packet) < 0) {
			csp_buffer_free(packet);
			return 0;
		}

	}

#ifdef CSP_USE_RDP
	/* Pass packet to RDP module */
	if (packet->id.flags & CSP_FRDP) {
		csp_rdp_new_packet(conn, packet);
		return 0;
	}
#endif

	/* Pass packet to UDP module */
	csp_udp_new_packet(conn, packet);
	return 0;
}
Beispiel #2
0
int csp_send_direct(csp_id_t idout, csp_packet_t * packet, uint32_t timeout) {

	if (packet == NULL) {
		csp_log_error("csp_send_direct called with NULL packet\r\n");
		goto err;
	}

	csp_route_t * ifout = csp_route_if(idout.dst);

	if ((ifout == NULL) || (ifout->interface == NULL) || (ifout->interface->nexthop == NULL)) {
		csp_log_error("No route to host: %#08x\r\n", idout.ext);
		goto err;
	}

	csp_log_packet("Output: Src %u, Dst %u, Dport %u, Sport %u, Pri %u, Flags 0x%02X, Size %u VIA: %s\r\n",
		idout.src, idout.dst, idout.dport, idout.sport, idout.pri, idout.flags, packet->length, ifout->interface->name);

	/*
	 * Copy identifier to packet.  This originally happened below (after
	 * encryption), but doing it here makes logging simpler and doesn't
	 * affect the encryption stuff at all.
	 */
	packet->id.ext = idout.ext;

	/* Log the packet as sent by the application (before encryption) */
	if (csp_packet_callback)
		csp_packet_callback(CSP_OUTPUT, ifout->interface->name, packet);

#if 0
#ifdef __linux__
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        double sec = ts.tv_sec + ts.tv_nsec / 1e9;
#else
        double sec = (float)xTaskGetTickCount() / configTICK_RATE_HZ;
#endif

        printf("%.3f: packet contents (%d bytes):", sec,
            packet->length);

        for (int i = 0; i < packet->length; i++) {
            if (i % 16 == 0) printf("\n");
            printf("%02x ", packet->data[i]);
        }
        printf("\n\n");
#endif

#ifdef CSP_USE_PROMISC
	/* Loopback traffic is added to promisc queue by the router */
	if (idout.dst != my_address && idout.src == my_address) {
		packet->id.ext = idout.ext;
		csp_promisc_add(packet, csp_promisc_queue);
	}
#endif

	/* Only encrypt packets from the current node */
	if (idout.src == my_address) {
		/* Append HMAC */
		if (idout.flags & CSP_FHMAC) {
#ifdef CSP_USE_HMAC
			/* Calculate and add HMAC */
			if (csp_hmac_append(packet) != 0) {
				/* HMAC append failed */
				csp_log_warn("HMAC append failed!\r\n");
				goto tx_err;
			}
#else
			csp_log_warn("Attempt to send packet with HMAC, but CSP was compiled without HMAC support. Discarding packet\r\n");
			goto tx_err;
#endif
		}

		/* Append CRC32 */
		if (idout.flags & CSP_FCRC32) {
#ifdef CSP_USE_CRC32
			/* Calculate and add CRC32 */
			if (csp_crc32_append(packet) != 0) {
				/* CRC32 append failed */
				csp_log_warn("CRC32 append failed!\r\n");
				goto tx_err;
			}
#else
			csp_log_warn("Attempt to send packet with CRC32, but CSP was compiled without CRC32 support. Sending without CRC32r\n");
			idout.flags &= ~(CSP_FCRC32);
#endif
		}

		if (idout.flags & CSP_FXTEA) {
#ifdef CSP_USE_XTEA
			/* Create nonce */
			uint32_t nonce, nonce_n;
			nonce = (uint32_t)rand();
			nonce_n = csp_hton32(nonce);
			memcpy(&packet->data[packet->length], &nonce_n, sizeof(nonce_n));

			/* Create initialization vector */
			uint32_t iv[2] = {nonce, 1};

			/* Encrypt data */
			if (csp_xtea_encrypt(packet->data, packet->length, iv) != 0) {
				/* Encryption failed */
				csp_log_warn("Encryption failed! Discarding packet\r\n");
				goto tx_err;
			}

			packet->length += sizeof(nonce_n);
#else
			csp_log_warn("Attempt to send XTEA encrypted packet, but CSP was compiled without XTEA support. Discarding packet\r\n");
			goto tx_err;
#endif
		}
	}

	/* Store length before passing to interface */
	uint16_t bytes = packet->length;
	uint16_t mtu = ifout->interface->mtu;

	if (mtu > 0 && bytes > mtu) {
		csp_log_warn("Attempt to send a packet larger than the interface's mtu.\r\n");
		goto tx_err;
	}

	/* Log the packet as sent over the interface */
	if (csp_packet_callback)
		csp_packet_callback(CSP_OUTPUT_RAW, ifout->interface->name, packet);

	if ((*ifout->interface->nexthop)(ifout->interface, packet, timeout) != CSP_ERR_NONE)
		goto tx_err;

	/* Update our transmit-time estimates, if the interface supports it */
	if (ifout->interface->tx_ms_per_byte) {
		/*
		 * If the completion time is in the past, that means
		 * the interface is not currently transmitting.
		 */
		uint32_t time_now = csp_get_ms();
		if (csp_time_after(time_now, ifout->interface->tx_done_time))
			ifout->interface->tx_done_time = time_now;

		ifout->interface->tx_done_time +=
			ifout->interface->tx_ms_per_packet
			+ bytes * ifout->interface->tx_ms_per_byte;

#if 0
		printf("DEBUG: now %u, expected completion at %u\n",
			time_now, ifout->interface->tx_done_time);
#endif
	}

	ifout->interface->tx++;
	ifout->interface->txbytes += bytes;
	return CSP_ERR_NONE;

tx_err:
	ifout->interface->tx_error++;
err:
	return CSP_ERR_TX;

}
Beispiel #3
0
int csp_send_direct(csp_id_t idout, csp_packet_t * packet, uint32_t timeout) {

    if (packet == NULL) {
        csp_log_error("csp_send_direct called with NULL packet\r\n");
        goto err;
    }

    csp_route_t * ifout = csp_route_if(idout.dst);

    if ((ifout == NULL) || (ifout->interface == NULL) || (ifout->interface->nexthop == NULL)) {
        csp_log_error("No route to host: %#08x\r\n", idout.ext);
        goto err;
    }

    csp_log_packet("Sending packet size %u from %u to %u port %u via interface %s\r\n", packet->length, idout.src, idout.dst, idout.dport, ifout->interface->name);

#ifdef CSP_USE_PROMISC
    /* Loopback traffic is added to promisc queue by the router */
    if (idout.dst != my_address) {
        packet->id.ext = idout.ext;
        csp_promisc_add(packet, csp_promisc_queue);
    }
#endif

    if (idout.flags & CSP_SEQNR) {
#ifdef CSP_USE_SEQNR
        /*Append the gloal seqnr. to the packet	*/
        if(csp_seqnr_append(packet) != 0) {
            /* SEQNR append failed */
            csp_log_warn("SEQNR append failed !\r\n");
            goto tx_err;
        }
#else
        csp_log_warn("Attempt to send packet with SEQNR, but csp was compiled without SEQNR support. Discarding packet\r\n");
        goto tx_err;
#endif
    }



    /* Only encrypt packets from the current node */
    if (idout.src == my_address) {
        /* Append HMAC */
        if (idout.flags & CSP_FHMAC) {
#ifdef CSP_USE_HMAC
            /* Calculate and add HMAC */
            if (csp_hmac_append(packet) != 0) {
                /* HMAC append failed */
                csp_log_warn("HMAC append failed!\r\n");
                goto tx_err;
            }
#else
            csp_log_warn("Attempt to send packet with HMAC, but CSP was compiled without HMAC support. Discarding packet\r\n");
            goto tx_err;
#endif
        }

        /* Append CRC32 */
        if (idout.flags & CSP_FCRC32) {
#ifdef CSP_USE_CRC32
            /* Calculate and add CRC32 */
            if (csp_crc32_append(packet) != 0) {
                /* CRC32 append failed */
                csp_log_warn("CRC32 append failed!\r\n");
                goto tx_err;
            }
#else
            csp_log_warn("Attempt to send packet with CRC32, but CSP was compiled without CRC32 support. Sending without CRC32r\n");
            idout.flags &= ~(CSP_FCRC32);
#endif
        }

        if (idout.flags & CSP_FXTEA) {
#ifdef CSP_USE_XTEA
            /* Create nonce */
            uint32_t nonce, nonce_n;
            nonce = (uint32_t)rand();
            nonce_n = csp_hton32(nonce);
            memcpy(&packet->data[packet->length], &nonce_n, sizeof(nonce_n));

            /* Create initialization vector */
            uint32_t iv[2] = {nonce, 1};

            /* Encrypt data */
            if (csp_xtea_encrypt(packet->data, packet->length, iv) != 0) {
                /* Encryption failed */
                csp_log_warn("Encryption failed! Discarding packet\r\n");
                goto tx_err;
            }

            packet->length += sizeof(nonce_n);
#else
            csp_log_warn("Attempt to send XTEA encrypted packet, but CSP was compiled without XTEA support. Discarding packet\r\n");
            goto tx_err;
#endif
        }
    }

    /* Copy identifier to packet */
    packet->id.ext = idout.ext;

    /* Store length before passing to interface */
    uint16_t bytes = packet->length;
    uint16_t mtu = ifout->interface->mtu;

    if (mtu > 0 && bytes > mtu)
        goto tx_err;

    if ((*ifout->interface->nexthop)(packet, timeout) != CSP_ERR_NONE)
        goto tx_err;

    ifout->interface->tx++;
    ifout->interface->txbytes += bytes;
    return CSP_ERR_NONE;

tx_err:
    ifout->interface->tx_error++;
err:
    return CSP_ERR_TX;

}
Beispiel #4
0
int csp_send_direct(csp_id_t idout, csp_packet_t * packet, csp_iface_t * ifout, uint32_t timeout) {

	if (packet == NULL) {
		csp_log_error("csp_send_direct called with NULL packet");
		goto err;
	}

	if ((ifout == NULL) || (ifout->nexthop == NULL)) {
		csp_log_error("No route to host: %#08x", idout.ext);
		goto err;
	}

	csp_log_packet("OUT: S %u, D %u, Dp %u, Sp %u, Pr %u, Fl 0x%02X, Sz %u VIA: %s",
		idout.src, idout.dst, idout.dport, idout.sport, idout.pri, idout.flags, packet->length, ifout->name);

	/* Copy identifier to packet (before crc, xtea and hmac) */
	packet->id.ext = idout.ext;

#ifdef CSP_USE_PROMISC
	/* Loopback traffic is added to promisc queue by the router */
	if (idout.dst != csp_get_address() && idout.src == csp_get_address()) {
		packet->id.ext = idout.ext;
		csp_promisc_add(packet);
	}
#endif

	/* Only encrypt packets from the current node */
	if (idout.src == csp_get_address()) {
		/* Append HMAC */
		if (idout.flags & CSP_FHMAC) {
#ifdef CSP_USE_HMAC
			/* Calculate and add HMAC (does not include header for backwards compatability with csp1.x) */
			if (csp_hmac_append(packet, false) != 0) {
				/* HMAC append failed */
				csp_log_warn("HMAC append failed!");
				goto tx_err;
			}
#else
			csp_log_warn("Attempt to send packet with HMAC, but CSP was compiled without HMAC support. Discarding packet");
			goto tx_err;
#endif
		}

		/* Append CRC32 */
		if (idout.flags & CSP_FCRC32) {
#ifdef CSP_USE_CRC32
			/* Calculate and add CRC32 (does not include header for backwards compatability with csp1.x) */
			if (csp_crc32_append(packet, false) != 0) {
				/* CRC32 append failed */
				csp_log_warn("CRC32 append failed!");
				goto tx_err;
			}
#else
			csp_log_warn("Attempt to send packet with CRC32, but CSP was compiled without CRC32 support. Sending without CRC32r");
			idout.flags &= ~(CSP_FCRC32);
#endif
		}

		if (idout.flags & CSP_FXTEA) {
#ifdef CSP_USE_XTEA
			/* Create nonce */
			uint32_t nonce, nonce_n;
			nonce = (uint32_t)rand();
			nonce_n = csp_hton32(nonce);
			memcpy(&packet->data[packet->length], &nonce_n, sizeof(nonce_n));

			/* Create initialization vector */
			uint32_t iv[2] = {nonce, 1};

			/* Encrypt data */
			if (csp_xtea_encrypt(packet->data, packet->length, iv) != 0) {
				/* Encryption failed */
				csp_log_warn("Encryption failed! Discarding packet");
				goto tx_err;
			}

			packet->length += sizeof(nonce_n);
#else
			csp_log_warn("Attempt to send XTEA encrypted packet, but CSP was compiled without XTEA support. Discarding packet");
			goto tx_err;
#endif
		}
	}

	/* Store length before passing to interface */
	uint16_t bytes = packet->length;
	uint16_t mtu = ifout->mtu;

	if (mtu > 0 && bytes > mtu)
		goto tx_err;

	if ((*ifout->nexthop)(ifout, packet, timeout) != CSP_ERR_NONE)
		goto tx_err;

	ifout->tx++;
	ifout->txbytes += bytes;
	return CSP_ERR_NONE;

tx_err:
	ifout->tx_error++;
err:
	return CSP_ERR_TX;

}