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:
parent
c1cffbf8b8
commit
269ea2d396
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
Loading…
Reference in New Issue