Home | History | Annotate | Line # | Download | only in src
      1 /* SPDX-License-Identifier: BSD-2-Clause */
      2 /*
      3  * dhcpcd - DHCP client daemon
      4  * Copyright (c) 2006-2025 Roy Marples <roy (at) marples.name>
      5  * All rights reserved
      6 
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <arpa/inet.h>
     30 
     31 #include <assert.h>
     32 #include <errno.h>
     33 #include <stdbool.h>
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include <string.h>
     37 #include <unistd.h>
     38 
     39 #define ELOOP_QUEUE	IPV4LL
     40 #include "config.h"
     41 #include "arp.h"
     42 #include "common.h"
     43 #include "dhcp.h"
     44 #include "eloop.h"
     45 #include "if.h"
     46 #include "if-options.h"
     47 #include "ipv4.h"
     48 #include "ipv4ll.h"
     49 #include "logerr.h"
     50 #include "sa.h"
     51 #include "script.h"
     52 
     53 static void ipv4ll_start_arp(void *arg);
     54 
     55 static const struct in_addr inaddr_llmask = {
     56 	.s_addr = HTONL(LINKLOCAL_MASK)
     57 };
     58 static const struct in_addr inaddr_llbcast = {
     59 	.s_addr = HTONL(LINKLOCAL_BCAST)
     60 };
     61 
     62 static void
     63 ipv4ll_pickaddr(struct interface *ifp)
     64 {
     65 	struct in_addr addr = { .s_addr = 0 };
     66 	struct ipv4ll_state *state;
     67 
     68 	state = IPV4LL_STATE(ifp);
     69 	setstate(state->randomstate);
     70 
     71 	do {
     72 		long r;
     73 
     74 again:
     75 		/* RFC 3927 Section 2.1 states that the first 256 and
     76 		 * last 256 addresses are reserved for future use.
     77 		 * See ipv4ll_start for why we don't use arc4random. */
     78 		/* coverity[dont_call] */
     79 		r = random();
     80 		addr.s_addr = ntohl(LINKLOCAL_ADDR |
     81 		    ((uint32_t)(r % 0xFD00) + 0x0100));
     82 
     83 		/* No point using a failed address */
     84 		if (IN_ARE_ADDR_EQUAL(&addr, &state->pickedaddr))
     85 			goto again;
     86 		/* Ensure we don't have the address on another interface */
     87 	} while (ipv4_findaddr(ifp->ctx, &addr) != NULL);
     88 
     89 	/* Restore the original random state */
     90 	setstate(ifp->ctx->randomstate);
     91 	state->pickedaddr = addr;
     92 }
     93 
     94 int
     95 ipv4ll_subnetroute(rb_tree_t *routes, struct interface *ifp)
     96 {
     97 	struct ipv4ll_state *state;
     98 	struct rt *rt;
     99 	struct in_addr in;
    100 
    101 	assert(ifp != NULL);
    102 	if ((state = IPV4LL_STATE(ifp)) == NULL ||
    103 	    state->addr == NULL)
    104 		return 0;
    105 
    106 	if ((rt = rt_new(ifp)) == NULL)
    107 		return -1;
    108 
    109 	in.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
    110 	sa_in_init(&rt->rt_dest, &in);
    111 	in.s_addr = state->addr->mask.s_addr;
    112 	sa_in_init(&rt->rt_netmask, &in);
    113 	in.s_addr = INADDR_ANY;
    114 	sa_in_init(&rt->rt_gateway, &in);
    115 	sa_in_init(&rt->rt_ifa, &state->addr->addr);
    116 	rt->rt_dflags |= RTDF_IPV4LL;
    117 	return rt_proto_add(routes, rt) ? 1 : 0;
    118 }
    119 
    120 int
    121 ipv4ll_defaultroute(rb_tree_t *routes, struct interface *ifp)
    122 {
    123 	struct ipv4ll_state *state;
    124 	struct rt *rt;
    125 	struct in_addr in;
    126 
    127 	assert(ifp != NULL);
    128 	if ((state = IPV4LL_STATE(ifp)) == NULL ||
    129 	    state->addr == NULL)
    130 		return 0;
    131 
    132 	if ((rt = rt_new(ifp)) == NULL)
    133 		return -1;
    134 
    135 	in.s_addr = INADDR_ANY;
    136 	sa_in_init(&rt->rt_dest, &in);
    137 	sa_in_init(&rt->rt_netmask, &in);
    138 	sa_in_init(&rt->rt_gateway, &in);
    139 	sa_in_init(&rt->rt_ifa, &state->addr->addr);
    140 	rt->rt_dflags |= RTDF_IPV4LL;
    141 #ifdef HAVE_ROUTE_METRIC
    142 	rt->rt_metric += RTMETRIC_IPV4LL;
    143 #endif
    144 	return rt_proto_add(routes, rt) ? 1 : 0;
    145 }
    146 
    147 ssize_t
    148 ipv4ll_env(FILE *fp, const char *prefix, const struct interface *ifp)
    149 {
    150 	const struct ipv4ll_state *state;
    151 	const char *pf = prefix == NULL ? "" : "_";
    152 	struct in_addr netnum;
    153 
    154 	assert(ifp != NULL);
    155 	if ((state = IPV4LL_CSTATE(ifp)) == NULL || state->addr == NULL)
    156 		return 0;
    157 
    158 	/* Emulate a DHCP environment */
    159 	if (efprintf(fp, "%s%sip_address=%s",
    160 	    prefix, pf, inet_ntoa(state->addr->addr)) == -1)
    161 		return -1;
    162 	if (efprintf(fp, "%s%ssubnet_mask=%s",
    163 	    prefix, pf, inet_ntoa(state->addr->mask)) == -1)
    164 		return -1;
    165 	if (efprintf(fp, "%s%ssubnet_cidr=%d",
    166 	    prefix, pf, inet_ntocidr(state->addr->mask)) == -1)
    167 		return -1;
    168 	if (efprintf(fp, "%s%sbroadcast_address=%s",
    169 	    prefix, pf, inet_ntoa(state->addr->brd)) == -1)
    170 		return -1;
    171 	netnum.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
    172 	if (efprintf(fp, "%s%snetwork_number=%s",
    173 	    prefix, pf, inet_ntoa(netnum)) == -1)
    174 		return -1;
    175 	return 5;
    176 }
    177 
    178 #ifndef KERNEL_RFC5227
    179 static void
    180 ipv4ll_announced_arp(struct arp_state *astate)
    181 {
    182 	struct ipv4ll_state *state = IPV4LL_STATE(astate->iface);
    183 
    184 	state->conflicts = 0;
    185 }
    186 
    187 /* This is the callback by ARP freeing */
    188 static void
    189 ipv4ll_free_arp(struct arp_state *astate)
    190 {
    191 	struct ipv4ll_state *state;
    192 
    193 	state = IPV4LL_STATE(astate->iface);
    194 	if (state != NULL && state->arp == astate)
    195 		state->arp = NULL;
    196 }
    197 
    198 /* This is us freeing any ARP state */
    199 static void
    200 ipv4ll_freearp(struct interface *ifp)
    201 {
    202 	struct ipv4ll_state *state;
    203 
    204 	state = IPV4LL_STATE(ifp);
    205 	if (state == NULL || state->arp == NULL)
    206 		return;
    207 
    208 	eloop_timeout_delete(ifp->ctx->eloop, NULL, state->arp);
    209 	arp_free(state->arp);
    210 	state->arp = NULL;
    211 }
    212 #else
    213 #define	ipv4ll_freearp(ifp)
    214 #endif
    215 
    216 static void
    217 ipv4ll_not_found(struct interface *ifp)
    218 {
    219 	struct ipv4ll_state *state;
    220 	struct ipv4_addr *ia;
    221 
    222 	state = IPV4LL_STATE(ifp);
    223 	ia = ipv4_iffindaddr(ifp, &state->pickedaddr, &inaddr_llmask);
    224 #ifdef IN_IFF_NOTREADY
    225 	if (ia == NULL || ia->addr_flags & IN_IFF_NOTREADY)
    226 #endif
    227 		loginfox("%s: using IPv4LL address %s",
    228 		  ifp->name, inet_ntoa(state->pickedaddr));
    229 	if (ia == NULL) {
    230 		if (ifp->ctx->options & DHCPCD_TEST) {
    231 			ia = malloc(sizeof(*ia));
    232 			if (ia == NULL) {
    233 				logerr(__func__);
    234 				return;
    235 			}
    236 			ia->iface = ifp;
    237 			ia->addr = state->pickedaddr;
    238 		} else if (!(ifp->options->options & DHCPCD_CONFIGURE)) {
    239 			logwarnx("%s: refusing to add IPv4LL address %s",
    240 			    ifp->name, inet_ntoa(state->pickedaddr));
    241 			return;
    242 		}
    243 		ia = ipv4_addaddr(ifp, &state->pickedaddr,
    244 		    &inaddr_llmask, &inaddr_llbcast,
    245 		    DHCP_INFINITE_LIFETIME, DHCP_INFINITE_LIFETIME);
    246 	}
    247 	if (ia == NULL)
    248 		return;
    249 #ifdef IN_IFF_NOTREADY
    250 	if (ia->addr_flags & IN_IFF_NOTREADY)
    251 		return;
    252 	logdebugx("%s: DAD completed for %s", ifp->name, ia->saddr);
    253 #endif
    254 
    255 	state->addr = ia;
    256 	state->down = false;
    257 	if (ifp->ctx->options & DHCPCD_TEST) {
    258 		script_runreason(ifp, "TEST");
    259 		eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
    260 		return;
    261 	}
    262 	rt_build(ifp->ctx, AF_INET);
    263 
    264 	script_runreason(ifp, "IPV4LL");
    265 	dhcpcd_daemonise(ifp->ctx);
    266 }
    267 
    268 static void
    269 ipv4ll_found(struct interface *ifp)
    270 {
    271 	struct ipv4ll_state *state = IPV4LL_STATE(ifp);
    272 
    273 	ipv4ll_freearp(ifp);
    274 	if (++state->conflicts == MAX_CONFLICTS)
    275 		logerrx("%s: failed to acquire an IPv4LL address",
    276 		    ifp->name);
    277 	ipv4ll_pickaddr(ifp);
    278 	eloop_timeout_add_sec(ifp->ctx->eloop,
    279 	    state->conflicts >= MAX_CONFLICTS ?
    280 	    RATE_LIMIT_INTERVAL : PROBE_WAIT,
    281 	    ipv4ll_start_arp, ifp);
    282 }
    283 
    284 static void
    285 ipv4ll_defend_failed(struct interface *ifp)
    286 {
    287 	struct ipv4ll_state *state = IPV4LL_STATE(ifp);
    288 
    289 	ipv4ll_freearp(ifp);
    290 	if (ifp->options->options & DHCPCD_CONFIGURE)
    291 		ipv4_deladdr(state->addr, 1);
    292 	state->addr = NULL;
    293 	rt_build(ifp->ctx, AF_INET);
    294 	script_runreason(ifp, "IPV4LL");
    295 	ipv4ll_pickaddr(ifp);
    296 	ipv4ll_start_arp(ifp);
    297 }
    298 
    299 #ifndef KERNEL_RFC5227
    300 static void
    301 ipv4ll_not_found_arp(struct arp_state *astate)
    302 {
    303 
    304 	ipv4ll_not_found(astate->iface);
    305 }
    306 
    307 static void
    308 ipv4ll_found_arp(struct arp_state *astate, __unused const struct arp_msg *amsg)
    309 {
    310 
    311 	ipv4ll_found(astate->iface);
    312 }
    313 
    314 static void
    315 ipv4ll_defend_failed_arp(struct arp_state *astate)
    316 {
    317 
    318 	ipv4ll_defend_failed(astate->iface);
    319 }
    320 #endif
    321 
    322 void
    323 ipv4ll_start(void *arg)
    324 {
    325 	struct interface *ifp = arg;
    326 	struct ipv4ll_state *state;
    327 	struct ipv4_addr *ia;
    328 	bool repick;
    329 
    330 	if ((state = IPV4LL_STATE(ifp)) == NULL) {
    331 		ifp->if_data[IF_DATA_IPV4LL] = calloc(1, sizeof(*state));
    332 		if ((state = IPV4LL_STATE(ifp)) == NULL) {
    333 			logerr(__func__);
    334 			return;
    335 		}
    336 	}
    337 
    338 	if (state->running)
    339 		return;
    340 	state->running = true;
    341 
    342 	/* RFC 3927 Section 2.1 states that the random number generator
    343 	 * SHOULD be seeded with a value derived from persistent information
    344 	 * such as the IEEE 802 MAC address so that it usually picks
    345 	 * the same address without persistent storage. */
    346 	if (!state->seeded) {
    347 		unsigned int seed;
    348 		char *orig;
    349 
    350 		if (sizeof(seed) > ifp->hwlen) {
    351 			seed = 0;
    352 			memcpy(&seed, ifp->hwaddr, ifp->hwlen);
    353 		} else
    354 			memcpy(&seed, ifp->hwaddr + ifp->hwlen - sizeof(seed),
    355 			    sizeof(seed));
    356 		/* coverity[dont_call] */
    357 		orig = initstate(seed,
    358 		    state->randomstate, sizeof(state->randomstate));
    359 
    360 		/* Save the original state. */
    361 		if (ifp->ctx->randomstate == NULL)
    362 			ifp->ctx->randomstate = orig;
    363 
    364 		/* Set back the original state until we need the seeded one. */
    365 		setstate(ifp->ctx->randomstate);
    366 		state->seeded = true;
    367 	}
    368 
    369 	/* Find the previosuly used address. */
    370 	if (state->pickedaddr.s_addr != INADDR_ANY)
    371 		ia = ipv4_iffindaddr(ifp, &state->pickedaddr, NULL);
    372 	else
    373 		ia = NULL;
    374 
    375 	/* Find an existing IPv4LL address and ensure we can work with it. */
    376 	if (ia == NULL)
    377 		ia = ipv4_iffindlladdr(ifp);
    378 
    379 	repick = false;
    380 #ifdef IN_IFF_DUPLICATED
    381 	if (ia != NULL && ia->addr_flags & IN_IFF_DUPLICATED) {
    382 		state->pickedaddr = ia->addr; /* So it's not picked again. */
    383 		repick = true;
    384 		if (ifp->options->options & DHCPCD_CONFIGURE)
    385 			ipv4_deladdr(ia, 0);
    386 		ia = NULL;
    387 	}
    388 #endif
    389 
    390 	state->addr = ia;
    391 	state->down = true;
    392 	if (ia != NULL) {
    393 		state->pickedaddr = ia->addr;
    394 #ifdef IN_IFF_TENTATIVE
    395 		if (ia->addr_flags & (IN_IFF_TENTATIVE | IN_IFF_DETACHED)) {
    396 			loginfox("%s: waiting for DAD to complete on %s",
    397 			    ifp->name, inet_ntoa(ia->addr));
    398 			return;
    399 		}
    400 #endif
    401 #ifdef IN_IFF_DUPLICATED
    402 		loginfox("%s: using IPv4LL address %s", ifp->name, ia->saddr);
    403 #endif
    404 	} else if (ifp->options->options & DHCPCD_CONFIGURE) {
    405 		loginfox("%s: probing for an IPv4LL address", ifp->name);
    406 		if (repick || state->pickedaddr.s_addr == INADDR_ANY)
    407 			ipv4ll_pickaddr(ifp);
    408 	} else {
    409 		logwarnx("%s: refusing to configure IPv4LL", ifp->name);
    410 		return;
    411 	}
    412 
    413 	ipv4ll_start_arp(ifp);
    414 }
    415 
    416 static void
    417 ipv4ll_start_arp(void *arg)
    418 {
    419 	struct interface *ifp = arg;
    420 #ifdef KERNEL_RFC5227
    421 	ipv4ll_not_found(ifp);
    422 #else
    423 	struct ipv4ll_state *state;
    424 	struct arp_state *astate;
    425 
    426 	state = IPV4LL_STATE(ifp);
    427 
    428 	ipv4ll_freearp(ifp);
    429 	state->arp = astate = arp_new(ifp, &state->pickedaddr);
    430 	if (state->arp == NULL)
    431 		return;
    432 
    433 	astate->found_cb = ipv4ll_found_arp;
    434 	astate->not_found_cb = ipv4ll_not_found_arp;
    435 	astate->announced_cb = ipv4ll_announced_arp;
    436 	astate->defend_failed_cb = ipv4ll_defend_failed_arp;
    437 	astate->free_cb = ipv4ll_free_arp;
    438 	arp_probe(astate);
    439 #endif
    440 }
    441 
    442 void
    443 ipv4ll_drop(struct interface *ifp)
    444 {
    445 	struct ipv4ll_state *state;
    446 	bool dropped = false;
    447 	struct ipv4_state *istate;
    448 
    449 	assert(ifp != NULL);
    450 
    451 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
    452 	ipv4ll_freearp(ifp);
    453 
    454 	if ((ifp->options->options & DHCPCD_NODROP) == DHCPCD_NODROP)
    455 		goto free;
    456 
    457 	state = IPV4LL_STATE(ifp);
    458 	if (state) {
    459 		state->running = false;
    460 		if (state->addr != NULL) {
    461 			if (ifp->options->options & DHCPCD_CONFIGURE)
    462 				ipv4_deladdr(state->addr, 1);
    463 			state->addr = NULL;
    464 			dropped = true;
    465 		}
    466 	}
    467 
    468 	/* Free any other link local addresses that might exist. */
    469 	if ((istate = IPV4_STATE(ifp)) != NULL) {
    470 		struct ipv4_addr *ia, *ian;
    471 
    472 		TAILQ_FOREACH_SAFE(ia, &istate->addrs, next, ian) {
    473 			if (IN_LINKLOCAL(ntohl(ia->addr.s_addr))) {
    474 				if (ifp->options->options & DHCPCD_CONFIGURE)
    475 					ipv4_deladdr(ia, 0);
    476 				dropped = true;
    477 			}
    478 		}
    479 	}
    480 
    481 	if (dropped) {
    482 		rt_build(ifp->ctx, AF_INET);
    483 		script_runreason(ifp, "IPV4LL");
    484 	}
    485 
    486 free:
    487 	ipv4ll_free(ifp);
    488 	dhcpcd_dropped(ifp);
    489 }
    490 
    491 void
    492 ipv4ll_reset(struct interface *ifp)
    493 {
    494 	struct ipv4ll_state *state = IPV4LL_STATE(ifp);
    495 
    496 	if (state == NULL)
    497 		return;
    498 	ipv4ll_freearp(ifp);
    499 	state->pickedaddr.s_addr = INADDR_ANY;
    500 	state->seeded = false;
    501 }
    502 
    503 void
    504 ipv4ll_free(struct interface *ifp)
    505 {
    506 
    507 	assert(ifp != NULL);
    508 
    509 	ipv4ll_freearp(ifp);
    510 	free(IPV4LL_STATE(ifp));
    511 	ifp->if_data[IF_DATA_IPV4LL] = NULL;
    512 }
    513 
    514 /* This may cause issues in BSD systems, where running as a single dhcpcd
    515  * daemon would solve this issue easily. */
    516 #ifdef HAVE_ROUTE_METRIC
    517 int
    518 ipv4ll_recvrt(__unused int cmd, const struct rt *rt)
    519 {
    520 	struct dhcpcd_ctx *ctx;
    521 	struct interface *ifp;
    522 
    523 	/* Only interested in default route changes. */
    524 	if (sa_is_unspecified(&rt->rt_dest))
    525 		return 0;
    526 
    527 	/* If any interface is running IPv4LL, rebuild our routing table. */
    528 	ctx = rt->rt_ifp->ctx;
    529 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
    530 		if (IPV4LL_STATE_RUNNING(ifp)) {
    531 			rt_build(ctx, AF_INET);
    532 			break;
    533 		}
    534 	}
    535 
    536 	return 0;
    537 }
    538 #endif
    539 
    540 struct ipv4_addr *
    541 ipv4ll_handleifa(int cmd, struct ipv4_addr *ia, pid_t pid)
    542 {
    543 	struct interface *ifp;
    544 	struct ipv4ll_state *state;
    545 
    546 	ifp = ia->iface;
    547 	state = IPV4LL_STATE(ifp);
    548 	if (state == NULL)
    549 		return ia;
    550 
    551 	if (cmd == RTM_DELADDR &&
    552 	    state->addr != NULL &&
    553 	    IN_ARE_ADDR_EQUAL(&state->addr->addr, &ia->addr))
    554 	{
    555 		loginfox("%s: pid %d deleted IP address %s",
    556 		    ifp->name, (int)pid, ia->saddr);
    557 		ipv4ll_defend_failed(ifp);
    558 		return ia;
    559 	}
    560 
    561 #ifdef IN_IFF_DUPLICATED
    562 	if (cmd != RTM_NEWADDR)
    563 		return ia;
    564 	if (!IN_ARE_ADDR_EQUAL(&state->pickedaddr, &ia->addr))
    565 		return ia;
    566 	if (!(ia->addr_flags & IN_IFF_NOTUSEABLE))
    567 		ipv4ll_not_found(ifp);
    568 	else if (ia->addr_flags & IN_IFF_DUPLICATED) {
    569 		logerrx("%s: DAD detected %s", ifp->name, ia->saddr);
    570 		ipv4ll_freearp(ifp);
    571 		if (ifp->options->options & DHCPCD_CONFIGURE)
    572 			ipv4_deladdr(ia, 1);
    573 		state->addr = NULL;
    574 		rt_build(ifp->ctx, AF_INET);
    575 		ipv4ll_found(ifp);
    576 		return NULL;
    577 	}
    578 #endif
    579 
    580 	return ia;
    581 }
    582