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