diff options
Diffstat (limited to 'nhrpd/nhrp_peer.c')
-rw-r--r-- | nhrpd/nhrp_peer.c | 235 |
1 files changed, 154 insertions, 81 deletions
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index dfede1d7d..9899b4fa0 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -183,8 +183,7 @@ static void *nhrp_peer_create(void *data) .ref = 0, .ifp = key->ifp, .vc = key->vc, - .notifier_list = - NOTIFIER_LIST_INITIALIZER(&p->notifier_list), + .notifier_list = NOTIFIER_LIST_INITIALIZER(&p->notifier_list), }; nhrp_vc_notify_add(p->vc, &p->vc_notifier, nhrp_peer_vc_notify); nhrp_interface_notify_add(p->ifp, &p->ifp_notifier, @@ -293,15 +292,19 @@ static int nhrp_peer_defer_vici_request(struct thread *t) char buf[256]; THREAD_OFF(p->t_timer); - if(p->online) { - debugf(NHRP_DEBUG_COMMON, "IPsec connection to %s already established\n", sockunion2str(&vc->remote.nbma, buf, sizeof(buf)) ? buf : "NULL"); - } - else { - vici_request_vc(nifp->ipsec_profile, &vc->local.nbma, &vc->remote.nbma, - p->prio); - thread_add_timer(master, nhrp_peer_request_timeout, p, - (nifp->ipsec_fallback_profile && !p->prio) ? 15 : 30, - &p->t_fallback); + if (p->online) { + debugf(NHRP_DEBUG_COMMON, + "IPsec connection to %s already established\n", + sockunion2str(&vc->remote.nbma, buf, sizeof(buf)) + ? buf + : "NULL"); + } else { + vici_request_vc(nifp->ipsec_profile, &vc->local.nbma, + &vc->remote.nbma, p->prio); + thread_add_timer( + master, nhrp_peer_request_timeout, p, + (nifp->ipsec_fallback_profile && !p->prio) ? 15 : 30, + &p->t_fallback); } return 0; } @@ -329,20 +332,24 @@ int nhrp_peer_check(struct nhrp_peer *p, int establish) p->prio = establish > 1; p->requested = 1; - //All NHRP registration requests are prioritized - if(p->prio) - { - vici_request_vc(nifp->ipsec_profile, &vc->local.nbma, &vc->remote.nbma, - p->prio); - thread_add_timer(master, nhrp_peer_request_timeout, p, - (nifp->ipsec_fallback_profile && !p->prio) ? 15 : 30, - &p->t_fallback); - } - else - { - int r_time_ms = rand() % 1000; //Maximum timeout is 1 seconds - debugf(NHRP_DEBUG_COMMON, "Initiating IPsec connection request to %s after %d ms:\n", sockunion2str(&vc->remote.nbma, buf, sizeof(buf)) ? buf : "NULL", r_time_ms); - thread_add_timer_msec(master, nhrp_peer_defer_vici_request, p, r_time_ms, &p->t_timer); + /* All NHRP registration requests are prioritized */ + if (p->prio) { + vici_request_vc(nifp->ipsec_profile, &vc->local.nbma, + &vc->remote.nbma, p->prio); + thread_add_timer( + master, nhrp_peer_request_timeout, p, + (nifp->ipsec_fallback_profile && !p->prio) ? 15 : 30, + &p->t_fallback); + } else { + int r_time_ms = rand() % 1000; // Maximum timeout is 1 seconds + debugf(NHRP_DEBUG_COMMON, + "Initiating IPsec connection request to %s after %d ms:\n", + sockunion2str(&vc->remote.nbma, buf, sizeof(buf)) + ? buf + : "NULL", + r_time_ms); + thread_add_timer_msec(master, nhrp_peer_defer_vici_request, + p, r_time_ms, &p->t_timer); } return 0; @@ -376,7 +383,9 @@ void nhrp_peer_send(struct nhrp_peer *p, struct zbuf *zb) zbuf_reset(zb); } -static void nhrp_process_nat_extension(struct nhrp_packet_parser *pp, union sockunion *proto, union sockunion *cie_nbma) +static void nhrp_process_nat_extension(struct nhrp_packet_parser *pp, + union sockunion *proto, + union sockunion *cie_nbma) { char buf[2][256]; union sockunion cie_proto; @@ -385,31 +394,46 @@ static void nhrp_process_nat_extension(struct nhrp_packet_parser *pp, union sock struct zbuf *extensions; - if(!proto || !cie_nbma || sockunion_family(proto) == AF_UNSPEC) + if (!proto || !cie_nbma || sockunion_family(proto) == AF_UNSPEC) return; sockunion_family(cie_nbma) = AF_UNSPEC; /* Handle extensions */ extensions = zbuf_alloc(zbuf_used(&pp->extensions)); - if(extensions) - { - zbuf_copy_peek(extensions, &pp->extensions, zbuf_used(&pp->extensions)); + if (extensions) { + zbuf_copy_peek(extensions, &pp->extensions, + zbuf_used(&pp->extensions)); while ((ext = nhrp_ext_pull(extensions, &payload)) != NULL) { - switch (htons(ext->type) & ~NHRP_EXTENSION_FLAG_COMPULSORY) { + switch (htons(ext->type) + & ~NHRP_EXTENSION_FLAG_COMPULSORY) { case NHRP_EXTENSION_NAT_ADDRESS: - /* Process the NBMA and proto address in NAT extension and update the cache - * without which the neighbor table in the kernel contains the source NBMA address - * which is not reachable since it is behind a NAT device */ - debugf(NHRP_DEBUG_COMMON,"Processing NAT Extension for %s", sockunion2str(proto, buf[0], sizeof(buf[0])) ? buf[0] : "NULL"); - while (nhrp_cie_pull(&payload, pp->hdr, cie_nbma, &cie_proto)) - { - if(sockunion_family(&cie_proto) == AF_UNSPEC) + /* Process the NBMA and proto address in NAT + * extension and update the cache without which + * the neighbor table in the kernel contains the + * source NBMA address which is not reachable + * since it is behind a NAT device */ + debugf(NHRP_DEBUG_COMMON, + "Processing NAT Extension for %s", + sockunion2str(proto, buf[0], + sizeof(buf[0])) + ? buf[0] + : "NULL"); + while (nhrp_cie_pull(&payload, pp->hdr, + cie_nbma, &cie_proto)) { + if (sockunion_family(&cie_proto) + == AF_UNSPEC) continue; - if(!sockunion_cmp(proto, &cie_proto)) - { - debugf(NHRP_DEBUG_COMMON,"cie_nbma for proto %s is %s", buf[0] ? buf[0] : "NULL", sockunion2str(cie_nbma, buf[1], sizeof(buf[1])) ? buf[1] : "NULL"); + if (!sockunion_cmp(proto, &cie_proto)) { + debugf(NHRP_DEBUG_COMMON, + "cie_nbma for proto %s is %s", + buf[0] ? buf[0] : "NULL", + sockunion2str( + cie_nbma, buf[1], + sizeof(buf[1])) + ? buf[1] + : "NULL"); break; } } @@ -427,7 +451,8 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *pp) struct nhrp_cie_header *cie; struct nhrp_extension_header *ext; struct nhrp_cache *c; - union sockunion cie_nbma, cie_nbma_nat, cie_proto, *proto_addr, *nbma_addr, *claimed_nbma_addr; + union sockunion cie_nbma, cie_nbma_nat, cie_proto, *proto_addr, + *nbma_addr, *claimed_nbma_addr; int holdtime, prefix_len, hostprefix_len; struct nhrp_interface *nifp = ifp->info; struct nhrp_peer *peer; @@ -486,31 +511,43 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *pp) ? &pp->src_proto : &cie_proto; - /* Check if there is an entry for this proto_addr in NHRP_NAT_EXTENSION */ + /* Check if there is an entry for this proto_addr in + * NHRP_NAT_EXTENSION */ nhrp_process_nat_extension(pp, proto_addr, &cie_nbma_nat); - if(sockunion_family(&cie_nbma_nat) == AF_UNSPEC) - { - /* It may be possible that this resolution reply is coming directly from NATTED Spoke - * and there is not NAT Extension present */ - debugf(NHRP_DEBUG_COMMON,"No NAT Extension for %s", sockunion2str(proto_addr, buf, sizeof(buf)) ? buf : "NULL"); - - if (!sockunion_same(&pp->src_nbma, &pp->peer->vc->remote.nbma) && !nhrp_nhs_match_ip(&pp->peer->vc->remote.nbma, nifp)) - { - debugf(NHRP_DEBUG_COMMON,"Remote Device is NATTED"); + if (sockunion_family(&cie_nbma_nat) == AF_UNSPEC) { + /* It may be possible that this resolution reply is + * coming directly from NATTED Spoke and there is not + * NAT Extension present */ + debugf(NHRP_DEBUG_COMMON, "No NAT Extension for %s", + sockunion2str(proto_addr, buf, sizeof(buf)) + ? buf + : "NULL"); + + if (!sockunion_same(&pp->src_nbma, + &pp->peer->vc->remote.nbma) + && !nhrp_nhs_match_ip(&pp->peer->vc->remote.nbma, + nifp)) { + debugf(NHRP_DEBUG_COMMON, + "Remote Device is NATTED"); cie_nbma_nat = pp->peer->vc->remote.nbma; - debugf(NHRP_DEBUG_COMMON,"Device is natted using %s as cie_nbma", sockunion2str(&cie_nbma_nat, buf, sizeof(buf)) ? buf : "NULL"); + debugf(NHRP_DEBUG_COMMON, + "Device is natted using %s as cie_nbma", + sockunion2str(&cie_nbma_nat, buf, + sizeof(buf)) + ? buf + : "NULL"); } } - if(sockunion_family(&cie_nbma_nat) != AF_UNSPEC) + if (sockunion_family(&cie_nbma_nat) != AF_UNSPEC) nbma_addr = &cie_nbma_nat; - else if(sockunion_family(&cie_nbma) != AF_UNSPEC) + else if (sockunion_family(&cie_nbma) != AF_UNSPEC) nbma_addr = &cie_nbma; else nbma_addr = &pp->src_nbma; - if(sockunion_family(&cie_nbma) != AF_UNSPEC) + if (sockunion_family(&cie_nbma) != AF_UNSPEC) claimed_nbma_addr = &cie_nbma; else claimed_nbma_addr = &pp->src_nbma; @@ -536,9 +573,10 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *pp) debugf(NHRP_DEBUG_COMMON, "shortcut res_rep: updating binding for nmba addr %s", nbma_addr ? buf : "(NULL)"); - if (!nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC, holdtime, - nhrp_peer_get(pp->ifp, nbma_addr), - htons(cie->mtu), nbma_addr, claimed_nbma_addr)) { + if (!nhrp_cache_update_binding( + c, NHRP_CACHE_DYNAMIC, holdtime, + nhrp_peer_get(pp->ifp, nbma_addr), htons(cie->mtu), + nbma_addr, claimed_nbma_addr)) { cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED; continue; } @@ -580,7 +618,8 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *pp) goto err; if (sockunion_family(&nifp->nat_nbma) != AF_UNSPEC) { cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, - &nifp->nat_nbma, &pp->if_ad->addr); + &nifp->nat_nbma, + &pp->if_ad->addr); if (!cie) goto err; cie->mtu = htons(pp->if_ad->mtu); @@ -665,9 +704,11 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p) : &cie_nbma; nbma_natoa = NULL; if (natted) { - nbma_natoa = (sockunion_family(&p->peer->vc->remote.nbma) == AF_UNSPEC) - ? nbma_addr - : &p->peer->vc->remote.nbma; + nbma_natoa = + (sockunion_family(&p->peer->vc->remote.nbma) + == AF_UNSPEC) + ? nbma_addr + : &p->peer->vc->remote.nbma; } holdtime = htons(cie->holding_time); @@ -682,7 +723,8 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p) if (!nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC, holdtime, nhrp_peer_ref(p->peer), - htons(cie->mtu), nbma_natoa, nbma_addr)) { + htons(cie->mtu), nbma_natoa, + nbma_addr)) { cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED; continue; } @@ -701,8 +743,11 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p) zbuf_copy(zb, &payload, zbuf_used(&payload)); if (natted) { cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, - &p->peer->vc->remote.nbma, - &p->src_proto); + &p->peer->vc->remote.nbma, + &p->src_proto); + cie->prefix_length = + 8 * sockunion_get_addrlen( + &p->if_ad->addr); cie->mtu = htons(p->if_ad->mtu); } nhrp_ext_complete(zb, ext); @@ -909,7 +954,8 @@ static void nhrp_peer_forward(struct nhrp_peer *p, struct nhrp_cie_header *cie; struct nhrp_interface *nifp = pp->ifp->info; struct nhrp_afi_data *if_ad = pp->if_ad; - union sockunion cie_nbma, cie_protocol, cie_protocol_mandatory, *proto = NULL; + union sockunion cie_nbma, cie_protocol, cie_protocol_mandatory, + *proto = NULL; uint16_t type, len; struct nhrp_cache *c; char buf[SU_ADDRSTRLEN]; @@ -971,32 +1017,59 @@ static void nhrp_peer_forward(struct nhrp_peer *p, } break; case NHRP_EXTENSION_NAT_ADDRESS: - /* if NAT extension is not empty then copy it across else attempt to populate it */ + /* if NAT extension is not empty then copy it across + * else attempt to populate it */ if (len > 0) { zbuf_copy(zb, &extpl, len); } else { - if(packet_types[hdr->type].type == PACKET_REQUEST) { - debugf(NHRP_DEBUG_COMMON,"Processing NHRP_EXTENSION_NAT_ADDRESS while forwarding the request packet"); + if (packet_types[hdr->type].type + == PACKET_REQUEST) { + debugf(NHRP_DEBUG_COMMON, + "Processing NHRP_EXTENSION_NAT_ADDRESS while forwarding the request packet"); proto = &pp->src_proto; - } else if(packet_types[hdr->type].type == PACKET_REPLY) { - debugf(NHRP_DEBUG_COMMON,"Processing NHRP_EXTENSION_NAT_ADDRESS while forwarding the reply packet"); - /* For reply packet use protocol specified in CIE of mandatory part for cache lookup */ - if(sockunion_family(&cie_protocol_mandatory) != AF_UNSPEC) + } else if (packet_types[hdr->type].type + == PACKET_REPLY) { + debugf(NHRP_DEBUG_COMMON, + "Processing NHRP_EXTENSION_NAT_ADDRESS while forwarding the reply packet"); + /* For reply packet use protocol + * specified in CIE of mandatory part + * for cache lookup */ + if (sockunion_family( + &cie_protocol_mandatory) + != AF_UNSPEC) proto = &cie_protocol_mandatory; } - if(proto) { - debugf(NHRP_DEBUG_COMMON,"Proto is %s", sockunion2str(proto, buf, sizeof(buf))); + if (proto) { + debugf(NHRP_DEBUG_COMMON, "Proto is %s", + sockunion2str(proto, buf, + sizeof(buf))); c = nhrp_cache_get(nifp->ifp, proto, 0); - if(c) { - debugf(NHRP_DEBUG_COMMON,"c->cur.remote_nbma_natoa is %s", sockunion2str(&c->cur.remote_nbma_natoa, buf, sizeof(buf)) ? buf : "NULL"); - if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) { - cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS,&c->cur.remote_nbma_natoa, proto); + if (c) { + debugf(NHRP_DEBUG_COMMON, + "c->cur.remote_nbma_natoa is %s", + sockunion2str( + &c->cur.remote_nbma_natoa, + buf, sizeof(buf)) + ? buf + : "NULL"); + if (sockunion_family( + &c->cur.remote_nbma_natoa) + != AF_UNSPEC) { + cie = nhrp_cie_push( + zb, + NHRP_CODE_SUCCESS, + &c->cur.remote_nbma_natoa, + proto); if (!cie) goto err; } } else { - debugf(NHRP_DEBUG_COMMON,"No cache entry for Proto is %s", sockunion2str(proto, buf, sizeof(buf))); + debugf(NHRP_DEBUG_COMMON, + "No cache entry for Proto is %s", + sockunion2str( + proto, buf, + sizeof(buf))); zbuf_put(zb, extpl.head, len); } } else { |