1 /* $OpenBSD: interface.c,v 1.51 2019/06/28 13:32:48 deraadt 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 /* ARGSUSED */ 378 static void 379 if_hello_timer(int fd, short event, void *arg) 380 { 381 struct iface_af *ia = arg; 382 383 send_hello(HELLO_LINK, ia, NULL); 384 if_start_hello_timer(ia); 385 } 386 387 static void 388 if_start_hello_timer(struct iface_af *ia) 389 { 390 struct timeval tv; 391 392 timerclear(&tv); 393 tv.tv_sec = ia->hello_interval; 394 if (evtimer_add(&ia->hello_timer, &tv) == -1) 395 fatal(__func__); 396 } 397 398 static void 399 if_stop_hello_timer(struct iface_af *ia) 400 { 401 if (evtimer_pending(&ia->hello_timer, NULL) && 402 evtimer_del(&ia->hello_timer) == -1) 403 fatal(__func__); 404 } 405 406 struct ctl_iface * 407 if_to_ctl(struct iface_af *ia) 408 { 409 static struct ctl_iface ictl; 410 struct timeval now; 411 struct adj *adj; 412 413 ictl.af = ia->af; 414 memcpy(ictl.name, ia->iface->name, sizeof(ictl.name)); 415 ictl.ifindex = ia->iface->ifindex; 416 ictl.state = ia->state; 417 ictl.flags = ia->iface->flags; 418 ictl.linkstate = ia->iface->linkstate; 419 ictl.type = ia->iface->type; 420 ictl.if_type = ia->iface->if_type; 421 ictl.hello_holdtime = ia->hello_holdtime; 422 ictl.hello_interval = ia->hello_interval; 423 424 gettimeofday(&now, NULL); 425 if (ia->state != IF_STA_DOWN && 426 ia->uptime != 0) { 427 ictl.uptime = now.tv_sec - ia->uptime; 428 } else 429 ictl.uptime = 0; 430 431 ictl.adj_cnt = 0; 432 LIST_FOREACH(adj, &ia->adj_list, ia_entry) 433 ictl.adj_cnt++; 434 435 return (&ictl); 436 } 437 438 /* multicast membership sockopts */ 439 in_addr_t 440 if_get_ipv4_addr(struct iface *iface) 441 { 442 struct if_addr *if_addr; 443 444 LIST_FOREACH(if_addr, &iface->addr_list, entry) 445 if (if_addr->af == AF_INET) 446 return (if_addr->addr.v4.s_addr); 447 448 return (INADDR_ANY); 449 } 450 451 static int 452 if_join_ipv4_group(struct iface *iface, struct in_addr *addr) 453 { 454 struct ip_mreq mreq; 455 456 log_debug("%s: interface %s addr %s", __func__, iface->name, 457 inet_ntoa(*addr)); 458 459 mreq.imr_multiaddr = *addr; 460 mreq.imr_interface.s_addr = if_get_ipv4_addr(iface); 461 462 if (setsockopt(global.ipv4.ldp_disc_socket, IPPROTO_IP, 463 IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) == -1) { 464 log_warn("%s: error IP_ADD_MEMBERSHIP, interface %s address %s", 465 __func__, iface->name, inet_ntoa(*addr)); 466 return (-1); 467 } 468 return (0); 469 } 470 471 static int 472 if_leave_ipv4_group(struct iface *iface, struct in_addr *addr) 473 { 474 struct ip_mreq mreq; 475 476 log_debug("%s: interface %s addr %s", __func__, iface->name, 477 inet_ntoa(*addr)); 478 479 mreq.imr_multiaddr = *addr; 480 mreq.imr_interface.s_addr = if_get_ipv4_addr(iface); 481 482 if (setsockopt(global.ipv4.ldp_disc_socket, IPPROTO_IP, 483 IP_DROP_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) == -1) { 484 log_warn("%s: error IP_DROP_MEMBERSHIP, interface %s " 485 "address %s", __func__, iface->name, inet_ntoa(*addr)); 486 return (-1); 487 } 488 489 return (0); 490 } 491 492 static int 493 if_join_ipv6_group(struct iface *iface, struct in6_addr *addr) 494 { 495 struct ipv6_mreq mreq; 496 497 log_debug("%s: interface %s addr %s", __func__, iface->name, 498 log_in6addr(addr)); 499 500 mreq.ipv6mr_multiaddr = *addr; 501 mreq.ipv6mr_interface = iface->ifindex; 502 503 if (setsockopt(global.ipv6.ldp_disc_socket, IPPROTO_IPV6, 504 IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1) { 505 log_warn("%s: error IPV6_JOIN_GROUP, interface %s address %s", 506 __func__, iface->name, log_in6addr(addr)); 507 return (-1); 508 } 509 510 return (0); 511 } 512 513 static int 514 if_leave_ipv6_group(struct iface *iface, struct in6_addr *addr) 515 { 516 struct ipv6_mreq mreq; 517 518 log_debug("%s: interface %s addr %s", __func__, iface->name, 519 log_in6addr(addr)); 520 521 mreq.ipv6mr_multiaddr = *addr; 522 mreq.ipv6mr_interface = iface->ifindex; 523 524 if (setsockopt(global.ipv6.ldp_disc_socket, IPPROTO_IPV6, 525 IPV6_LEAVE_GROUP, (void *)&mreq, sizeof(mreq)) == -1) { 526 log_warn("%s: error IPV6_LEAVE_GROUP, interface %s address %s", 527 __func__, iface->name, log_in6addr(addr)); 528 return (-1); 529 } 530 531 return (0); 532 } 533