|
|
|
|
@ -151,94 +151,55 @@ static void routing_pkt_from_etcp_cb(struct ETCP_CONN* conn, struct ll_entry* en
|
|
|
|
|
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"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!instance->rt) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: no route table"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: invalid instance"); return; } |
|
|
|
|
|
|
|
|
|
if (!instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: no route table"); return; } |
|
|
|
|
|
|
|
|
|
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_data_get(instance->tun->output_queue); |
|
|
|
|
if (!pkt) return; |
|
|
|
|
|
|
|
|
|
bool pkt_freed = false; |
|
|
|
|
|
|
|
|
|
if (pkt->ll.dgram && pkt->ll.len > 0) { |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
if (!pkt->ll.dgram || pkt->ll.len <= 0) break; |
|
|
|
|
|
|
|
|
|
dump_ip_packet("TUN->routing", (const uint8_t*)pkt->ll.dgram, pkt->ll.len); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t dst_ip = extract_dst_ip(pkt->ll.dgram, pkt->ll.len); |
|
|
|
|
if (dst_ip == 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Failed to extract destination IP, dropping packet"); |
|
|
|
|
u_free(pkt->ll.dgram); |
|
|
|
|
pkt->ll.dgram = NULL; |
|
|
|
|
memory_pool_free(instance->tun->pool, pkt); |
|
|
|
|
pkt_freed = true; |
|
|
|
|
} else { |
|
|
|
|
struct in_addr addr; |
|
|
|
|
addr.s_addr = htonl(dst_ip); |
|
|
|
|
|
|
|
|
|
struct ROUTE_ARRAY* routes = route_table_lookup(instance->rt, dst_ip); |
|
|
|
|
if (!routes || routes->routes == 0) { |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "No route to %s, dropping packet", ip_to_str(&addr, AF_INET).str); |
|
|
|
|
u_free(pkt->ll.dgram); |
|
|
|
|
pkt->ll.dgram = NULL; |
|
|
|
|
memory_pool_free(instance->tun->pool, pkt); |
|
|
|
|
pkt_freed = true; |
|
|
|
|
} else { |
|
|
|
|
struct ETCP_CONN* conn = routes->entries[0]->next_hop; |
|
|
|
|
if (!conn) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Route to %s has no next_hop, dropping packet", ip_to_str(&addr, AF_INET).str); |
|
|
|
|
u_free(pkt->ll.dgram); |
|
|
|
|
pkt->ll.dgram = NULL; |
|
|
|
|
memory_pool_free(instance->tun->pool, pkt); |
|
|
|
|
pkt_freed = true; |
|
|
|
|
} else if (!conn->normalizer) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Connection for %s has no normalizer, dropping packet", ip_to_str(&addr, AF_INET).str); |
|
|
|
|
u_free(pkt->ll.dgram); |
|
|
|
|
pkt->ll.dgram = NULL; |
|
|
|
|
memory_pool_free(instance->tun->pool, pkt); |
|
|
|
|
pkt_freed = true; |
|
|
|
|
} else { |
|
|
|
|
size_t etcp_data_len = 1 + pkt->ll.len; |
|
|
|
|
struct ll_entry* entry = ll_alloc_lldgram(etcp_data_len); |
|
|
|
|
if (!entry) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to allocate entry for ETCP send"); |
|
|
|
|
u_free(pkt->ll.dgram); |
|
|
|
|
pkt->ll.dgram = NULL; |
|
|
|
|
memory_pool_free(instance->tun->pool, pkt); |
|
|
|
|
pkt_freed = true; |
|
|
|
|
} else { |
|
|
|
|
entry->dgram[0] = ETCP_ID_DATA; |
|
|
|
|
memcpy(entry->dgram + 1, pkt->ll.dgram, pkt->ll.len); |
|
|
|
|
entry->len = etcp_data_len; |
|
|
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "Sendign dgram to ETCP %s len=%d", conn->log_name, entry->len); |
|
|
|
|
if (etcp_send(conn, entry) != 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "etcp_send failed for %s", ip_to_str(&addr, AF_INET).str); |
|
|
|
|
queue_entry_free(entry); |
|
|
|
|
queue_dgram_free(entry); |
|
|
|
|
}
|
|
|
|
|
if (dst_ip == 0) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Failed to extract destination IP, dropping packet"); break; } |
|
|
|
|
|
|
|
|
|
goto cleanup; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
memory_pool_free(instance->tun->pool, pkt); |
|
|
|
|
pkt_freed = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cleanup: |
|
|
|
|
if (!pkt_freed) { |
|
|
|
|
if (pkt->ll.dgram) { |
|
|
|
|
u_free(pkt->ll.dgram); |
|
|
|
|
struct in_addr addr; |
|
|
|
|
addr.s_addr = htonl(dst_ip); |
|
|
|
|
|
|
|
|
|
struct ROUTE_ARRAY* routes = route_table_lookup(instance->rt, dst_ip); |
|
|
|
|
if (!routes || routes->routes == 0) { DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "No route to %s, dropping packet", ip_to_str(&addr, AF_INET).str); break; } |
|
|
|
|
|
|
|
|
|
struct ETCP_CONN* conn = routes->entries[0]->next_hop; |
|
|
|
|
if (!conn) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Route to %s has no next_hop, dropping packet", ip_to_str(&addr, AF_INET).str); break; } |
|
|
|
|
|
|
|
|
|
if (!conn->normalizer) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Connection for %s has no normalizer, dropping packet", ip_to_str(&addr, AF_INET).str); break; } |
|
|
|
|
|
|
|
|
|
size_t etcp_data_len = 1 + pkt->ll.len; |
|
|
|
|
struct ll_entry* entry = ll_alloc_lldgram(etcp_data_len); |
|
|
|
|
if (!entry) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to allocate entry for ETCP send"); break; } |
|
|
|
|
|
|
|
|
|
entry->dgram[0] = ETCP_ID_DATA; |
|
|
|
|
memcpy(entry->dgram + 1, pkt->ll.dgram, pkt->ll.len); |
|
|
|
|
entry->len = etcp_data_len; |
|
|
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "Sending dgram to ETCP %s len=%d", conn->log_name, entry->len); |
|
|
|
|
if (etcp_send(conn, entry) != 0) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "etcp_send failed for %s", ip_to_str(&addr, AF_INET).str); |
|
|
|
|
queue_dgram_free(entry); |
|
|
|
|
queue_entry_free(entry); |
|
|
|
|
} |
|
|
|
|
memory_pool_free(instance->tun->pool, pkt); |
|
|
|
|
|
|
|
|
|
} while (0); |
|
|
|
|
|
|
|
|
|
if (pkt->ll.dgram) { |
|
|
|
|
u_free(pkt->ll.dgram); |
|
|
|
|
pkt->ll.dgram = NULL; |
|
|
|
|
} |
|
|
|
|
memory_pool_free(instance->tun->pool, pkt); |
|
|
|
|
|
|
|
|
|
queue_resume_callback(instance->tun->output_queue); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|