1 /* $OpenBSD: database.c,v 1.21 2021/11/03 21:40:03 sthen Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2004, 2005, 2007 Esben Norby <norby@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/socket.h> 22 #include <netinet/in.h> 23 #include <netinet/ip6.h> 24 #include <arpa/inet.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 #include "ospf6d.h" 30 #include "ospf6.h" 31 #include "log.h" 32 #include "ospfe.h" 33 34 void db_sum_list_next(struct nbr *); 35 36 /* database description packet handling */ 37 int 38 send_db_description(struct nbr *nbr) 39 { 40 struct in6_addr dst; 41 struct db_dscrp_hdr dd_hdr; 42 struct lsa_entry *le, *nle; 43 struct ibuf *buf; 44 u_int8_t bits = 0; 45 46 if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip6_hdr))) == NULL) 47 fatal("send_db_description"); 48 49 /* OSPF header */ 50 if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_DD)) 51 goto fail; 52 53 /* reserve space for database description header */ 54 if (ibuf_reserve(buf, sizeof(dd_hdr)) == NULL) 55 goto fail; 56 57 switch (nbr->state) { 58 case NBR_STA_DOWN: 59 case NBR_STA_ATTEMPT: 60 case NBR_STA_INIT: 61 case NBR_STA_2_WAY: 62 case NBR_STA_SNAP: 63 log_debug("send_db_description: neighbor ID %s (%s): " 64 "cannot send packet in state %s", inet_ntoa(nbr->id), 65 nbr->iface->name, nbr_state_name(nbr->state)); 66 goto fail; 67 case NBR_STA_XSTRT: 68 bits |= OSPF_DBD_MS | OSPF_DBD_M | OSPF_DBD_I; 69 nbr->dd_more = 1; 70 break; 71 case NBR_STA_XCHNG: 72 if (nbr->dd_master) 73 bits |= OSPF_DBD_MS; 74 else 75 bits &= ~OSPF_DBD_MS; 76 77 if (TAILQ_EMPTY(&nbr->db_sum_list)) { 78 bits &= ~OSPF_DBD_M; 79 nbr->dd_more = 0; 80 } else { 81 bits |= OSPF_DBD_M; 82 nbr->dd_more = 1; 83 } 84 85 bits &= ~OSPF_DBD_I; 86 87 /* build LSA list */ 88 for (le = TAILQ_FIRST(&nbr->db_sum_list); le != NULL && 89 ibuf_left(buf) >= sizeof(struct lsa_hdr); le = nle) { 90 nbr->dd_end = nle = TAILQ_NEXT(le, entry); 91 if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr))) 92 goto fail; 93 } 94 break; 95 case NBR_STA_LOAD: 96 case NBR_STA_FULL: 97 if (nbr->dd_master) 98 bits |= OSPF_DBD_MS; 99 else 100 bits &= ~OSPF_DBD_MS; 101 bits &= ~OSPF_DBD_M; 102 bits &= ~OSPF_DBD_I; 103 104 nbr->dd_more = 0; 105 break; 106 default: 107 fatalx("send_db_description: unknown neighbor state"); 108 } 109 110 bzero(&dd_hdr, sizeof(dd_hdr)); 111 112 switch (nbr->iface->type) { 113 case IF_TYPE_POINTOPOINT: 114 inet_pton(AF_INET6, AllSPFRouters, &dst); 115 dd_hdr.iface_mtu = htons(nbr->iface->mtu); 116 break; 117 case IF_TYPE_BROADCAST: 118 dst = nbr->addr; 119 dd_hdr.iface_mtu = htons(nbr->iface->mtu); 120 break; 121 case IF_TYPE_NBMA: 122 case IF_TYPE_POINTOMULTIPOINT: 123 /* XXX not supported */ 124 break; 125 case IF_TYPE_VIRTUALLINK: 126 dst = nbr->iface->dst; 127 dd_hdr.iface_mtu = 0; 128 break; 129 default: 130 fatalx("send_db_description: unknown interface type"); 131 } 132 133 dd_hdr.opts = htonl(area_ospf_options(nbr->iface->area)); 134 dd_hdr.bits = bits; 135 dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num); 136 137 memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(dd_hdr)), 138 &dd_hdr, sizeof(dd_hdr)); 139 140 /* calculate checksum */ 141 if (upd_ospf_hdr(buf, nbr->iface)) 142 goto fail; 143 144 /* transmit packet */ 145 if (send_packet(nbr->iface, buf, &dst) == -1) 146 goto fail; 147 148 ibuf_free(buf); 149 return (0); 150 fail: 151 log_warn("send_db_description"); 152 ibuf_free(buf); 153 return (-1); 154 } 155 156 void 157 recv_db_description(struct nbr *nbr, char *buf, u_int16_t len) 158 { 159 struct db_dscrp_hdr dd_hdr; 160 int dupe = 0; 161 162 if (len < sizeof(dd_hdr)) { 163 log_warnx("recv_db_description: neighbor ID %s (%s): " 164 "bad packet size", inet_ntoa(nbr->id), nbr->iface->name); 165 return; 166 } 167 memcpy(&dd_hdr, buf, sizeof(dd_hdr)); 168 buf += sizeof(dd_hdr); 169 len -= sizeof(dd_hdr); 170 171 /* db description packet sanity checks */ 172 if (ntohs(dd_hdr.iface_mtu) > nbr->iface->mtu) { 173 log_warnx("recv_db_description: neighbor ID %s (%s): " 174 "invalid MTU %d expected %d", inet_ntoa(nbr->id), 175 nbr->iface->name, ntohs(dd_hdr.iface_mtu), 176 nbr->iface->mtu); 177 return; 178 } 179 180 if (nbr->last_rx_options == dd_hdr.opts && 181 nbr->last_rx_bits == dd_hdr.bits && 182 ntohl(dd_hdr.dd_seq_num) == nbr->dd_seq_num - nbr->dd_master ? 183 1 : 0) { 184 log_debug("recv_db_description: dupe from " 185 "neighbor ID %s (%s)", inet_ntoa(nbr->id), 186 nbr->iface->name); 187 dupe = 1; 188 } 189 190 switch (nbr->state) { 191 case NBR_STA_DOWN: 192 case NBR_STA_ATTEMPT: 193 case NBR_STA_2_WAY: 194 case NBR_STA_SNAP: 195 log_debug("recv_db_description: neighbor ID %s (%s): " 196 "packet ignored in state %s", inet_ntoa(nbr->id), 197 nbr->iface->name, nbr_state_name(nbr->state)); 198 return; 199 case NBR_STA_INIT: 200 /* evaluate dr and bdr after issuing a 2-Way event */ 201 nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD); 202 if_fsm(nbr->iface, IF_EVT_NBR_CHNG); 203 if (nbr->state != NBR_STA_XSTRT) 204 return; 205 /* FALLTHROUGH */ 206 case NBR_STA_XSTRT: 207 if (dupe) 208 return; 209 /* 210 * check bits: either I,M,MS or only M 211 */ 212 if (dd_hdr.bits == (OSPF_DBD_I | OSPF_DBD_M | OSPF_DBD_MS)) { 213 /* if nbr Router ID is larger than own -> slave */ 214 if ((ntohl(nbr->id.s_addr)) > 215 ntohl(ospfe_router_id())) { 216 /* slave */ 217 nbr->dd_master = 0; 218 nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num); 219 220 /* event negotiation done */ 221 nbr_fsm(nbr, NBR_EVT_NEG_DONE); 222 } 223 } else if (!(dd_hdr.bits & (OSPF_DBD_I | OSPF_DBD_MS))) { 224 /* M only case: we are master */ 225 if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) { 226 log_warnx("recv_db_description: " 227 "neighbor ID %s (%s): " 228 "invalid seq num, mine %x his %x", 229 inet_ntoa(nbr->id), nbr->iface->name, 230 nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num)); 231 return; 232 } 233 nbr->dd_seq_num++; 234 235 /* event negotiation done */ 236 nbr_fsm(nbr, NBR_EVT_NEG_DONE); 237 238 /* this packet may already have data so pass it on */ 239 if (len > 0) { 240 nbr->dd_pending++; 241 ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 242 0, buf, len); 243 } 244 } else { 245 /* ignore packet */ 246 log_debug("recv_db_description: neighbor ID %s (%s): " 247 "packet ignored in state %s (bad flags)", 248 inet_ntoa(nbr->id), nbr->iface->name, 249 nbr_state_name(nbr->state)); 250 } 251 break; 252 case NBR_STA_XCHNG: 253 case NBR_STA_LOAD: 254 case NBR_STA_FULL: 255 if (dd_hdr.bits & OSPF_DBD_I || 256 !(dd_hdr.bits & OSPF_DBD_MS) == !nbr->dd_master) { 257 log_warnx("recv_db_description: neighbor ID %s (%s): " 258 "seq num mismatch, bad flags", inet_ntoa(nbr->id), 259 nbr->iface->name); 260 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 261 return; 262 } 263 264 if (nbr->last_rx_options != dd_hdr.opts) { 265 log_warnx("recv_db_description: neighbor ID %s (%s): " 266 "seq num mismatch, bad options", 267 inet_ntoa(nbr->id), nbr->iface->name); 268 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 269 return; 270 } 271 272 if (dupe) { 273 if (!nbr->dd_master) 274 /* retransmit */ 275 start_db_tx_timer(nbr); 276 return; 277 } 278 279 if (nbr->state != NBR_STA_XCHNG) { 280 log_warnx("recv_db_description: neighbor ID %s (%s): " 281 "invalid seq num, mine %x his %x", 282 inet_ntoa(nbr->id), nbr->iface->name, 283 nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num)); 284 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 285 return; 286 } 287 288 /* sanity check dd seq number */ 289 if (nbr->dd_master) { 290 /* master */ 291 if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) { 292 log_warnx("recv_db_description: " 293 "neighbor ID %s (%s): " 294 "invalid seq num, mine %x his %x, master", 295 inet_ntoa(nbr->id), nbr->iface->name, 296 nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num)); 297 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 298 return; 299 } 300 nbr->dd_seq_num++; 301 } else { 302 /* slave */ 303 if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num + 1) { 304 log_warnx("recv_db_description: " 305 "neighbor ID %s (%s): " 306 "invalid seq num, mine %x his %x, slave", 307 inet_ntoa(nbr->id), nbr->iface->name, 308 nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num)); 309 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 310 return; 311 } 312 nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num); 313 } 314 315 /* forward to RDE and let it decide which LSAs to request */ 316 if (len > 0) { 317 nbr->dd_pending++; 318 ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 0, 319 buf, len); 320 } 321 322 /* next packet */ 323 db_sum_list_next(nbr); 324 start_db_tx_timer(nbr); 325 326 if (!(dd_hdr.bits & OSPF_DBD_M) && 327 TAILQ_EMPTY(&nbr->db_sum_list)) 328 if (!nbr->dd_master || !nbr->dd_more) 329 nbr_fsm(nbr, NBR_EVT_XCHNG_DONE); 330 break; 331 default: 332 fatalx("recv_db_description: unknown neighbor state"); 333 } 334 335 nbr->last_rx_options = dd_hdr.opts; 336 nbr->last_rx_bits = dd_hdr.bits; 337 } 338 339 void 340 db_sum_list_add(struct nbr *nbr, struct lsa_hdr *lsa) 341 { 342 struct lsa_entry *le; 343 344 if ((le = calloc(1, sizeof(*le))) == NULL) 345 fatal("db_sum_list_add"); 346 347 TAILQ_INSERT_TAIL(&nbr->db_sum_list, le, entry); 348 le->le_lsa = lsa; 349 } 350 351 void 352 db_sum_list_next(struct nbr *nbr) 353 { 354 struct lsa_entry *le; 355 356 while ((le = TAILQ_FIRST(&nbr->db_sum_list)) != nbr->dd_end) { 357 TAILQ_REMOVE(&nbr->db_sum_list, le, entry); 358 free(le->le_lsa); 359 free(le); 360 } 361 } 362 363 void 364 db_sum_list_clr(struct nbr *nbr) 365 { 366 nbr->dd_end = NULL; 367 db_sum_list_next(nbr); 368 } 369 370 /* timers */ 371 /* ARGSUSED */ 372 void 373 db_tx_timer(int fd, short event, void *arg) 374 { 375 struct nbr *nbr = arg; 376 struct timeval tv; 377 378 switch (nbr->state) { 379 case NBR_STA_DOWN: 380 case NBR_STA_ATTEMPT: 381 case NBR_STA_INIT: 382 case NBR_STA_2_WAY: 383 case NBR_STA_SNAP: 384 return ; 385 case NBR_STA_XSTRT: 386 case NBR_STA_XCHNG: 387 case NBR_STA_LOAD: 388 case NBR_STA_FULL: 389 send_db_description(nbr); 390 break; 391 default: 392 log_debug("db_tx_timer: neighbor ID %s (%s): " 393 "unknown neighbor state", 394 inet_ntoa(nbr->id), nbr->iface->name); 395 break; 396 } 397 398 /* reschedule db_tx_timer but only in master mode */ 399 if (nbr->dd_master) { 400 timerclear(&tv); 401 tv.tv_sec = nbr->iface->rxmt_interval; 402 if (evtimer_add(&nbr->db_tx_timer, &tv) == -1) 403 fatal("db_tx_timer"); 404 } 405 } 406 407 void 408 start_db_tx_timer(struct nbr *nbr) 409 { 410 struct timeval tv; 411 412 if (nbr == nbr->iface->self) 413 return; 414 415 timerclear(&tv); 416 if (evtimer_add(&nbr->db_tx_timer, &tv) == -1) 417 fatal("start_db_tx_timer"); 418 } 419 420 void 421 stop_db_tx_timer(struct nbr *nbr) 422 { 423 if (nbr == nbr->iface->self) 424 return; 425 426 if (evtimer_del(&nbr->db_tx_timer) == -1) 427 fatal("stop_db_tx_timer"); 428 } 429