/* * Don't learn certain addresses. */ bool mroute_learnable_address(const struct mroute_addr *addr, struct gc_arena *gc) { int i; bool all_zeros = true; bool all_ones = true; for (i = 0; i < addr->len; ++i) { int b = addr->raw_addr[i]; if (b != 0x00) { all_zeros = false; } if (b != 0xFF) { all_ones = false; } } /* only networkss shorter than 8 bits are allowed to be all 0s. */ if (all_zeros && !((addr->type & MR_WITH_NETBITS) && (addr->netbits < 8))) { msg(D_MULTI_LOW, "Can't learn %s: network is all 0s, but netbits >= 8", mroute_addr_print(addr, gc)); return false; } if (all_ones) { msg(D_MULTI_LOW, "Can't learn %s: network is all 1s", mroute_addr_print(addr, gc)); return false; } if (is_mac_mcast_maddr(addr)) { msg(D_MULTI_LOW, "Can't learn %s: network is a multicast address", mroute_addr_print(addr, gc)); return false; } return true; }
static struct multi_instance * multi_create_instance_tcp(struct multi_context *m) { struct gc_arena gc = gc_new(); struct multi_instance *mi = NULL; struct hash *hash = m->hash; mi = multi_create_instance(m, NULL); if (mi) { struct hash_element *he; const uint32_t hv = hash_value(hash, &mi->real); struct hash_bucket *bucket = hash_bucket(hash, hv); he = hash_lookup_fast(hash, bucket, &mi->real, hv); if (he) { struct multi_instance *oldmi = (struct multi_instance *) he->value; msg(D_MULTI_LOW, "MULTI TCP: new incoming client address matches existing client address -- new client takes precedence"); oldmi->did_real_hash = false; multi_close_instance(m, oldmi, false); he->key = &mi->real; he->value = mi; } else { hash_add_fast(hash, bucket, &mi->real, hv, mi); } mi->did_real_hash = true; } #ifdef ENABLE_DEBUG if (mi) { dmsg(D_MULTI_DEBUG, "MULTI TCP: instance added: %s", mroute_addr_print(&mi->real, &gc)); } else { dmsg(D_MULTI_DEBUG, "MULTI TCP: new client instance failed"); } #endif gc_free(&gc); ASSERT(!(mi && mi->halt)); return mi; }
struct multi_instance * multi_get_create_instance_udp (struct multi_context *m) { struct gc_arena gc = gc_new (); struct mroute_addr real; struct multi_instance *mi = NULL; struct hash *hash = m->hash; if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true)) { struct hash_element *he; const uint32_t hv = hash_value (hash, &real); struct hash_bucket *bucket = hash_bucket (hash, hv); he = hash_lookup_fast (hash, bucket, &real, hv); if (he) { mi = (struct multi_instance *) he->value; } else { if (!m->top.c2.tls_auth_standalone || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf)) { if (frequency_limit_event_allowed (m->new_connection_limiter)) { mi = multi_create_instance (m, &real); if (mi) { hash_add_fast (hash, bucket, &mi->real, hv, mi); mi->did_real_hash = true; } } else { msg (D_MULTI_ERRORS, "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq", mroute_addr_print (&real, &gc)); } } } #ifdef ENABLE_DEBUG if (check_debug_level (D_MULTI_DEBUG)) { const char *status; if (he && mi) status = "[succeeded]"; else if (!he && mi) status = "[created]"; else status = "[failed]"; dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s", mroute_addr_print (&real, &gc), status); } #endif } gc_free (&gc); ASSERT (!(mi && mi->halt)); return mi; }
struct multi_instance * multi_get_create_instance_udp (struct multi_context *m, bool *floated) { struct gc_arena gc = gc_new (); struct mroute_addr real; struct multi_instance *mi = NULL; struct hash *hash = m->hash; if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true) && m->top.c2.buf.len > 0) { struct hash_element *he; const uint32_t hv = hash_value (hash, &real); struct hash_bucket *bucket = hash_bucket (hash, hv); uint8_t* ptr = BPTR(&m->top.c2.buf); uint8_t op = ptr[0] >> P_OPCODE_SHIFT; /* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */ if (op == P_DATA_V2 && m->top.c2.buf.len >= (1 + 3)) { uint32_t peer_id = ntohl(*(uint32_t*)ptr) & 0xFFFFFF; if ((peer_id < m->max_clients) && (m->instances[peer_id])) { mi = m->instances[peer_id]; *floated = !link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from); if (*floated) { /* reset prefix, since here we are not sure peer is the one it claims to be */ ungenerate_prefix(mi); msg (D_MULTI_ERRORS, "Untrusted peer %" PRIu32 " wants to float to %s", peer_id, mroute_addr_print (&real, &gc)); } } } else { he = hash_lookup_fast (hash, bucket, &real, hv); if (he) { mi = (struct multi_instance *) he->value; } } if (!mi) { if (!m->top.c2.tls_auth_standalone || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf)) { if (frequency_limit_event_allowed (m->new_connection_limiter)) { mi = multi_create_instance (m, &real); if (mi) { int i; hash_add_fast (hash, bucket, &mi->real, hv, mi); mi->did_real_hash = true; for (i = 0; i < m->max_clients; ++i) { if (!m->instances[i]) { mi->context.c2.tls_multi->peer_id = i; m->instances[i] = mi; break; } } /* should not really end up here, since multi_create_instance returns null * if amount of clients exceeds max_clients */ ASSERT(i < m->max_clients); } } else { msg (D_MULTI_ERRORS, "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq", mroute_addr_print (&real, &gc)); } } } #ifdef ENABLE_DEBUG if (check_debug_level (D_MULTI_DEBUG)) { const char *status = mi ? "[ok]" : "[failed]"; dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s", mroute_addr_print (&real, &gc), status); } #endif } gc_free (&gc); ASSERT (!(mi && mi->halt)); return mi; }