summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ldpd/address.c8
-rw-r--r--usr.sbin/ldpd/init.c5
-rw-r--r--usr.sbin/ldpd/keepalive.c5
-rw-r--r--usr.sbin/ldpd/labelmapping.c19
-rw-r--r--usr.sbin/ldpd/ldp.h7
-rw-r--r--usr.sbin/ldpd/ldpd.c33
-rw-r--r--usr.sbin/ldpd/ldpd.h12
-rw-r--r--usr.sbin/ldpd/ldpe.c4
-rw-r--r--usr.sbin/ldpd/ldpe.h17
-rw-r--r--usr.sbin/ldpd/neighbor.c33
-rw-r--r--usr.sbin/ldpd/packet.c229
11 files changed, 228 insertions, 144 deletions
diff --git a/usr.sbin/ldpd/address.c b/usr.sbin/ldpd/address.c
index d6c3bb76a76..54d60c0f0d0 100644
--- a/usr.sbin/ldpd/address.c
+++ b/usr.sbin/ldpd/address.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: address.c,v 1.3 2010/02/20 21:28:39 michele Exp $ */
+/* $OpenBSD: address.c,v 1.4 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -77,8 +77,7 @@ send_address(struct nbr *nbr, struct iface *iface)
gen_address_list_tlv(buf, iface, size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
@@ -192,8 +191,7 @@ send_address_withdraw(struct nbr *nbr, struct iface *iface)
gen_address_list_tlv(buf, iface, size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
diff --git a/usr.sbin/ldpd/init.c b/usr.sbin/ldpd/init.c
index 5a9cc7b0fb5..b8f1601d9a1 100644
--- a/usr.sbin/ldpd/init.c
+++ b/usr.sbin/ldpd/init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init.c,v 1.3 2010/02/20 21:28:39 michele Exp $ */
+/* $OpenBSD: init.c,v 1.4 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -65,8 +65,7 @@ send_init(struct nbr *nbr)
gen_init_prms_tlv(buf, nbr, size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
diff --git a/usr.sbin/ldpd/keepalive.c b/usr.sbin/ldpd/keepalive.c
index c816a030782..ccf3d997668 100644
--- a/usr.sbin/ldpd/keepalive.c
+++ b/usr.sbin/ldpd/keepalive.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: keepalive.c,v 1.4 2010/02/20 21:28:39 michele Exp $ */
+/* $OpenBSD: keepalive.c,v 1.5 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -57,8 +57,7 @@ send_keepalive(struct nbr *nbr)
gen_msg_tlv(buf, MSG_TYPE_KEEPALIVE, size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c
index 04274360d59..b7f6c2c7773 100644
--- a/usr.sbin/ldpd/labelmapping.c
+++ b/usr.sbin/ldpd/labelmapping.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: labelmapping.c,v 1.6 2010/02/22 09:44:04 claudio Exp $ */
+/* $OpenBSD: labelmapping.c,v 1.7 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -82,8 +82,7 @@ send_labelmapping(struct nbr *nbr)
ldp_hdr = buf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
@@ -194,8 +193,7 @@ send_labelrequest(struct nbr *nbr)
ldp_hdr = buf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
@@ -304,9 +302,7 @@ send_labelwithdraw(struct nbr *nbr)
ldp_hdr = buf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
-
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
@@ -378,8 +374,7 @@ send_labelrelease(struct nbr *nbr)
ldp_hdr = buf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
@@ -430,9 +425,7 @@ send_labelabortreq(struct nbr *nbr)
gen_msg_tlv(buf, MSG_TYPE_LABELABORTREQ, size);
- bufferevent_write(nbr->bev, buf->buf, buf->wpos);
-
- buf_free(buf);
+ evbuf_enqueue(&nbr->wbuf, buf);
}
int
diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h
index 31e8057e21d..bc85ae7b836 100644
--- a/usr.sbin/ldpd/ldp.h
+++ b/usr.sbin/ldpd/ldp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldp.h,v 1.2 2009/12/09 12:19:29 michele Exp $ */
+/* $OpenBSD: ldp.h,v 1.3 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -91,11 +91,8 @@ struct ldp_hdr {
u_int16_t length;
u_int32_t lsr_id;
u_int16_t lspace_id;
- u_int8_t pad;
};
-#define PDU_HDR_SIZE 4
-
#define LDP_HDR_SIZE 10
#define INFINITE_HOLDTIME 0xffff
@@ -108,7 +105,7 @@ struct ldp_msg {
/* Optional Parameters */
};
-#define LDP_MSG_LEN 6
+#define LDP_MSG_LEN 8
#define TLV_HDR_LEN 4
#define UNKNOWN_FLAGS_MASK 0xc000
diff --git a/usr.sbin/ldpd/ldpd.c b/usr.sbin/ldpd/ldpd.c
index 9e5d93bc11b..1288759ba2a 100644
--- a/usr.sbin/ldpd/ldpd.c
+++ b/usr.sbin/ldpd/ldpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.c,v 1.5 2009/11/02 20:34:58 claudio Exp $ */
+/* $OpenBSD: ldpd.c,v 1.6 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -518,6 +518,37 @@ imsg_compose_event(struct imsgev *iev, u_int16_t type,
return (ret);
}
+void
+evbuf_enqueue(struct evbuf *eb, struct buf *buf)
+{
+ buf_close(&eb->wbuf, buf);
+ evbuf_event_add(eb);
+}
+
+void
+evbuf_event_add(struct evbuf *eb)
+{
+ if (eb->wbuf.queued)
+ event_add(&eb->ev, NULL);
+}
+
+void
+evbuf_init(struct evbuf *eb, int fd, void (*handler)(int, short, void *),
+ void *arg)
+{
+ msgbuf_init(&eb->wbuf);
+ eb->wbuf.fd = fd;
+ event_set(&eb->ev, eb->wbuf.fd, EV_WRITE, handler, arg);
+}
+
+void
+evbuf_clear(struct evbuf *eb)
+{
+ event_del(&eb->ev);
+ msgbuf_clear(&eb->wbuf);
+ eb->wbuf.fd = -1;
+}
+
/*
int
ldp_reload(void)
diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h
index ce02a1811a0..1f657c34389 100644
--- a/usr.sbin/ldpd/ldpd.h
+++ b/usr.sbin/ldpd/ldpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.h,v 1.9 2010/01/02 14:56:02 michele Exp $ */
+/* $OpenBSD: ldpd.h,v 1.10 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -57,6 +57,11 @@
#define F_DYNAMIC 0x0040
#define F_REDISTRIBUTED 0x0100
+struct evbuf {
+ struct msgbuf wbuf;
+ struct event ev;
+};
+
struct imsgev {
struct imsgbuf ibuf;
void (*handler)(int, short, void *);
@@ -433,7 +438,10 @@ void merge_config(struct ldpd_conf *, struct ldpd_conf *);
int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t, pid_t,
int, void *, u_int16_t);
void imsg_event_add(struct imsgev *);
-
+void evbuf_enqueue(struct evbuf *, struct buf *);
+void evbuf_event_add(struct evbuf *);
+void evbuf_init(struct evbuf *, int, void (*)(int, short, void *), void *);
+void evbuf_clear(struct evbuf *);
/* printconf.c */
void print_config(struct ldpd_conf *);
diff --git a/usr.sbin/ldpd/ldpe.c b/usr.sbin/ldpd/ldpe.c
index e13cb6c795a..68b3f2061a8 100644
--- a/usr.sbin/ldpd/ldpe.c
+++ b/usr.sbin/ldpd/ldpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.c,v 1.4 2010/02/18 10:50:14 claudio Exp $ */
+/* $OpenBSD: ldpe.c,v 1.5 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -204,7 +204,7 @@ ldpe(struct ldpd_conf *xconf, int pipe_parent2ldpe[2], int pipe_ldpe2lde[2],
event_add(&leconf->disc_ev, NULL);
event_set(&leconf->sess_ev, leconf->ldp_session_socket,
- EV_READ|EV_PERSIST, session_recv_packet, leconf);
+ EV_READ|EV_PERSIST, session_accept, leconf);
event_add(&leconf->sess_ev, NULL);
/* listen on ldpd control socket */
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h
index 2cbf7750c33..8c709d0f0e1 100644
--- a/usr.sbin/ldpd/ldpe.h
+++ b/usr.sbin/ldpd/ldpe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.h,v 1.5 2010/02/22 09:44:04 claudio Exp $ */
+/* $OpenBSD: ldpe.h,v 1.6 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
@@ -38,7 +38,8 @@ struct mapping_entry {
struct nbr {
LIST_ENTRY(nbr) entry, hash;
- struct bufferevent *bev;
+ struct evbuf wbuf;
+ struct event rev;
struct event inactivity_timer;
struct event keepalive_timer;
struct event keepalive_timeout;
@@ -50,17 +51,16 @@ struct nbr {
struct mapping_head release_list;
struct mapping_head abortreq_list;
- int fd;
-
struct in_addr addr;
struct in_addr id;
+ struct buf_read *rbuf;
struct iface *iface;
time_t uptime;
-
u_int32_t peerid; /* unique ID in DB */
+ int fd;
int state;
u_int16_t lspace;
@@ -177,7 +177,6 @@ void nbr_reset_idtimer(struct nbr *);
int nbr_pending_idtimer(struct nbr *);
int nbr_act_session_establish(struct nbr *, int);
-int nbr_close_connection(struct nbr *);
void nbr_mapping_add(struct nbr *, struct mapping_head *,
struct map *);
@@ -195,10 +194,10 @@ int gen_ldp_hdr(struct buf *, struct iface *, u_int16_t);
int gen_msg_tlv(struct buf *, u_int32_t, u_int16_t);
int send_packet(struct iface *, void *, size_t, struct sockaddr_in *);
void disc_recv_packet(int, short, void *);
-void session_recv_packet(int, short, void *);
+void session_accept(int, short, void *);
-void session_read(struct bufferevent *, void *);
-void session_error(struct bufferevent *, short, void *);
+void session_read(int, short, void *);
+void session_write(int, short, void *);
void session_close(struct nbr *);
void session_shutdown(struct nbr *, u_int32_t, u_int32_t, u_int32_t);
diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c
index 94a3c326c49..1c20eb22fdb 100644
--- a/usr.sbin/ldpd/neighbor.c
+++ b/usr.sbin/ldpd/neighbor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: neighbor.c,v 1.10 2010/02/21 20:41:35 michele Exp $ */
+/* $OpenBSD: neighbor.c,v 1.11 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -233,6 +233,10 @@ nbr_new(u_int32_t nbr_id, u_int16_t lspace, struct iface *iface, int self)
if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
fatal("nbr_new");
+ if (!self)
+ if ((nbr->rbuf = calloc(1, sizeof(struct buf_read))) == NULL)
+ fatal("nbr_new");
+
nbr->state = NBR_STA_DOWN;
nbr->id.s_addr = nbr_id;
nbr->lspace = lspace;
@@ -281,6 +285,8 @@ nbr_del(struct nbr *nbr)
{
ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0, NULL, 0);
+ session_close(nbr);
+
if (evtimer_pending(&nbr->inactivity_timer, NULL))
evtimer_del(&nbr->inactivity_timer);
if (evtimer_pending(&nbr->keepalive_timer, NULL))
@@ -295,6 +301,7 @@ nbr_del(struct nbr *nbr)
LIST_REMOVE(nbr, entry);
LIST_REMOVE(nbr, hash);
+ free(nbr->rbuf);
free(nbr);
}
@@ -565,34 +572,16 @@ nbr_establish_connection(struct nbr *nbr)
}
int
-nbr_close_connection(struct nbr *nbr)
-{
- bufferevent_disable(nbr->bev, EV_READ|EV_WRITE);
- bufferevent_free(nbr->bev);
- close(nbr->fd);
-
- return (0);
-}
-
-int
nbr_act_session_establish(struct nbr *nbr, int active)
{
- evbuffercb readfn = session_read;
- everrorcb errorfn = session_error;
-
if (active) {
if (nbr_establish_connection(nbr) < 0)
return (-1);
}
- nbr->bev = bufferevent_new(nbr->fd, readfn, NULL, errorfn, nbr);
- if (nbr->bev == NULL) {
- log_warn("nbr_act_session_establish: bufferevent_new");
- return (-1);
- }
-
- bufferevent_settimeout(nbr->bev, 0, 0);
- bufferevent_enable(nbr->bev, EV_READ|EV_WRITE);
+ 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);
if (active) {
send_init(nbr);
diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c
index b286a3827aa..5b8b8bf260d 100644
--- a/usr.sbin/ldpd/packet.c
+++ b/usr.sbin/ldpd/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.3 2009/11/01 11:09:58 michele Exp $ */
+/* $OpenBSD: packet.c,v 1.4 2010/02/25 17:40:46 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -43,6 +43,7 @@ int ldp_hdr_sanity_check(struct ldp_hdr *, u_int16_t,
const struct iface *);
struct iface *find_iface(struct ldpd_conf *, unsigned int, struct in_addr);
struct iface *session_find_iface(struct ldpd_conf *, struct in_addr);
+ssize_t session_get_pdu(struct buf_read *, char **);
static int msgcnt = 0;
@@ -175,19 +176,18 @@ disc_recv_packet(int fd, short event, void *bula)
return;
}
- if (ntohs(ldp_hdr->length) > len ||
- len <= sizeof(struct ldp_hdr)) {
+ if ((l = ldp_hdr_sanity_check(ldp_hdr, len, iface)) == -1)
+ return;
+
+ if (l > len) {
log_debug("disc_recv_packet: invalid LDP packet length %d",
ntohs(ldp_hdr->length));
return;
}
- if ((l = ldp_hdr_sanity_check(ldp_hdr, len, iface)) == -1)
- return;
-
ldp_msg = (struct ldp_msg *)(buf + LDP_HDR_SIZE);
- if (len < LDP_MSG_LEN) {
+ if (len < LDP_HDR_SIZE + LDP_MSG_LEN) {
log_debug("disc_recv_packet: invalid LDP packet length %d",
ntohs(ldp_hdr->length));
return;
@@ -264,7 +264,7 @@ find_iface(struct ldpd_conf *xconf, unsigned int ifindex, struct in_addr src)
}
void
-session_recv_packet(int fd, short event, void *bula)
+session_accept(int fd, short event, void *bula)
{
struct sockaddr_in src;
struct ldpd_conf *xconf = bula;
@@ -308,102 +308,143 @@ session_recv_packet(int fd, short event, void *bula)
}
void
-session_read(struct bufferevent *bev, void *arg)
+session_read(int fd, short event, void *arg)
{
- struct nbr *nbr = (struct nbr *)arg;
+ struct nbr *nbr = arg;
struct iface *iface = nbr->iface;
struct ldp_hdr *ldp_hdr;
struct ldp_msg *ldp_msg;
- u_int16_t len = EVBUFFER_LENGTH(EVBUFFER_INPUT(bev));
+ char *buf, *pdu;
+ ssize_t n, len;
+ int l, msg_size;
u_int16_t pdu_len;
- char buffer[LDP_MAX_LEN];
- char *buf = buffer;
- int l, msg_size = 0;
- bufferevent_read(bev, buf, len);
-
-another_packet:
- ldp_hdr = (struct ldp_hdr *)buf;
-
- if (ntohs(ldp_hdr->version) != LDP_VERSION) {
- session_shutdown(nbr, S_BAD_PROTO_VER, 0, 0);
+ if (event != EV_READ) {
+ log_debug("session_read: spurious event");
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 ((n = read(fd, nbr->rbuf->buf + nbr->rbuf->wpos,
+ sizeof(nbr->rbuf->buf) - nbr->rbuf->wpos)) == -1) {
+ if (errno != EINTR && errno != EAGAIN) {
+ /* XXX find better error */
+ session_shutdown(nbr, S_SHUTDOWN, 0, 0);
+ return;
+ }
+ /* retry read */
return;
}
-
- if ((l = ldp_hdr_sanity_check(ldp_hdr, len, iface)) == -1)
+ if (n == 0) {
+ /* connection closed */
+ event_del(&nbr->rev);
+ session_shutdown(nbr, S_SHUTDOWN, 0, 0);
return;
+ }
+ nbr->rbuf->wpos += n;
- buf += LDP_HDR_SIZE;
- len -= LDP_HDR_SIZE;
-
- pdu_len -= LDP_HDR_SIZE - PDU_HDR_SIZE;
-
- while (pdu_len > LDP_MSG_LEN) {
- ldp_msg = (struct ldp_msg *)buf;
+ while ((len = session_get_pdu(nbr->rbuf, &buf)) > 0) {
+ ldp_hdr = (struct ldp_hdr *)pdu = buf;
+ if (ntohs(ldp_hdr->version) != LDP_VERSION) {
+ session_shutdown(nbr, S_BAD_PROTO_VER, 0, 0);
+ free(buf);
+ return;
+ }
- /* switch LDP packet type */
- switch (ntohs(ldp_msg->type)) {
- case MSG_TYPE_NOTIFICATION:
- msg_size = recv_notification(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_INIT:
- msg_size = recv_init(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_KEEPALIVE:
- msg_size = recv_keepalive(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_ADDR:
- msg_size = recv_address(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_ADDRWITHDRAW:
- msg_size = recv_address_withdraw(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_LABELMAPPING:
- msg_size = recv_labelmapping(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_LABELREQUEST:
- msg_size = recv_labelrequest(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_LABELWITHDRAW:
- msg_size = recv_labelwithdraw(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_LABELRELEASE:
- msg_size = recv_labelrelease(nbr, buf, pdu_len);
- break;
- case MSG_TYPE_LABELABORTREQ:
- case MSG_TYPE_HELLO:
- default:
- log_debug("session_read: unknown LDP packet type "
- "interface %s", iface->name);
+ 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);
+ free(buf);
return;
}
- if (msg_size < 0)
+ if ((l = ldp_hdr_sanity_check(ldp_hdr, len, iface)) == -1) {
+ session_shutdown(nbr, S_BAD_LDP_ID, 0, 0);
+ free(buf);
return;
+ }
- /* Analyse the next message */
- buf += msg_size + TLV_HDR_LEN;
- len -= msg_size + TLV_HDR_LEN;
- pdu_len -= msg_size + TLV_HDR_LEN;
+ pdu += LDP_HDR_SIZE;
+ len -= LDP_HDR_SIZE;
+
+ while (len >= LDP_MSG_LEN) {
+ ldp_msg = (struct ldp_msg *)pdu;
+
+ pdu_len = ntohs(ldp_msg->length) + TLV_HDR_LEN;
+ if (pdu_len > len ||
+ pdu_len < LDP_MSG_LEN - TLV_HDR_LEN) {
+ session_shutdown(nbr, S_BAD_TLV_LEN, 0, 0);
+ free(buf);
+ return;
+ }
+
+ /* switch LDP packet type */
+ switch (ntohs(ldp_msg->type)) {
+ case MSG_TYPE_NOTIFICATION:
+ msg_size = recv_notification(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_INIT:
+ msg_size = recv_init(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_KEEPALIVE:
+ msg_size = recv_keepalive(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_ADDR:
+ msg_size = recv_address(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_ADDRWITHDRAW:
+ msg_size = recv_address_withdraw(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_LABELMAPPING:
+ msg_size = recv_labelmapping(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_LABELREQUEST:
+ msg_size = recv_labelrequest(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_LABELWITHDRAW:
+ msg_size = recv_labelwithdraw(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_LABELRELEASE:
+ msg_size = recv_labelrelease(nbr, pdu, pdu_len);
+ break;
+ case MSG_TYPE_LABELABORTREQ:
+ case MSG_TYPE_HELLO:
+ default:
+ log_debug("session_read: unknown LDP packet type "
+ "interface %s", iface->name);
+ free(buf);
+ return;
+ }
+
+ if (msg_size == -1) {
+ /* parser failed, giving up */
+ free(buf);
+ return;
+ }
+
+ /* Analyse the next message */
+ pdu += msg_size + TLV_HDR_LEN;
+ len -= msg_size + TLV_HDR_LEN;
+ }
+ free(buf);
+ if (len != 0) {
+ session_shutdown(nbr, S_BAD_PDU_LEN, 0, 0);
+ return;
+ }
}
-
- if (len > LDP_HDR_SIZE)
- goto another_packet;
}
void
-session_error(struct bufferevent *bev, short what, void *arg)
+session_write(int fd, short event, void *arg)
{
struct nbr *nbr = arg;
- nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
+ if (event & EV_WRITE) {
+ if (msgbuf_write(&nbr->wbuf.wbuf) == -1)
+ nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
+ } else
+ log_debug("session_write: spurious event");
+
+ evbuf_event_add(&nbr->wbuf);
}
void
@@ -422,12 +463,13 @@ session_close(struct nbr *nbr)
log_debug("session_close: closing session with nbr ID %s",
inet_ntoa(nbr->id));
+ evbuf_clear(&nbr->wbuf);
+
if (evtimer_pending(&nbr->keepalive_timer, NULL))
evtimer_del(&nbr->keepalive_timer);
if (evtimer_pending(&nbr->keepalive_timeout, NULL))
evtimer_del(&nbr->keepalive_timeout);
- bufferevent_free(nbr->bev);
close(nbr->fd);
}
@@ -460,3 +502,32 @@ session_find_iface(struct ldpd_conf *xconf, struct in_addr src)
return (NULL);
}
+
+ssize_t
+session_get_pdu(struct buf_read *r, char **b)
+{
+ struct ldp_hdr l;
+ size_t av, dlen, left;
+
+ av = r->wpos;
+ if (av < sizeof(l))
+ return (0);
+
+ memcpy(&l, r->buf, sizeof(l));
+ dlen = ntohs(l.length) + TLV_HDR_LEN;
+ if (dlen > av)
+ return (0);
+
+ if ((*b = malloc(dlen)) == NULL)
+ return (-1);
+
+ memcpy(*b, r->buf, dlen);
+ if (dlen < av) {
+ left = av - dlen;
+ memmove(r->buf, r->buf + dlen, left);
+ r->wpos = left;
+ } else
+ r->wpos = 0;
+
+ return (dlen);
+}