diff options
-rw-r--r-- | usr.sbin/ldpd/address.c | 8 | ||||
-rw-r--r-- | usr.sbin/ldpd/init.c | 5 | ||||
-rw-r--r-- | usr.sbin/ldpd/keepalive.c | 5 | ||||
-rw-r--r-- | usr.sbin/ldpd/labelmapping.c | 19 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldp.h | 7 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.c | 33 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.h | 12 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.c | 4 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.h | 17 | ||||
-rw-r--r-- | usr.sbin/ldpd/neighbor.c | 33 | ||||
-rw-r--r-- | usr.sbin/ldpd/packet.c | 229 |
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); +} |