1 /* $OpenBSD: interface.c,v 1.52 2023/03/08 04:43:13 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> 5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/time.h> 23 #include <arpa/inet.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 #include "ldpd.h" 28 #include "ldpe.h" 29 #include "log.h" 30 31 static struct if_addr *if_addr_new(struct kaddr *); 32 static struct if_addr *if_addr_lookup(struct if_addr_head *, struct kaddr *); 33 static int if_start(struct iface *, int); 34 static int if_reset(struct iface *, int); 35 static void if_update_af(struct iface_af *, int); 36 static void if_hello_timer(int, short, void *); 37 static void if_start_hello_timer(struct iface_af *); 38 static void if_stop_hello_timer(struct iface_af *); 39 static int if_join_ipv4_group(struct iface *, struct in_addr *); 40 static int if_leave_ipv4_group(struct iface *, struct in_addr *); 41 static int if_join_ipv6_group(struct iface *, struct in6_addr *); 42 static int if_leave_ipv6_group(struct iface *, struct in6_addr *); 43 44 struct iface * 45 if_new(struct kif *kif) 46 { 47 struct iface *iface; 48 49 if ((iface = calloc(1, sizeof(*iface))) == NULL) 50 fatal("if_new: calloc"); 51 52 strlcpy(iface->name, kif->ifname, sizeof(iface->name)); 53 54 /* get type */ 55 if (kif->flags & IFF_POINTOPOINT) 56 iface->type = IF_TYPE_POINTOPOINT; 57 if (kif->flags & IFF_BROADCAST && 58 kif->flags & IFF_MULTICAST) 59 iface->type = IF_TYPE_BROADCAST; 60 61 /* get index and flags */ 62 LIST_INIT(&iface->addr_list); 63 iface->ifindex = kif->ifindex; 64 iface->rdomain = kif->rdomain; 65 iface->flags = kif->flags; 66 iface->linkstate = kif->link_state; 67 iface->if_type = kif->if_type; 68 69 /* ipv4 */ 70 iface->ipv4.af = AF_INET; 71 iface->ipv4.iface = iface; 72 iface->ipv4.enabled = 0; 73 iface->ipv4.state = IF_STA_DOWN; 74 LIST_INIT(&iface->ipv4.adj_list); 75 76 /* ipv6 */ 77 iface->ipv6.af = AF_INET6; 78 iface->ipv6.iface = iface; 79 iface->ipv6.enabled = 0; 80 iface->ipv6.state = IF_STA_DOWN; 81 LIST_INIT(&iface->ipv6.adj_list); 82 83 return (iface); 84 } 85 86 void 87 if_exit(struct iface *iface) 88 { 89 struct if_addr *if_addr; 90 91 log_debug("%s: interface %s", __func__, iface->name); 92 93 if (iface->ipv4.state == IF_STA_ACTIVE) 94 if_reset(iface, AF_INET); 95 if (iface->ipv6.state == IF_STA_ACTIVE) 96 if_reset(iface, AF_INET6); 97 98 while ((if_addr = LIST_FIRST(&iface->addr_list)) != NULL) { 99 LIST_REMOVE(if_addr, entry); 100 free(if_addr); 101 } 102 } 103 104 struct iface * 105 if_lookup(struct ldpd_conf *xconf, unsigned short ifindex) 106 { 107 struct iface *iface; 108 109 LIST_FOREACH(iface, &xconf->iface_list, entry) 110 if (iface->ifindex == ifindex) 111 return (iface); 112 113 return (NULL); 114 } 115 116 struct iface_af * 117 iface_af_get(struct iface *iface, int af) 118 { 119 switch (af) { 120 case AF_INET: 121 return (&iface->ipv4); 122 case AF_INET6: 123 return (&iface->ipv6); 124 default: 125 fatalx("iface_af_get: unknown af"); 126 } 127 } 128 129 static struct if_addr * 130 if_addr_new(struct kaddr *ka) 131 { 132 struct if_addr *if_addr; 133 134 if ((if_addr = calloc(1, sizeof(*if_addr))) == NULL) 135 fatal(__func__); 136 137 if_addr->af = ka->af; 138 if_addr->addr = ka->addr; 139 if_addr->prefixlen = ka->prefixlen; 140 if_addr->dstbrd = ka->dstbrd; 141 142 return (if_addr); 143 } 144 145 static struct if_addr * 146 if_addr_lookup(struct if_addr_head *addr_list, struct kaddr *ka) 147 { 148 struct if_addr *if_addr; 149 int af = ka->af; 150 151 LIST_FOREACH(if_addr, addr_list, entry) 152 if (!ldp_addrcmp(af, &if_addr->addr, &ka->addr) && 153 if_addr->prefixlen == ka->prefixlen && 154 !ldp_addrcmp(af, &if_addr->dstbrd, &ka->dstbrd)) 155 return (if_addr); 156 157 return (NULL); 158 } 159 160 void 161 if_addr_add(struct kaddr *ka) 162 { 163 struct iface *iface; 164 struct if_addr *if_addr; 165 struct nbr *nbr; 166 167 if (if_addr_lookup(&global.addr_list, ka) == NULL) { 168 if_addr = if_addr_new(ka); 169 170 LIST_INSERT_HEAD(&global.addr_list, if_addr, entry); 171 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 172 if (nbr->state != NBR_STA_OPER) 173 continue; 174 if (if_addr->af == AF_INET && !nbr->v4_enabled) 175 continue; 176 if (if_addr->af == AF_INET6 && !nbr->v6_enabled) 177 continue; 178 179 send_address_single(nbr, if_addr, 0); 180 } 181 } 182 183 iface = if_lookup(leconf, ka->ifindex); 184 if (iface) { 185 if (ka->af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&ka->addr.v6)) 186 iface->linklocal = ka->addr.v6; 187 188 if (if_addr_lookup(&iface->addr_list, ka) == NULL) { 189 if_addr = if_addr_new(ka); 190 LIST_INSERT_HEAD(&iface->addr_list, if_addr, entry); 191 if_update(iface, if_addr->af); 192 } 193 } 194 } 195 196 void 197 if_addr_del(struct kaddr *ka) 198 { 199 struct iface *iface; 200 struct if_addr *if_addr; 201 struct nbr *nbr; 202 203 iface = if_lookup(leconf, ka->ifindex); 204 if (iface) { 205 if (ka->af == AF_INET6 && 206 IN6_ARE_ADDR_EQUAL(&iface->linklocal, &ka->addr.v6)) 207 memset(&iface->linklocal, 0, sizeof(iface->linklocal)); 208 209 if_addr = if_addr_lookup(&iface->addr_list, ka); 210 if (if_addr) { 211 LIST_REMOVE(if_addr, entry); 212 if_update(iface, if_addr->af); 213 free(if_addr); 214 } 215 } 216 217 if_addr = if_addr_lookup(&global.addr_list, ka); 218 if (if_addr) { 219 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { 220 if (nbr->state != NBR_STA_OPER) 221 continue; 222 if (if_addr->af == AF_INET && !nbr->v4_enabled) 223 continue; 224 if (if_addr->af == AF_INET6 && !nbr->v6_enabled) 225 continue; 226 send_address_single(nbr, if_addr, 1); 227 } 228 LIST_REMOVE(if_addr, entry); 229 free(if_addr); 230 } 231 } 232 233 static int 234 if_start(struct iface *iface, int af) 235 { 236 struct iface_af *ia; 237 struct timeval now; 238 239 log_debug("%s: %s address-family %s", __func__, iface->name, 240 af_name(af)); 241 242 ia = iface_af_get(iface, af); 243 244 gettimeofday(&now, NULL); 245 ia->uptime = now.tv_sec; 246 247 switch (af) { 248 case AF_INET: 249 if (if_join_ipv4_group(iface, &global.mcast_addr_v4)) 250 return (-1); 251 break; 252 case AF_INET6: 253 if (if_join_ipv6_group(iface, &global.mcast_addr_v6)) 254 return (-1); 255 break; 256 default: 257 fatalx("if_start: unknown af"); 258 } 259 260 send_hello(HELLO_LINK, ia, NULL); 261 262 evtimer_set(&ia->hello_timer, if_hello_timer, ia); 263 if_start_hello_timer(ia); 264 return (0); 265 } 266 267 static int 268 if_reset(struct iface *iface, int af) 269 { 270 struct iface_af *ia; 271 struct adj *adj; 272 273 log_debug("%s: %s address-family %s", __func__, iface->name, 274 af_name(af)); 275 276 ia = iface_af_get(iface, af); 277 if_stop_hello_timer(ia); 278 279 while ((adj = LIST_FIRST(&ia->adj_list)) != NULL) 280 adj_del(adj, S_SHUTDOWN); 281 282 /* try to cleanup */ 283 switch (af) { 284 case AF_INET: 285 if (global.ipv4.ldp_disc_socket != -1) 286 if_leave_ipv4_group(iface, &global.mcast_addr_v4); 287 break; 288 case AF_INET6: 289 if (global.ipv6.ldp_disc_socket != -1) 290 if_leave_ipv6_group(iface, &global.mcast_addr_v6); 291 break; 292 default: 293 fatalx("if_start: unknown af"); 294 } 295 296 return (0); 297 } 298 299 static void 300 if_update_af(struct iface_af *ia, int link_ok) 301 { 302 int addr_ok = 0, socket_ok, rtr_id_ok; 303 struct if_addr *if_addr; 304 305 switch (ia->af) { 306 case AF_INET: 307 /* 308 * NOTE: for LDPv4, each interface should have at least one 309 * valid IP address otherwise they can not be enabled. 310 */ 311 LIST_FOREACH(if_addr, &ia->iface->addr_list, entry) { 312 if (if_addr->af == AF_INET) { 313 addr_ok = 1; 314 break; 315 } 316 } 317 break; 318 case AF_INET6: 319 /* for IPv6 the link-local address is enough. */ 320 if (IN6_IS_ADDR_LINKLOCAL(&ia->iface->linklocal)) 321 addr_ok = 1; 322 break; 323 default: 324 fatalx("if_update_af: unknown af"); 325 } 326 327 if ((ldp_af_global_get(&global, ia->af))->ldp_disc_socket != -1) 328 socket_ok = 1; 329 else 330 socket_ok = 0; 331 332 if (leconf->rtr_id.s_addr != INADDR_ANY) 333 rtr_id_ok = 1; 334 else 335 rtr_id_ok = 0; 336 337 if (ia->state == IF_STA_DOWN) { 338 if (!ia->enabled || !link_ok || !addr_ok || !socket_ok || 339 !rtr_id_ok) 340 return; 341 342 ia->state = IF_STA_ACTIVE; 343 if_start(ia->iface, ia->af); 344 } else if (ia->state == IF_STA_ACTIVE) { 345 if (ia->enabled && link_ok && addr_ok && socket_ok && rtr_id_ok) 346 return; 347 348 ia->state = IF_STA_DOWN; 349 if_reset(ia->iface, ia->af); 350 } 351 } 352 353 void 354 if_update(struct iface *iface, int af) 355 { 356 int link_ok; 357 358 link_ok = (iface->flags & IFF_UP) && 359 LINK_STATE_IS_UP(iface->linkstate); 360 361 if (af == AF_INET || af == AF_UNSPEC) 362 if_update_af(&iface->ipv4, link_ok); 363 if (af == AF_INET6 || af == AF_UNSPEC) 364 if_update_af(&iface->ipv6, link_ok); 365 } 366 367 void 368 if_update_all(int af) 369 { 370 struct iface *iface; 371 372 LIST_FOREACH(iface, &leconf->iface_list, entry) 373 if_update(iface, af); 374 } 375 376 /* timers */ 377 static void 378 if_hello_timer(int fd, short event, void *arg) 379 { 380 struct iface_af *ia = arg; 381 382 send_hello(HELLO_LINK, ia, NULL); 383 if_start_hello_timer(ia); 384 } 385 386 static void 387 if_start_hello_timer(struct iface_af *ia) 388 { 389 struct timeval tv; 390 391 timerclear(&tv); 392 tv.tv_sec = ia->hello_interval; 393 if (evtimer_add(&ia->hello_timer, &tv) == -1) 394 fatal(__func__); 395 } 396 397 static void 398 if_stop_hello_timer(struct iface_af *ia) 399 { 400 if (evtimer_pending(&ia->hello_timer, NULL) && 401 evtimer_del(&ia->hello_timer) == -1) 402 fatal(__func__); 403 } 404 405 struct ctl_iface * 406 if_to_ctl(struct iface_af *ia) 407 { 408 static struct ctl_iface ictl; 409 struct timeval now; 410 struct adj *adj; 411 412 ictl.af = ia->af; 413 memcpy(ictl.name, ia->iface->name, sizeof(ictl.name)); 414 ictl.ifindex = ia->iface->ifindex; 415 ictl.state = ia->state; 416 ictl.flags = ia->iface->flags; 417 ictl.linkstate = ia->iface->linkstate; 418 ictl.type = ia->iface->type; 419 ictl.if_type = ia->iface->if_type; 420 ictl.hello_holdtime = ia->hello_holdtime; 421 ictl.hello_interval = ia->hello_interval; 422 423 gettimeofday(&now, NULL); 424 if (ia->state != IF_STA_DOWN && 425 ia->uptime != 0) { 426 ictl.uptime = now.tv_sec - ia->uptime; 427 } else 428 ictl.uptime = 0; 429 430 ictl.adj_cnt = 0; 431 LIST_FOREACH(adj, &ia->adj_list, ia_entry) 432 ictl.adj_cnt++; 433 434 return (&ictl); 435 } 436 437 /* multicast membership sockopts */ 438 in_addr_t 439 if_get_ipv4_addr(struct iface *iface) 440 { 441 struct if_addr *if_addr; 442 443 LIST_FOREACH(if_addr, &iface->addr_list, entry) 444 if (if_addr->af == AF_INET) 445 return (if_addr->addr.v4.s_addr); 446 447 return (INADDR_ANY); 448 } 449 450 static int 451 if_join_ipv4_group(struct iface *iface, struct in_addr *addr) 452 { 453 struct ip_mreq mreq; 454 455 log_debug("%s: interface %s addr %s", __func__, iface->name, 456 inet_ntoa(*addr)); 457 458 mreq.imr_multiaddr = *addr; 459 mreq.imr_interface.s_addr = if_get_ipv4_addr(iface); 460 461 if (setsockopt(global.ipv4.ldp_disc_socket, IPPROTO_IP, 462 IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) == -1) { 463 log_warn("%s: error IP_ADD_MEMBERSHIP, interface %s address %s", 464 __func__, iface->name, inet_ntoa(*addr)); 465 return (-1); 466 } 467 return (0); 468 } 469 470 static int 471 if_leave_ipv4_group(struct iface *iface, struct in_addr *addr) 472 { 473 struct ip_mreq mreq; 474 475 log_debug("%s: interface %s addr %s", __func__, iface->name, 476 inet_ntoa(*addr)); 477 478 mreq.imr_multiaddr = *addr; 479 mreq.imr_interface.s_addr = if_get_ipv4_addr(iface); 480 481 if (setsockopt(global.ipv4.ldp_disc_socket, IPPROTO_IP, 482 IP_DROP_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) == -1) { 483 log_warn("%s: error IP_DROP_MEMBERSHIP, interface %s " 484 "address %s", __func__, iface->name, inet_ntoa(*addr)); 485 return (-1); 486 } 487 488 return (0); 489 } 490 491 static int 492 if_join_ipv6_group(struct iface *iface, struct in6_addr *addr) 493 { 494 struct ipv6_mreq mreq; 495 496 log_debug("%s: interface %s addr %s", __func__, iface->name, 497 log_in6addr(addr)); 498 499 mreq.ipv6mr_multiaddr = *addr; 500 mreq.ipv6mr_interface = iface->ifindex; 501 502 if (setsockopt(global.ipv6.ldp_disc_socket, IPPROTO_IPV6, 503 IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1) { 504 log_warn("%s: error IPV6_JOIN_GROUP, interface %s address %s", 505 __func__, iface->name, log_in6addr(addr)); 506 return (-1); 507 } 508 509 return (0); 510 } 511 512 static int 513 if_leave_ipv6_group(struct iface *iface, struct in6_addr *addr) 514 { 515 struct ipv6_mreq mreq; 516 517 log_debug("%s: interface %s addr %s", __func__, iface->name, 518 log_in6addr(addr)); 519 520 mreq.ipv6mr_multiaddr = *addr; 521 mreq.ipv6mr_interface = iface->ifindex; 522 523 if (setsockopt(global.ipv6.ldp_disc_socket, IPPROTO_IPV6, 524 IPV6_LEAVE_GROUP, (void *)&mreq, sizeof(mreq)) == -1) { 525 log_warn("%s: error IPV6_LEAVE_GROUP, interface %s address %s", 526 __func__, iface->name, log_in6addr(addr)); 527 return (-1); 528 } 529 530 return (0); 531 } 532