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