diff options
| author | kefren <kefren@NetBSD.org> | 2013-02-05 13:02:33 +0000 |
|---|---|---|
| committer | kefren <kefren@NetBSD.org> | 2013-02-05 13:02:33 +0000 |
| commit | 00a254a70697c471ee4cea8309f50d5e8550f33e (patch) | |
| tree | 2210dce6843bbdd444954c08de5482ba7db2f558 /usr.sbin/ldpd | |
| parent | e041116831c947aebd361da99c8ac158d773efd8 (diff) | |
Stop confusing peer hello source with peer transport address
Diffstat (limited to 'usr.sbin/ldpd')
| -rw-r--r-- | usr.sbin/ldpd/fsm.c | 95 |
1 files changed, 47 insertions, 48 deletions
diff --git a/usr.sbin/ldpd/fsm.c b/usr.sbin/ldpd/fsm.c index 2a43912153a..5748a1fb032 100644 --- a/usr.sbin/ldpd/fsm.c +++ b/usr.sbin/ldpd/fsm.c @@ -1,4 +1,4 @@ -/* $NetBSD: fsm.c,v 1.9 2013/02/03 19:41:59 kefren Exp $ */ +/* $NetBSD: fsm.c,v 1.10 2013/02/05 13:02:33 kefren Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -56,7 +56,8 @@ run_ldp_hello(struct ldp_pdu * pduid, struct hello_tlv * ht, { struct ldp_peer *peer = NULL; struct transport_address_tlv *trtlv; - struct hello_info *hi; + struct hello_info *hi = NULL; + union sockunion traddr; if ((!pduid) || (!ht)) return; @@ -65,32 +66,58 @@ run_ldp_hello(struct ldp_pdu * pduid, struct hello_tlv * ht, debugp("Hello: Type: 0x%.4X Length: %.2d ID: %.8X\n", ht->type, ht->length, ht->messageid); + if (ht->length <= 4) /* Common hello parameters */ + return; + ht->ch.type = ntohs(ht->ch.type); + ht->ch.length = ntohs(ht->ch.length); + ht->ch.holdtime = ntohs(ht->ch.holdtime); + ht->ch.res = ntohs(ht->ch.res); + debugp("Common hello Type: 0x%.4X Length: %.2d R:%d T:%d" + " Hold time: %d\n", ht->ch.type, ht->ch.length, + ht->ch.tr / 2, ht->ch.tr % 2, ht->ch.holdtime); + + memset(&traddr, 0, sizeof(traddr)); + /* Check transport TLV */ + if (pduid->length - PDU_PAYLOAD_LENGTH - + sizeof(struct hello_tlv) >= 8) { + trtlv = (struct transport_address_tlv *)(ht + 1); + if (trtlv->type == htons(TLV_IPV4_TRANSPORT)) { + traddr.sin.sin_family = AF_INET; + traddr.sin.sin_len = sizeof(struct sockaddr_in); + memcpy(&traddr.sin.sin_addr, + &trtlv->address, sizeof(struct in_addr)); + } else if (trtlv->type == htons(TLV_IPV6_TRANSPORT)) { + traddr.sin6.sin6_family = AF_INET6; + traddr.sin6.sin6_len = sizeof(struct sockaddr_in6); + memcpy(&traddr.sin6.sin6_addr, + &trtlv->address, sizeof(struct in6_addr)); + } else + warnp("Unknown AF %x for transport address\n", + ntohs(trtlv->type)); + } else { + /* Use LDP ID as transport address */ + traddr.sin.sin_family = AF_INET; + traddr.sin.sin_len = sizeof(struct sockaddr_in); + memcpy(&traddr.sin.sin_addr, + &pduid->ldp_id, sizeof(struct in_addr)); + } /* Add it to hello list or just update timer */ SLIST_FOREACH(hi, &hello_info_head, infos) - if (hi->ldp_id.s_addr == pduid->ldp_id.s_addr) + if (hi->ldp_id.s_addr == pduid->ldp_id.s_addr && + sockaddr_cmp(&hi->transport_address.sa, &traddr.sa) == 0) break; if (hi == NULL) { - hi = malloc(sizeof(*hi)); + hi = calloc(1, sizeof(*hi)); if (!hi) { fatalp("Cannot alloc a hello info structure"); return; } hi->ldp_id.s_addr = pduid->ldp_id.s_addr; - hi->transport_address.sa.sa_family = 0; + memcpy(&hi->transport_address, &traddr, traddr.sa.sa_len); SLIST_INSERT_HEAD(&hello_info_head, hi, infos); - } else - /* Just update timer */ - hi->keepalive = LDP_HELLO_KEEP; + } - if (ht->length <= 4) /* Common hello parameters */ - return; - ht->ch.type = ntohs(ht->ch.type); - ht->ch.length = ntohs(ht->ch.length); - ht->ch.holdtime = ntohs(ht->ch.holdtime); - ht->ch.res = ntohs(ht->ch.res); - debugp("Common hello Type: 0x%.4X Length: %.2d R:%d T:%d" - " Hold time: %d\n", ht->ch.type, ht->ch.length, - ht->ch.tr / 2, ht->ch.tr % 2, ht->ch.holdtime); + /* Update expire timer */ if (ht->ch.holdtime != 0) hi->keepalive = ht->ch.holdtime; else { @@ -99,44 +126,16 @@ run_ldp_hello(struct ldp_pdu * pduid, struct hello_tlv * ht, else hi->keepalive = LDP_THELLO_KEEP; } + if (!get_ldp_peer_by_id(&pduid->ldp_id)) { - /* Check transport TLV */ - if (pduid->length - PDU_PAYLOAD_LENGTH - - sizeof(struct hello_tlv) >= 8) { - trtlv = (struct transport_address_tlv *)(ht + 1); - if (trtlv->type == htons(TLV_IPV4_TRANSPORT)) { - hi->transport_address.sin.sin_family = AF_INET; - hi->transport_address.sin.sin_len = - sizeof(struct sockaddr_in); - memcpy(&hi->transport_address.sin.sin_addr, - &trtlv->address, sizeof(struct in_addr)); - } else if (trtlv->type == htons(TLV_IPV6_TRANSPORT)) { - hi->transport_address.sin6.sin6_family = - AF_INET6; - hi->transport_address.sin6.sin6_len = - sizeof(struct sockaddr_in6); - memcpy(&hi->transport_address.sin6.sin6_addr, - &trtlv->address, sizeof(struct in6_addr)); - } else - warnp("Unknown AF %x for transport address\n", - ntohs(trtlv->type)); - } else { - trtlv = NULL; - hi->transport_address.sin.sin_family = AF_INET; - hi->transport_address.sin.sin_len = - sizeof(struct sockaddr_in); - memcpy(&hi->transport_address.sin.sin_addr, - &pduid->ldp_id, sizeof(struct in_addr)); - } /* * RFC 5036 2.5.2: If A1 > A2, LSR1 plays the active role; * otherwise it is passive. */ - /* XXX TODO: check for IPv6 too */ if (may_connect == true && - hi->transport_address.sa.sa_family == AF_INET && + (hi->transport_address.sa.sa_family == AF_INET && ntohl(hi->transport_address.sin.sin_addr.s_addr) < - ntohl(ladd->s_addr)) { + ntohl(ladd->s_addr))) { peer = ldp_peer_new(&pduid->ldp_id, padd, &hi->transport_address.sa, ht->ch.holdtime, 0); |
