1*4f4fe40bSflorian /* $OpenBSD: database.c,v 1.38 2024/08/21 15:18:00 florian Exp $ */ 2204df0f8Sclaudio 3204df0f8Sclaudio /* 4204df0f8Sclaudio * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5367f601bSnorby * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 6204df0f8Sclaudio * 7204df0f8Sclaudio * Permission to use, copy, modify, and distribute this software for any 8204df0f8Sclaudio * purpose with or without fee is hereby granted, provided that the above 9204df0f8Sclaudio * copyright notice and this permission notice appear in all copies. 10204df0f8Sclaudio * 11204df0f8Sclaudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12204df0f8Sclaudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13204df0f8Sclaudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14204df0f8Sclaudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15204df0f8Sclaudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16204df0f8Sclaudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17204df0f8Sclaudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18204df0f8Sclaudio */ 19204df0f8Sclaudio 20204df0f8Sclaudio #include <sys/types.h> 21204df0f8Sclaudio #include <sys/socket.h> 22204df0f8Sclaudio #include <netinet/in.h> 230491ce75Sclaudio #include <netinet/ip.h> 24204df0f8Sclaudio #include <arpa/inet.h> 25204df0f8Sclaudio #include <stdlib.h> 26204df0f8Sclaudio #include <string.h> 27204df0f8Sclaudio #include <unistd.h> 28204df0f8Sclaudio 29204df0f8Sclaudio #include "ospfd.h" 30204df0f8Sclaudio #include "ospf.h" 31204df0f8Sclaudio #include "log.h" 32204df0f8Sclaudio #include "ospfe.h" 33204df0f8Sclaudio 34204df0f8Sclaudio extern struct ospfd_conf *oeconf; 35204df0f8Sclaudio 36204df0f8Sclaudio void db_sum_list_next(struct nbr *); 37204df0f8Sclaudio 38204df0f8Sclaudio /* database description packet handling */ 39204df0f8Sclaudio int 40204df0f8Sclaudio send_db_description(struct nbr *nbr) 41204df0f8Sclaudio { 42204df0f8Sclaudio struct sockaddr_in dst; 430491ce75Sclaudio struct db_dscrp_hdr dd_hdr; 44204df0f8Sclaudio struct lsa_entry *le, *nle; 45e39620e5Snicm struct ibuf *buf; 464d267a96Sclaudio u_int8_t bits = 0; 47204df0f8Sclaudio 48e39620e5Snicm if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL) 49204df0f8Sclaudio fatal("send_db_description"); 50204df0f8Sclaudio 51204df0f8Sclaudio /* OSPF header */ 520491ce75Sclaudio if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_DD)) 530491ce75Sclaudio goto fail; 54204df0f8Sclaudio 550491ce75Sclaudio /* reserve space for database description header */ 5643e70bb4Sclaudio if (ibuf_add_zero(buf, sizeof(dd_hdr)) == -1) 570491ce75Sclaudio goto fail; 58204df0f8Sclaudio 59204df0f8Sclaudio switch (nbr->state) { 60204df0f8Sclaudio case NBR_STA_DOWN: 61204df0f8Sclaudio case NBR_STA_ATTEMPT: 62204df0f8Sclaudio case NBR_STA_INIT: 63204df0f8Sclaudio case NBR_STA_2_WAY: 64204df0f8Sclaudio case NBR_STA_SNAP: 659cc19ef1Ssthen log_debug("send_db_description: neighbor ID %s (%s): " 669a2eee35Sclaudio "cannot send packet in state %s", inet_ntoa(nbr->id), 679cc19ef1Ssthen nbr->iface->name, nbr_state_name(nbr->state)); 6825a742ccSremi goto fail; 69204df0f8Sclaudio case NBR_STA_XSTRT: 704d267a96Sclaudio bits |= OSPF_DBD_MS | OSPF_DBD_M | OSPF_DBD_I; 714d267a96Sclaudio nbr->dd_more = 1; 72204df0f8Sclaudio break; 73204df0f8Sclaudio case NBR_STA_XCHNG: 744d267a96Sclaudio if (nbr->dd_master) 754d267a96Sclaudio bits |= OSPF_DBD_MS; 764d267a96Sclaudio else 774d267a96Sclaudio bits &= ~OSPF_DBD_MS; 784d267a96Sclaudio 794d267a96Sclaudio if (TAILQ_EMPTY(&nbr->db_sum_list)) { 804d267a96Sclaudio bits &= ~OSPF_DBD_M; 814d267a96Sclaudio nbr->dd_more = 0; 82204df0f8Sclaudio } else { 834d267a96Sclaudio bits |= OSPF_DBD_M; 844d267a96Sclaudio nbr->dd_more = 1; 85204df0f8Sclaudio } 86204df0f8Sclaudio 874d267a96Sclaudio bits &= ~OSPF_DBD_I; 88204df0f8Sclaudio 890491ce75Sclaudio /* build LSA list, keep space for a possible md5 sum */ 900491ce75Sclaudio for (le = TAILQ_FIRST(&nbr->db_sum_list); le != NULL && 91e39620e5Snicm ibuf_left(buf) >= MD5_DIGEST_LENGTH + sizeof(struct lsa_hdr); 929627de93Sclaudio le = nle) { 93204df0f8Sclaudio nbr->dd_end = nle = TAILQ_NEXT(le, entry); 94e39620e5Snicm if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr))) 950491ce75Sclaudio goto fail; 96204df0f8Sclaudio } 97204df0f8Sclaudio break; 98204df0f8Sclaudio case NBR_STA_LOAD: 99204df0f8Sclaudio case NBR_STA_FULL: 1004d267a96Sclaudio if (nbr->dd_master) 1014d267a96Sclaudio bits |= OSPF_DBD_MS; 1024d267a96Sclaudio else 1034d267a96Sclaudio bits &= ~OSPF_DBD_MS; 1044d267a96Sclaudio bits &= ~OSPF_DBD_M; 1054d267a96Sclaudio bits &= ~OSPF_DBD_I; 106204df0f8Sclaudio 1074d267a96Sclaudio nbr->dd_more = 0; 108204df0f8Sclaudio break; 109204df0f8Sclaudio default: 1100491ce75Sclaudio fatalx("send_db_description: unknown neighbor state"); 111204df0f8Sclaudio } 112204df0f8Sclaudio 113204df0f8Sclaudio /* set destination */ 114204df0f8Sclaudio dst.sin_family = AF_INET; 115204df0f8Sclaudio dst.sin_len = sizeof(struct sockaddr_in); 116204df0f8Sclaudio 117204df0f8Sclaudio switch (nbr->iface->type) { 118204df0f8Sclaudio case IF_TYPE_POINTOPOINT: 119*4f4fe40bSflorian inet_pton(AF_INET, AllSPFRouters, &dst.sin_addr); 1200491ce75Sclaudio dd_hdr.iface_mtu = htons(nbr->iface->mtu); 121204df0f8Sclaudio break; 122204df0f8Sclaudio case IF_TYPE_BROADCAST: 123204df0f8Sclaudio dst.sin_addr = nbr->addr; 1240491ce75Sclaudio dd_hdr.iface_mtu = htons(nbr->iface->mtu); 125204df0f8Sclaudio break; 126204df0f8Sclaudio case IF_TYPE_NBMA: 127204df0f8Sclaudio case IF_TYPE_POINTOMULTIPOINT: 128bfa55e2fSnorby /* XXX not supported */ 129bfa55e2fSnorby break; 130204df0f8Sclaudio case IF_TYPE_VIRTUALLINK: 131bfa55e2fSnorby dst.sin_addr = nbr->iface->dst; 1320491ce75Sclaudio dd_hdr.iface_mtu = 0; 133204df0f8Sclaudio break; 134204df0f8Sclaudio default: 135204df0f8Sclaudio fatalx("send_db_description: unknown interface type"); 136204df0f8Sclaudio } 137204df0f8Sclaudio 138097ed198Sclaudio /* XXX button or not for opaque LSA? */ 139097ed198Sclaudio dd_hdr.opts = area_ospf_options(nbr->iface->area) | OSPF_OPTION_O; 1404d267a96Sclaudio dd_hdr.bits = bits; 1410491ce75Sclaudio dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num); 1420491ce75Sclaudio 14343e70bb4Sclaudio if (ibuf_set(buf, sizeof(struct ospf_hdr), &dd_hdr, 14443e70bb4Sclaudio sizeof(dd_hdr)) == -1) 14543e70bb4Sclaudio goto fail; 146204df0f8Sclaudio 147204df0f8Sclaudio /* update authentication and calculate checksum */ 1480491ce75Sclaudio if (auth_gen(buf, nbr->iface)) 1490491ce75Sclaudio goto fail; 150204df0f8Sclaudio 151204df0f8Sclaudio /* transmit packet */ 15225a742ccSremi if (send_packet(nbr->iface, buf, &dst) == -1) 15325a742ccSremi goto fail; 15425a742ccSremi 155e39620e5Snicm ibuf_free(buf); 15625a742ccSremi return (0); 1570491ce75Sclaudio fail: 15825a742ccSremi log_warn("%s", __func__); 159e39620e5Snicm ibuf_free(buf); 1600491ce75Sclaudio return (-1); 161204df0f8Sclaudio } 162204df0f8Sclaudio 163204df0f8Sclaudio void 164204df0f8Sclaudio recv_db_description(struct nbr *nbr, char *buf, u_int16_t len) 165204df0f8Sclaudio { 166204df0f8Sclaudio struct db_dscrp_hdr dd_hdr; 167204df0f8Sclaudio int dupe = 0; 168204df0f8Sclaudio 169204df0f8Sclaudio if (len < sizeof(dd_hdr)) { 1709cc19ef1Ssthen log_warnx("recv_db_description: neighbor ID %s (%s): " 1719cc19ef1Ssthen "bad packet size", inet_ntoa(nbr->id), nbr->iface->name); 172204df0f8Sclaudio return; 173204df0f8Sclaudio } 174204df0f8Sclaudio memcpy(&dd_hdr, buf, sizeof(dd_hdr)); 175204df0f8Sclaudio buf += sizeof(dd_hdr); 176204df0f8Sclaudio len -= sizeof(dd_hdr); 177204df0f8Sclaudio 178204df0f8Sclaudio /* db description packet sanity checks */ 179c1d15234Sclaudio if (ntohs(dd_hdr.iface_mtu) > nbr->iface->mtu) { 1809cc19ef1Ssthen log_warnx("recv_db_description: neighbor ID %s (%s): " 1819a2eee35Sclaudio "invalid MTU %d expected %d", inet_ntoa(nbr->id), 1829cc19ef1Ssthen nbr->iface->name, ntohs(dd_hdr.iface_mtu), 1839cc19ef1Ssthen nbr->iface->mtu); 184204df0f8Sclaudio return; 185204df0f8Sclaudio } 186204df0f8Sclaudio 187204df0f8Sclaudio if (nbr->last_rx_options == dd_hdr.opts && 188204df0f8Sclaudio nbr->last_rx_bits == dd_hdr.bits && 1894d267a96Sclaudio ntohl(dd_hdr.dd_seq_num) == nbr->dd_seq_num - nbr->dd_master ? 1904d267a96Sclaudio 1 : 0) { 1919cc19ef1Ssthen log_debug("recv_db_description: dupe from " 1929cc19ef1Ssthen "neighbor ID %s (%s)", inet_ntoa(nbr->id), 1939cc19ef1Ssthen nbr->iface->name); 194204df0f8Sclaudio dupe = 1; 195204df0f8Sclaudio } 196204df0f8Sclaudio 197204df0f8Sclaudio switch (nbr->state) { 198204df0f8Sclaudio case NBR_STA_DOWN: 199204df0f8Sclaudio case NBR_STA_ATTEMPT: 200204df0f8Sclaudio case NBR_STA_2_WAY: 201204df0f8Sclaudio case NBR_STA_SNAP: 2029cc19ef1Ssthen log_debug("recv_db_description: neighbor ID %s (%s): " 2039a2eee35Sclaudio "packet ignored in state %s", inet_ntoa(nbr->id), 2049cc19ef1Ssthen nbr->iface->name, nbr_state_name(nbr->state)); 205204df0f8Sclaudio return; 206204df0f8Sclaudio case NBR_STA_INIT: 2073bb9eff8Sclaudio /* evaluate dr and bdr after issuing a 2-Way event */ 208204df0f8Sclaudio nbr_fsm(nbr, NBR_EVT_2_WAY_RCVD); 2093bb9eff8Sclaudio if_fsm(nbr->iface, IF_EVT_NBR_CHNG); 210204df0f8Sclaudio if (nbr->state != NBR_STA_XSTRT) 211204df0f8Sclaudio return; 212204df0f8Sclaudio /* FALLTHROUGH */ 213204df0f8Sclaudio case NBR_STA_XSTRT: 214204df0f8Sclaudio if (dupe) 215204df0f8Sclaudio return; 216097ed198Sclaudio nbr->capa_options = dd_hdr.opts; 217097ed198Sclaudio if ((nbr->capa_options & nbr->options) != nbr->options) { 2189cc19ef1Ssthen log_warnx("recv_db_description: neighbor ID %s (%s) " 219097ed198Sclaudio "sent inconsistent options %x vs. %x", 2209cc19ef1Ssthen inet_ntoa(nbr->id), nbr->iface->name, 2219cc19ef1Ssthen nbr->capa_options, nbr->options); 222097ed198Sclaudio } 223204df0f8Sclaudio /* 224204df0f8Sclaudio * check bits: either I,M,MS or only M 225204df0f8Sclaudio */ 226204df0f8Sclaudio if (dd_hdr.bits == (OSPF_DBD_I | OSPF_DBD_M | OSPF_DBD_MS)) { 227204df0f8Sclaudio /* if nbr Router ID is larger than own -> slave */ 228204df0f8Sclaudio if ((ntohl(nbr->id.s_addr)) > 229f12637e5Smsf ntohl(ospfe_router_id())) { 230204df0f8Sclaudio /* slave */ 2314d267a96Sclaudio nbr->dd_master = 0; 232204df0f8Sclaudio nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num); 233204df0f8Sclaudio 234204df0f8Sclaudio /* event negotiation done */ 235204df0f8Sclaudio nbr_fsm(nbr, NBR_EVT_NEG_DONE); 236204df0f8Sclaudio } 237d7363de5Sclaudio } else if (!(dd_hdr.bits & (OSPF_DBD_I | OSPF_DBD_MS))) { 2383bb9eff8Sclaudio /* M only case: we are master */ 239204df0f8Sclaudio if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) { 2409a2eee35Sclaudio log_warnx("recv_db_description: " 2419cc19ef1Ssthen "neighbor ID %s (%s): " 2429a2eee35Sclaudio "invalid seq num, mine %x his %x", 2439cc19ef1Ssthen inet_ntoa(nbr->id), nbr->iface->name, 2449cc19ef1Ssthen nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num)); 245204df0f8Sclaudio return; 246204df0f8Sclaudio } 247204df0f8Sclaudio nbr->dd_seq_num++; 248204df0f8Sclaudio 24998b447a7Sclaudio /* event negotiation done */ 25098b447a7Sclaudio nbr_fsm(nbr, NBR_EVT_NEG_DONE); 25198b447a7Sclaudio 252204df0f8Sclaudio /* this packet may already have data so pass it on */ 253299d99d9Sclaudio if (len > 0) { 254299d99d9Sclaudio nbr->dd_pending++; 255204df0f8Sclaudio ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 256204df0f8Sclaudio 0, buf, len); 257299d99d9Sclaudio } 258204df0f8Sclaudio } else { 259204df0f8Sclaudio /* ignore packet */ 2609cc19ef1Ssthen log_debug("recv_db_description: neighbor ID %s (%s): " 2619a2eee35Sclaudio "packet ignored in state %s (bad flags)", 2629cc19ef1Ssthen inet_ntoa(nbr->id), nbr->iface->name, 2639cc19ef1Ssthen nbr_state_name(nbr->state)); 264204df0f8Sclaudio } 265204df0f8Sclaudio break; 266204df0f8Sclaudio case NBR_STA_XCHNG: 267204df0f8Sclaudio case NBR_STA_LOAD: 268204df0f8Sclaudio case NBR_STA_FULL: 269204df0f8Sclaudio if (dd_hdr.bits & OSPF_DBD_I || 2704d267a96Sclaudio !(dd_hdr.bits & OSPF_DBD_MS) == !nbr->dd_master) { 2719cc19ef1Ssthen log_warnx("recv_db_description: neighbor ID %s (%s): " 2729cc19ef1Ssthen "seq num mismatch, bad flags", inet_ntoa(nbr->id), 2739cc19ef1Ssthen nbr->iface->name); 274204df0f8Sclaudio nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 275204df0f8Sclaudio return; 276204df0f8Sclaudio } 277204df0f8Sclaudio 278204df0f8Sclaudio if (nbr->last_rx_options != dd_hdr.opts) { 2799cc19ef1Ssthen log_warnx("recv_db_description: neighbor ID %s (%s): " 2809a2eee35Sclaudio "seq num mismatch, bad options", 2819cc19ef1Ssthen inet_ntoa(nbr->id), nbr->iface->name); 282204df0f8Sclaudio nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 283204df0f8Sclaudio return; 284204df0f8Sclaudio } 285204df0f8Sclaudio 286204df0f8Sclaudio if (dupe) { 2874d267a96Sclaudio if (!nbr->dd_master) 288204df0f8Sclaudio /* retransmit */ 289204df0f8Sclaudio start_db_tx_timer(nbr); 290204df0f8Sclaudio return; 291204df0f8Sclaudio } 292204df0f8Sclaudio 293204df0f8Sclaudio if (nbr->state != NBR_STA_XCHNG) { 2949cc19ef1Ssthen log_warnx("recv_db_description: neighbor ID %s (%s): " 2959a2eee35Sclaudio "invalid seq num, mine %x his %x", 2969cc19ef1Ssthen inet_ntoa(nbr->id), nbr->iface->name, 2979cc19ef1Ssthen nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num)); 298204df0f8Sclaudio nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 299204df0f8Sclaudio return; 300204df0f8Sclaudio } 301204df0f8Sclaudio 302204df0f8Sclaudio /* sanity check dd seq number */ 3034d267a96Sclaudio if (nbr->dd_master) { 304204df0f8Sclaudio /* master */ 305204df0f8Sclaudio if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num) { 3069a2eee35Sclaudio log_warnx("recv_db_description: " 3079cc19ef1Ssthen "neighbor ID %s (%s): " 3089a2eee35Sclaudio "invalid seq num, mine %x his %x, master", 3099cc19ef1Ssthen inet_ntoa(nbr->id), nbr->iface->name, 3109cc19ef1Ssthen nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num)); 311204df0f8Sclaudio nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 312204df0f8Sclaudio return; 313204df0f8Sclaudio } 314204df0f8Sclaudio nbr->dd_seq_num++; 315204df0f8Sclaudio } else { 316204df0f8Sclaudio /* slave */ 317204df0f8Sclaudio if (ntohl(dd_hdr.dd_seq_num) != nbr->dd_seq_num + 1) { 3189a2eee35Sclaudio log_warnx("recv_db_description: " 3199cc19ef1Ssthen "neighbor ID %s (%s): " 3209a2eee35Sclaudio "invalid seq num, mine %x his %x, slave", 3219cc19ef1Ssthen inet_ntoa(nbr->id), nbr->iface->name, 3229cc19ef1Ssthen nbr->dd_seq_num, ntohl(dd_hdr.dd_seq_num)); 323204df0f8Sclaudio nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); 324204df0f8Sclaudio return; 325204df0f8Sclaudio } 326204df0f8Sclaudio nbr->dd_seq_num = ntohl(dd_hdr.dd_seq_num); 327204df0f8Sclaudio } 328204df0f8Sclaudio 329611e3786Sclaudio /* forward to RDE and let it decide which LSAs to request */ 330299d99d9Sclaudio if (len > 0) { 331299d99d9Sclaudio nbr->dd_pending++; 332204df0f8Sclaudio ospfe_imsg_compose_rde(IMSG_DD, nbr->peerid, 0, 333204df0f8Sclaudio buf, len); 334299d99d9Sclaudio } 335204df0f8Sclaudio 336204df0f8Sclaudio /* next packet */ 337204df0f8Sclaudio db_sum_list_next(nbr); 338204df0f8Sclaudio start_db_tx_timer(nbr); 339204df0f8Sclaudio 340204df0f8Sclaudio if (!(dd_hdr.bits & OSPF_DBD_M) && 341204df0f8Sclaudio TAILQ_EMPTY(&nbr->db_sum_list)) 3424d267a96Sclaudio if (!nbr->dd_master || !nbr->dd_more) 343204df0f8Sclaudio nbr_fsm(nbr, NBR_EVT_XCHNG_DONE); 344204df0f8Sclaudio break; 345204df0f8Sclaudio default: 346204df0f8Sclaudio fatalx("recv_db_description: unknown neighbor state"); 347204df0f8Sclaudio } 348204df0f8Sclaudio 349204df0f8Sclaudio nbr->last_rx_options = dd_hdr.opts; 350204df0f8Sclaudio nbr->last_rx_bits = dd_hdr.bits; 351204df0f8Sclaudio } 352204df0f8Sclaudio 353204df0f8Sclaudio void 354204df0f8Sclaudio db_sum_list_add(struct nbr *nbr, struct lsa_hdr *lsa) 355204df0f8Sclaudio { 356204df0f8Sclaudio struct lsa_entry *le; 357204df0f8Sclaudio 358204df0f8Sclaudio if ((le = calloc(1, sizeof(*le))) == NULL) 359204df0f8Sclaudio fatal("db_sum_list_add"); 360204df0f8Sclaudio 361204df0f8Sclaudio TAILQ_INSERT_TAIL(&nbr->db_sum_list, le, entry); 362204df0f8Sclaudio le->le_lsa = lsa; 363204df0f8Sclaudio } 364204df0f8Sclaudio 365204df0f8Sclaudio void 366204df0f8Sclaudio db_sum_list_next(struct nbr *nbr) 367204df0f8Sclaudio { 368204df0f8Sclaudio struct lsa_entry *le; 369204df0f8Sclaudio 370204df0f8Sclaudio while ((le = TAILQ_FIRST(&nbr->db_sum_list)) != nbr->dd_end) { 371204df0f8Sclaudio TAILQ_REMOVE(&nbr->db_sum_list, le, entry); 372204df0f8Sclaudio free(le->le_lsa); 373204df0f8Sclaudio free(le); 374204df0f8Sclaudio } 375204df0f8Sclaudio } 376204df0f8Sclaudio 377204df0f8Sclaudio void 378204df0f8Sclaudio db_sum_list_clr(struct nbr *nbr) 379204df0f8Sclaudio { 380204df0f8Sclaudio nbr->dd_end = NULL; 381204df0f8Sclaudio db_sum_list_next(nbr); 382204df0f8Sclaudio } 383204df0f8Sclaudio 384204df0f8Sclaudio /* timers */ 385204df0f8Sclaudio void 386204df0f8Sclaudio db_tx_timer(int fd, short event, void *arg) 387204df0f8Sclaudio { 388204df0f8Sclaudio struct nbr *nbr = arg; 389204df0f8Sclaudio struct timeval tv; 390204df0f8Sclaudio 391204df0f8Sclaudio switch (nbr->state) { 392204df0f8Sclaudio case NBR_STA_DOWN: 393204df0f8Sclaudio case NBR_STA_ATTEMPT: 394204df0f8Sclaudio case NBR_STA_INIT: 395204df0f8Sclaudio case NBR_STA_2_WAY: 396204df0f8Sclaudio case NBR_STA_SNAP: 397204df0f8Sclaudio return ; 398204df0f8Sclaudio case NBR_STA_XSTRT: 399204df0f8Sclaudio case NBR_STA_XCHNG: 400d7363de5Sclaudio case NBR_STA_LOAD: 401204df0f8Sclaudio case NBR_STA_FULL: 402204df0f8Sclaudio send_db_description(nbr); 403204df0f8Sclaudio break; 404204df0f8Sclaudio default: 4059cc19ef1Ssthen log_debug("db_tx_timer: neighbor ID %s (%s): " 4069cc19ef1Ssthen "unknown neighbor state", 4079cc19ef1Ssthen inet_ntoa(nbr->id), nbr->iface->name); 408204df0f8Sclaudio break; 409204df0f8Sclaudio } 410204df0f8Sclaudio 411204df0f8Sclaudio /* reschedule db_tx_timer but only in master mode */ 4124d267a96Sclaudio if (nbr->dd_master) { 413204df0f8Sclaudio timerclear(&tv); 414204df0f8Sclaudio tv.tv_sec = nbr->iface->rxmt_interval; 4153aede346Sclaudio if (evtimer_add(&nbr->db_tx_timer, &tv) == -1) 4163aede346Sclaudio fatal("db_tx_timer"); 417204df0f8Sclaudio } 418204df0f8Sclaudio } 419204df0f8Sclaudio 4203aede346Sclaudio void 421204df0f8Sclaudio start_db_tx_timer(struct nbr *nbr) 422204df0f8Sclaudio { 423204df0f8Sclaudio struct timeval tv; 424204df0f8Sclaudio 425204df0f8Sclaudio if (nbr == nbr->iface->self) 4263aede346Sclaudio return; 427204df0f8Sclaudio 428204df0f8Sclaudio timerclear(&tv); 4293aede346Sclaudio if (evtimer_add(&nbr->db_tx_timer, &tv) == -1) 4303aede346Sclaudio fatal("start_db_tx_timer"); 431204df0f8Sclaudio } 432204df0f8Sclaudio 4333aede346Sclaudio void 434204df0f8Sclaudio stop_db_tx_timer(struct nbr *nbr) 435204df0f8Sclaudio { 436204df0f8Sclaudio if (nbr == nbr->iface->self) 4373aede346Sclaudio return; 438204df0f8Sclaudio 4393aede346Sclaudio if (evtimer_del(&nbr->db_tx_timer) == -1) 4403aede346Sclaudio fatal("stop_db_tx_timer"); 441204df0f8Sclaudio } 442