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