1 /* $OpenBSD: database.c,v 1.34 2019/07/15 18:26:39 remi Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2004, 2005 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/ip.h> 24 #include <arpa/inet.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 #include "ospfd.h" 30 #include "ospf.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 sockaddr_in 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 ip))) == 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, keep space for a possible md5 sum */ 90 for (le = TAILQ_FIRST(&nbr->db_sum_list); le != NULL && 91 ibuf_left(buf) >= MD5_DIGEST_LENGTH + sizeof(struct lsa_hdr); 92 le = nle) { 93 nbr->dd_end = nle = TAILQ_NEXT(le, entry); 94 if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr))) 95 goto fail; 96 } 97 break; 98 case NBR_STA_LOAD: 99 case NBR_STA_FULL: 100 if (nbr->dd_master) 101 bits |= OSPF_DBD_MS; 102 else 103 bits &= ~OSPF_DBD_MS; 104 bits &= ~OSPF_DBD_M; 105 bits &= ~OSPF_DBD_I; 106 107 nbr->dd_more = 0; 108 break; 109 default: 110 fatalx("send_db_description: unknown neighbor state"); 111 } 112 113 /* set destination */ 114 dst.sin_family = AF_INET; 115 dst.sin_len = sizeof(struct sockaddr_in); 116 117 switch (nbr->iface->type) { 118 case IF_TYPE_POINTOPOINT: 119 inet_aton(AllSPFRouters, &dst.sin_addr); 120 dd_hdr.iface_mtu = htons(nbr->iface->mtu); 121 break; 122 case IF_TYPE_BROADCAST: 123 dst.sin_addr = nbr->addr; 124 dd_hdr.iface_mtu = htons(nbr->iface->mtu); 125 break; 126 case IF_TYPE_NBMA: 127 case IF_TYPE_POINTOMULTIPOINT: 128 /* XXX not supported */ 129 break; 130 case IF_TYPE_VIRTUALLINK: 131 dst.sin_addr = nbr->iface->dst; 132 dd_hdr.iface_mtu = 0; 133 break; 134 default: 135 fatalx("send_db_description: unknown interface type"); 136 } 137 138 /* XXX button or not for opaque LSA? */ 139 dd_hdr.opts = area_ospf_options(nbr->iface->area) | OSPF_OPTION_O; 140 dd_hdr.bits = bits; 141 dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num); 142 143 memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(dd_hdr)), 144 &dd_hdr, sizeof(dd_hdr)); 145 146 /* update authentication and calculate checksum */ 147 if (auth_gen(buf, nbr->iface)) 148 goto fail; 149 150 /* transmit packet */ 151 if (send_packet(nbr->iface, buf, &dst) == -1) 152 goto fail; 153 154 ibuf_free(buf); 155 return (0); 156 fail: 157 log_warn("%s", __func__); 158 ibuf_free(buf); 159 return (-1); 160 } 161 162 void 163 recv_db_description(struct nbr *nbr, char *buf, u_int16_t len) 164 { 165 struct db_dscrp_hdr dd_hdr; 166 int dupe = 0; 167 168 if (len < sizeof(dd_hdr)) { 169 log_warnx("recv_db_description: neighbor ID %s: " 170 "bad packet size", inet_ntoa(nbr->id)); 171 return; 172 } 173 memcpy(&dd_hdr, buf, sizeof(dd_hdr)); 174 buf += sizeof(dd_hdr); 175 len -= sizeof(dd_hdr); 176 177 /* db description packet sanity checks */ 178 if (ntohs(dd_hdr.iface_mtu) > nbr->iface->mtu) { 179 log_warnx("recv_db_description: neighbor ID %s: " 180 "invalid MTU %d expected %d", inet_ntoa(nbr->id), 181 ntohs(dd_hdr.iface_mtu), nbr->iface->mtu); 182 return; 183 } 184 185 if (nbr->last_rx_options == dd_hdr.opts && 186 nbr->last_rx_bits == dd_hdr.bits && 187 ntohl(dd_hdr.dd_seq_num) == nbr->dd_seq_num - nbr->dd_master ? 188 1 : 0) { 189 log_debug("recv_db_description: dupe from neighbor ID %s", 190 inet_ntoa(nbr->id)); 191 dupe = 1; 192 } 193 194 switch (nbr->state) { 195 case NBR_STA_DOWN: 196 case NBR_STA_ATTEMPT: 197 case NBR_STA_2_WAY: 198 case NBR_STA_SNAP: 199 log_debug("recv_db_description: neighbor ID %s: " 200 "packet ignored in state %s", inet_ntoa(nbr->id), 201 nbr_state_name(nbr->state)); 202 return; 203 case NBR_STA_INIT: 204 /* evaluate dr and bdr after issuing a 2-Way event */ 205 nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD); 206 if_fsm(nbr->iface, IF_EVT_NBR_CHNG); 207 if (nbr->state != NBR_STA_XSTRT) 208 return; 209 /* FALLTHROUGH */ 210 case NBR_STA_XSTRT: 211 if (dupe) 212 return; 213 nbr->capa_options = dd_hdr.opts; 214 if ((nbr->capa_options & nbr->options) != nbr->options) { 215 log_warnx("recv_db_description: neighbor ID %s " 216 "sent inconsistent options %x vs. %x", 217 inet_ntoa(nbr->id), nbr->capa_options, 218 nbr->options); 219 } 220 /* 221 * check bits: either I,M,MS or only M 222 */ 223 if (dd_hdr.bits == (OSPF_DBD_I | OSPF_DBD_M | OSPF_DBD_MS)) { 224 /* if nbr Router ID is larger than own -> slave */ 225 if ((ntohl(nbr->id.s_addr)) > 226 ntohl(ospfe_router_id())) { 227 /* slave */ 228 nbr->dd_master = 0; 229 nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num); 230 231 /* event negotiation done */ 232 nbr_fsm(nbr, NBR_EVT_NEG_DONE); 233 } 234 } else if (!(dd_hdr.bits & (OSPF_DBD_I | OSPF_DBD_MS))) { 235 /* M only case: we are master */ 236 if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) { 237 log_warnx("recv_db_description: " 238 "neighbor ID %s: " 239 "invalid seq num, mine %x his %x", 240 inet_ntoa(nbr->id), nbr->dd_seq_num, 241 ntohl(dd_hdr.dd_seq_num)); 242 return; 243 } 244 nbr->dd_seq_num++; 245 246 /* event negotiation done */ 247 nbr_fsm(nbr, NBR_EVT_NEG_DONE); 248 249 /* this packet may already have data so pass it on */ 250 if (len > 0) { 251 nbr->dd_pending++; 252 ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 253 0, buf, len); 254 } 255 } else { 256 /* ignore packet */ 257 log_debug("recv_db_description: neighbor ID %s: " 258 "packet ignored in state %s (bad flags)", 259 inet_ntoa(nbr->id), nbr_state_name(nbr->state)); 260 } 261 break; 262 case NBR_STA_XCHNG: 263 case NBR_STA_LOAD: 264 case NBR_STA_FULL: 265 if (dd_hdr.bits & OSPF_DBD_I || 266 !(dd_hdr.bits & OSPF_DBD_MS) == !nbr->dd_master) { 267 log_warnx("recv_db_description: neighbor ID %s: " 268 "seq num mismatch, bad flags", inet_ntoa(nbr->id)); 269 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 270 return; 271 } 272 273 if (nbr->last_rx_options != dd_hdr.opts) { 274 log_warnx("recv_db_description: neighbor ID %s: " 275 "seq num mismatch, bad options", 276 inet_ntoa(nbr->id)); 277 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 278 return; 279 } 280 281 if (dupe) { 282 if (!nbr->dd_master) 283 /* retransmit */ 284 start_db_tx_timer(nbr); 285 return; 286 } 287 288 if (nbr->state != NBR_STA_XCHNG) { 289 log_warnx("recv_db_description: neighbor ID %s: " 290 "invalid seq num, mine %x his %x", 291 inet_ntoa(nbr->id), nbr->dd_seq_num, 292 ntohl(dd_hdr.dd_seq_num)); 293 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 294 return; 295 } 296 297 /* sanity check dd seq number */ 298 if (nbr->dd_master) { 299 /* master */ 300 if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) { 301 log_warnx("recv_db_description: " 302 "neighbor ID %s: " 303 "invalid seq num, mine %x his %x, master", 304 inet_ntoa(nbr->id), nbr->dd_seq_num, 305 ntohl(dd_hdr.dd_seq_num)); 306 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 307 return; 308 } 309 nbr->dd_seq_num++; 310 } else { 311 /* slave */ 312 if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num + 1) { 313 log_warnx("recv_db_description: " 314 "neighbor ID %s: " 315 "invalid seq num, mine %x his %x, slave", 316 inet_ntoa(nbr->id), nbr->dd_seq_num, 317 ntohl(dd_hdr.dd_seq_num)); 318 nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 319 return; 320 } 321 nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num); 322 } 323 324 /* forward to RDE and let it decide which LSAs to request */ 325 if (len > 0) { 326 nbr->dd_pending++; 327 ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 0, 328 buf, len); 329 } 330 331 /* next packet */ 332 db_sum_list_next(nbr); 333 start_db_tx_timer(nbr); 334 335 if (!(dd_hdr.bits & OSPF_DBD_M) && 336 TAILQ_EMPTY(&nbr->db_sum_list)) 337 if (!nbr->dd_master || !nbr->dd_more) 338 nbr_fsm(nbr, NBR_EVT_XCHNG_DONE); 339 break; 340 default: 341 fatalx("recv_db_description: unknown neighbor state"); 342 } 343 344 nbr->last_rx_options = dd_hdr.opts; 345 nbr->last_rx_bits = dd_hdr.bits; 346 } 347 348 void 349 db_sum_list_add(struct nbr *nbr, struct lsa_hdr *lsa) 350 { 351 struct lsa_entry *le; 352 353 if ((le = calloc(1, sizeof(*le))) == NULL) 354 fatal("db_sum_list_add"); 355 356 TAILQ_INSERT_TAIL(&nbr->db_sum_list, le, entry); 357 le->le_lsa = lsa; 358 } 359 360 void 361 db_sum_list_next(struct nbr *nbr) 362 { 363 struct lsa_entry *le; 364 365 while ((le = TAILQ_FIRST(&nbr->db_sum_list)) != nbr->dd_end) { 366 TAILQ_REMOVE(&nbr->db_sum_list, le, entry); 367 free(le->le_lsa); 368 free(le); 369 } 370 } 371 372 void 373 db_sum_list_clr(struct nbr *nbr) 374 { 375 nbr->dd_end = NULL; 376 db_sum_list_next(nbr); 377 } 378 379 /* timers */ 380 /* ARGSUSED */ 381 void 382 db_tx_timer(int fd, short event, void *arg) 383 { 384 struct nbr *nbr = arg; 385 struct timeval tv; 386 387 switch (nbr->state) { 388 case NBR_STA_DOWN: 389 case NBR_STA_ATTEMPT: 390 case NBR_STA_INIT: 391 case NBR_STA_2_WAY: 392 case NBR_STA_SNAP: 393 return ; 394 case NBR_STA_XSTRT: 395 case NBR_STA_XCHNG: 396 case NBR_STA_LOAD: 397 case NBR_STA_FULL: 398 send_db_description(nbr); 399 break; 400 default: 401 log_debug("db_tx_timer: neighbor ID %s: unknown neighbor state", 402 inet_ntoa(nbr->id)); 403 break; 404 } 405 406 /* reschedule db_tx_timer but only in master mode */ 407 if (nbr->dd_master) { 408 timerclear(&tv); 409 tv.tv_sec = nbr->iface->rxmt_interval; 410 if (evtimer_add(&nbr->db_tx_timer, &tv) == -1) 411 fatal("db_tx_timer"); 412 } 413 } 414 415 void 416 start_db_tx_timer(struct nbr *nbr) 417 { 418 struct timeval tv; 419 420 if (nbr == nbr->iface->self) 421 return; 422 423 timerclear(&tv); 424 if (evtimer_add(&nbr->db_tx_timer, &tv) == -1) 425 fatal("start_db_tx_timer"); 426 } 427 428 void 429 stop_db_tx_timer(struct nbr *nbr) 430 { 431 if (nbr == nbr->iface->self) 432 return; 433 434 if (evtimer_del(&nbr->db_tx_timer) == -1) 435 fatal("stop_db_tx_timer"); 436 } 437