diff options
author | 2013-06-04 02:34:48 +0000 | |
---|---|---|
committer | 2013-06-04 02:34:48 +0000 | |
commit | 699b7d06c4c43fc31e802807ce75d0a15945e2a0 (patch) | |
tree | 1c2d19fcbb1487e5adb4a032af0d4120f99f59c4 | |
parent | Tiny typo. "Just commit" -- claudio@ (diff) | |
download | wireguard-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.c | 6 | ||||
-rw-r--r-- | usr.sbin/ldpd/init.c | 4 | ||||
-rw-r--r-- | usr.sbin/ldpd/keepalive.c | 4 | ||||
-rw-r--r-- | usr.sbin/ldpd/labelmapping.c | 12 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.h | 3 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.h | 26 | ||||
-rw-r--r-- | usr.sbin/ldpd/neighbor.c | 51 | ||||
-rw-r--r-- | usr.sbin/ldpd/notification.c | 14 | ||||
-rw-r--r-- | usr.sbin/ldpd/packet.c | 137 |
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(); } |