1 /* $OpenBSD: lsreq.c,v 1.22 2021/01/19 09:25:53 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/socket.h> 21 #include <netinet/in.h> 22 #include <arpa/inet.h> 23 #include <stdlib.h> 24 25 #include "ospfd.h" 26 #include "ospf.h" 27 #include "log.h" 28 #include "ospfe.h" 29 30 /* link state request packet handling */ 31 int 32 send_ls_req(struct nbr *nbr) 33 { 34 struct sockaddr_in dst; 35 struct ls_req_hdr ls_req_hdr; 36 struct lsa_entry *le, *nle; 37 struct ibuf *buf; 38 39 if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL) 40 fatal("send_ls_req"); 41 42 /* set destination */ 43 dst.sin_family = AF_INET; 44 dst.sin_len = sizeof(struct sockaddr_in); 45 46 switch (nbr->iface->type) { 47 case IF_TYPE_POINTOPOINT: 48 inet_aton(AllSPFRouters, &dst.sin_addr); 49 break; 50 case IF_TYPE_BROADCAST: 51 case IF_TYPE_NBMA: 52 case IF_TYPE_POINTOMULTIPOINT: 53 case IF_TYPE_VIRTUALLINK: 54 dst.sin_addr.s_addr = nbr->addr.s_addr; 55 break; 56 default: 57 fatalx("send_ls_req: unknown interface type"); 58 } 59 60 /* OSPF header */ 61 if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_LS_REQUEST)) 62 goto fail; 63 64 /* LSA header(s), keep space for a possible md5 sum */ 65 for (le = TAILQ_FIRST(&nbr->ls_req_list); le != NULL && 66 ibuf_left(buf) >= sizeof(struct ls_req_hdr) + MD5_DIGEST_LENGTH; 67 le = nle) { 68 nbr->ls_req = nle = TAILQ_NEXT(le, entry); 69 ls_req_hdr.type = htonl(le->le_lsa->type); 70 ls_req_hdr.ls_id = le->le_lsa->ls_id; 71 ls_req_hdr.adv_rtr = le->le_lsa->adv_rtr; 72 if (ibuf_add(buf, &ls_req_hdr, sizeof(ls_req_hdr))) 73 goto fail; 74 } 75 76 /* update authentication and calculate checksum */ 77 if (auth_gen(buf, nbr->iface)) 78 goto fail; 79 80 if (send_packet(nbr->iface, buf, &dst) == -1) 81 goto fail; 82 83 ibuf_free(buf); 84 return (0); 85 fail: 86 log_warn("%s", __func__); 87 ibuf_free(buf); 88 return (-1); 89 } 90 91 void 92 recv_ls_req(struct nbr *nbr, char *buf, u_int16_t len) 93 { 94 switch (nbr->state) { 95 case NBR_STA_DOWN: 96 case NBR_STA_ATTEMPT: 97 case NBR_STA_INIT: 98 case NBR_STA_2_WAY: 99 case NBR_STA_XSTRT: 100 case NBR_STA_SNAP: 101 log_debug("recv_ls_req: packet ignored in state %s, " 102 "neighbor ID %s", nbr_state_name(nbr->state), 103 inet_ntoa(nbr->id)); 104 break; 105 case NBR_STA_XCHNG: 106 case NBR_STA_LOAD: 107 case NBR_STA_FULL: 108 ospfe_imsg_compose_rde(IMSG_LS_REQ, nbr->peerid, 0, buf, len); 109 break; 110 default: 111 fatalx("recv_ls_req: unknown neighbor state"); 112 } 113 } 114 115 /* link state request list */ 116 void 117 ls_req_list_add(struct nbr *nbr, struct lsa_hdr *lsa) 118 { 119 struct lsa_entry *le; 120 121 if (lsa == NULL) 122 fatalx("ls_req_list_add: no LSA header"); 123 124 if ((le = calloc(1, sizeof(*le))) == NULL) 125 fatal("ls_req_list_add"); 126 127 TAILQ_INSERT_TAIL(&nbr->ls_req_list, le, entry); 128 le->le_lsa = lsa; 129 nbr->ls_req_cnt++; 130 } 131 132 struct lsa_entry * 133 ls_req_list_get(struct nbr *nbr, struct lsa_hdr *lsa_hdr) 134 { 135 struct lsa_entry *le; 136 137 TAILQ_FOREACH(le, &nbr->ls_req_list, entry) { 138 if ((lsa_hdr->type == le->le_lsa->type) && 139 (lsa_hdr->ls_id == le->le_lsa->ls_id) && 140 (lsa_hdr->adv_rtr == le->le_lsa->adv_rtr)) 141 return (le); 142 } 143 return (NULL); 144 } 145 146 void 147 ls_req_list_free(struct nbr *nbr, struct lsa_entry *le) 148 { 149 if (nbr->ls_req == le) { 150 nbr->ls_req = TAILQ_NEXT(le, entry); 151 } 152 153 TAILQ_REMOVE(&nbr->ls_req_list, le, entry); 154 free(le->le_lsa); 155 free(le); 156 nbr->ls_req_cnt--; 157 158 /* received all requested LSA(s), send a new LS req */ 159 if (nbr->ls_req != NULL && 160 nbr->ls_req == TAILQ_FIRST(&nbr->ls_req_list)) { 161 start_ls_req_tx_timer(nbr); 162 } 163 164 /* we might not have received all DDs and are still in XCHNG */ 165 if (ls_req_list_empty(nbr) && nbr->dd_pending == 0 && 166 nbr->state != NBR_STA_XCHNG) 167 nbr_fsm(nbr, NBR_EVT_LOAD_DONE); 168 } 169 170 void 171 ls_req_list_clr(struct nbr *nbr) 172 { 173 struct lsa_entry *le; 174 175 while ((le = TAILQ_FIRST(&nbr->ls_req_list)) != NULL) { 176 TAILQ_REMOVE(&nbr->ls_req_list, le, entry); 177 free(le->le_lsa); 178 free(le); 179 } 180 181 nbr->ls_req_cnt = 0; 182 nbr->ls_req = NULL; 183 } 184 185 int 186 ls_req_list_empty(struct nbr *nbr) 187 { 188 return (TAILQ_EMPTY(&nbr->ls_req_list)); 189 } 190 191 /* timers */ 192 /* ARGSUSED */ 193 void 194 ls_req_tx_timer(int fd, short event, void *arg) 195 { 196 struct nbr *nbr = arg; 197 struct timeval tv; 198 199 switch (nbr->state) { 200 case NBR_STA_DOWN: 201 case NBR_STA_ATTEMPT: 202 case NBR_STA_INIT: 203 case NBR_STA_2_WAY: 204 case NBR_STA_SNAP: 205 case NBR_STA_XSTRT: 206 case NBR_STA_XCHNG: 207 return; 208 case NBR_STA_LOAD: 209 send_ls_req(nbr); 210 break; 211 case NBR_STA_FULL: 212 return; 213 default: 214 log_debug("ls_req_tx_timer: unknown neighbor state, " 215 "neighbor ID %s", inet_ntoa(nbr->id)); 216 break; 217 } 218 219 /* reschedule lsreq_tx_timer */ 220 if (nbr->state == NBR_STA_LOAD) { 221 timerclear(&tv); 222 tv.tv_sec = nbr->iface->rxmt_interval; 223 if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1) 224 fatal("ls_req_tx_timer"); 225 } 226 } 227 228 void 229 start_ls_req_tx_timer(struct nbr *nbr) 230 { 231 struct timeval tv; 232 233 if (nbr == nbr->iface->self) 234 return; 235 236 timerclear(&tv); 237 if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1) 238 fatal("start_ls_req_tx_timer"); 239 } 240 241 void 242 stop_ls_req_tx_timer(struct nbr *nbr) 243 { 244 if (nbr == nbr->iface->self) 245 return; 246 247 if (evtimer_del(&nbr->lsreq_tx_timer) == -1) 248 fatal("stop_ls_req_tx_timer"); 249 } 250