1 /* $OpenBSD: lsreq.c,v 1.13 2021/11/03 21:40:03 sthen Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 2005, 2007 Esben Norby <norby@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 <sys/socket.h> 21 #include <netinet/in.h> 22 #include <netinet/ip6.h> 23 #include <arpa/inet.h> 24 #include <stdlib.h> 25 26 #include "ospf6d.h" 27 #include "ospf6.h" 28 #include "log.h" 29 #include "ospfe.h" 30 31 /* link state request packet handling */ 32 int 33 send_ls_req(struct nbr *nbr) 34 { 35 struct in6_addr dst; 36 struct ls_req_hdr ls_req_hdr; 37 struct lsa_entry *le, *nle; 38 struct ibuf *buf; 39 40 if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip6_hdr))) == NULL) 41 fatal("send_ls_req"); 42 43 switch (nbr->iface->type) { 44 case IF_TYPE_POINTOPOINT: 45 inet_pton(AF_INET6, AllSPFRouters, &dst); 46 break; 47 case IF_TYPE_BROADCAST: 48 case IF_TYPE_NBMA: 49 case IF_TYPE_POINTOMULTIPOINT: 50 case IF_TYPE_VIRTUALLINK: 51 dst = nbr->addr; 52 break; 53 default: 54 fatalx("send_ls_req: unknown interface type"); 55 } 56 57 /* OSPF header */ 58 if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_LS_REQUEST)) 59 goto fail; 60 61 /* LSA header(s) */ 62 for (le = TAILQ_FIRST(&nbr->ls_req_list); le != NULL && 63 buf->wpos + sizeof(struct ls_req_hdr) < buf->max; le = nle) { 64 nbr->ls_req = nle = TAILQ_NEXT(le, entry); 65 ls_req_hdr.zero = 0; 66 ls_req_hdr.type = le->le_lsa->type; 67 ls_req_hdr.ls_id = le->le_lsa->ls_id; 68 ls_req_hdr.adv_rtr = le->le_lsa->adv_rtr; 69 if (ibuf_add(buf, &ls_req_hdr, sizeof(ls_req_hdr))) 70 goto fail; 71 } 72 73 /* calculate checksum */ 74 if (upd_ospf_hdr(buf, nbr->iface)) 75 goto fail; 76 77 if (send_packet(nbr->iface, buf, &dst) == -1) 78 goto fail; 79 80 ibuf_free(buf); 81 return (0); 82 fail: 83 log_warn("send_ls_req"); 84 ibuf_free(buf); 85 return (-1); 86 } 87 88 void 89 recv_ls_req(struct nbr *nbr, char *buf, u_int16_t len) 90 { 91 switch (nbr->state) { 92 case NBR_STA_DOWN: 93 case NBR_STA_ATTEMPT: 94 case NBR_STA_INIT: 95 case NBR_STA_2_WAY: 96 case NBR_STA_XSTRT: 97 case NBR_STA_SNAP: 98 log_debug("recv_ls_req: packet ignored in state %s, " 99 "neighbor ID %s (%s)", nbr_state_name(nbr->state), 100 inet_ntoa(nbr->id), nbr->iface->name); 101 break; 102 case NBR_STA_XCHNG: 103 case NBR_STA_LOAD: 104 case NBR_STA_FULL: 105 ospfe_imsg_compose_rde(IMSG_LS_REQ, nbr->peerid, 0, buf, len); 106 break; 107 default: 108 fatalx("recv_ls_req: unknown neighbor state"); 109 } 110 } 111 112 /* link state request list */ 113 void 114 ls_req_list_add(struct nbr *nbr, struct lsa_hdr *lsa) 115 { 116 struct lsa_entry *le; 117 118 if (lsa == NULL) 119 fatalx("ls_req_list_add: no LSA header"); 120 121 if ((le = calloc(1, sizeof(*le))) == NULL) 122 fatal("ls_req_list_add"); 123 124 TAILQ_INSERT_TAIL(&nbr->ls_req_list, le, entry); 125 le->le_lsa = lsa; 126 nbr->ls_req_cnt++; 127 } 128 129 struct lsa_entry * 130 ls_req_list_get(struct nbr *nbr, struct lsa_hdr *lsa_hdr) 131 { 132 struct lsa_entry *le; 133 134 TAILQ_FOREACH(le, &nbr->ls_req_list, entry) { 135 if ((lsa_hdr->type == le->le_lsa->type) && 136 (lsa_hdr->ls_id == le->le_lsa->ls_id) && 137 (lsa_hdr->adv_rtr == le->le_lsa->adv_rtr)) 138 return (le); 139 } 140 return (NULL); 141 } 142 143 void 144 ls_req_list_free(struct nbr *nbr, struct lsa_entry *le) 145 { 146 if (nbr->ls_req == le) { 147 nbr->ls_req = TAILQ_NEXT(le, entry); 148 } 149 150 TAILQ_REMOVE(&nbr->ls_req_list, le, entry); 151 free(le->le_lsa); 152 free(le); 153 nbr->ls_req_cnt--; 154 155 /* received all requested LSA(s), send a new LS req */ 156 if (nbr->ls_req != NULL && 157 nbr->ls_req == TAILQ_FIRST(&nbr->ls_req_list)) { 158 start_ls_req_tx_timer(nbr); 159 } 160 161 /* we might not have received all DDs and are still in XCHNG */ 162 if (ls_req_list_empty(nbr) && nbr->dd_pending == 0 && 163 nbr->state != NBR_STA_XCHNG) 164 nbr_fsm(nbr, NBR_EVT_LOAD_DONE); 165 } 166 167 void 168 ls_req_list_clr(struct nbr *nbr) 169 { 170 struct lsa_entry *le; 171 172 while ((le = TAILQ_FIRST(&nbr->ls_req_list)) != NULL) { 173 TAILQ_REMOVE(&nbr->ls_req_list, le, entry); 174 free(le->le_lsa); 175 free(le); 176 } 177 178 nbr->ls_req_cnt = 0; 179 nbr->ls_req = NULL; 180 } 181 182 int 183 ls_req_list_empty(struct nbr *nbr) 184 { 185 return (TAILQ_EMPTY(&nbr->ls_req_list)); 186 } 187 188 /* timers */ 189 /* ARGSUSED */ 190 void 191 ls_req_tx_timer(int fd, short event, void *arg) 192 { 193 struct nbr *nbr = arg; 194 struct timeval tv; 195 196 switch (nbr->state) { 197 case NBR_STA_DOWN: 198 case NBR_STA_ATTEMPT: 199 case NBR_STA_INIT: 200 case NBR_STA_2_WAY: 201 case NBR_STA_SNAP: 202 case NBR_STA_XSTRT: 203 case NBR_STA_XCHNG: 204 return; 205 case NBR_STA_LOAD: 206 send_ls_req(nbr); 207 break; 208 case NBR_STA_FULL: 209 return; 210 default: 211 log_debug("ls_req_tx_timer: unknown neighbor state, " 212 "neighbor ID %s (%s)", inet_ntoa(nbr->id), 213 nbr->iface->name); 214 break; 215 } 216 217 /* reschedule lsreq_tx_timer */ 218 if (nbr->state == NBR_STA_LOAD) { 219 timerclear(&tv); 220 tv.tv_sec = nbr->iface->rxmt_interval; 221 if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1) 222 fatal("ls_req_tx_timer"); 223 } 224 } 225 226 void 227 start_ls_req_tx_timer(struct nbr *nbr) 228 { 229 struct timeval tv; 230 231 if (nbr == nbr->iface->self) 232 return; 233 234 timerclear(&tv); 235 if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1) 236 fatal("start_ls_req_tx_timer"); 237 } 238 239 void 240 stop_ls_req_tx_timer(struct nbr *nbr) 241 { 242 if (nbr == nbr->iface->self) 243 return; 244 245 if (evtimer_del(&nbr->lsreq_tx_timer) == -1) 246 fatal("stop_ls_req_tx_timer"); 247 } 248