1 /* $OpenBSD: lsack.c,v 1.18 2009/01/31 08:55:00 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 <netinet/in_systm.h> 23 #include <netinet/ip.h> 24 #include <arpa/inet.h> 25 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "ospfd.h" 30 #include "ospf.h" 31 #include "log.h" 32 #include "ospfe.h" 33 34 void start_ls_ack_tx_timer_now(struct iface *); 35 36 /* link state acknowledgement packet handling */ 37 int 38 send_ls_ack(struct iface *iface, struct in_addr addr, void *data, size_t len) 39 { 40 struct sockaddr_in dst; 41 struct buf *buf; 42 int ret; 43 44 /* XXX READ_BUF_SIZE */ 45 if ((buf = buf_dynamic(PKG_DEF_SIZE, READ_BUF_SIZE)) == NULL) 46 fatal("send_ls_ack"); 47 48 dst.sin_family = AF_INET; 49 dst.sin_len = sizeof(struct sockaddr_in); 50 dst.sin_addr.s_addr = addr.s_addr; 51 52 /* OSPF header */ 53 if (gen_ospf_hdr(buf, iface, PACKET_TYPE_LS_ACK)) 54 goto fail; 55 56 /* LS ack(s) */ 57 if (buf_add(buf, data, len)) 58 goto fail; 59 60 /* update authentication and calculate checksum */ 61 if (auth_gen(buf, iface)) 62 goto fail; 63 64 ret = send_packet(iface, buf, &dst); 65 66 buf_free(buf); 67 return (ret); 68 fail: 69 log_warn("send_ls_ack"); 70 buf_free(buf); 71 return (-1); 72 } 73 74 void 75 recv_ls_ack(struct nbr *nbr, char *buf, u_int16_t len) 76 { 77 struct lsa_hdr lsa_hdr; 78 79 switch (nbr->state) { 80 case NBR_STA_DOWN: 81 case NBR_STA_ATTEMPT: 82 case NBR_STA_INIT: 83 case NBR_STA_2_WAY: 84 case NBR_STA_XSTRT: 85 case NBR_STA_SNAP: 86 log_debug("recv_ls_ack: packet ignored in state %s, " 87 "neighbor ID %s", nbr_state_name(nbr->state), 88 inet_ntoa(nbr->id)); 89 break; 90 case NBR_STA_XCHNG: 91 case NBR_STA_LOAD: 92 case NBR_STA_FULL: 93 while (len >= sizeof(lsa_hdr)) { 94 memcpy(&lsa_hdr, buf, sizeof(lsa_hdr)); 95 96 if (lsa_hdr_check(nbr, &lsa_hdr)) { 97 /* try both list in case of DROTHER */ 98 if (nbr->iface->state & IF_STA_DROTHER) 99 (void)ls_retrans_list_del( 100 nbr->iface->self, &lsa_hdr); 101 (void)ls_retrans_list_del(nbr, &lsa_hdr); 102 } 103 104 buf += sizeof(lsa_hdr); 105 len -= sizeof(lsa_hdr); 106 } 107 if (len > 0) { 108 log_warnx("recv_ls_ack: bad packet size, " 109 "neighbor ID %s", inet_ntoa(nbr->id)); 110 return; 111 } 112 break; 113 default: 114 fatalx("recv_ls_ack: unknown neighbor state"); 115 } 116 } 117 118 int 119 lsa_hdr_check(struct nbr *nbr, struct lsa_hdr *lsa_hdr) 120 { 121 /* invalid age */ 122 if ((ntohs(lsa_hdr->age) < 1) || (ntohs(lsa_hdr->age) > MAX_AGE)) { 123 log_debug("lsa_hdr_check: invalid age, neighbor ID %s", 124 inet_ntoa(nbr->id)); 125 return (0); 126 } 127 128 /* invalid type */ 129 switch (lsa_hdr->type) { 130 case LSA_TYPE_ROUTER: 131 case LSA_TYPE_NETWORK: 132 case LSA_TYPE_SUM_NETWORK: 133 case LSA_TYPE_SUM_ROUTER: 134 case LSA_TYPE_EXTERNAL: 135 break; 136 default: 137 log_debug("lsa_hdr_check: invalid LSA type %d, neighbor ID %s", 138 lsa_hdr->type, inet_ntoa(nbr->id)); 139 return (0); 140 } 141 142 /* invalid sequence number */ 143 if (ntohl(lsa_hdr->seq_num) == RESV_SEQ_NUM) { 144 log_debug("ls_hdr_check: invalid seq num, neighbor ID %s", 145 inet_ntoa(nbr->id)); 146 return (0); 147 } 148 149 return (1); 150 } 151 152 /* link state ack list */ 153 void 154 ls_ack_list_add(struct iface *iface, struct lsa_hdr *lsa) 155 { 156 struct lsa_entry *le; 157 158 if (lsa == NULL) 159 fatalx("ls_ack_list_add: no LSA header"); 160 161 if ((le = calloc(1, sizeof(*le))) == NULL) 162 fatal("ls_ack_list_add"); 163 164 if (ls_ack_list_empty(iface)) 165 start_ls_ack_tx_timer(iface); 166 167 TAILQ_INSERT_TAIL(&iface->ls_ack_list, le, entry); 168 le->le_lsa = lsa; 169 iface->ls_ack_cnt++; 170 171 /* reschedule now if we have enough for a full packet */ 172 if (iface->ls_ack_cnt > 173 ((iface->mtu - PACKET_HDR) / sizeof(struct lsa_hdr))) { 174 start_ls_ack_tx_timer_now(iface); 175 } 176 177 } 178 179 void 180 ls_ack_list_free(struct iface *iface, struct lsa_entry *le) 181 { 182 TAILQ_REMOVE(&iface->ls_ack_list, le, entry); 183 free(le->le_lsa); 184 free(le); 185 186 iface->ls_ack_cnt--; 187 } 188 189 void 190 ls_ack_list_clr(struct iface *iface) 191 { 192 struct lsa_entry *le; 193 194 while ((le = TAILQ_FIRST(&iface->ls_ack_list)) != NULL) { 195 TAILQ_REMOVE(&iface->ls_ack_list, le, entry); 196 free(le->le_lsa); 197 free(le); 198 } 199 iface->ls_ack_cnt = 0; 200 } 201 202 int 203 ls_ack_list_empty(struct iface *iface) 204 { 205 return (TAILQ_EMPTY(&iface->ls_ack_list)); 206 } 207 208 /* timers */ 209 /* ARGSUSED */ 210 void 211 ls_ack_tx_timer(int fd, short event, void *arg) 212 { 213 struct in_addr addr; 214 struct iface *iface = arg; 215 struct lsa_hdr *lsa_hdr; 216 struct lsa_entry *le, *nle; 217 struct nbr *nbr; 218 char *buf; 219 char *ptr; 220 int cnt = 0; 221 222 if ((buf = calloc(1, READ_BUF_SIZE)) == NULL) 223 fatal("ls_ack_tx_timer"); 224 225 while (!ls_ack_list_empty(iface)) { 226 ptr = buf; 227 cnt = 0; 228 for (le = TAILQ_FIRST(&iface->ls_ack_list); le != NULL && 229 (ptr - buf < iface->mtu - PACKET_HDR); le = nle) { 230 nle = TAILQ_NEXT(le, entry); 231 memcpy(ptr, le->le_lsa, sizeof(struct lsa_hdr)); 232 ptr += sizeof(*lsa_hdr); 233 ls_ack_list_free(iface, le); 234 cnt++; 235 } 236 237 /* send LS ack(s) but first set correct destination */ 238 switch (iface->type) { 239 case IF_TYPE_POINTOPOINT: 240 inet_aton(AllSPFRouters, &addr); 241 send_ls_ack(iface, addr, buf, ptr - buf); 242 break; 243 case IF_TYPE_BROADCAST: 244 if (iface->state & IF_STA_DRORBDR) 245 inet_aton(AllSPFRouters, &addr); 246 else 247 inet_aton(AllDRouters, &addr); 248 send_ls_ack(iface, addr, buf, ptr - buf); 249 break; 250 case IF_TYPE_NBMA: 251 case IF_TYPE_POINTOMULTIPOINT: 252 case IF_TYPE_VIRTUALLINK: 253 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 254 if (nbr == iface->self) 255 continue; 256 if (!(nbr->state & NBR_STA_FLOOD)) 257 continue; 258 send_ls_ack(iface, nbr->addr, buf, ptr - buf); 259 } 260 break; 261 default: 262 fatalx("lsa_ack_tx_timer: unknown interface type"); 263 } 264 } 265 266 free(buf); 267 } 268 269 void 270 start_ls_ack_tx_timer(struct iface *iface) 271 { 272 struct timeval tv; 273 274 timerclear(&tv); 275 tv.tv_sec = iface->rxmt_interval / 2; 276 277 if (evtimer_add(&iface->lsack_tx_timer, &tv) == -1) 278 fatal("start_ls_ack_tx_timer"); 279 } 280 281 void 282 start_ls_ack_tx_timer_now(struct iface *iface) 283 { 284 struct timeval tv; 285 286 timerclear(&tv); 287 if (evtimer_add(&iface->lsack_tx_timer, &tv) == -1) 288 fatal("start_ls_ack_tx_timer_now"); 289 } 290 291 void 292 stop_ls_ack_tx_timer(struct iface *iface) 293 { 294 if (evtimer_del(&iface->lsack_tx_timer) == -1) 295 fatal("stop_ls_ack_tx_timer"); 296 } 297