1 /* $OpenBSD: hello.c,v 1.5 2016/09/02 16:29:55 renato Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <netinet/in.h> 21 #include <netinet/ip.h> 22 23 #include <arpa/inet.h> 24 #include <string.h> 25 26 #include "eigrpd.h" 27 #include "eigrpe.h" 28 #include "log.h" 29 30 /* hello packet handling */ 31 32 void 33 send_hello(struct eigrp_iface *ei, struct seq_addr_head *seq_addr_list, 34 uint32_t mcast_seq) 35 { 36 struct eigrp *eigrp = ei->eigrp; 37 struct ibuf *buf; 38 uint8_t flags = 0; 39 40 if ((buf = ibuf_dynamic(PKG_DEF_SIZE, 41 IP_MAXPACKET - sizeof(struct ip))) == NULL) 42 fatal("send_hello"); 43 44 /* EIGRP header */ 45 if (gen_eigrp_hdr(buf, EIGRP_OPC_HELLO, flags, 0, eigrp->as)) 46 goto fail; 47 48 if (gen_parameter_tlv(buf, ei, 0)) 49 goto fail; 50 51 if (gen_sw_version_tlv(buf)) 52 goto fail; 53 54 if (seq_addr_list && !TAILQ_EMPTY(seq_addr_list) && 55 gen_sequence_tlv(buf, seq_addr_list)) 56 goto fail; 57 58 if (mcast_seq && gen_mcast_seq_tlv(buf, mcast_seq)) 59 goto fail; 60 61 /* send unreliably */ 62 send_packet(ei, NULL, 0, buf); 63 ibuf_free(buf); 64 return; 65 fail: 66 log_warnx("%s: failed to send message", __func__); 67 ibuf_free(buf); 68 } 69 70 void 71 send_peerterm(struct nbr *nbr) 72 { 73 struct eigrp *eigrp = nbr->ei->eigrp; 74 struct ibuf *buf; 75 uint8_t flags = 0; 76 77 if ((buf = ibuf_dynamic(PKG_DEF_SIZE, 78 IP_MAXPACKET - sizeof(struct ip))) == NULL) 79 fatal("send_hello"); 80 81 /* EIGRP header */ 82 if (gen_eigrp_hdr(buf, EIGRP_OPC_HELLO, flags, 0, eigrp->as)) 83 goto fail; 84 85 if (gen_parameter_tlv(buf, nbr->ei, 1)) 86 goto fail; 87 88 /* send unreliably */ 89 send_packet(nbr->ei, nbr, 0, buf); 90 ibuf_free(buf); 91 return; 92 fail: 93 log_warnx("%s: failed to send message", __func__); 94 ibuf_free(buf); 95 } 96 97 98 void 99 recv_hello(struct eigrp_iface *ei, union eigrpd_addr *src, struct nbr *nbr, 100 struct tlv_parameter *tp) 101 { 102 /* 103 * Some old Cisco routers seems to use the "parameters tlv" with all 104 * K-values set to 255 (except k6) to inform that the neighbor has been 105 * reset. The "peer termination" tlv described in the draft for the same 106 * purpose is probably something introduced recently. Let's check for 107 * this case to maintain backward compatibility. 108 */ 109 if (tp->kvalues[0] == 255 && tp->kvalues[1] == 255 && 110 tp->kvalues[2] == 255 && tp->kvalues[3] == 255 && 111 tp->kvalues[4] == 255 && tp->kvalues[5] == 0) { 112 if (nbr) { 113 log_debug("%s: peer temination", __func__); 114 nbr_del(nbr); 115 } 116 return; 117 } 118 119 if (nbr == NULL) { 120 if (memcmp(ei->eigrp->kvalues, tp->kvalues, 6) != 0) { 121 log_debug("%s: k-values don't match (nbr %s)", 122 __func__, log_addr(ei->eigrp->af, src)); 123 return; 124 } 125 126 nbr = nbr_new(ei, src, ntohs(tp->holdtime), 0); 127 128 /* send an expedited hello */ 129 send_hello(ei, NULL, 0); 130 131 send_update(nbr->ei, nbr, EIGRP_HDR_FLAG_INIT, NULL); 132 } 133 } 134