1*3a50f0a9Sjmc /* $OpenBSD: hello.c,v 1.6 2022/12/28 21:30:16 jmc Exp $ */
243509a12Srenato
343509a12Srenato /*
443509a12Srenato * Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
543509a12Srenato *
643509a12Srenato * Permission to use, copy, modify, and distribute this software for any
743509a12Srenato * purpose with or without fee is hereby granted, provided that the above
843509a12Srenato * copyright notice and this permission notice appear in all copies.
943509a12Srenato *
1043509a12Srenato * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1143509a12Srenato * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1243509a12Srenato * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1343509a12Srenato * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1443509a12Srenato * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1543509a12Srenato * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1643509a12Srenato * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1743509a12Srenato */
1843509a12Srenato
198072de9bSrenato #include <sys/types.h>
208072de9bSrenato #include <netinet/in.h>
218072de9bSrenato #include <netinet/ip.h>
228072de9bSrenato
2343509a12Srenato #include <arpa/inet.h>
248072de9bSrenato #include <string.h>
2543509a12Srenato
2643509a12Srenato #include "eigrpd.h"
2743509a12Srenato #include "eigrpe.h"
288072de9bSrenato #include "log.h"
2943509a12Srenato
3043509a12Srenato /* hello packet handling */
3143509a12Srenato
3243509a12Srenato void
send_hello(struct eigrp_iface * ei,struct seq_addr_head * seq_addr_list,uint32_t mcast_seq)3343509a12Srenato send_hello(struct eigrp_iface *ei, struct seq_addr_head *seq_addr_list,
340e96235eSrenato uint32_t mcast_seq)
3543509a12Srenato {
3643509a12Srenato struct eigrp *eigrp = ei->eigrp;
3743509a12Srenato struct ibuf *buf;
3843509a12Srenato uint8_t flags = 0;
3943509a12Srenato
4043509a12Srenato if ((buf = ibuf_dynamic(PKG_DEF_SIZE,
4143509a12Srenato IP_MAXPACKET - sizeof(struct ip))) == NULL)
4243509a12Srenato fatal("send_hello");
4343509a12Srenato
4443509a12Srenato /* EIGRP header */
4543509a12Srenato if (gen_eigrp_hdr(buf, EIGRP_OPC_HELLO, flags, 0, eigrp->as))
4643509a12Srenato goto fail;
4743509a12Srenato
480e96235eSrenato if (gen_parameter_tlv(buf, ei, 0))
4943509a12Srenato goto fail;
5043509a12Srenato
5143509a12Srenato if (gen_sw_version_tlv(buf))
5243509a12Srenato goto fail;
5343509a12Srenato
5443509a12Srenato if (seq_addr_list && !TAILQ_EMPTY(seq_addr_list) &&
5543509a12Srenato gen_sequence_tlv(buf, seq_addr_list))
5643509a12Srenato goto fail;
5743509a12Srenato
5843509a12Srenato if (mcast_seq && gen_mcast_seq_tlv(buf, mcast_seq))
5943509a12Srenato goto fail;
6043509a12Srenato
6143509a12Srenato /* send unreliably */
6243509a12Srenato send_packet(ei, NULL, 0, buf);
6343509a12Srenato ibuf_free(buf);
6443509a12Srenato return;
6543509a12Srenato fail:
6643509a12Srenato log_warnx("%s: failed to send message", __func__);
6743509a12Srenato ibuf_free(buf);
6843509a12Srenato }
6943509a12Srenato
7043509a12Srenato void
send_peerterm(struct nbr * nbr)710e96235eSrenato send_peerterm(struct nbr *nbr)
720e96235eSrenato {
730e96235eSrenato struct eigrp *eigrp = nbr->ei->eigrp;
740e96235eSrenato struct ibuf *buf;
750e96235eSrenato uint8_t flags = 0;
760e96235eSrenato
770e96235eSrenato if ((buf = ibuf_dynamic(PKG_DEF_SIZE,
780e96235eSrenato IP_MAXPACKET - sizeof(struct ip))) == NULL)
790e96235eSrenato fatal("send_hello");
800e96235eSrenato
810e96235eSrenato /* EIGRP header */
820e96235eSrenato if (gen_eigrp_hdr(buf, EIGRP_OPC_HELLO, flags, 0, eigrp->as))
830e96235eSrenato goto fail;
840e96235eSrenato
850e96235eSrenato if (gen_parameter_tlv(buf, nbr->ei, 1))
860e96235eSrenato goto fail;
870e96235eSrenato
880e96235eSrenato /* send unreliably */
890e96235eSrenato send_packet(nbr->ei, nbr, 0, buf);
900e96235eSrenato ibuf_free(buf);
910e96235eSrenato return;
920e96235eSrenato fail:
930e96235eSrenato log_warnx("%s: failed to send message", __func__);
940e96235eSrenato ibuf_free(buf);
950e96235eSrenato }
960e96235eSrenato
970e96235eSrenato
980e96235eSrenato void
recv_hello(struct eigrp_iface * ei,union eigrpd_addr * src,struct nbr * nbr,struct tlv_parameter * tp)9943509a12Srenato recv_hello(struct eigrp_iface *ei, union eigrpd_addr *src, struct nbr *nbr,
10043509a12Srenato struct tlv_parameter *tp)
10143509a12Srenato {
10243509a12Srenato /*
10343509a12Srenato * Some old Cisco routers seems to use the "parameters tlv" with all
10443509a12Srenato * K-values set to 255 (except k6) to inform that the neighbor has been
10543509a12Srenato * reset. The "peer termination" tlv described in the draft for the same
10643509a12Srenato * purpose is probably something introduced recently. Let's check for
10743509a12Srenato * this case to maintain backward compatibility.
10843509a12Srenato */
10943509a12Srenato if (tp->kvalues[0] == 255 && tp->kvalues[1] == 255 &&
11043509a12Srenato tp->kvalues[2] == 255 && tp->kvalues[3] == 255 &&
11143509a12Srenato tp->kvalues[4] == 255 && tp->kvalues[5] == 0) {
11243509a12Srenato if (nbr) {
113*3a50f0a9Sjmc log_debug("%s: peer termination", __func__);
11443509a12Srenato nbr_del(nbr);
11543509a12Srenato }
11643509a12Srenato return;
11743509a12Srenato }
11843509a12Srenato
11943509a12Srenato if (nbr == NULL) {
12043509a12Srenato if (memcmp(ei->eigrp->kvalues, tp->kvalues, 6) != 0) {
12143509a12Srenato log_debug("%s: k-values don't match (nbr %s)",
12243509a12Srenato __func__, log_addr(ei->eigrp->af, src));
12343509a12Srenato return;
12443509a12Srenato }
12543509a12Srenato
12643509a12Srenato nbr = nbr_new(ei, src, ntohs(tp->holdtime), 0);
12743509a12Srenato
12843509a12Srenato /* send an expedited hello */
1290e96235eSrenato send_hello(ei, NULL, 0);
13043509a12Srenato
1315c6a958cSrenato send_update(nbr->ei, nbr, EIGRP_HDR_FLAG_INIT, NULL);
13243509a12Srenato }
13343509a12Srenato }
134