|
|
|
|
@ -53,7 +53,8 @@ static uint32_t extract_dst_ip(uint8_t* data, size_t len) {
|
|
|
|
|
// entry format: <id 1 byte> <ip_packet ...>
|
|
|
|
|
static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) { |
|
|
|
|
if (!instance || !entry) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_pkt: invalid arguments"); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_pkt: invalid arguments: instance=%p entry=%p entry->len=%zu", |
|
|
|
|
(void*)instance, (void*)entry, entry ? entry->len : 0); |
|
|
|
|
if (entry) { |
|
|
|
|
queue_entry_free(entry); |
|
|
|
|
queue_dgram_free(entry); |
|
|
|
|
@ -77,7 +78,7 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
|
|
|
|
|
|
|
|
|
|
// Check packet data (skip cmd byte)
|
|
|
|
|
if (!entry->dgram || entry->len < 2) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: packet too small or no data"); |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: packet too small: len=%zu, expected >=2", entry->len); |
|
|
|
|
queue_entry_free(entry); |
|
|
|
|
queue_dgram_free(entry); |
|
|
|
|
return; |
|
|
|
|
@ -89,8 +90,8 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
|
|
|
|
|
|
|
|
|
|
// Check MTU
|
|
|
|
|
if (ip_len > TUN_MAX_PACKET_SIZE) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: packet too large: %zu bytes (max %d)", |
|
|
|
|
ip_len, TUN_MAX_PACKET_SIZE); |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: packet too large: len=%zu max=%d, dropping", |
|
|
|
|
ip_len, TUN_MAX_PACKET_SIZE); |
|
|
|
|
queue_entry_free(entry); |
|
|
|
|
queue_dgram_free(entry); |
|
|
|
|
return; |
|
|
|
|
@ -99,7 +100,8 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
|
|
|
|
|
// Extract destination IP
|
|
|
|
|
uint32_t dst_ip = extract_dst_ip(ip_data, ip_len); |
|
|
|
|
if (dst_ip == 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to extract destination IP, dropping"); |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to extract dst IP: len=%zu first_byte=0x%02x, dropping", |
|
|
|
|
ip_len, ip_data ? ip_data[0] : 0); |
|
|
|
|
queue_entry_free(entry); |
|
|
|
|
queue_dgram_free(entry); |
|
|
|
|
return; |
|
|
|
|
@ -122,8 +124,10 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
|
|
|
|
|
// Check route type
|
|
|
|
|
if (routes->entries[0]->type == ROUTE_TYPE_LOCAL) { |
|
|
|
|
// Local route - send to TUN (entry has [cmd=0][IP data], TUN skips cmd byte)
|
|
|
|
|
if (queue_data_put(instance->tun->input_queue, entry, 0) != 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to put to TUN input_queue"); |
|
|
|
|
int put_err = queue_data_put(instance->tun->input_queue, entry, 0); |
|
|
|
|
if (put_err != 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to put to TUN: dst=%s err=%d", |
|
|
|
|
ip_to_str(&addr, AF_INET).str, put_err); |
|
|
|
|
instance->dropped_packets++; |
|
|
|
|
queue_entry_free(entry); |
|
|
|
|
queue_dgram_free(entry); |
|
|
|
|
@ -155,8 +159,10 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
|
|
|
|
|
|
|
|
|
|
// Send to ETCP
|
|
|
|
|
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to ETCP %s", ip_len, conn->log_name); |
|
|
|
|
if (etcp_send(conn, entry) != 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_send failed for %s", ip_to_str(&addr, AF_INET).str); |
|
|
|
|
int send_err = etcp_send(conn, entry); |
|
|
|
|
if (send_err != 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_send failed: dst=%s err=%d", |
|
|
|
|
ip_to_str(&addr, AF_INET).str, send_err); |
|
|
|
|
instance->dropped_packets++; |
|
|
|
|
queue_entry_free(entry); |
|
|
|
|
queue_dgram_free(entry); |
|
|
|
|
@ -170,7 +176,8 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
|
|
|
|
|
// Callback for packets from ETCP (via etcp_bind id=0)
|
|
|
|
|
static void routing_pkt_from_etcp_cb(struct ETCP_CONN* conn, struct ll_entry* pkt) { |
|
|
|
|
if (!conn || !pkt) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: invalid arguments"); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: invalid arguments: conn=%p pkt=%p", |
|
|
|
|
(void*)conn, (void*)pkt); |
|
|
|
|
if (pkt) { |
|
|
|
|
queue_entry_free(pkt); |
|
|
|
|
queue_dgram_free(pkt); |
|
|
|
|
@ -180,7 +187,8 @@ static void routing_pkt_from_etcp_cb(struct ETCP_CONN* conn, struct ll_entry* pk
|
|
|
|
|
|
|
|
|
|
struct UTUN_INSTANCE* instance = conn->instance; |
|
|
|
|
if (!instance) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: connection has no instance"); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: connection has no instance: conn=%p pkt_len=%zu", |
|
|
|
|
(void*)conn, pkt->len); |
|
|
|
|
queue_entry_free(pkt); |
|
|
|
|
queue_dgram_free(pkt); |
|
|
|
|
return; |
|
|
|
|
@ -194,7 +202,7 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
|
|
|
|
|
(void)q; |
|
|
|
|
struct UTUN_INSTANCE* instance = (struct UTUN_INSTANCE*)arg; |
|
|
|
|
if (!instance) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: invalid instance"); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: invalid instance arg=%p", arg); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -218,19 +226,22 @@ int routing_create(struct UTUN_INSTANCE* instance) {
|
|
|
|
|
// Create route table
|
|
|
|
|
instance->rt = route_table_create(); |
|
|
|
|
if (!instance->rt) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to create route table"); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_create: failed to create route table for node %016llx", |
|
|
|
|
(unsigned long long)instance->node_id); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Bind ID=0 for receiving data packets from ETCP
|
|
|
|
|
if (etcp_bind(instance, ETCP_ID_DATA, routing_pkt_from_etcp_cb) != 0) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to bind ETCP ID=0"); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_create: failed to bind ETCP ID=0 for node %016llx", |
|
|
|
|
(unsigned long long)instance->node_id); |
|
|
|
|
route_table_destroy(instance->rt); |
|
|
|
|
instance->rt = NULL; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing module initialized for instance"); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing module initialized for instance node_id=%016llx", |
|
|
|
|
(unsigned long long)instance->node_id); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
@ -239,7 +250,8 @@ int routing_create(struct UTUN_INSTANCE* instance) {
|
|
|
|
|
void routing_destroy(struct UTUN_INSTANCE* instance) { |
|
|
|
|
if (!instance) return; |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Destroying routing module"); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Destroying routing module for node_id=%016llx", |
|
|
|
|
(unsigned long long)instance->node_id); |
|
|
|
|
|
|
|
|
|
// Unbind ETCP ID=0
|
|
|
|
|
etcp_unbind(instance, ETCP_ID_DATA); |
|
|
|
|
@ -273,12 +285,14 @@ void routing_set_tun(struct UTUN_INSTANCE* instance) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!instance->tun) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_set_tun: instance has no TUN"); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_set_tun: instance %016llx has no TUN", |
|
|
|
|
(unsigned long long)instance->node_id); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set callback on TUN output queue (packets from TUN to routing)
|
|
|
|
|
queue_set_callback(instance->tun->output_queue, routing_pkt_from_tun_cb, instance); |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "TUN interface registered in routing module"); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "TUN interface registered: ifname=%s node_id=%016llx", |
|
|
|
|
instance->tun->ifname, (unsigned long long)instance->node_id); |
|
|
|
|
} |
|
|
|
|
|