modify structures in order to accomodate IPv6 according to

draft-ietf-mpls-ldp-ipv6. Correct a little bit IPv6 hello path
This commit is contained in:
kefren 2013-01-26 17:29:55 +00:00
parent c1cffbf8b8
commit 269ea2d396
21 changed files with 593 additions and 375 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: fsm.c,v 1.6 2012/11/12 18:39:00 kefren Exp $ */
/* $NetBSD: fsm.c,v 1.7 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -52,11 +52,10 @@ struct sockaddr mplssockaddr;
/* Processing a hello */
void
run_ldp_hello(struct ldp_pdu * pduid, struct hello_tlv * ht,
struct in_addr * padd, struct in_addr * ladd, int mysock)
struct sockaddr * padd, struct in_addr * ladd, int mysock)
{
struct ldp_peer *peer = NULL;
struct in_addr peer_addr;
struct in6_addr peer_addr6;
union sockunion peer_addr;
struct transport_address_tlv *trtlv;
struct hello_info *hi;
@ -90,7 +89,7 @@ run_ldp_hello(struct ldp_pdu * pduid, struct hello_tlv * ht,
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,
" Hold time: %d\n", ht->ch.type, ht->ch.length,
ht->ch.tr / 2, ht->ch.tr % 2, ht->ch.holdtime);
if (ht->ch.holdtime != 0)
hi->keepalive = ht->ch.holdtime;
@ -100,34 +99,41 @@ run_ldp_hello(struct ldp_pdu * pduid, struct hello_tlv * ht,
else
hi->keepalive = LDP_THELLO_KEEP;
}
if (!get_ldp_peer(&pduid->ldp_id)) {
/* First of all set peer_addr to announced LDP_ID */
memcpy(&peer_addr, &pduid->ldp_id,
sizeof(struct in_addr));
/*
* Now let's see if there is any transport TLV in
* there
*/
if (!get_ldp_peer_by_id(&pduid->ldp_id)) {
/* Check transport TLV */
if (pduid->length - PDU_PAYLOAD_LENGTH -
sizeof(struct hello_tlv) > 3) {
trtlv = (struct transport_address_tlv *) &ht[1];
if (trtlv->type == TLV_IPV4_TRANSPORT)
memcpy(&peer_addr, &trtlv->address,
if (trtlv->type == TLV_IPV4_TRANSPORT) {
peer_addr.sin.sin_family = AF_INET;
peer_addr.sin.sin_len =
sizeof(struct sockaddr_in);
memcpy(&peer_addr.sin.sin_addr, &trtlv->address,
sizeof(struct in_addr));
else if (trtlv->type == TLV_IPV6_TRANSPORT)
memcpy(&peer_addr6, &trtlv->address,
sizeof(struct in6_addr));
} else
} else if (trtlv->type == TLV_IPV6_TRANSPORT) {
peer_addr.sin6.sin6_family = AF_INET6;
peer_addr.sin6.sin6_len =
sizeof(struct sockaddr_in6);
memcpy(&peer_addr.sin6.sin6_addr,
&trtlv->address, sizeof(struct in6_addr));
}
} else {
trtlv = NULL;
peer_addr.sin.sin_family = AF_INET;
peer_addr.sin.sin_len = sizeof(struct sockaddr_in);
memcpy(&peer_addr.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.
*/
if (ntohl(peer_addr.s_addr) < ntohl(ladd->s_addr)) {
#define TR_INET4_ADDR (trtlv && trtlv->type == TLV_IPV4_TRANSPORT) ? &peer_addr : NULL
#define TR_INET6_ADDR NULL
/* XXX: check for IPv6 too */
if (peer_addr.sa.sa_family == AF_INET &&
ntohl(peer_addr.sin.sin_addr.s_addr)< ntohl(ladd->s_addr)) {
peer = ldp_peer_new(&pduid->ldp_id, padd,
TR_INET4_ADDR, TR_INET6_ADDR, ht->ch.holdtime, 0);
trtlv != NULL ? &peer_addr.sa : NULL,
ht->ch.holdtime, 0);
if (!peer)
return;
if (peer && peer->state == LDP_PEER_CONNECTED)

View File

@ -1,4 +1,4 @@
/* $NetBSD: fsm.h,v 1.1 2010/12/08 07:20:14 kefren Exp $ */
/* $NetBSD: fsm.h,v 1.2 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -36,7 +36,7 @@
#include "pdu.h"
void run_ldp_hello(struct ldp_pdu *, struct hello_tlv *,
struct in_addr *, struct in_addr *, int);
struct sockaddr *, struct in_addr *, int);
struct address_list_tlv * build_address_list_tlv(void);
int set_my_ldp_id(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: label.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
/* $NetBSD: label.c,v 1.4 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -89,7 +89,7 @@ label_add(union sockunion * so_dest, union sockunion * so_pref,
warnp("[label_add] added binding %d for %s/%s\n", l->binding,
union_ntoa(so_dest), spreftmp);
send_label_tlv_to_all(&(so_dest->sin.sin_addr),
send_label_tlv_to_all(&(so_dest->sa),
from_union_to_cidr(so_pref), l->binding);
return l;
}
@ -223,12 +223,12 @@ label_del_by_binding(uint32_t binding, int readd)
* For Compatibility with old bindinds code
*/
struct label*
label_get_by_prefix(struct in_addr *a, int prefixlen)
label_get_by_prefix(const struct sockaddr *a, int prefixlen)
{
union sockunion *so_dest, *so_pref;
struct label *l;
so_dest = make_inet_union(inet_ntoa(*a));
so_dest = make_inet_union(satos(a)); // XXX: grobian
so_pref = from_cidr_to_union(prefixlen);
l = label_get(so_dest, so_pref);
@ -264,10 +264,10 @@ get_free_local_label()
void
change_local_label(struct label *l, uint32_t newbind)
{
send_withdraw_tlv_to_all(&(l->so_dest.sin.sin_addr),
send_withdraw_tlv_to_all(&(l->so_dest.sa),
from_union_to_cidr(&(l->so_pref)));
l->binding = newbind;
send_label_tlv_to_all(&(l->so_dest.sin.sin_addr),
send_label_tlv_to_all(&(l->so_dest.sa),
from_union_to_cidr(&(l->so_pref)),
l->binding);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: label.h,v 1.1 2010/12/08 07:20:14 kefren Exp $ */
/* $NetBSD: label.h,v 1.2 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -44,14 +44,13 @@
/*
* MPLS label descriptor
*
* so_dest and so_pref are obvious
* so_gate is the IPV4 gate
* so_dest, so_pref and so_gate are the prefix identification and its GW
* binding is the local label
* label is the peer associated label
*/
struct label {
union sockunion so_dest, so_pref, so_gate;
int binding, label;
int binding, label;
struct ldp_peer *p;
SLIST_ENTRY(label) labels;
};
@ -65,7 +64,7 @@ void del_all_peer_labels(struct ldp_peer*, int);
void label_reattach_all_peer_labels(struct ldp_peer*, int);
void label_del_by_binding(uint32_t, int);
struct label * label_get(union sockunion *sodest, union sockunion *sopref);
struct label * label_get_by_prefix(struct in_addr*, int);
struct label * label_get_by_prefix(const struct sockaddr *, int);
uint32_t get_free_local_label(void);
void change_local_label(struct label*, uint32_t);
void label_reattach_route(struct label*, int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ldp.h,v 1.4 2012/11/12 18:39:00 kefren Exp $ */
/* $NetBSD: ldp.h,v 1.5 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -35,9 +35,13 @@
#include <sys/types.h>
#include <netinet/in.h>
/* RFC5036 */
#define ALL_ROUTERS "224.0.0.2"
/* draft-ietf-mpls-ldp-ipv6 */
#define ALL_ROUTERS6 "FF02::2"
/* RFC5036 */
#define LDP_PORT 646
#define LDP_COMMAND_PORT 2626
#define LDPD_VER "0.4.0"

View File

@ -1,4 +1,4 @@
/* $NetBSD: ldp_command.c,v 1.7 2011/12/24 23:54:26 christos Exp $ */
/* $NetBSD: ldp_command.c,v 1.8 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -167,6 +167,7 @@ create_command_socket(int port)
close(s);
return -1;
}
debugp("Command socket created (%d)\n", s);
return s;
}
@ -410,16 +411,21 @@ show_neighbours(int s, char *recvspace)
socklen_t sin_len = sizeof(struct sockaddr_in);
int enc;
socklen_t enclen = sizeof(enc);
char traddress[39], nhaddress[39];
SLIST_FOREACH(p, &ldp_peer_head, peers) {
snprintf(sendspace, MAXSEND, "LDP peer: %s\n",
inet_ntoa(p->ldp_id));
writestr(s, sendspace);
inet_ntop(p->transport_address->sa_family,
p->transport_address->sa_data, traddress, 39);
snprintf(sendspace, MAXSEND, "Transport address: %s\n",
inet_ntoa(p->transport_address));
traddress);
writestr(s, sendspace);
inet_ntop(p->address->sa_family, p->address->sa_data,
nhaddress, 39);
snprintf(sendspace, MAXSEND, "Next-hop address: %s\n",
inet_ntoa(p->address));
nhaddress);
writestr(s, sendspace);
snprintf(sendspace, MAXSEND, "State: %s\n",
ldp_state_to_name(p->state));
@ -465,8 +471,11 @@ show_neighbours(int s, char *recvspace)
snprintf(sendspace, MAXSEND,"Addresses bounded to this peer: ");
writestr(s, sendspace);
SLIST_FOREACH(wp, &p->ldp_peer_address_head, addresses) {
/* XXX: TODO */
if (wp->address.sa.sa_family != AF_INET)
continue;
snprintf(sendspace, MAXSEND, "%s ",
inet_ntoa(wp->address));
inet_ntoa(wp->address.sin.sin_addr));
writestr(s, sendspace);
}
sendspace[0] = sendspace[1] = '\n';
@ -487,7 +496,11 @@ show_labels(int s, char *recvspace)
continue;
SLIST_FOREACH(lm, &p->label_mapping_head, mappings) {
char lma[256];
strlcpy(lma, inet_ntoa(lm->address), sizeof(lma));
/* XXX: TODO */
if (lm->address.sa.sa_family != AF_INET)
continue;
strlcpy(lma, inet_ntoa(lm->address.sin.sin_addr),
sizeof(lma));
snprintf(sendspace, MAXSEND, "%s:%d\t%s/%d\n",
inet_ntoa(p->ldp_id), lm->label, lma, lm->prefix);
writestr(s, sendspace);
@ -500,6 +513,7 @@ static int
show_bindings(int s, char *recvspace)
{
struct label *l;
char labelgw[39];
snprintf(sendspace, MAXSEND, "Local label\tNetwork\t\t\t\tNexthop\n");
writestr(s, sendspace);
@ -509,10 +523,12 @@ show_bindings(int s, char *recvspace)
writestr(s, sendspace);
snprintf(sendspace, MAXSEND, "%s", union_ntoa(&l->so_pref));
writestr(s, sendspace);
if (l->p)
if (l->p) {
inet_ntop(l->p->address->sa_family,
l->p->address->sa_data, labelgw, 39);
snprintf(sendspace, MAXSEND, "\t%s:%d\n",
inet_ntoa(l->p->address), l->label);
else
labelgw, l->label);
} else
snprintf(sendspace, MAXSEND, "\n");
writestr(s, sendspace);
}

View File

@ -1,6 +1,6 @@
/* $NetBSD: ldp_errors.c,v 1.2 2012/03/15 02:02:24 joerg Exp $ */
/* $NetBSD: ldp_errors.c,v 1.3 2013/01/26 17:29:55 kefren Exp $ */
/*-
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
@ -29,6 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
@ -42,6 +43,8 @@
int debug_f = 0, warn_f = 0, syslog_f = 0;
static void do_syslog(int, const char*, va_list) __printflike(2, 0);
static char satos_str[INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN :
INET_ADDRSTRLEN];
void
debugp(const char *fmt, ...)
@ -108,3 +111,31 @@ printtime()
buf[i] = 0;
printf("%s ", buf);
}
const char *
satos(const struct sockaddr *sa)
{
switch (sa->sa_family) {
case AF_INET:
{
const struct sockaddr_in *sin =
(const struct sockaddr_in *)sa;
if (inet_ntop(AF_INET, &(sin->sin_addr), satos_str,
sizeof(satos_str)) == NULL)
return "INET ERROR";
break;
}
case AF_INET6:
{
const struct sockaddr_in6 *sin6 =
(const struct sockaddr_in6 *)sa;
if (inet_ntop(AF_INET6, &(sin6->sin6_addr), satos_str,
sizeof(satos_str)) == NULL)
return "INET6 ERROR";
break;
}
default:
return "UNKNOWN AF";
}
return satos_str;
}

View File

@ -1,6 +1,6 @@
/* $NetBSD: ldp_errors.h,v 1.3 2012/03/15 02:02:24 joerg Exp $ */
/* $NetBSD: ldp_errors.h,v 1.4 2013/01/26 17:29:55 kefren Exp $ */
/*-
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
@ -55,5 +55,6 @@ void printtime(void);
void debugp(const char *, ...) __printflike(1, 2);
void fatalp(const char *, ...) __printflike(1, 2);
void warnp(const char *, ...) __printflike(1, 2);
const char * satos(const struct sockaddr *);
#endif /* !_LDP_ERRORS_H_ */

View File

@ -1,6 +1,6 @@
/* $NetBSD: ldp_peer.c,v 1.4 2012/11/12 18:39:00 kefren Exp $ */
/* $NetBSD: ldp_peer.c,v 1.5 2013/01/26 17:29:55 kefren Exp $ */
/*-
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
@ -36,11 +36,12 @@
#include <netmpls/mpls.h>
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "conffile.h"
#include "socketops.h"
@ -62,38 +63,56 @@ ldp_peer_init(void)
myaddresses = NULL;
}
static int
sockaddr_cmp(const struct sockaddr *a, const struct sockaddr *b)
{
if (a->sa_len != b->sa_len || a->sa_family == b->sa_family)
return -1;
return memcmp(&a->sa_data, &b->sa_data, a->sa_len);
}
/*
* soc should be > 1 if there is already a TCP socket for this else we'll
* initiate a new one
*/
struct ldp_peer *
ldp_peer_new(struct in_addr * ldp_id, struct in_addr * a,
struct in_addr * tradd, struct in6_addr * tradd6,
uint16_t holdtime, int soc)
ldp_peer_new(const struct in_addr * ldp_id, struct sockaddr * padd,
struct sockaddr * tradd, uint16_t holdtime, int soc)
{
struct ldp_peer *p;
int s = soc;
struct sockaddr_in sa;
struct sockaddr *connecting_sa = NULL;
/* disabled - see below
struct conf_neighbour *cn;
*/
if (tradd != NULL)
assert(tradd->sa_family == padd->sa_family);
if (s < 1) {
if (soc < 1) {
s = socket(PF_INET, SOCK_STREAM, 0);
memset(&sa, 0, sizeof(sa));
sa.sin_len = sizeof(sa);
sa.sin_family = AF_INET;
if (tradd)
memcpy(&sa.sin_addr, tradd,
sizeof(struct in_addr));
if (s < 0) {
fatalp("ldp_peer_new: cannot create socket\n");
return NULL;
}
if (tradd != NULL)
connecting_sa = tradd;
else
memcpy(&sa.sin_addr, a,
sizeof(struct in_addr));
sa.sin_port = htons(LDP_PORT);
connecting_sa = padd;
assert(connecting_sa->sa_family == AF_INET ||
connecting_sa->sa_family == AF_INET6);
if (connecting_sa->sa_family == AF_INET)
((struct sockaddr_in*)connecting_sa)->sin_port =
htons(LDP_PORT);
else
((struct sockaddr_in6*)connecting_sa)->sin6_port =
htons(LDP_PORT);
set_ttl(s);
}
/* MD5 authentication needed ? */
/* XXX: disabled for now - need to make sure NetBSD handles TCPSIG correctly
SLIST_FOREACH(cn, &conei_head, neilist)
if (cn->authenticate != 0 && (a->s_addr == cn->address.s_addr ||
(tradd && tradd->s_addr == cn->address.s_addr))) {
@ -103,7 +122,7 @@ ldp_peer_new(struct in_addr * ldp_id, struct in_addr * a,
strerror(errno));
break;
}
*/
/* Set the peer in CONNECTING/CONNECTED state */
p = calloc(1, sizeof(*p));
@ -113,15 +132,15 @@ ldp_peer_new(struct in_addr * ldp_id, struct in_addr * a,
}
SLIST_INSERT_HEAD(&ldp_peer_head, p, peers);
memcpy(&p->address, a, sizeof(struct in_addr));
p->address = (struct sockaddr *)malloc(padd->sa_len);
p->transport_address = (struct sockaddr *)malloc(padd->sa_len);
memcpy(p->address, padd, padd->sa_len);
memcpy(&p->ldp_id, ldp_id, sizeof(struct in_addr));
if (tradd)
memcpy(&p->transport_address, tradd,
sizeof(struct in_addr));
if (tradd != NULL)
memcpy(p->transport_address, tradd, tradd->sa_len);
else
memcpy(&p->transport_address, a,
sizeof(struct in_addr));
p->holdtime = holdtime > ldp_holddown_time ? holdtime : ldp_holddown_time;
memcpy(p->transport_address, padd, padd->sa_len);
p->holdtime=holdtime > ldp_holddown_time ? holdtime : ldp_holddown_time;
p->socket = s;
if (soc < 1) {
p->state = LDP_PEER_CONNECTING;
@ -137,13 +156,13 @@ ldp_peer_new(struct in_addr * ldp_id, struct in_addr * a,
/* And connect to peer */
if (soc < 1)
if (connect(s, (struct sockaddr *) & sa, sizeof(sa)) == -1) {
if (connect(s, connecting_sa, connecting_sa->sa_len) == -1) {
if (errno == EINTR) {
return p; /* We take care of this in
* big_loop */
}
warnp("connect to %s failed: %s\n",
inet_ntoa(sa.sin_addr), strerror(errno));
satos(connecting_sa), strerror(errno));
ldp_peer_holddown(p);
return NULL;
}
@ -189,24 +208,40 @@ ldp_peer_delete(struct ldp_peer * p)
SLIST_REMOVE(&ldp_peer_head, p, ldp_peer, peers);
close(p->socket);
warnp("LDP Neighbor %s holddown timer expired\n", inet_ntoa(p->ldp_id));
free(p->address);
free(p->transport_address);
free(p);
}
struct ldp_peer *
get_ldp_peer(struct in_addr * a)
get_ldp_peer(const struct sockaddr * a)
{
struct ldp_peer *p;
const struct sockaddr_in *a_inet = (const struct sockaddr_in *)a;
SLIST_FOREACH(p, &ldp_peer_head, peers) {
if (a->sa_family == AF_INET &&
memcmp((const void *) &a_inet->sin_addr,
(const void *) &p->ldp_id,
sizeof(struct in_addr)) == 0)
return p;
if (sockaddr_cmp(a, p->address) == 0)
return p;
if (a->sa_family == AF_INET && check_ifaddr(p,a))
return p;
}
return NULL;
}
struct ldp_peer *
get_ldp_peer_by_id(const struct in_addr *a)
{
struct ldp_peer *p;
SLIST_FOREACH(p, &ldp_peer_head, peers) {
if (!memcmp((void *) a, (void *) &p->ldp_id,
sizeof(struct in_addr)))
SLIST_FOREACH(p, &ldp_peer_head, peers)
if (memcmp((const void*)a,
(const void*)&p->ldp_id, sizeof(*a)) == 0)
return p;
if (!memcmp((void *) a, (void *) &p->address,
sizeof(struct in_addr)))
return p;
if (check_ifaddr(p, a))
return p;
}
return NULL;
}
@ -230,7 +265,11 @@ add_ifaddresses(struct ldp_peer * p, struct al_tlv * a)
{
int i, c, n;
struct in_addr *ia;
struct sockaddr_in ipa;
memset(&ipa, 0, sizeof(ipa));
ipa.sin_len = sizeof(ipa);
ipa.sin_family = AF_INET;
/*
* Check if tlv is Address type, if it's correct size (at least one
* address) and if it's IPv4
@ -248,7 +287,8 @@ add_ifaddresses(struct ldp_peer * p, struct al_tlv * a)
inet_ntoa(p->ldp_id));
for (ia = (struct in_addr *) & a->address, c = 0, i = 0; i < n; i++) {
if (add_ifaddr(p, &ia[i]) == LDP_E_OK)
memcpy(&ipa.sin_addr, &ia[i], sizeof(ipa.sin_addr));
if (add_ifaddr(p, (struct sockaddr *)&ipa) == LDP_E_OK)
c++;
}
@ -262,7 +302,11 @@ del_ifaddresses(struct ldp_peer * p, struct al_tlv * a)
{
int i, c, n;
struct in_addr *ia;
struct sockaddr_in ipa;
memset(&ipa, 0, sizeof(ipa));
ipa.sin_len = sizeof(ipa);
ipa.sin_family = AF_INET;
/*
* Check if tlv is Address type, if it's correct size (at least one
* address) and if it's IPv4
@ -279,7 +323,8 @@ del_ifaddresses(struct ldp_peer * p, struct al_tlv * a)
inet_ntoa(p->ldp_id));
for (ia = (struct in_addr *) & a[1], c = 0, i = 0; i < n; i++) {
if (del_ifaddr(p, &ia[i]) == LDP_E_OK)
memcpy(&ipa.sin_addr, &ia[i], sizeof(ipa.sin_addr));
if (del_ifaddr(p, (struct sockaddr *)&ipa) == LDP_E_OK)
c++;
}
@ -289,9 +334,9 @@ del_ifaddresses(struct ldp_peer * p, struct al_tlv * a)
}
/* Adds a _SINGLE_ address to a specific peer */
/* Adds a _SINGLE_ INET address to a specific peer */
int
add_ifaddr(struct ldp_peer * p, struct in_addr * a)
add_ifaddr(struct ldp_peer * p, struct sockaddr * a)
{
struct ldp_peer_address *lpa;
@ -306,7 +351,9 @@ add_ifaddr(struct ldp_peer * p, struct in_addr * a)
return LDP_E_MEMORY;
}
memcpy(&lpa->address, a, sizeof(struct in_addr));
assert(a->sa_len <= sizeof(union sockunion));
memcpy(&lpa->address.sa, a, a->sa_len);
SLIST_INSERT_HEAD(&p->ldp_peer_address_head, lpa, addresses);
return LDP_E_OK;
@ -314,7 +361,7 @@ add_ifaddr(struct ldp_peer * p, struct in_addr * a)
/* Deletes an address bounded to a specific peer */
int
del_ifaddr(struct ldp_peer * p, struct in_addr * a)
del_ifaddr(struct ldp_peer * p, struct sockaddr * a)
{
struct ldp_peer_address *wp;
@ -330,12 +377,12 @@ del_ifaddr(struct ldp_peer * p, struct in_addr * a)
/* Checks if an address is already bounded */
struct ldp_peer_address *
check_ifaddr(struct ldp_peer * p, struct in_addr * a)
check_ifaddr(struct ldp_peer * p, const struct sockaddr * a)
{
struct ldp_peer_address *wp;
SLIST_FOREACH(wp, &p->ldp_peer_address_head, addresses)
if (memcmp(a, &wp->address, sizeof(struct in_addr)) == 0)
if (sockaddr_cmp(a, &wp->address.sa) == 0)
return wp;
return NULL;
}
@ -356,12 +403,14 @@ void
print_bounded_addresses(struct ldp_peer * p)
{
struct ldp_peer_address *wp;
char abuf[512];
char abuf[512], peername[39];
inet_ntop(p->address->sa_family, p->address->sa_data, peername, 39);
snprintf(abuf, sizeof(abuf), "Addresses bounded to peer %s: ",
inet_ntoa(p->address));
peername);
SLIST_FOREACH(wp, &p->ldp_peer_address_head, addresses) {
strncat(abuf, inet_ntoa(wp->address), sizeof(abuf) -1);
strncat(abuf, satos(&wp->address.sa),
sizeof(abuf) -1);
strncat(abuf, " ", sizeof(abuf) -1);
}
warnp("%s\n", abuf);
@ -382,7 +431,7 @@ add_my_if_addrs(struct in_addr * a, int count)
/* Adds a label and a prefix to a specific peer */
int
ldp_peer_add_mapping(struct ldp_peer * p, struct in_addr * a, int prefix,
ldp_peer_add_mapping(struct ldp_peer * p, struct sockaddr * a, int prefix,
int label)
{
struct label_mapping *lma;
@ -399,7 +448,7 @@ ldp_peer_add_mapping(struct ldp_peer * p, struct in_addr * a, int prefix,
return LDP_E_MEMORY;
}
memcpy(&lma->address, a, sizeof(struct in_addr));
memcpy(&lma->address, a, a->sa_len);
lma->prefix = prefix;
lma->label = label;
@ -409,7 +458,7 @@ ldp_peer_add_mapping(struct ldp_peer * p, struct in_addr * a, int prefix,
}
int
ldp_peer_delete_mapping(struct ldp_peer * p, struct in_addr * a, int prefix)
ldp_peer_delete_mapping(struct ldp_peer * p, struct sockaddr * a, int prefix)
{
struct label_mapping *lma;
@ -427,7 +476,7 @@ ldp_peer_delete_mapping(struct ldp_peer * p, struct in_addr * a, int prefix)
}
struct label_mapping *
ldp_peer_get_lm(struct ldp_peer * p, struct in_addr * a, int prefix)
ldp_peer_get_lm(struct ldp_peer * p, struct sockaddr * a, uint prefix)
{
struct label_mapping *rv;
@ -435,8 +484,7 @@ ldp_peer_get_lm(struct ldp_peer * p, struct in_addr * a, int prefix)
return NULL;
SLIST_FOREACH(rv, &p->label_mapping_head, mappings)
if ((rv->prefix == prefix) && (!memcmp(a, &rv->address,
sizeof(struct in_addr))))
if (rv->prefix == prefix && sockaddr_cmp(a, &rv->address.sa)==0)
break;
return rv;
@ -459,7 +507,7 @@ ldp_peer_delete_all_mappings(struct ldp_peer * p)
/* returns a mapping and its peer */
struct peer_map *
ldp_test_mapping(struct in_addr * a, int prefix, struct in_addr * gate)
ldp_test_mapping(struct sockaddr * a, int prefix, struct sockaddr * gate)
{
struct ldp_peer *lpeer;
struct peer_map *rv = NULL;
@ -469,7 +517,7 @@ ldp_test_mapping(struct in_addr * a, int prefix, struct in_addr * gate)
lpeer = get_ldp_peer(gate);
if (!lpeer) {
debugp("Gateway %s is not an LDP peer\n", inet_ntoa(*gate));
debugp("ldp_test_mapping: Gateway is not an LDP peer\n");
return NULL;
}
if (lpeer->state != LDP_PEER_ESTABLISHED) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: ldp_peer.h,v 1.2 2012/11/12 18:39:00 kefren Exp $ */
/* $NetBSD: ldp_peer.h,v 1.3 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -36,35 +36,37 @@
#include "sys/queue.h"
#include "netinet/in.h"
#include "mpls_routes.h"
#include "tlv.h"
struct ldp_peer_address {
struct in_addr address;
union sockunion address;
SLIST_ENTRY(ldp_peer_address) addresses;
};
struct label_mapping {
struct in_addr address;
int prefix;
int label;
union sockunion address;
uint prefix;
uint label;
SLIST_ENTRY(label_mapping) mappings;
};
struct ldp_peer {
/*
* I add routes to address.
* I maintain LDP TCP connection on transport_address.
* I use ldp_id as peer identificator.
*/
struct in_addr address, transport_address, ldp_id;
struct sockaddr *address, *transport_address;
/* According to draft-ietf-mpls-ldp-ipv6-07 ID is IPv4 only for now */
struct in_addr ldp_id;
/* TCP socket */
int socket;
/* Usual peer parameters */
/* Rest of the peer parameters */
uint16_t holdtime, timeout;
int master; /* 0 if we're passive */
int state; /* see below for possible states */
time_t established_t; /* time when it did connected */
time_t established_t; /* time when it did connect */
/* Here I maintain all the addresses announced by a peer */
SLIST_HEAD(,ldp_peer_address) ldp_peer_address_head;
SLIST_HEAD(,label_mapping) label_mapping_head;
@ -85,33 +87,31 @@ struct peer_map {
#define LDP_PEER_HOLDDOWN 3
void ldp_peer_init(void);
struct ldp_peer * ldp_peer_new(struct in_addr *, struct in_addr *,
struct in_addr *, struct in6_addr *, uint16_t, int);
struct ldp_peer * ldp_peer_new(const struct in_addr *, struct sockaddr *,
struct sockaddr *, uint16_t, int);
void ldp_peer_holddown(struct ldp_peer *);
void ldp_peer_delete(struct ldp_peer *);
struct ldp_peer * get_ldp_peer(struct in_addr *);
struct ldp_peer * get_ldp_peer_by_socket(int);
int add_ifaddresses(struct ldp_peer *, struct al_tlv *);
int add_ifaddr(struct ldp_peer *, struct in_addr *);
int del_ifaddr(struct ldp_peer *, struct in_addr *);
struct ldp_peer_address * check_ifaddr(struct ldp_peer *,
struct in_addr *);
void print_bounded_addresses(struct ldp_peer *);
void del_all_ifaddr(struct ldp_peer *);
int del_ifaddresses(struct ldp_peer *, struct al_tlv *);
void add_my_if_addrs(struct in_addr *, int);
struct ldp_peer * get_ldp_peer(const struct sockaddr *);
struct ldp_peer * get_ldp_peer_by_id(const struct in_addr *);
struct ldp_peer * get_ldp_peer_by_socket(int);
int add_ifaddresses(struct ldp_peer *, struct al_tlv *);
int add_ifaddr(struct ldp_peer *, struct sockaddr *);
int del_ifaddr(struct ldp_peer *, struct sockaddr *);
struct ldp_peer_address * check_ifaddr(struct ldp_peer *,
const struct sockaddr *);
void print_bounded_addresses(struct ldp_peer *);
void del_all_ifaddr(struct ldp_peer *);
int del_ifaddresses(struct ldp_peer *, struct al_tlv *);
void add_my_if_addrs(struct in_addr *, int);
int ldp_peer_add_mapping(struct ldp_peer *, struct in_addr *,
int, int);
int ldp_peer_delete_mapping(struct ldp_peer *, struct in_addr *,
int);
struct label_mapping * ldp_peer_get_lm(struct ldp_peer *, struct in_addr *,
int);
int ldp_peer_delete_all_mappings(struct ldp_peer *);
void ldp_peer_holddown_all(void);
int ldp_peer_add_mapping(struct ldp_peer *, struct sockaddr *, int, int);
int ldp_peer_delete_mapping(struct ldp_peer *, struct sockaddr *, int);
struct label_mapping * ldp_peer_get_lm(struct ldp_peer *, struct sockaddr *,
uint);
int ldp_peer_delete_all_mappings(struct ldp_peer *);
void ldp_peer_holddown_all(void);
struct peer_map * ldp_test_mapping(struct in_addr *, int,
struct in_addr *);
struct peer_map * ldp_test_mapping(struct sockaddr *, int, struct sockaddr *);
const char * ldp_state_to_name(int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpls_interface.c,v 1.6 2011/06/14 11:28:51 kefren Exp $ */
/* $NetBSD: mpls_interface.c,v 1.7 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -54,18 +54,18 @@ extern int no_default_route;
int
mpls_add_label(struct ldp_peer * p, struct rt_msg * inh_rg,
struct in_addr * addr, int len, int label, int rlookup)
struct sockaddr * addr, int len, int label, int rlookup)
{
char padd[20];
int kount = 0, rv;
union sockunion *so_dest, *so_pref = NULL, *so_gate, *so_nexthop, *so_tag,
*so_oldifa = NULL, *so_ifa;
union sockunion *so_dest, *so_pref = NULL, *so_gate, *so_nexthop,
*so_tag, *so_oldifa = NULL, *so_ifa;
struct rt_msg rg;
struct rt_msg *rgp = &rg;
struct label *lab;
strlcpy(padd, inet_ntoa(p->address), 20);
debugp("Trying to add %s/%d as label %d to peer %s\n", inet_ntoa(*addr),
strlcpy(padd, satos(p->address), 20);
debugp("Trying to add %s/%d as label %d to peer %s\n", satos(addr),
len, label, padd);
/* Check if we should accept default route */
@ -83,7 +83,7 @@ mpls_add_label(struct ldp_peer * p, struct rt_msg * inh_rg,
* let's loop until we have it..
*/
if ((so_dest = make_inet_union(inet_ntoa(*addr))) == NULL)
if ((so_dest = make_inet_union(satos(addr))) == NULL) // XXX
return LDP_E_MEMORY;
if (len != 32 && (so_pref = from_cidr_to_union(len)) == NULL) {
free(so_dest);
@ -139,15 +139,15 @@ mpls_add_label(struct ldp_peer * p, struct rt_msg * inh_rg,
}
/* Check if the address is bounded to the peer */
if (check_ifaddr(p, &so_gate->sin.sin_addr) == NULL) {
if (check_ifaddr(p, &so_gate->sa) == NULL) {
debugp("Failed at next-hop check\n");
return LDP_E_ROUTE_ERROR;
}
/* CHECK IF WE HAVE A BINDING FOR THAT */
/* Verify if we have a binding for this prefix */
lab = label_get_by_prefix(addr, len);
/* We should have a label because we have a route */
/* And we should have one because we have a route for it */
assert (lab);
if (lab->binding == MPLS_LABEL_IMPLNULL) {
@ -160,7 +160,7 @@ mpls_add_label(struct ldp_peer * p, struct rt_msg * inh_rg,
warnp("[mpls_add_label] Adding %s/%d as local binding %d, label %d"
" to peer %s\n",
inet_ntoa(*addr), len, lab->binding, label, padd);
satos(addr), len, lab->binding, label, padd);
/* Modify existing label */
lab->label = label;
@ -185,7 +185,7 @@ mpls_add_label(struct ldp_peer * p, struct rt_msg * inh_rg,
return LDP_E_ROUTE_ERROR;
/* Now, let's add tag to IPv4 route and point it to mpls interface */
if ((so_dest = make_inet_union(inet_ntoa(*addr))) == NULL) {
if ((so_dest = make_inet_union(satos(addr))) == NULL) { // XXX: grobian
fatalp("Out of memory\n");
return LDP_E_MEMORY;
}
@ -230,7 +230,7 @@ mpls_add_label(struct ldp_peer * p, struct rt_msg * inh_rg,
if (add_route(so_dest, so_pref, so_nexthop, so_ifa, so_tag, FREESO, RTM_CHANGE) != LDP_E_OK)
return LDP_E_ROUTE_ERROR;
debugp("Added %s/%d as label %d to peer %s\n", inet_ntoa(*addr), len,
debugp("Added %s/%d as label %d to peer %s\n", satos(addr), len,
label, padd);
return LDP_E_OK;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpls_interface.h,v 1.1 2010/12/08 07:20:14 kefren Exp $ */
/* $NetBSD: mpls_interface.h,v 1.2 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -35,7 +35,7 @@
#include "mpls_routes.h"
int mpls_add_label(struct ldp_peer *, struct rt_msg *,
struct in_addr *, int, int, int);
struct sockaddr *, int, int, int);
int mpls_add_ldp_peer(struct ldp_peer *);
int mpls_delete_ldp_peer(struct ldp_peer *);
int mpls_start_ldp(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpls_routes.c,v 1.9 2012/03/15 02:02:24 joerg Exp $ */
/* $NetBSD: mpls_routes.c,v 1.10 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -154,7 +154,7 @@ su->sa.sa_len = 4 + from_union_to_cidr(su) / 8 +
/* creates a sockunion from an IP address */
union sockunion *
make_inet_union(char *s)
make_inet_union(const char *s)
{
union sockunion *so_inet;
@ -620,7 +620,7 @@ check_route(struct rt_msg * rg, uint rlen)
case RTM_CHANGE:
lab = label_get(so_dest, so_pref);
if (lab) {
send_withdraw_tlv_to_all(&so_dest->sin.sin_addr,
send_withdraw_tlv_to_all(&so_dest->sa,
prefixlen);
label_reattach_route(lab, LDP_READD_NODEL);
label_del(lab);
@ -639,13 +639,13 @@ check_route(struct rt_msg * rg, uint rlen)
label_add(so_dest, so_pref, NULL,
MPLS_LABEL_IMPLNULL, NULL, 0);
else {
pm = ldp_test_mapping(&so_dest->sin.sin_addr,
prefixlen, &so_gate->sin.sin_addr);
pm = ldp_test_mapping(&so_dest->sa,
prefixlen, &so_gate->sa);
if (pm) {
label_add(so_dest, so_pref,
so_gate, 0, NULL, 0);
mpls_add_label(pm->peer, rg,
&so_dest->sin.sin_addr, prefixlen,
&so_dest->sa, prefixlen,
pm->lm->label, ROUTE_LOOKUP_LOOP);
free(pm);
} else
@ -666,7 +666,7 @@ check_route(struct rt_msg * rg, uint rlen)
lab = label_get(so_dest, so_pref);
if (!lab)
break;
send_withdraw_tlv_to_all(&so_dest->sin.sin_addr, prefixlen);
send_withdraw_tlv_to_all(&so_dest->sa, prefixlen);
/* No readd or delete IP route. Just delete the MPLS route */
label_reattach_route(lab, LDP_READD_NODEL);
label_del(lab);
@ -765,8 +765,8 @@ bind_current_routes()
so_dst = (union sockunion *) & rtmes[1];
/*
* As this function is call only at startup use this ocassion
* to delete all MPLS routes
* This function is called only at startup, so use
* this ocassion to delete all MPLS routes
*/
if (so_dst->sa.sa_family == AF_MPLS) {
delete_route(so_dst, NULL, NO_FREESO);
@ -775,7 +775,7 @@ bind_current_routes()
}
if (so_dst->sa.sa_family != AF_INET) {
debugp("sa_dst is not AF_INET\n");
/*debugp("sa_dst is not AF_INET\n");*/
continue;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpls_routes.h,v 1.2 2013/01/16 08:28:44 kefren Exp $ */
/* $NetBSD: mpls_routes.h,v 1.3 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -59,7 +59,7 @@ struct rt_msg {
char m_space[512];
} __packed;
union sockunion * make_inet_union(char *);
union sockunion * make_inet_union(const char *);
union sockunion * make_mpls_union(uint32_t);
union sockunion * make_mplsinet_union(uint16_t peer, uint32_t label,
struct in_addr *addr);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pdu.c,v 1.1 2010/12/08 07:20:15 kefren Exp $ */
/* $NetBSD: pdu.c,v 1.2 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -70,7 +70,7 @@ check_recv_pdu(struct ldp_peer * p, struct ldp_pdu * rpdu, int c)
/* Check PDU for right LDP version */
if (ntohs(rpdu->version) != LDP_VERSION) {
fatalp("Invalid PDU version received from %s (%d)\n",
inet_ntoa(p->address), ntohs(rpdu->version));
satos(p->address), ntohs(rpdu->version));
notiftlv = build_notification(0, NOTIF_BAD_LDP_VER);
send_tlv(p, (struct tlv *) notiftlv);
free(notiftlv);
@ -79,7 +79,7 @@ check_recv_pdu(struct ldp_peer * p, struct ldp_pdu * rpdu, int c)
/* Check PDU for length validity */
if (ntohs(rpdu->length) > c - PDU_VER_LENGTH) {
fatalp("Invalid PDU length received from %s (announced %d, "
"received %d)\n", inet_ntoa(p->address),
"received %d)\n", satos(p->address),
ntohs(rpdu->length), (int) (c - PDU_VER_LENGTH));
notiftlv = build_notification(0, NOTIF_BAD_PDU_LEN);
send_tlv(p, (struct tlv *) notiftlv);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pdu.h,v 1.1 2010/12/08 07:20:15 kefren Exp $ */
/* $NetBSD: pdu.h,v 1.2 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -46,6 +46,7 @@
struct ldp_pdu {
uint16_t version;
uint16_t length;
/* draft-ietf-mpls-ldp-ipv6-07 keeps this IPv4 only for now */
struct in_addr ldp_id;
uint16_t label_space;
} __packed;

View File

@ -1,6 +1,6 @@
/* $NetBSD: socketops.c,v 1.16 2013/01/16 08:28:45 kefren Exp $ */
/* $NetBSD: socketops.c,v 1.17 2013/01/26 17:29:55 kefren Exp $ */
/*-
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
@ -62,10 +62,6 @@
int ls; /* TCP listening socket on port 646 */
int route_socket; /* used to see when a route is added/deleted */
int hello_socket; /* hello RX/TX multicast sockets */
#ifdef INET6
int hello6_socket; /* same as above */
#endif
int command_socket; /* Listening socket for interface command */
int current_msg_id = 0x233;
int command_port = LDP_COMMAND_PORT;
@ -82,69 +78,44 @@ int loop_detection = 0;
void recv_pdu(int);
void send_hello_alarm(int);
__dead static void bail_out(int);
static int bind_socket(int s, uint8_t stype);
static int set_mcast_ttl(int, int);
static int bind_socket(int s, int stype);
static int set_tos(int);
static int socket_reuse_port(int);
static int get_local_addr(struct sockaddr_dl *, struct in_addr *);
static int is_hello_socket(int);
int
create_hello_sockets()
{
struct ip_mreq mcast_addr;
int s;
int s, joined_groups;
#ifdef INET6
struct ipv6_mreq mcast_addr6;
int s6;
struct ifaddrs *ifa, *ifb;
uint lastifindex;
struct sockaddr_in6 *if_sa6;
#endif
struct hello_socket *hs;
SLIST_INIT(&hello_socket_head);
s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0)
return s;
#ifdef INET6
s6 = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (s6 < 0) {
close(s);
return s6;
}
#endif
debugp("INET4 socket created (%d)\n", s);
/*
* RFC5036 specifies we should listen to all subnet routers multicast
* group
*/
assert(inet_pton(AF_INET, ALL_ROUTERS, &mcast_addr.imr_multiaddr) == 1);
mcast_addr.imr_interface.s_addr = htonl(INADDR_ANY);
#ifdef INET6
assert(inet_pton(AF_INET6, ALL_ROUTERS6,
&mcast_addr6.ipv6mr_multiaddr) == 1);
/*
* XXXXX: kefren. This should be 0, else I should create a socket
* for every interface. Need to investigate why is not working
* as documented in ip6(4)
*/
mcast_addr6.ipv6mr_interface = 1;
#endif
if (socket_reuse_port(s) < 0)
goto chs_error;
#ifdef INET6
if (socket_reuse_port(s6) < 0)
goto chs_error;
#endif
/* Bind it to port 646 on specific address */
if (bind_socket(s, 4) == -1) {
/* Bind it to port 646 */
if (bind_socket(s, AF_INET) == -1) {
warnp("Cannot bind INET hello socket\n");
goto chs_error;
}
#ifdef INET6
if (bind_socket(s6, 6) == -1) {
fatalp("Cannot bind INET6 hello socket\n");
goto chs_error;
}
#endif
/* We don't need to receive back our messages */
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &(u_char){0},
@ -152,64 +123,159 @@ create_hello_sockets()
fatalp("INET setsockopt IP_MCAST_LOOP: %s\n", strerror(errno));
goto chs_error;
}
#ifdef INET6
if (setsockopt(s6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &(uint32_t){0},
sizeof(uint32_t)) == -1) {
fatalp("INET6 setsocketopt IP_MCAST_LOOP: %s\n",
strerror(errno));
goto chs_error;
/* Finally join the group on all interfaces */
if (getifaddrs(&ifa) == -1) {
fatalp("Cannot iterate interfaces\n");
return -1;
}
#endif
lastifindex = UINT_MAX;
joined_groups = 0;
for (ifb = ifa; ifb; ifb = ifb->ifa_next) {
struct sockaddr_in *if_sa = (struct sockaddr_in *) ifb->ifa_addr;
if (if_sa->sin_family != AF_INET || (!(ifb->ifa_flags & IFF_UP)) ||
(ifb->ifa_flags & IFF_LOOPBACK) ||
(ntohl(if_sa->sin_addr.s_addr) >> 24 == IN_LOOPBACKNET) ||
lastifindex == if_nametoindex(ifb->ifa_name))
continue;
lastifindex = if_nametoindex(ifb->ifa_name);
/* Finally join the group */
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mcast_addr,
sizeof(mcast_addr)) == -1) {
fatalp("setsockopt ADD_MEMBER: %s\n", strerror(errno));
goto chs_error;
}
#ifdef INET6
if (setsockopt(s6, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mcast_addr6,
sizeof(mcast_addr6)) == -1) {
fatalp("INET6 setsockopt JOIN: %s\n", strerror(errno));
mcast_addr.imr_interface.s_addr = if_sa->sin_addr.s_addr;
debugp("Join IPv4 mcast on %s\n", ifb->ifa_name);
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mcast_addr,
sizeof(mcast_addr)) == -1) {
fatalp("setsockopt ADD_MEMBER: %s\n", strerror(errno));
goto chs_error;
}
joined_groups++;
if (joined_groups == IP_MAX_MEMBERSHIPS) {
warnp("Maximum group memberships reached for INET socket\n");
break;
}
}
/* TTL:1 for IPv4 */
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &(int){1},
sizeof(int)) == -1) {
fatalp("set mcast ttl: %s\n", strerror(errno));
goto chs_error;
}
#endif
/* TTL:1, TOS: 0xc0 */
if (set_mcast_ttl(s, 4) == -1)
goto chs_error;
#ifdef INET6
if (set_mcast_ttl(s6, 6) == -1)
goto chs_error;
#endif
/* TOS :0xc0 for IPv4 */
if (set_tos(s) == -1) {
fatalp("set_tos: %s", strerror(errno));
goto chs_error;
}
/* we need to get the input interface for message processing */
if (setsockopt(s, IPPROTO_IP, IP_RECVIF, &(uint32_t){1}, sizeof(uint32_t)) == -1) {
if (setsockopt(s, IPPROTO_IP, IP_RECVIF, &(uint32_t){1},
sizeof(uint32_t)) == -1) {
fatalp("Cannot set IP_RECVIF\n");
goto chs_error;
}
#ifdef INET6
if (setsockopt(s6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &(uint32_t){1}, sizeof(uint32_t)) == -1)
goto chs_error;
#endif
hello_socket = s;
#ifdef INET6
hello6_socket = s6;
#endif
hs = (struct hello_socket *)malloc(sizeof(*hs));
if (hs == NULL) {
fatalp("Cannot alloc hello_socket structure\n");
goto chs_error;
}
hs->type = AF_INET;
hs->socket = s;
SLIST_INSERT_HEAD(&hello_socket_head, hs, listentry);
#ifdef INET6
/*
* Now we do the same for IPv6
*/
s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0) {
fatalp("Cannot create INET6 socket\n");
return -1;
}
debugp("INET6 socket created (%d)\n", s);
if (socket_reuse_port(s) < 0)
goto chs_error;
if (bind_socket(s, AF_INET6) == -1) {
fatalp("Cannot bind INET6 hello socket\n");
goto chs_error;
}
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
&(uint){0}, sizeof(uint)) == -1) {
fatalp("INET6 setsocketopt IP_MCAST_LOOP: %s\n",
strerror(errno));
goto chs_error;
}
lastifindex = UINT_MAX;
assert(inet_pton(AF_INET6, ALL_ROUTERS6,
&mcast_addr6.ipv6mr_multiaddr) == 1);
for (ifb = ifa; ifb; ifb = ifb->ifa_next) {
if_sa6 = (struct sockaddr_in6 *) ifb->ifa_addr;
if (if_sa6->sin6_family != AF_INET6 ||
(!(ifb->ifa_flags & IFF_UP)) ||
(ifb->ifa_flags & IFF_LOOPBACK) ||
IN6_IS_ADDR_LOOPBACK(&if_sa6->sin6_addr))
continue;
/*
* draft-ietf-mpls-ldp-ipv6-07 Section 5.1:
* Additionally, the link-local
* IPv6 address MUST be used as the source IP address in IPv6
* LDP Link Hellos.
*/
if (IN6_IS_ADDR_LINKLOCAL(&if_sa6->sin6_addr) == 0)
continue;
/* We should have only one LLADDR per interface, but... */
if (lastifindex == if_nametoindex(ifb->ifa_name))
continue;
mcast_addr6.ipv6mr_interface = lastifindex =
if_nametoindex(ifb->ifa_name);
debugp("Join IPv6 mcast on %s\n", ifb->ifa_name);
if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char *)&mcast_addr6, sizeof(mcast_addr6)) == -1) {
fatalp("INET6 setsockopt JOIN: %s\n", strerror(errno));
goto chs_error;
}
}
freeifaddrs(ifa);
/* TTL: 255 for IPv6 - draft-ietf-mpls-ldp-ipv6-07 Section 9 */
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
&(int){255}, sizeof(int)) == -1) {
fatalp("set mcast hops: %s\n", strerror(errno));
goto chs_error;
}
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
&(uint32_t){1}, sizeof(uint32_t)) == -1)
goto chs_error;
hs = (struct hello_socket *)malloc(sizeof(*hs));
if (hs == NULL) {
fatalp("Memory alloc problem: hs\n");
goto chs_error;
}
hs->type = AF_INET6;
hs->socket = s;
SLIST_INSERT_HEAD(&hello_socket_head, hs, listentry);
#endif
return 0;
chs_error:
close(s);
#ifdef INET6
close(s6);
#endif
return -1;
}
/* Check if parameter is a hello socket */
int
is_hello_socket(int s)
{
struct hello_socket *hs;
SLIST_FOREACH(hs, &hello_socket_head, listentry)
if (hs->socket == s)
return 1;
return 0;
}
/* Sets the TTL to 1 as we don't want to transmit outside this subnet */
int
set_ttl(int s)
@ -221,20 +287,6 @@ set_ttl(int s)
return ret;
}
/* Sets multicast TTL to 1 */
static int
set_mcast_ttl(int s, int stype)
{
int ret;
assert(stype == 4 || stype == 6);
if ((ret = setsockopt(s, stype == 4 ? IPPROTO_IP : IPPROTO_IPV6,
stype == 4 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS, &(int){1},
sizeof(int))) == -1)
fatalp("set_mcast_ttl: %s", strerror(errno));
return ret;
}
/* Sets TOS to 0xc0 aka IP Precedence 6 */
static int
set_tos(int s)
@ -258,20 +310,20 @@ socket_reuse_port(int s)
/* binds an UDP socket */
static int
bind_socket(int s, uint8_t stype)
bind_socket(int s, int stype)
{
union sockunion su;
assert (stype == 4 || stype == 6);
assert (stype == AF_INET || stype == AF_INET6);
if (stype == 4) {
if (stype == AF_INET) {
su.sin.sin_len = sizeof(su.sin);
su.sin.sin_family = AF_INET;
su.sin.sin_addr.s_addr = INADDR_ANY;
su.sin.sin_addr.s_addr = htonl(INADDR_ANY);
su.sin.sin_port = htons(LDP_PORT);
}
#ifdef INET6
else if (stype == 6) {
else if (stype == AF_INET6) {
su.sin6.sin6_len = sizeof(su.sin6);
su.sin6.sin6_family = AF_INET6;
su.sin6.sin6_addr = in6addr_any;
@ -334,11 +386,13 @@ send_hello(void)
ssize_t sb = 0; /* sent bytes */
struct ifaddrs *ifa, *ifb;
struct sockaddr_in *if_sa;
int ip4socket = -1;
uint lastifindex;
struct hello_socket *hs;
#ifdef INET6
struct sockaddr_in6 sadest6;
struct sockaddr_in6 *if_sa6;
int ip6socket = -1;
#endif
char lastifname[20];
#define BASIC_HELLO_MSG_SIZE (sizeof(struct ldp_pdu) + /* PDU */ \
TLV_TYPE_LENGTH + MSGID_SIZE + /* Hello TLV */ \
@ -400,12 +454,21 @@ send_hello(void)
sadest.sin_port = htons(LDP_PORT);
inet_aton(ALL_ROUTERS, &sadest.sin_addr);
/* Find our socket */
SLIST_FOREACH(hs, &hello_socket_head, listentry)
if (hs->type == AF_INET) {
ip4socket = hs->socket;
break;
}
assert(ip4socket >= 0);
if (getifaddrs(&ifa) == -1) {
free(v);
fatalp("Cannot enumerate interfaces\n");
return;
}
lastifname[0] = '\0';
lastifindex = UINT_MAX;
/* Loop all interfaces in order to send IPv4 hellos */
for (ifb = ifa; ifb; ifb = ifb->ifa_next) {
if_sa = (struct sockaddr_in *) ifb->ifa_addr;
@ -416,34 +479,30 @@ send_hello(void)
continue;
/* Send only once per interface, using primary address */
if (strcmp(ifb->ifa_name, lastifname) == 0)
if (lastifindex == if_nametoindex(ifb->ifa_name))
continue;
debugp("Sending hello on %s\n", ifb->ifa_name);
if (setsockopt(hello_socket, IPPROTO_IP, IP_MULTICAST_IF,
lastifindex = if_nametoindex(ifb->ifa_name);
if (setsockopt(ip4socket, IPPROTO_IP, IP_MULTICAST_IF,
&if_sa->sin_addr, sizeof(struct in_addr)) == -1) {
warnp("setsockopt failed: %s\n", strerror(errno));
continue;
}
trtlv->address.ip4addr.s_addr = if_sa->sin_addr.s_addr;
strlcpy(lastifname, ifb->ifa_name, sizeof(lastifname));
/* Send to the wire */
sb = sendto(hello_socket, v, IPV4_HELLO_MSG_SIZE,
0, (struct sockaddr *) & sadest, sizeof(sadest));
/* Put it on the wire */
sb = sendto(ip4socket, v, IPV4_HELLO_MSG_SIZE, 0,
(struct sockaddr *) & sadest, sizeof(sadest));
if (sb < (ssize_t)(IPV4_HELLO_MSG_SIZE))
fatalp("send: %s", strerror(errno));
else
debugp("Sent (IP4) %zd bytes on %s"
"(PDU: %d, Hello TLV: %d, CH: %d, TR: %d)\n",
debugp("Sent (IPv4) %zd bytes on %s"
" (PDU: %d, Hello TLV: %d, CH: %d, TR: %d)\n",
sb, ifb->ifa_name,
ntohs(spdu->length), ntohs(t->length),
ntohs(cht->length), ntohs(trtlv->length));
}
#ifdef INET6
/* Let's do the same thing for IPv6 */
lastifname[0]='\0';
/* Adjust lengths */
spdu->length = htons(IPV6_HELLO_MSG_SIZE - PDU_VER_LENGTH);
t->length = htons(MSGID_SIZE +
@ -459,12 +518,20 @@ send_hello(void)
sadest6.sin6_port = htons(LDP_PORT);
assert(inet_pton(AF_INET6, ALL_ROUTERS6, &sadest6.sin6_addr) == 1);
SLIST_FOREACH(hs, &hello_socket_head, listentry)
if (hs->type == AF_INET6) {
ip6socket = hs->socket;
break;
}
lastifindex = UINT_MAX;
for (ifb = ifa; ifb; ifb = ifb->ifa_next) {
unsigned int if_index;
if_sa6 = (struct sockaddr_in6 *) ifb->ifa_addr;
if (if_sa6->sin6_family != AF_INET6)
continue;
if (IN6_IS_ADDR_LOOPBACK(&if_sa6->sin6_addr))
struct sockaddr_in6 * if_sa6 =
(struct sockaddr_in6 *) ifb->ifa_addr;
if (if_sa6->sin6_family != AF_INET6 ||
(!(ifb->ifa_flags & IFF_UP)) ||
(ifb->ifa_flags & IFF_LOOPBACK) ||
IN6_IS_ADDR_LOOPBACK(&if_sa6->sin6_addr))
continue;
/*
* draft-ietf-mpls-ldp-ipv6-07 Section 5.1:
@ -474,36 +541,32 @@ send_hello(void)
*/
if (IN6_IS_ADDR_LINKLOCAL(&if_sa6->sin6_addr) == 0)
continue;
/* We should have only one LLADDR per interface, but... */
if (lastifindex == if_nametoindex(ifb->ifa_name))
continue;
lastifindex = if_nametoindex(ifb->ifa_name);
/* Send only once per interface, using primary address */
if (strcmp(ifb->ifa_name, lastifname) == 0)
continue;
if_index = if_nametoindex(ifb->ifa_name);
if (if_index == 0)
continue;
if (setsockopt(hello6_socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&if_index, sizeof(int)) == -1) {
warnp("setsockopt6 failed in sendhello(): %s\n",
strerror(errno));
if (setsockopt(ip6socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&lastifindex, sizeof(int)) == -1) {
fatalp("ssopt6 IPV6_MULTICAST_IF failed: %s for %s\n",
strerror(errno), ifb->ifa_name);
continue;
}
memcpy(&trtlv->address.ip6addr, &if_sa6->sin6_addr,
sizeof(struct in6_addr));
strlcpy(lastifname, ifb->ifa_name, sizeof(lastifname));
/* Put it on the wire */
sb = sendto(hello6_socket, v, IPV6_HELLO_MSG_SIZE,
sb = sendto(ip6socket, v, IPV6_HELLO_MSG_SIZE,
0, (struct sockaddr *)&sadest6, sizeof(sadest6));
if (sb < (ssize_t)(IPV6_HELLO_MSG_SIZE))
fatalp("send6 on %s: %s", ifb->ifa_name, strerror(errno));
fatalp("send6: %s", strerror(errno));
else
debugp("Sent (IPv6) %zd bytes on %s"
debugp("Sent (IPv6) %zd bytes on %s "
"(PDU: %d, Hello TLV: %d, CH: %d TR: %d)\n",
sb, ifb->ifa_name,
htons(spdu->length), htons(t->length),
htons(cht->length), htons(trtlv->length));
sb, ifb->ifa_name, htons(spdu->length),
htons(t->length), htons(cht->length),
htons(trtlv->length));
}
#endif
freeifaddrs(ifa);
@ -551,7 +614,7 @@ recv_pdu(int sock)
struct iovec iov[1];
unsigned char recvspace[MAX_PDU_SIZE];
struct hello_tlv *t;
struct sockaddr_in fromsa;
union sockunion sender;
struct sockaddr_dl *sdl = NULL;
struct in_addr my_ldp_addr, local_addr;
struct cmsghdr *cmptr;
@ -560,23 +623,18 @@ recv_pdu(int sock)
char control[1024];
} control_un;
debugp("Entering RECV_PDU\n");
memset(&msg, 0, sizeof(msg));
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
msg.msg_flags = 0;
msg.msg_name = &fromsa;
msg.msg_namelen = sizeof(fromsa);
msg.msg_name = &sender;
msg.msg_namelen = sizeof(sender);
iov[0].iov_base = recvspace;
iov[0].iov_len = sizeof(recvspace);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
c = recvmsg(sock, &msg, MSG_WAITALL);
debugp("Incoming PDU size: %d\n", c);
debugp("PDU from: %s\n", inet_ntoa(fromsa.sin_addr));
/* Check to see if this is larger than MIN_PDU_SIZE */
if (c < MIN_PDU_SIZE)
@ -585,16 +643,20 @@ recv_pdu(int sock)
/* Read the PDU */
i = get_pdu(recvspace, &rpdu);
debugp("recv_pdu(%d): PDU(size: %d) from: %s\n", sock,
c, satos(&sender.sa));
/* We currently understand Version 1 */
if (rpdu.version != LDP_VERSION) {
fatalp("recv_pdu: Version mismatch\n");
warnp("recv_pdu: Version mismatch\n");
return;
}
/* Maybe it's our hello */
/* Check if it's our hello */
inet_aton(LDP_ID, &my_ldp_addr);
if (rpdu.ldp_id.s_addr == my_ldp_addr.s_addr) {
fatalp("Received our PDU..\n"); /* it should be not looped */
/* It should not be looped. We set MULTICAST_LOOP 0 */
fatalp("Received our PDU. Ignoring it\n");
return;
}
@ -619,7 +681,7 @@ recv_pdu(int sock)
/* Fill the TLV messages */
t = get_hello_tlv(recvspace + i, c - i);
run_ldp_hello(&rpdu, t, &fromsa.sin_addr, &local_addr, sock);
run_ldp_hello(&rpdu, t, &sender.sa, &local_addr, sock);
}
void
@ -703,8 +765,10 @@ the_big_loop(void)
struct ldp_peer *p;
struct com_sock *cs;
struct pollfd pfd[MAX_POLL_FDS];
struct hello_socket *hs;
nfds_t pollsum;
assert(MAX_POLL_FDS > 3);
assert(MAX_POLL_FDS > 5);
SLIST_INIT(&hello_info_head);
@ -712,7 +776,9 @@ the_big_loop(void)
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, bail_out);
signal(SIGTERM, bail_out);
send_hello_alarm(1);
/* Send first hellos in 5 seconds. Avoid No hello notifications */
alarm(5);
route_socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
@ -723,8 +789,6 @@ the_big_loop(void)
}
for (;;) {
nfds_t pollsum = 4;
pfd[0].fd = ls;
pfd[0].events = POLLRDNORM;
pfd[0].revents = 0;
@ -737,10 +801,14 @@ the_big_loop(void)
pfd[2].events = POLLRDNORM;
pfd[2].revents = 0;
/* Hello socket */
pfd[3].fd = hello_socket;
pfd[3].events = POLLIN;
pfd[3].revents = 0;
/* Hello sockets */
pollsum = 3;
SLIST_FOREACH(hs, &hello_socket_head, listentry) {
pfd[pollsum].fd = hs->socket;
pfd[pollsum].events = POLLIN;
pfd[pollsum].revents = 0;
pollsum++;
}
/* Command sockets */
for (i=0; i < MAX_COMMAND_SOCKETS; i++)
@ -806,7 +874,7 @@ the_big_loop(void)
check_route(&xbuf, l);
} else if (pfd[i].fd == hello_socket) {
} else if (is_hello_socket(pfd[i].fd) == 1) {
/* Receiving hello socket */
recv_pdu(pfd[i].fd);
} else if (pfd[i].fd == command_socket) {
@ -859,7 +927,7 @@ new_peer_connection()
return;
}
if (get_ldp_peer(&sa.sin_addr) != NULL) {
if (get_ldp_peer((const struct sockaddr *)&sa) != NULL) {
close(s);
return;
}
@ -880,7 +948,7 @@ new_peer_connection()
return;
}
/* XXX: sa.sin_addr is not peer LDP ID ... */
ldp_peer_new(&sa.sin_addr, &sa.sin_addr, NULL, NULL, ldp_holddown_time, s);
ldp_peer_new(&sa.sin_addr, (struct sockaddr *)&sa, NULL, ldp_holddown_time, s);
}
@ -993,6 +1061,7 @@ recv_session_pdu(struct ldp_peer * p)
/* Check size */
if (ntohs(itlv->length) <
sizeof(struct init_tlv) - TLV_TYPE_LENGTH) {
debugp("Bad size\n");
send_notification(p, 0,
NOTIF_BAD_PDU_LEN | NOTIF_FATAL);
ldp_peer_holddown(p);
@ -1000,6 +1069,7 @@ recv_session_pdu(struct ldp_peer * p)
}
/* Check version */
if (ntohs(itlv->cs_version) != LDP_VERSION) {
debugp("Bad version");
send_notification(p, ntohl(itlv->messageid),
NOTIF_BAD_LDP_VER | NOTIF_FATAL);
ldp_peer_holddown(p);
@ -1010,6 +1080,7 @@ recv_session_pdu(struct ldp_peer * p)
if (hi->ldp_id.s_addr == rpdu->ldp_id.s_addr)
break;
if (hi == NULL) {
debugp("No hello. Moving peer to holddown\n");
send_notification(p, ntohl(itlv->messageid),
NOTIF_SESSION_REJECTED_NO_HELLO | NOTIF_FATAL);
ldp_peer_holddown(p);

View File

@ -1,4 +1,4 @@
/* $NetBSD: socketops.h,v 1.3 2012/11/12 18:39:00 kefren Exp $ */
/* $NetBSD: socketops.h,v 1.4 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -62,4 +62,10 @@ struct hello_info {
};
SLIST_HEAD(,hello_info) hello_info_head;
struct hello_socket {
int type, socket;
SLIST_ENTRY(hello_socket) listentry;
};
SLIST_HEAD(,hello_socket) hello_socket_head;
#endif /* !_SOCKETOPS_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: tlv.h,v 1.2 2012/11/12 18:39:00 kefren Exp $ */
/* $NetBSD: tlv.h,v 1.3 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -87,7 +87,7 @@ struct hello_tlv {
/* XXX: optional parameters */
} __packed;
/* IPv4 Transport address TLV */
/* Transport address TLV */
struct transport_address_tlv {
uint16_t type;
uint16_t length;

View File

@ -1,4 +1,4 @@
/* $NetBSD: tlv_stack.c,v 1.5 2012/11/12 18:39:00 kefren Exp $ */
/* $NetBSD: tlv_stack.c,v 1.6 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -62,7 +62,7 @@ map_label(struct ldp_peer * p, struct fec_tlv * f, struct label_tlv * l)
{
int n;
struct prefix_tlv *pref;
struct in_addr inatmp;
union sockunion socktmp;
if (ntohs(f->type) != TLV_FEC) {
debugp("Invalid FEC TLV !\n");
@ -83,7 +83,8 @@ map_label(struct ldp_peer * p, struct fec_tlv * f, struct label_tlv * l)
debugp("Label %u for:\n", ntohl(l->label));
pref = (struct prefix_tlv *) & f[1];
pref = (struct prefix_tlv *) (f + 1);
memset (&socktmp, 0, sizeof(socktmp));
/*
* Section 3.4.1
@ -96,8 +97,14 @@ map_label(struct ldp_peer * p, struct fec_tlv * f, struct label_tlv * l)
for (; n > 0; pref = (struct prefix_tlv *) ((unsigned char *) pref +
ldp_ceil8(pref->prelen) + TLV_TYPE_LENGTH)) {
n -= ldp_ceil8(pref->prelen) + TLV_TYPE_LENGTH;
if (ntohs(pref->af) != LDP_AF_INET) {
debugp("BAD ADDRESS FAMILY (%d) ! (prefix type %d, "
if (ntohs(pref->af) == LDP_AF_INET) {
socktmp.sa.sa_family = AF_INET;
socktmp.sa.sa_len = sizeof(socktmp.sin);
} else if (ntohs(pref->af) == LDP_AF_INET6) {
socktmp.sa.sa_family = AF_INET6;
socktmp.sa.sa_len = sizeof(socktmp.sin6);
} else {
warnp("BAD ADDRESS FAMILY (%d) ! (prefix type %d, "
"length %d)\n", ntohs(pref->af), pref->type,
pref->prelen);
return LDP_E_BAD_AF;
@ -105,22 +112,26 @@ map_label(struct ldp_peer * p, struct fec_tlv * f, struct label_tlv * l)
switch(pref->type) {
case FEC_PREFIX:
case FEC_HOST:
memset(&inatmp, 0, sizeof(struct in_addr));
memcpy(&inatmp, &pref->prefix, ldp_ceil8(pref->prelen));
debugp("Prefix/Host add: %s/%d\n", inet_ntoa(inatmp),
if (socktmp.sa.sa_family == AF_INET)
memcpy(&socktmp.sin.sin_addr, &pref->prefix,
ldp_ceil8(pref->prelen));
else
memcpy(&socktmp.sin6.sin6_addr, &pref->prefix,
ldp_ceil8(pref->prelen));
debugp("Prefix/Host add: %s/%d\n", satos(&socktmp.sa),
pref->prelen);
ldp_peer_add_mapping(p, &inatmp, pref->prelen,
ldp_peer_add_mapping(p, &socktmp.sa, pref->prelen,
ntohl(l->label));
/* Try to change RIB only if label is installed */
if (label_get_by_prefix(&inatmp, pref->prelen) != NULL)
mpls_add_label(p, NULL, &inatmp, pref->prelen,
if (label_get_by_prefix(&socktmp.sa, pref->prelen) != NULL)
mpls_add_label(p, NULL, &socktmp.sa, pref->prelen,
ntohl(l->label), 1);
break;
case FEC_WILDCARD:
fatalp("LDP: Wildcard add from peer %s\n",
inet_ntoa(p->address));
satos(p->address));
return LDP_E_BAD_FEC;
default:
fatalp("Unknown FEC type %d\n", pref->type);
@ -136,7 +147,7 @@ withdraw_label(struct ldp_peer * p, struct fec_tlv * f)
{
int n;
struct prefix_tlv *pref;
struct in_addr inatmp;
union sockunion socktmp;
struct label *lab;
if (ntohs(f->type) != TLV_FEC) {
@ -148,27 +159,39 @@ withdraw_label(struct ldp_peer * p, struct fec_tlv * f)
return LDP_E_BAD_FEC;
pref = (struct prefix_tlv *) & f[1];
if (ntohs(pref->af) != LDP_AF_INET) {
debugp("BAD ADDRESS FAMILY (%d)! (prefix type %d, length %d)\n",
memset(&socktmp, 0, sizeof(socktmp));
if (ntohs(pref->af) == LDP_AF_INET) {
socktmp.sa.sa_family = AF_INET;
socktmp.sa.sa_len = sizeof(socktmp.sin);
} else if (ntohs(pref->af) != LDP_AF_INET6) {
socktmp.sa.sa_family = AF_INET6;
socktmp.sa.sa_len = sizeof(socktmp.sin6);
} else {
warnp("WITHDRAW: Bad AF (%d)! (prefix type %d, length %d)\n",
ntohs(pref->af), pref->type, pref->prelen);
return LDP_E_BAD_AF;
}
switch(pref->type) {
case FEC_PREFIX:
case FEC_HOST:
memset(&inatmp, 0, sizeof(struct in_addr));
memcpy(&inatmp, &pref->prefix, ldp_ceil8(pref->prelen));
debugp("Prefix/Host withdraw: %s/%d\n", inet_ntoa(inatmp),
if (socktmp.sa.sa_family == AF_INET)
memcpy(&socktmp.sin.sin_addr, &pref->prefix,
ldp_ceil8(pref->prelen));
else
memcpy(&socktmp.sin6.sin6_addr, &pref->prefix,
ldp_ceil8(pref->prelen));
debugp("Prefix/Host withdraw: %s/%d\n", satos(&socktmp.sa),
pref->prelen);
/* Delete mapping */
ldp_peer_delete_mapping(p, &inatmp, pref->prelen);
ldp_peer_delete_mapping(p, &socktmp.sa, pref->prelen);
/* Get label, see if we're pointing to this peer
* if so, send withdraw, reattach IP route and announce
* POP Label
*/
lab = label_get_by_prefix(&inatmp, pref->prelen);
lab = label_get_by_prefix(&socktmp.sa, pref->prelen);
if ((lab) && (lab->p == p)) {
change_local_label(lab, MPLS_LABEL_IMPLNULL);
label_reattach_route(lab, LDP_READD_CHANGE);
@ -176,7 +199,7 @@ withdraw_label(struct ldp_peer * p, struct fec_tlv * f)
break;
case FEC_WILDCARD:
fatalp("LDP neighbour %s: Wildcard withdraw !!!\n",
inet_ntoa(p->address));
satos(p->address));
ldp_peer_delete_mapping(p, NULL, 0);
label_reattach_all_peer_labels(p, LDP_READD_CHANGE);
break;
@ -206,7 +229,7 @@ prepare_release(struct tlv * v)
/* Sends a label mapping */
void
send_label_tlv(struct ldp_peer * peer, struct in_addr * addr,
send_label_tlv(struct ldp_peer * peer, struct sockaddr * addr,
uint8_t prefixlen, uint32_t label, struct label_request_tlv *lrt)
{
struct label_map_tlv *lmt;
@ -282,7 +305,7 @@ send_label_tlv(struct ldp_peer * peer, struct in_addr * addr,
}
void
send_label_tlv_to_all(struct in_addr * addr, uint8_t prefixlen, uint32_t label)
send_label_tlv_to_all(struct sockaddr * addr, uint8_t prefixlen, uint32_t label)
{
struct ldp_peer *p;
SLIST_FOREACH(p, &ldp_peer_head, peers)
@ -298,14 +321,14 @@ send_all_bindings(struct ldp_peer * peer)
struct label *l;
SLIST_FOREACH(l, &label_head, labels)
send_label_tlv(peer, &((struct sockaddr_in*)(&l->so_dest))->sin_addr,
send_label_tlv(peer, &l->so_dest.sa,
from_union_to_cidr(&l->so_pref), l->binding, NULL);
}
/* Sends a label WITHDRAW */
void
send_withdraw_tlv(struct ldp_peer * peer, struct in_addr * addr,
send_withdraw_tlv(struct ldp_peer * peer, struct sockaddr * addr,
uint8_t prefixlen)
{
struct label_map_tlv *lmt;
@ -360,7 +383,7 @@ send_withdraw_tlv(struct ldp_peer * peer, struct in_addr * addr,
}
void
send_withdraw_tlv_to_all(struct in_addr * addr, uint8_t prefixlen)
send_withdraw_tlv_to_all(struct sockaddr * addr, uint8_t prefixlen)
{
struct ldp_peer *p;
SLIST_FOREACH(p, &ldp_peer_head, peers)
@ -372,7 +395,7 @@ request_respond(struct ldp_peer *p, struct label_map_tlv *lmt,
struct fec_tlv *fec)
{
struct prefix_tlv *pref;
struct in_addr inatmp;
union sockunion socktmp;
struct label *lab;
struct label_request_tlv lrm;
@ -382,7 +405,14 @@ request_respond(struct ldp_peer *p, struct label_map_tlv *lmt,
}
pref = (struct prefix_tlv *) (fec + 1);
if (ntohs(pref->af) != LDP_AF_INET) {
memset(&socktmp, 0, sizeof(socktmp));
if (ntohs(pref->af) == LDP_AF_INET) {
socktmp.sa.sa_family = AF_INET;
socktmp.sa.sa_len = sizeof(socktmp.sin);
} else if (ntohs(pref->af) == LDP_AF_INET6) {
socktmp.sa.sa_family = AF_INET6;
socktmp.sa.sa_len = sizeof(socktmp.sin6);
} else {
debugp("request_respond: Bad address family\n");
return LDP_E_BAD_AF;
}
@ -391,18 +421,23 @@ request_respond(struct ldp_peer *p, struct label_map_tlv *lmt,
case FEC_PREFIX:
case FEC_HOST:
memset(&inatmp, 0, sizeof(struct in_addr));
memcpy(&inatmp, &pref->prefix, ldp_ceil8(pref->prelen));
debugp("Prefix/Host request: %s/%d\n", inet_ntoa(inatmp),
if (socktmp.sa.sa_family == AF_INET)
memcpy(&socktmp.sin.sin_addr, &pref->prefix,
ldp_ceil8(pref->prelen));
else /* AF_INET6 */
memcpy(&socktmp.sin6.sin6_addr, &pref->prefix,
ldp_ceil8(pref->prelen));
debugp("Prefix/Host request: %s/%d\n", satos(&socktmp.sa),
pref->prelen);
lab = label_get_by_prefix(&inatmp, pref->prelen);
lab = label_get_by_prefix(&socktmp.sa, pref->prelen);
if (!lab)
return LDP_E_NO_SUCH_ROUTE;
lrm.type = htons(TLV_LABEL_REQUEST);
lrm.length = htons(sizeof(uint32_t));
/* XXX - use sizeof */
lrm.length = htons(socktmp.sa.sa_family == AF_INET ? 4 : 16);
lrm.messageid = lmt->messageid;
send_label_tlv(p, &inatmp, pref->prelen, lab->binding, &lrm);
send_label_tlv(p, &socktmp.sa, pref->prelen, lab->binding, &lrm);
break;
case FEC_WILDCARD:

View File

@ -1,4 +1,4 @@
/* $NetBSD: tlv_stack.h,v 1.1 2010/12/08 07:20:15 kefren Exp $ */
/* $NetBSD: tlv_stack.h,v 1.2 2013/01/26 17:29:55 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -42,12 +42,12 @@
int map_label(struct ldp_peer *, struct fec_tlv *, struct label_tlv *);
int withdraw_label(struct ldp_peer *, struct fec_tlv *);
void prepare_release(struct tlv *);
void send_label_tlv(struct ldp_peer *, struct in_addr *, uint8_t,
void send_label_tlv(struct ldp_peer *, struct sockaddr *, uint8_t,
uint32_t, struct label_request_tlv *);
void send_label_tlv_to_all(struct in_addr *, uint8_t, uint32_t);
void send_label_tlv_to_all(struct sockaddr *, uint8_t, uint32_t);
void send_all_bindings(struct ldp_peer *);
void send_withdraw_tlv(struct ldp_peer *, struct in_addr *, uint8_t);
void send_withdraw_tlv_to_all(struct in_addr *, uint8_t);
void send_withdraw_tlv(struct ldp_peer *, struct sockaddr *, uint8_t);
void send_withdraw_tlv_to_all(struct sockaddr *, uint8_t);
int request_respond(struct ldp_peer *, struct label_map_tlv *,
struct fec_tlv *);