summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2013-06-04 02:34:48 +0000
committerclaudio <claudio@openbsd.org>2013-06-04 02:34:48 +0000
commit699b7d06c4c43fc31e802807ce75d0a15945e2a0 (patch)
tree1c2d19fcbb1487e5adb4a032af0d4120f99f59c4
parentTiny typo. "Just commit" -- claudio@ (diff)
downloadwireguard-openbsd-699b7d06c4c43fc31e802807ce75d0a15945e2a0.tar.xz
wireguard-openbsd-699b7d06c4c43fc31e802807ce75d0a15945e2a0.zip
Always accept TCP connection requests and identify to which neighbor
it belongs only _after_ receiving an Initialization message containing the information we need. Before an Initialization message is received, the TCP connection shouldn't be associated with any neighbor/adjacency. Therefor refactor that part into a own module. From Renato Westphal
-rw-r--r--usr.sbin/ldpd/address.c6
-rw-r--r--usr.sbin/ldpd/init.c4
-rw-r--r--usr.sbin/ldpd/keepalive.c4
-rw-r--r--usr.sbin/ldpd/labelmapping.c12
-rw-r--r--usr.sbin/ldpd/ldpd.h3
-rw-r--r--usr.sbin/ldpd/ldpe.h26
-rw-r--r--usr.sbin/ldpd/neighbor.c51
-rw-r--r--usr.sbin/ldpd/notification.c14
-rw-r--r--usr.sbin/ldpd/packet.c137
9 files changed, 144 insertions, 113 deletions
diff --git a/usr.sbin/ldpd/address.c b/usr.sbin/ldpd/address.c
index 3cfdf0faba8..7fa2d3ae4dc 100644
--- a/usr.sbin/ldpd/address.c
+++ b/usr.sbin/ldpd/address.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: address.c,v 1.12 2013/06/04 00:41:18 claudio Exp $ */
+/* $OpenBSD: address.c,v 1.13 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -72,7 +72,7 @@ send_address(struct nbr *nbr, struct if_addr *if_addr)
gen_address_list_tlv(buf, if_addr, size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
@@ -186,6 +186,6 @@ send_address_withdraw(struct nbr *nbr, struct if_addr *if_addr)
gen_address_list_tlv(buf, if_addr, size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
diff --git a/usr.sbin/ldpd/init.c b/usr.sbin/ldpd/init.c
index 90937841f53..26680dc9d24 100644
--- a/usr.sbin/ldpd/init.c
+++ b/usr.sbin/ldpd/init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init.c,v 1.11 2013/06/04 01:32:16 claudio Exp $ */
+/* $OpenBSD: init.c,v 1.12 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -65,7 +65,7 @@ send_init(struct nbr *nbr)
gen_init_prms_tlv(buf, nbr, size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
}
int
diff --git a/usr.sbin/ldpd/keepalive.c b/usr.sbin/ldpd/keepalive.c
index 0207a983973..443697991cc 100644
--- a/usr.sbin/ldpd/keepalive.c
+++ b/usr.sbin/ldpd/keepalive.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: keepalive.c,v 1.9 2013/06/01 18:47:07 claudio Exp $ */
+/* $OpenBSD: keepalive.c,v 1.10 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -54,7 +54,7 @@ send_keepalive(struct nbr *nbr)
gen_msg_tlv(buf, MSG_TYPE_KEEPALIVE, size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
}
int
diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c
index f4fd3566f25..2ed93570578 100644
--- a/usr.sbin/ldpd/labelmapping.c
+++ b/usr.sbin/ldpd/labelmapping.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: labelmapping.c,v 1.23 2013/06/01 19:42:07 claudio Exp $ */
+/* $OpenBSD: labelmapping.c,v 1.24 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -83,7 +83,7 @@ send_labelmapping(struct nbr *nbr)
ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
@@ -184,7 +184,7 @@ send_labelrequest(struct nbr *nbr)
ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
@@ -281,7 +281,7 @@ send_labelwithdraw(struct nbr *nbr)
ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
@@ -414,7 +414,7 @@ send_labelrelease(struct nbr *nbr)
ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
@@ -525,7 +525,7 @@ send_labelabortreq(struct nbr *nbr)
gen_msg_tlv(buf, MSG_TYPE_LABELABORTREQ, size);
- evbuf_enqueue(&nbr->wbuf, buf);
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h
index c966f78ab40..b1a8d9d772e 100644
--- a/usr.sbin/ldpd/ldpd.h
+++ b/usr.sbin/ldpd/ldpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.h,v 1.41 2013/06/04 02:28:27 claudio Exp $ */
+/* $OpenBSD: ldpd.h,v 1.42 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -153,6 +153,7 @@ enum iface_type {
/* neighbor events */
enum nbr_event {
NBR_EVT_NOTHING,
+ NBR_EVT_MATCH_ADJ,
NBR_EVT_CONNECT_UP,
NBR_EVT_CLOSE_SESSION,
NBR_EVT_INIT_RCVD,
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h
index e9f7255b04f..473ae4d54d8 100644
--- a/usr.sbin/ldpd/ldpe.h
+++ b/usr.sbin/ldpd/ldpe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.h,v 1.26 2013/06/04 02:28:27 claudio Exp $ */
+/* $OpenBSD: ldpe.h,v 1.27 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
@@ -48,10 +48,18 @@ struct adj {
struct in_addr addr;
};
-struct nbr {
- RB_ENTRY(nbr) id_tree, addr_tree, pid_tree;
+struct nbr;
+struct tcp_conn {
+ struct nbr *nbr;
+ int fd;
+ struct ibuf_read *rbuf;
struct evbuf wbuf;
struct event rev;
+};
+
+struct nbr {
+ RB_ENTRY(nbr) id_tree, pid_tree;
+ struct tcp_conn *tcp;
LIST_HEAD(, adj) adj_list; /* adjacencies */
struct event ev_connect;
struct event keepalive_timer;
@@ -67,15 +75,12 @@ struct nbr {
struct in_addr addr;
struct in_addr id;
- struct ibuf_read *rbuf;
-
time_t uptime;
u_int32_t peerid; /* unique ID in DB */
int fd;
int state;
int idtimer_cnt;
-
u_int16_t keepalive;
};
@@ -105,7 +110,8 @@ int recv_keepalive(struct nbr *, char *, u_int16_t);
/* notification.c */
void send_notification_nbr(struct nbr *, u_int32_t, u_int32_t, u_int32_t);
-struct ibuf *send_notification(u_int32_t, u_int32_t, u_int32_t);
+void send_notification(u_int32_t, struct tcp_conn *, u_int32_t,
+ u_int32_t);
int recv_notification(struct nbr *, char *, u_int16_t);
/* address.c */
@@ -176,7 +182,6 @@ void ldpe_adj_ctl(struct ctl_conn *);
struct nbr *nbr_new(struct in_addr, struct in_addr);
void nbr_del(struct nbr *);
-struct nbr *nbr_find_ip(u_int32_t);
struct nbr *nbr_find_ldpid(u_int32_t);
struct nbr *nbr_find_peerid(u_int32_t);
@@ -196,7 +201,6 @@ int nbr_pending_idtimer(struct nbr *);
int nbr_pending_connect(struct nbr *);
int nbr_establish_connection(struct nbr *);
-void nbr_act_connect_setup(struct nbr *);
void nbr_mapping_add(struct nbr *, struct mapping_head *,
struct map *);
@@ -217,6 +221,10 @@ int send_packet(int, struct iface *, void *, size_t, struct sockaddr_in *);
void disc_recv_packet(int, short, void *);
void session_accept(int, short, void *);
+struct tcp_conn *tcp_new(int, struct nbr *);
+void tcp_close(struct tcp_conn *);
+
+
void session_read(int, short, void *);
void session_write(int, short, void *);
void session_close(struct nbr *);
diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c
index f9ecb08b36b..b04628980f2 100644
--- a/usr.sbin/ldpd/neighbor.c
+++ b/usr.sbin/ldpd/neighbor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: neighbor.c,v 1.36 2013/06/04 02:25:28 claudio Exp $ */
+/* $OpenBSD: neighbor.c,v 1.37 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -46,15 +46,11 @@ void nbr_send_labelmappings(struct nbr *);
int nbr_act_session_operational(struct nbr *);
static __inline int nbr_id_compare(struct nbr *, struct nbr *);
-static __inline int nbr_addr_compare(struct nbr *, struct nbr *);
static __inline int nbr_pid_compare(struct nbr *, struct nbr *);
RB_HEAD(nbr_id_head, nbr);
RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare)
RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare)
-RB_HEAD(nbr_addr_head, nbr);
-RB_PROTOTYPE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare)
-RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare)
RB_HEAD(nbr_pid_head, nbr);
RB_PROTOTYPE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
@@ -66,19 +62,12 @@ nbr_id_compare(struct nbr *a, struct nbr *b)
}
static __inline int
-nbr_addr_compare(struct nbr *a, struct nbr *b)
-{
- return (ntohl(a->addr.s_addr) - ntohl(b->addr.s_addr));
-}
-
-static __inline int
nbr_pid_compare(struct nbr *a, struct nbr *b)
{
return (a->peerid - b->peerid);
}
struct nbr_id_head nbrs_by_id = RB_INITIALIZER(&nbrs_by_id);
-struct nbr_addr_head nbrs_by_addr = RB_INITIALIZER(&nbrs_by_addr);
struct nbr_pid_head nbrs_by_pid = RB_INITIALIZER(&nbrs_by_pid);
u_int32_t peercnt = NBR_CNTSTART;
@@ -92,11 +81,12 @@ struct {
int new_state;
} nbr_fsm_tbl[] = {
/* current state event that happened action to take resulting state */
- {NBR_STA_PRESENT, NBR_EVT_CONNECT_UP, NBR_ACT_CONNECT_SETUP, NBR_STA_INITIAL},
/* Passive Role */
+ {NBR_STA_PRESENT, NBR_EVT_MATCH_ADJ, NBR_ACT_NOTHING, NBR_STA_INITIAL},
{NBR_STA_INITIAL, NBR_EVT_INIT_RCVD, NBR_ACT_PASSIVE_INIT, NBR_STA_OPENREC},
{NBR_STA_OPENREC, NBR_EVT_KEEPALIVE_RCVD, NBR_ACT_SESSION_EST, NBR_STA_OPER},
/* Active Role */
+ {NBR_STA_PRESENT, NBR_EVT_CONNECT_UP, NBR_ACT_CONNECT_SETUP, NBR_STA_INITIAL},
{NBR_STA_INITIAL, NBR_EVT_INIT_SENT, NBR_ACT_NOTHING, NBR_STA_OPENSENT},
{NBR_STA_OPENSENT, NBR_EVT_INIT_RCVD, NBR_ACT_KEEPALIVE_SEND, NBR_STA_OPENREC},
/* Session Maintenance */
@@ -110,6 +100,7 @@ struct {
const char * const nbr_event_names[] = {
"NOTHING",
+ "ADJACENCY MATCHED",
"CONNECTION UP",
"SESSION CLOSE",
"INIT RECEIVED",
@@ -187,13 +178,11 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event)
nbr_send_labelmappings(nbr);
break;
case NBR_ACT_CONNECT_SETUP:
- nbr_act_connect_setup(nbr);
+ nbr->tcp = tcp_new(nbr->fd, nbr);
- if (nbr_session_active_role(nbr)) {
- /* trigger next state */
- send_init(nbr);
- nbr_fsm(nbr, NBR_EVT_INIT_SENT);
- }
+ /* trigger next state */
+ send_init(nbr);
+ nbr_fsm(nbr, NBR_EVT_INIT_SENT);
break;
case NBR_ACT_PASSIVE_INIT:
send_init(nbr);
@@ -225,8 +214,6 @@ nbr_new(struct in_addr id, struct in_addr addr)
if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
fatal("nbr_new");
- if ((nbr->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL)
- fatal("nbr_new");
nbr->state = NBR_STA_PRESENT;
nbr->id.s_addr = id.s_addr;
@@ -239,8 +226,6 @@ nbr_new(struct in_addr id, struct in_addr addr)
if (RB_INSERT(nbr_pid_head, &nbrs_by_pid, nbr) != NULL)
fatalx("nbr_new: RB_INSERT(nbrs_by_pid) failed");
- if (RB_INSERT(nbr_addr_head, &nbrs_by_addr, nbr) != NULL)
- fatalx("nbr_new: RB_INSERT(nbrs_by_addr) failed");
if (RB_INSERT(nbr_id_head, &nbrs_by_id, nbr) != NULL)
fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed");
@@ -278,10 +263,8 @@ nbr_del(struct nbr *nbr)
nbr_mapping_list_clr(nbr, &nbr->abortreq_list);
RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr);
- RB_REMOVE(nbr_addr_head, &nbrs_by_addr, nbr);
RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr);
- free(nbr->rbuf);
free(nbr);
}
@@ -294,14 +277,6 @@ nbr_find_peerid(u_int32_t peerid)
}
struct nbr *
-nbr_find_ip(u_int32_t addr)
-{
- struct nbr n;
- n.addr.s_addr = addr;
- return (RB_FIND(nbr_addr_head, &nbrs_by_addr, &n));
-}
-
-struct nbr *
nbr_find_ldpid(u_int32_t rtr_id)
{
struct nbr n;
@@ -539,14 +514,6 @@ nbr_establish_connection(struct nbr *nbr)
return (0);
}
-void
-nbr_act_connect_setup(struct nbr *nbr)
-{
- evbuf_init(&nbr->wbuf, nbr->fd, session_write, nbr);
- event_set(&nbr->rev, nbr->fd, EV_READ | EV_PERSIST, session_read, nbr);
- event_add(&nbr->rev, NULL);
-}
-
int
nbr_act_session_operational(struct nbr *nbr)
{
@@ -646,7 +613,7 @@ ldpe_nbr_ctl(struct ctl_conn *c)
struct nbr *nbr;
struct ctl_nbr *nctl;
- RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
+ RB_FOREACH(nbr, nbr_pid_head, &nbrs_by_pid) {
nctl = nbr_to_ctl(nbr);
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
sizeof(struct ctl_nbr));
diff --git a/usr.sbin/ldpd/notification.c b/usr.sbin/ldpd/notification.c
index be57dd1acc4..f3e62868767 100644
--- a/usr.sbin/ldpd/notification.c
+++ b/usr.sbin/ldpd/notification.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: notification.c,v 1.13 2013/06/04 01:32:16 claudio Exp $ */
+/* $OpenBSD: notification.c,v 1.14 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -43,15 +43,13 @@ void
send_notification_nbr(struct nbr *nbr, u_int32_t status, u_int32_t msgid,
u_int32_t type)
{
- struct ibuf *buf;
-
- buf = send_notification(status, msgid, type);
- evbuf_enqueue(&nbr->wbuf, buf);
+ send_notification(status, nbr->tcp, msgid, type);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
-struct ibuf *
-send_notification(u_int32_t status, u_int32_t msgid, u_int32_t type)
+void
+send_notification(u_int32_t status, struct tcp_conn *tcp, u_int32_t msgid,
+ u_int32_t type)
{
struct ibuf *buf;
u_int16_t size;
@@ -71,7 +69,7 @@ send_notification(u_int32_t status, u_int32_t msgid, u_int32_t type)
gen_status_tlv(buf, status, msgid, type);
- return (buf);
+ evbuf_enqueue(&tcp->wbuf, buf);
}
int
diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c
index 98637b8d769..f1e90776559 100644
--- a/usr.sbin/ldpd/packet.c
+++ b/usr.sbin/ldpd/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.26 2013/06/04 02:25:28 claudio Exp $ */
+/* $OpenBSD: packet.c,v 1.27 2013/06/04 02:34:48 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -227,11 +227,41 @@ disc_find_iface(unsigned int ifindex, struct in_addr src)
return (NULL);
}
+struct tcp_conn *
+tcp_new(int fd, struct nbr *nbr)
+{
+ struct tcp_conn *tcp;
+
+ if ((tcp = calloc(1, sizeof(*tcp))) == NULL)
+ fatal("tcp_new");
+ if ((tcp->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL)
+ fatal("tcp_new");
+
+ if (nbr)
+ tcp->nbr = nbr;
+
+ tcp->fd = fd;
+ evbuf_init(&tcp->wbuf, tcp->fd, session_write, tcp);
+ event_set(&tcp->rev, tcp->fd, EV_READ | EV_PERSIST, session_read, tcp);
+ event_add(&tcp->rev, NULL);
+
+ return (tcp);
+}
+
+void
+tcp_close(struct tcp_conn *tcp)
+{
+ evbuf_clear(&tcp->wbuf);
+ event_del(&tcp->rev);
+ close(tcp->fd);
+ free(tcp->rbuf);
+ free(tcp);
+}
+
void
session_accept(int fd, short event, void *bula)
{
struct sockaddr_in src;
- struct nbr *nbr = NULL;
int newfd;
socklen_t len = sizeof(src);
@@ -255,28 +285,14 @@ session_accept(int fd, short event, void *bula)
session_socket_blockmode(newfd, BM_NONBLOCK);
- nbr = nbr_find_ip(src.sin_addr.s_addr);
- if (nbr == NULL) {
- struct ibuf *buf;
- /* If there is no neighbor matching there is no
- Hello adjacency: try to send notification */
- log_warnx("Connection attempt from unknown neighbor %s: %s",
- inet_ntoa(src.sin_addr), "NO HELLO");
- buf = send_notification(S_NO_HELLO, 0, 0);
- write(newfd, buf->buf, buf->wpos);
- ibuf_free(buf);
- close(newfd);
- return;
- }
-
- nbr->fd = newfd;
- nbr_fsm(nbr, NBR_EVT_CONNECT_UP);
+ tcp_new(newfd, NULL);
}
void
session_read(int fd, short event, void *arg)
{
- struct nbr *nbr = arg;
+ struct tcp_conn *tcp = arg;
+ struct nbr *nbr = tcp->nbr;
struct ldp_hdr *ldp_hdr;
struct ldp_msg *ldp_msg;
char *buf, *pdu;
@@ -289,11 +305,14 @@ session_read(int fd, short event, void *arg)
return;
}
- if ((n = read(fd, nbr->rbuf->buf + nbr->rbuf->wpos,
- sizeof(nbr->rbuf->buf) - nbr->rbuf->wpos)) == -1) {
+ if ((n = read(fd, tcp->rbuf->buf + tcp->rbuf->wpos,
+ sizeof(tcp->rbuf->buf) - tcp->rbuf->wpos)) == -1) {
if (errno != EINTR && errno != EAGAIN) {
log_warn("session_read: read error");
- nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
+ if (nbr)
+ nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
+ else
+ tcp_close(tcp);
return;
}
/* retry read */
@@ -302,32 +321,68 @@ session_read(int fd, short event, void *arg)
if (n == 0) {
/* connection closed */
log_debug("session_read: connection closed by remote end");
- nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
+ if (nbr)
+ nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
+ else
+ tcp_close(tcp);
return;
}
- nbr->rbuf->wpos += n;
+ tcp->rbuf->wpos += n;
- while ((len = session_get_pdu(nbr->rbuf, &buf)) > 0) {
+ while ((len = session_get_pdu(tcp->rbuf, &buf)) > 0) {
pdu = buf;
ldp_hdr = (struct ldp_hdr *)pdu;
if (ntohs(ldp_hdr->version) != LDP_VERSION) {
- session_shutdown(nbr, S_BAD_PROTO_VER, 0, 0);
+ if (nbr)
+ session_shutdown(nbr, S_BAD_PROTO_VER, 0, 0);
+ else {
+ send_notification(S_BAD_PROTO_VER, tcp, 0, 0);
+ msgbuf_write(&tcp->wbuf.wbuf);
+ tcp_close(tcp);
+ }
free(buf);
return;
}
pdu_len = ntohs(ldp_hdr->length);
if (pdu_len < LDP_HDR_SIZE || pdu_len > LDP_MAX_LEN) {
- session_shutdown(nbr, S_BAD_MSG_LEN, 0, 0);
+ if (nbr)
+ session_shutdown(nbr, S_BAD_MSG_LEN, 0, 0);
+ else {
+ send_notification(S_BAD_MSG_LEN, tcp, 0, 0);
+ msgbuf_write(&tcp->wbuf.wbuf);
+ tcp_close(tcp);
+ }
free(buf);
return;
}
- if (ldp_hdr->lsr_id != nbr->id.s_addr ||
- ldp_hdr->lspace_id != 0) {
- session_shutdown(nbr, S_BAD_LDP_ID, 0, 0);
- free(buf);
- return;
+ if (nbr) {
+ if (ldp_hdr->lsr_id != nbr->id.s_addr ||
+ ldp_hdr->lspace_id != 0) {
+ session_shutdown(nbr, S_BAD_LDP_ID, 0, 0);
+ free(buf);
+ return;
+ }
+ } else {
+ nbr = nbr_find_ldpid(ldp_hdr->lsr_id);
+ if (!nbr) {
+ send_notification(S_NO_HELLO, tcp, 0, 0);
+ msgbuf_write(&tcp->wbuf.wbuf);
+ tcp_close(tcp);
+ free(buf);
+ return;
+ }
+ /* handle duplicate SYNs */
+ if (nbr->tcp) {
+ tcp_close(tcp);
+ free(buf);
+ return;
+ }
+
+ nbr->tcp = tcp;
+ tcp->nbr = nbr;
+ nbr_fsm(nbr, NBR_EVT_MATCH_ADJ);
}
pdu += LDP_HDR_SIZE;
@@ -442,15 +497,18 @@ session_read(int fd, short event, void *arg)
void
session_write(int fd, short event, void *arg)
{
- struct nbr *nbr = arg;
+ struct tcp_conn *tcp = arg;
+ struct nbr *nbr = tcp->nbr;
if (event & EV_WRITE) {
- if (msgbuf_write(&nbr->wbuf.wbuf) == -1)
- nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
+ if (msgbuf_write(&tcp->wbuf.wbuf) == -1) {
+ if (nbr)
+ nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
+ }
} else
log_debug("session_write: spurious event");
- evbuf_event_add(&nbr->wbuf);
+ evbuf_event_add(&tcp->wbuf);
}
void
@@ -463,7 +521,7 @@ session_shutdown(struct nbr *nbr, u_int32_t status, u_int32_t msgid,
send_notification_nbr(nbr, status, msgid, type);
/* try to flush write buffer, if it fails tough shit */
- msgbuf_write(&nbr->wbuf.wbuf);
+ msgbuf_write(&nbr->tcp->wbuf.wbuf);
nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
}
@@ -474,13 +532,12 @@ session_close(struct nbr *nbr)
log_debug("session_close: closing session with nbr ID %s",
inet_ntoa(nbr->id));
- evbuf_clear(&nbr->wbuf);
- event_del(&nbr->rev);
+ tcp_close(nbr->tcp);
+ nbr->tcp = NULL;
nbr_stop_ktimer(nbr);
nbr_stop_ktimeout(nbr);
- close(nbr->fd);
accept_unpause();
}