1 /* $OpenBSD: message.c,v 1.15 2019/12/15 20:51:39 remi Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> 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 #include <netinet/udp.h> 25 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "ripd.h" 30 #include "rip.h" 31 #include "ripe.h" 32 #include "log.h" 33 34 extern struct ripd_conf *oeconf; 35 36 void delete_entry(struct rip_route *); 37 38 /* timers */ 39 /* ARGSUSED */ 40 void 41 report_timer(int fd, short event, void *arg) 42 { 43 struct timeval tv; 44 45 ripe_imsg_compose_rde(IMSG_FULL_RESPONSE, 0, 0, NULL, 0); 46 47 /* restart report timer */ 48 timerclear(&tv); 49 tv.tv_sec = KEEPALIVE + arc4random_uniform(OFFSET); 50 evtimer_add(&oeconf->report_timer, &tv); 51 } 52 53 int 54 start_report_timer(void) 55 { 56 struct timeval tv; 57 58 timerclear(&tv); 59 tv.tv_sec = KEEPALIVE + arc4random_uniform(OFFSET); 60 return (evtimer_add(&oeconf->report_timer, &tv)); 61 } 62 63 /* list handlers */ 64 void 65 add_entry(struct packet_head *r_list, struct rip_route *rr) 66 { 67 struct packet_entry *re; 68 69 if (rr == NULL) 70 fatalx("add_entry: no route report"); 71 72 if ((re = calloc(1, sizeof(*re))) == NULL) 73 fatal("add_entry"); 74 75 TAILQ_INSERT_TAIL(r_list, re, entry); 76 re->rr = rr; 77 rr->refcount++; 78 } 79 80 void 81 delete_entry(struct rip_route *rr) 82 { 83 if (--rr->refcount == 0) 84 free(rr); 85 } 86 87 void 88 clear_list(struct packet_head *r_list) 89 { 90 struct packet_entry *re; 91 92 while ((re = TAILQ_FIRST(r_list)) != NULL) { 93 TAILQ_REMOVE(r_list, re, entry); 94 delete_entry(re->rr); 95 free(re); 96 } 97 } 98 99 /* communications */ 100 int 101 send_triggered_update(struct iface *iface, struct rip_route *rr) 102 { 103 struct sockaddr_in dst; 104 struct ibuf *buf; 105 u_int16_t afi, route_tag; 106 u_int32_t address, netmask, nexthop, metric; 107 108 if (iface->passive) 109 return (0); 110 111 inet_aton(ALL_RIP_ROUTERS, &dst.sin_addr); 112 113 dst.sin_port = htons(RIP_PORT); 114 dst.sin_family = AF_INET; 115 dst.sin_len = sizeof(struct sockaddr_in); 116 117 if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) - 118 sizeof(struct udphdr))) == NULL) 119 fatal("send_triggered_update"); 120 121 gen_rip_hdr(buf, COMMAND_RESPONSE); 122 123 afi = htons(AF_INET); 124 route_tag = 0; 125 126 address = rr->address.s_addr; 127 netmask = rr->mask.s_addr; 128 nexthop = rr->nexthop.s_addr; 129 metric = htonl(rr->metric); 130 131 ibuf_add(buf, &afi, sizeof(afi)); 132 ibuf_add(buf, &route_tag, sizeof(route_tag)); 133 ibuf_add(buf, &address, sizeof(address)); 134 ibuf_add(buf, &netmask, sizeof(netmask)); 135 ibuf_add(buf, &nexthop, sizeof(nexthop)); 136 ibuf_add(buf, &metric, sizeof(metric)); 137 138 send_packet(iface, buf->buf, buf->wpos, &dst); 139 ibuf_free(buf); 140 141 return (0); 142 } 143 144 int 145 send_request(struct packet_head *r_list, struct iface *i, struct nbr *nbr) 146 { 147 struct ibuf *buf; 148 struct iface *iface; 149 struct packet_entry *entry; 150 struct sockaddr_in dst; 151 u_int8_t nentries; 152 u_int8_t single_entry = 0; 153 u_int32_t address, netmask, nexthop; 154 u_int16_t port, afi, route_tag; 155 u_int32_t metric; 156 157 if (i == NULL) { 158 /* directly to a nbr */ 159 iface = nbr->iface; 160 dst.sin_addr = nbr->addr; 161 port = htons(nbr->port); 162 } else { 163 /* multicast on interface */ 164 iface = i; 165 inet_aton(ALL_RIP_ROUTERS, &dst.sin_addr); 166 port = htons(RIP_PORT); 167 } 168 169 if (iface->passive) { 170 clear_list(r_list); 171 return (0); 172 } 173 174 dst.sin_port = port; 175 dst.sin_family = AF_INET; 176 dst.sin_len = sizeof(struct sockaddr_in); 177 178 while (!TAILQ_EMPTY(r_list)) { 179 if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) - 180 sizeof(struct udphdr))) == NULL) 181 fatal("send_request"); 182 183 gen_rip_hdr(buf, COMMAND_REQUEST); 184 185 route_tag = 0; 186 nentries = 0; 187 188 if (TAILQ_FIRST(r_list) == TAILQ_LAST(r_list, packet_head)) 189 single_entry = 1; 190 while (((entry = TAILQ_FIRST(r_list)) != NULL) && 191 nentries < MAX_RIP_ENTRIES) { 192 afi = htons(AF_INET); 193 194 address = entry->rr->address.s_addr; 195 netmask = entry->rr->mask.s_addr; 196 nexthop = entry->rr->nexthop.s_addr; 197 metric = htonl(entry->rr->metric); 198 199 if (metric == htonl(INFINITY) && single_entry) 200 afi = AF_UNSPEC; 201 202 ibuf_add(buf, &afi, sizeof(afi)); 203 ibuf_add(buf, &route_tag, sizeof(route_tag)); 204 ibuf_add(buf, &address, sizeof(address)); 205 ibuf_add(buf, &netmask, sizeof(netmask)); 206 ibuf_add(buf, &nexthop, sizeof(nexthop)); 207 ibuf_add(buf, &metric, sizeof(metric)); 208 nentries++; 209 210 TAILQ_REMOVE(r_list, entry, entry); 211 delete_entry(entry->rr); 212 free(entry); 213 } 214 send_packet(iface, buf->buf, buf->wpos, &dst); 215 ibuf_free(buf); 216 } 217 218 return (0); 219 } 220 221 int 222 send_response(struct packet_head *r_list, struct iface *i, struct nbr *nbr) 223 { 224 struct ibuf *buf; 225 struct iface *iface; 226 struct packet_entry *entry; 227 struct sockaddr_in dst; 228 u_int8_t nentries; 229 u_int16_t port, afi, route_tag; 230 u_int32_t address, netmask, nexthop; 231 u_int32_t metric; 232 233 if (i == NULL) { 234 /* directly to a nbr */ 235 iface = nbr->iface; 236 dst.sin_addr = nbr->addr; 237 port = htons(nbr->port); 238 } else { 239 /* multicast on interface */ 240 iface = i; 241 inet_aton(ALL_RIP_ROUTERS, &dst.sin_addr); 242 port = htons(RIP_PORT); 243 } 244 245 if (iface->passive) { 246 clear_list(r_list); 247 return (0); 248 } 249 250 dst.sin_port = port; 251 dst.sin_family = AF_INET; 252 dst.sin_len = sizeof(struct sockaddr_in); 253 254 while (!TAILQ_EMPTY(r_list)) { 255 if ((buf = ibuf_open(iface->mtu - sizeof(struct ip) - 256 sizeof(struct udphdr))) == NULL) 257 fatal("send_response"); 258 259 gen_rip_hdr(buf, COMMAND_RESPONSE); 260 261 afi = htons(AF_INET); 262 route_tag = 0; 263 nentries = 0; 264 265 if (iface->auth_type != AUTH_NONE) { 266 if (auth_gen(buf, iface) == -1) { 267 ibuf_free(buf); 268 return (-1); 269 } 270 nentries++; 271 } 272 273 while ((entry = TAILQ_FIRST(r_list)) != NULL && 274 nentries < MAX_RIP_ENTRIES) { 275 address = entry->rr->address.s_addr; 276 netmask = entry->rr->mask.s_addr; 277 nexthop = entry->rr->nexthop.s_addr; 278 metric = htonl(entry->rr->metric); 279 280 if (entry->rr->ifindex == iface->ifindex) { 281 if (oeconf->options & OPT_SPLIT_HORIZON) 282 goto free; 283 else if (oeconf->options & OPT_SPLIT_POISONED) 284 metric = htonl(INFINITY); 285 } 286 287 /* If the nexthop is not reachable through the 288 * outgoing interface set it to INADDR_ANY */ 289 if ((nexthop & iface->mask.s_addr) != 290 (iface->addr.s_addr & iface->mask.s_addr)) 291 nexthop = INADDR_ANY; 292 293 ibuf_add(buf, &afi, sizeof(afi)); 294 ibuf_add(buf, &route_tag, sizeof(route_tag)); 295 ibuf_add(buf, &address, sizeof(address)); 296 ibuf_add(buf, &netmask, sizeof(netmask)); 297 ibuf_add(buf, &nexthop, sizeof(nexthop)); 298 ibuf_add(buf, &metric, sizeof(metric)); 299 nentries++; 300 free: 301 TAILQ_REMOVE(r_list, entry, entry); 302 delete_entry(entry->rr); 303 free(entry); 304 } 305 306 if (iface->auth_type == AUTH_CRYPT) 307 auth_add_trailer(buf, iface); 308 309 send_packet(iface, buf->buf, buf->wpos, &dst); 310 ibuf_free(buf); 311 } 312 313 return (0); 314 } 315 316 void 317 recv_request(struct iface *i, struct nbr *nbr, u_int8_t *buf, u_int16_t len) 318 { 319 struct rip_entry *e; 320 struct rip_route rr; 321 int l = len; 322 323 bzero(&rr, sizeof(rr)); 324 325 if (len < RIP_ENTRY_LEN) { 326 log_debug("recv_request: bad packet size, interface %s", 327 i->name); 328 return; 329 } 330 331 /* 332 * XXX is it guaranteed that bus is properly aligned. 333 * If not this will bomb on strict alignment archs. 334 * */ 335 e = (struct rip_entry *)buf; 336 337 if (len > RIP_ENTRY_LEN * MAX_RIP_ENTRIES) { 338 log_debug("recv_request: packet too long\n"); 339 return; 340 } 341 342 l -= RIP_ENTRY_LEN; 343 344 /* 345 * If there is exactly one entry in the request, and it has 346 * an address family identifier of zero and a metric of 347 * infinity (i.e., 16), then this is a request to send the 348 * entire routing table. 349 */ 350 if (e->AFI == 0 && e->metric == ntohl(INFINITY) && l == 0) { 351 ripe_imsg_compose_rde(IMSG_FULL_RESPONSE, nbr->peerid, 352 0, NULL, 0); 353 return; 354 } 355 356 for ( ; l >= 0; l -= RIP_ENTRY_LEN) { 357 if (e->AFI != AF_INET) { 358 log_debug("recv_request: AFI %d not supported\n", 359 e->AFI); 360 return; 361 } 362 rr.address.s_addr = e->address; 363 rr.mask.s_addr = e->mask; 364 rr.nexthop.s_addr = e->nexthop; 365 rr.metric = e->metric; 366 rr.ifindex = i->ifindex; 367 368 ripe_imsg_compose_rde(IMSG_ROUTE_REQUEST, nbr->peerid, 369 0, &rr, sizeof(rr)); 370 371 e++; 372 } 373 374 ripe_imsg_compose_rde(IMSG_ROUTE_REQUEST_END, nbr->peerid, 375 0, NULL, 0); 376 } 377 378 void 379 recv_response(struct iface *i, struct nbr *nbr, u_int8_t *buf, u_int16_t len) 380 { 381 struct rip_route r; 382 struct rip_entry *e; 383 int l; 384 385 if (len < RIP_ENTRY_LEN) { 386 log_debug("recv_response: bad packet size, interface %s", 387 i->name); 388 return; 389 } 390 391 /* We must double check the length, because the only entry 392 * can be stripped off by authentication code 393 */ 394 if (len < RIP_ENTRY_LEN) { 395 /* If there are no entries, our work is finished here */ 396 return; 397 } 398 399 /* XXX again */ 400 e = (struct rip_entry *)buf; 401 402 if (len > RIP_ENTRY_LEN * MAX_RIP_ENTRIES) { 403 log_debug("recv_response: packet too long\n"); 404 return; 405 } 406 407 l = len - sizeof(*e); 408 409 for ( ; l >= 0; l -= RIP_ENTRY_LEN) { 410 if (ntohs(e->AFI) != AF_INET) { 411 log_debug("recv_response: AFI %d not supported\n", 412 e->AFI); 413 return; 414 } 415 416 r.address.s_addr = e->address; 417 r.mask.s_addr = e->mask; 418 419 if (e->nexthop == INADDR_ANY || 420 ((i->addr.s_addr & i->mask.s_addr) != 421 (e->nexthop & i->mask.s_addr))) 422 r.nexthop.s_addr = nbr->addr.s_addr; 423 else 424 r.nexthop.s_addr = e->nexthop; 425 426 r.metric = ntohl(e->metric); 427 r.ifindex = i->ifindex; 428 429 ripe_imsg_compose_rde(IMSG_ROUTE_FEED, 0, 0, &r, sizeof(r)); 430 431 e++; 432 } 433 } 434