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