1 /* $OpenBSD: database.c,v 1.19 2020/01/03 17:26:16 denis 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 extern struct ospfd_conf *oeconf; 35 36 void db_sum_list_next(struct nbr *); 37 38 /* database description packet handling */ 39 int 40 send_db_description(struct nbr *nbr) 41 { 42 struct in6_addr dst; 43 struct db_dscrp_hdr dd_hdr; 44 struct lsa_entry *le, *nle; 45 struct ibuf *buf; 46 u_int8_t bits = 0; 47 48 if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip6_hdr))) == NULL) 49 fatal("send_db_description"); 50 51 /* OSPF header */ 52 if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_DD)) 53 goto fail; 54 55 /* reserve space for database description header */ 56 if (ibuf_reserve(buf, sizeof(dd_hdr)) == NULL) 57 goto fail; 58 59 switch (nbr->state) { 60 case NBR_STA_DOWN: 61 case NBR_STA_ATTEMPT: 62 case NBR_STA_INIT: 63 case NBR_STA_2_WAY: 64 case NBR_STA_SNAP: 65 log_debug("send_db_description: neighbor ID %s: " 66 "cannot send packet in state %s", inet_ntoa(nbr->id), 67 nbr_state_name(nbr->state)); 68 goto fail; 69 case NBR_STA_XSTRT: 70 bits |= OSPF_DBD_MS | OSPF_DBD_M | OSPF_DBD_I; 71 nbr->dd_more = 1; 72 break; 73 case NBR_STA_XCHNG: 74 if (nbr->dd_master) 75 bits |= OSPF_DBD_MS; 76 else 77 bits &= ~OSPF_DBD_MS; 78 79 if (TAILQ_EMPTY(&nbr->db_sum_list)) { 80 bits &= ~OSPF_DBD_M; 81 nbr->dd_more = 0; 82 } else { 83 bits |= OSPF_DBD_M; 84 nbr->dd_more = 1; 85 } 86 87 bits &= ~OSPF_DBD_I; 88 89 /* build LSA list */ 90 for (le = TAILQ_FIRST(&nbr->db_sum_list); le != NULL && 91 ibuf_left(buf) >= sizeof(struct lsa_hdr); le = nle) { 92 nbr->dd_end = nle = TAILQ_NEXT(le, entry); 93 if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr))) 94 goto fail; 95 } 96 break; 97 case NBR_STA_LOAD: 98 case NBR_STA_FULL: 99 if (nbr->dd_master) 100 bits |= OSPF_DBD_MS; 101 else 102 bits &= ~OSPF_DBD_MS; 103 bits &= ~OSPF_DBD_M; 104 bits &= ~OSPF_DBD_I; 105 106 nbr->dd_more = 0; 107 break; 108 default: 109 fatalx("send_db_description: unknown neighbor state"); 110 } 111 112 bzero(&dd_hdr, sizeof(dd_hdr)); 113 114 switch (nbr->iface->type) { 115 case IF_TYPE_POINTOPOINT: 116 inet_pton(AF_INET6, AllSPFRouters, &dst); 117 dd_hdr.iface_mtu = htons(nbr->iface->mtu); 118 break; 119 case IF_TYPE_BROADCAST: 120 dst = nbr->addr; 121 dd_hdr.iface_mtu = htons(nbr->iface->mtu); 122 break; 123 case IF_TYPE_NBMA: 124 case IF_TYPE_POINTOMULTIPOINT: 125 /* XXX not supported */ 126 break; 127 case IF_TYPE_VIRTUALLINK: 128 dst = nbr->iface->dst; 129 dd_hdr.iface_mtu = 0; 130 break; 131 default: 132 fatalx("send_db_description: unknown interface type"); 133 } 134 135 dd_hdr.opts = htonl(area_ospf_options(nbr->iface->area)); 136 dd_hdr.bits = bits; 137 dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num); 138 139 memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(dd_hdr)), 140 &dd_hdr, sizeof(dd_hdr)); 141 142 /* calculate checksum */ 143 if (upd_ospf_hdr(buf, nbr->iface)) 144 goto fail; 145 146 /* transmit packet */ 147 if (send_packet(nbr->iface, buf, &dst) == -1) 148 goto fail; 149 150 ibuf_free(buf); 151 return (0); 152 fail: 153 log_warn("send_db_description"); 154 ibuf_free(buf); 155 return (-1); 156 } 157 158 void 159 recv_db_description(struct nbr *nbr, char *buf, u_int16_t len) 160 { 161 struct db_dscrp_hdr dd_hdr; 162 int dupe = 0; 163 164 if (len < sizeof(dd_hdr)) { 165 log_warnx("recv_db_description: neighbor ID %s: " 166 "bad packet size", inet_ntoa(nbr->id)); 167 return; 168 } 169 memcpy(&dd_hdr, buf, sizeof(dd_hdr)); 170 buf += sizeof(dd_hdr); 171 len -= sizeof(dd_hdr); 172 173 /* db description packet sanity checks */ 174 if (ntohs(dd_hdr.iface_mtu) > nbr->iface->mtu) { 175 log_warnx("recv_db_description: neighbor ID %s: " 176 "invalid MTU %d expected %d", inet_ntoa(nbr->id), 177 ntohs(dd_hdr.iface_mtu), nbr->iface->mtu); 178 return; 179 } 180 181 if (nbr->last_rx_options == dd_hdr.opts && 182 nbr->last_rx_bits == dd_hdr.bits && 183 ntohl(dd_hdr.dd_seq_num) == nbr->dd_seq_num - nbr->dd_master ? 184 1 : 0) { 185 log_debug("recv_db_description: dupe from neighbor ID %s", 186 inet_ntoa(nbr->id)); 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: " 196 "packet ignored in state %s", inet_ntoa(nbr->id), 197 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: " 228 "invalid seq num, mine %x his %x", 229 inet_ntoa(nbr->id), nbr->dd_seq_num, 230 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: " 247 "packet ignored in state %s (bad flags)", 248 inet_ntoa(nbr->id), nbr_state_name(nbr->state)); 249 } 250 break; 251 case NBR_STA_XCHNG: 252 case NBR_STA_LOAD: 253 case NBR_STA_FULL: 254 if (dd_hdr.bits & OSPF_DBD_I || 255 !(dd_hdr.bits & OSPF_DBD_MS) == !nbr->dd_master) { 256 log_warnx("recv_db_description: neighbor ID %s: " 257 "seq num mismatch, bad flags", inet_ntoa(nbr->id)); 258 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 259 return; 260 } 261 262 if (nbr->last_rx_options != dd_hdr.opts) { 263 log_warnx("recv_db_description: neighbor ID %s: " 264 "seq num mismatch, bad options", 265 inet_ntoa(nbr->id)); 266 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 267 return; 268 } 269 270 if (dupe) { 271 if (!nbr->dd_master) 272 /* retransmit */ 273 start_db_tx_timer(nbr); 274 return; 275 } 276 277 if (nbr->state != NBR_STA_XCHNG) { 278 log_warnx("recv_db_description: neighbor ID %s: " 279 "invalid seq num, mine %x his %x", 280 inet_ntoa(nbr->id), nbr->dd_seq_num, 281 ntohl(dd_hdr.dd_seq_num)); 282 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 283 return; 284 } 285 286 /* sanity check dd seq number */ 287 if (nbr->dd_master) { 288 /* master */ 289 if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) { 290 log_warnx("recv_db_description: " 291 "neighbor ID %s: " 292 "invalid seq num, mine %x his %x, master", 293 inet_ntoa(nbr->id), nbr->dd_seq_num, 294 ntohl(dd_hdr.dd_seq_num)); 295 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 296 return; 297 } 298 nbr->dd_seq_num++; 299 } else { 300 /* slave */ 301 if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num + 1) { 302 log_warnx("recv_db_description: " 303 "neighbor ID %s: " 304 "invalid seq num, mine %x his %x, slave", 305 inet_ntoa(nbr->id), nbr->dd_seq_num, 306 ntohl(dd_hdr.dd_seq_num)); 307 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 308 return; 309 } 310 nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num); 311 } 312 313 /* forward to RDE and let it decide which LSAs to request */ 314 if (len > 0) { 315 nbr->dd_pending++; 316 ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 0, 317 buf, len); 318 } 319 320 /* next packet */ 321 db_sum_list_next(nbr); 322 start_db_tx_timer(nbr); 323 324 if (!(dd_hdr.bits & OSPF_DBD_M) && 325 TAILQ_EMPTY(&nbr->db_sum_list)) 326 if (!nbr->dd_master || !nbr->dd_more) 327 nbr_fsm(nbr, NBR_EVT_XCHNG_DONE); 328 break; 329 default: 330 fatalx("recv_db_description: unknown neighbor state"); 331 } 332 333 nbr->last_rx_options = dd_hdr.opts; 334 nbr->last_rx_bits = dd_hdr.bits; 335 } 336 337 void 338 db_sum_list_add(struct nbr *nbr, struct lsa_hdr *lsa) 339 { 340 struct lsa_entry *le; 341 342 if ((le = calloc(1, sizeof(*le))) == NULL) 343 fatal("db_sum_list_add"); 344 345 TAILQ_INSERT_TAIL(&nbr->db_sum_list, le, entry); 346 le->le_lsa = lsa; 347 } 348 349 void 350 db_sum_list_next(struct nbr *nbr) 351 { 352 struct lsa_entry *le; 353 354 while ((le = TAILQ_FIRST(&nbr->db_sum_list)) != nbr->dd_end) { 355 TAILQ_REMOVE(&nbr->db_sum_list, le, entry); 356 free(le->le_lsa); 357 free(le); 358 } 359 } 360 361 void 362 db_sum_list_clr(struct nbr *nbr) 363 { 364 nbr->dd_end = NULL; 365 db_sum_list_next(nbr); 366 } 367 368 /* timers */ 369 /* ARGSUSED */ 370 void 371 db_tx_timer(int fd, short event, void *arg) 372 { 373 struct nbr *nbr = arg; 374 struct timeval tv; 375 376 switch (nbr->state) { 377 case NBR_STA_DOWN: 378 case NBR_STA_ATTEMPT: 379 case NBR_STA_INIT: 380 case NBR_STA_2_WAY: 381 case NBR_STA_SNAP: 382 return ; 383 case NBR_STA_XSTRT: 384 case NBR_STA_XCHNG: 385 case NBR_STA_LOAD: 386 case NBR_STA_FULL: 387 send_db_description(nbr); 388 break; 389 default: 390 log_debug("db_tx_timer: neighbor ID %s: unknown neighbor state", 391 inet_ntoa(nbr->id)); 392 break; 393 } 394 395 /* reschedule db_tx_timer but only in master mode */ 396 if (nbr->dd_master) { 397 timerclear(&tv); 398 tv.tv_sec = nbr->iface->rxmt_interval; 399 if (evtimer_add(&nbr->db_tx_timer, &tv) == -1) 400 fatal("db_tx_timer"); 401 } 402 } 403 404 void 405 start_db_tx_timer(struct nbr *nbr) 406 { 407 struct timeval tv; 408 409 if (nbr == nbr->iface->self) 410 return; 411 412 timerclear(&tv); 413 if (evtimer_add(&nbr->db_tx_timer, &tv) == -1) 414 fatal("start_db_tx_timer"); 415 } 416 417 void 418 stop_db_tx_timer(struct nbr *nbr) 419 { 420 if (nbr == nbr->iface->self) 421 return; 422 423 if (evtimer_del(&nbr->db_tx_timer) == -1) 424 fatal("stop_db_tx_timer"); 425 } 426