1d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/*
2d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * dhcpcd - DHCP client daemon
3d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
4d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * All rights reserved
5d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
6d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Redistribution and use in source and binary forms, with or without
7d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * modification, are permitted provided that the following conditions
8d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * are met:
9d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 1. Redistributions of source code must retain the above copyright
10d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    notice, this list of conditions and the following disclaimer.
11d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 2. Redistributions in binary form must reproduce the above copyright
12d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    notice, this list of conditions and the following disclaimer in the
13d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    documentation and/or other materials provided with the distribution.
14d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *
15d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * SUCH DAMAGE.
26d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */
27d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
28d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/stat.h>
29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/uio.h>
30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/wait.h>
31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/in.h>
33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <arpa/inet.h>
34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <ctype.h>
36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h>
37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <signal.h>
38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* We can't include spawn.h here because it may not exist.
39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * config.h will pull it in, or our compat one. */
40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h>
41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h>
42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h>
43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "config.h"
45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h"
46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp.h"
47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp6.h"
48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if.h"
49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if-options.h"
50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv6nd.h"
51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "script.h"
52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef HAVE_SPAWN_H
54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <spawn.h>
55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else
56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "compat/posix_spawn.h"
57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
58d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
59d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* Allow the OS to define another script env var name */
60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef RC_SVCNAME
61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define RC_SVCNAME "RC_SVCNAME"
62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define DEFAULT_PATH	"PATH=/usr/bin:/usr/sbin:/bin:/sbin"
65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic const char * const if_params[] = {
67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"interface",
68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"reason",
69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"pid",
70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"ifcarrier",
71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"ifmetric",
72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"ifwireless",
73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"ifflags",
74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"ssid",
75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"profile",
76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	"interface_order",
77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	NULL
78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan};
79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanif_printoptions(void)
82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const char * const *p;
84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	for (p = if_params; *p; p++)
86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		printf(" -  %s\n", *p);
87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
89d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int
90d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanexec_script(const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env)
91d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
92d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	pid_t pid;
93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	posix_spawnattr_t attr;
94d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	int i;
95d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef USE_SIGNALS
96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	short flags;
97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	sigset_t defsigs;
98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else
99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	UNUSED(ctx);
100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* posix_spawn is a safe way of executing another image
103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	 * and changing signals back to how they should be. */
104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (posix_spawnattr_init(&attr) == -1)
105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return -1;
106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef USE_SIGNALS
107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF;
108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	posix_spawnattr_setflags(&attr, flags);
109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	sigemptyset(&defsigs);
110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	for (i = 0; dhcpcd_handlesigs[i]; i++)
111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		sigaddset(&defsigs, dhcpcd_handlesigs[i]);
112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	posix_spawnattr_setsigdefault(&attr, &defsigs);
113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	posix_spawnattr_setsigmask(&attr, &ctx->sigset);
114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	errno = 0;
116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	i = posix_spawn(&pid, argv[0], NULL, &attr, argv, env);
117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (i) {
118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		errno = i;
119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return -1;
120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return pid;
122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic char *
126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanmake_var(struct dhcpcd_ctx *ctx, const char *prefix, const char *var)
127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	size_t len;
129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	char *v;
130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	len = strlen(prefix) + strlen(var) + 2;
132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	v = malloc(len);
133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (v == NULL) {
134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ctx, LOG_ERR, "%s: %m", __func__);
135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return NULL;
136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(v, len, "%s_%s", prefix, var);
138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return v;
139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int
143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanappend_config(struct dhcpcd_ctx *ctx, char ***env, size_t *len,
144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan    const char *prefix, const char *const *config)
145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	size_t i, j, e1;
147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	char **ne, *eq, **nep, *p;
148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	int ret;
149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (config == NULL)
151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return 0;
152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ne = *env;
154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ret = 0;
155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	for (i = 0; config[i] != NULL; i++) {
156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		eq = strchr(config[i], '=');
157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		e1 = (size_t)(eq - config[i] + 1);
158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		for (j = 0; j < *len; j++) {
159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (strncmp(ne[j] + strlen(prefix) + 1,
160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				config[i], e1) == 0)
161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			{
162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				p = make_var(ctx, prefix, config[i]);
163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				if (p == NULL) {
164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan					ret = -1;
165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan					break;
166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				}
167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				free(ne[j]);
168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				ne[j] = p;
169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				break;
170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			}
171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (j == *len) {
173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			j++;
174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			p = make_var(ctx, prefix, config[i]);
175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (p == NULL) {
176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				ret = -1;
177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				break;
178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			}
179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			nep = realloc(ne, sizeof(char *) * (j + 1));
180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (nep == NULL) {
181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				logger(ctx, LOG_ERR, "%s: %m", __func__);
182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				free(p);
183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				ret = -1;
184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				break;
185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			}
186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			ne = nep;
187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			ne[j - 1] = p;
188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			*len = j;
189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*env = ne;
192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return ret;
193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic ssize_t
197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarraytostr(const char *const *argv, char **s)
198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const char *const *ap;
200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	char *p;
201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	size_t len, l;
202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (*argv == NULL)
204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return 0;
205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	len = 0;
206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ap = argv;
207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	while (*ap)
208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		len += strlen(*ap++) + 1;
209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*s = p = malloc(len);
210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (p == NULL)
211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return -1;
212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ap = argv;
213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	while (*ap) {
214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		l = strlen(*ap) + 1;
215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		memcpy(p, *ap, l);
216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		p += l;
217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		ap++;
218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return (ssize_t)len;
220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic ssize_t
223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanmake_env(const struct interface *ifp, const char *reason, char ***argv)
224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	char **env, **nenv, *p;
226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	size_t e, elen, l;
227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(INET) || defined(INET6)
228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ssize_t n;
229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const struct if_options *ifo = ifp->options;
231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const struct interface *ifp2;
232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	int dhcp;
234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const struct dhcp_state *state;
235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const struct dhcp6_state *d6_state;
238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	int dhcp6, ra;
239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	dhcp = 0;
243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	state = D_STATE(ifp);
244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	dhcp6 = ra = 0;
247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	d6_state = D6_CSTATE(ifp);
248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (strcmp(reason, "TEST") == 0) {
250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (1 == 2) {}
251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		else if (d6_state && d6_state->new)
253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			dhcp6 = 1;
254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		else if (ipv6nd_hasra(ifp))
255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			ra = 1;
256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		else
259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			dhcp = 1;
260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else if (reason[strlen(reason) - 1] == '6')
264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		dhcp6 = 1;
265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else if (strcmp(reason, "ROUTERADVERT") == 0)
266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		ra = 1;
267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else if (strcmp(reason, "PREINIT") == 0 ||
269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(reason, "CARRIER") == 0 ||
270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(reason, "NOCARRIER") == 0 ||
271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(reason, "UNKNOWN") == 0 ||
272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(reason, "DEPARTED") == 0 ||
273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(reason, "STOPPED") == 0)
274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	{
275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* This space left intentionally blank */
276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else
279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		dhcp = 1;
280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
282d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* When dumping the lease, we only want to report interface and
283d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	   reason - the other interface variables are meaningless */
284d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ifp->ctx->options & DHCPCD_DUMPLEASE)
285d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		elen = 2;
286d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else
287d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		elen = 13;
288d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
289d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define EMALLOC(i, l) if ((env[(i)] = malloc((l))) == NULL) goto eexit;
290d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Make our env + space for profile, wireless and debug */
291d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	env = calloc(1, sizeof(char *) * (elen + 3 + 1));
292d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (env == NULL)
293d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		goto eexit;
294d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	e = strlen("interface") + strlen(ifp->name) + 2;
295d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(0, e);
296d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(env[0], e, "interface=%s", ifp->name);
297d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	e = strlen("reason") + strlen(reason) + 2;
298d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(1, e);
299d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(env[1], e, "reason=%s", reason);
300d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ifp->ctx->options & DHCPCD_DUMPLEASE)
301d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		goto dumplease;
302d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	e = 20;
303d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(2, e);
304d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(env[2], e, "pid=%d", getpid());
305d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(3, e);
306d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(env[3], e, "ifcarrier=%s",
307d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    ifp->carrier == LINK_UNKNOWN ? "unknown" :
308d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    ifp->carrier == LINK_UP ? "up" : "down");
309d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(4, e);
310d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(env[4], e, "ifmetric=%d", ifp->metric);
311d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(5, e);
312d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(env[5], e, "ifwireless=%d", ifp->wireless);
313d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(6, e);
314d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(env[6], e, "ifflags=%u", ifp->flags);
315d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(7, e);
316d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp->name));
317d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	l = e = strlen("interface_order=");
318d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
319d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (!(ifp2->options->options & DHCPCD_PFXDLGONLY))
320d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			e += strlen(ifp2->name) + 1;
321d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
322d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	EMALLOC(8, e);
323d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	p = env[8];
324d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	strlcpy(p, "interface_order=", e);
325d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	e -= l;
326d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	p += l;
327d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
328d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (!(ifp2->options->options & DHCPCD_PFXDLGONLY)) {
329d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			l = strlcpy(p, ifp2->name, e);
330d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			p += l;
331d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			e -= l;
332d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			*p++ = ' ';
333d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			e--;
334d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
335d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
336d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*--p = '\0';
337d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (strcmp(reason, "STOPPED") == 0) {
338d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[9] = strdup("if_up=false");
339d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (ifo->options & DHCPCD_RELEASE)
340d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			env[10] = strdup("if_down=true");
341d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		else
342d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			env[10] = strdup("if_down=false");
343d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	} else if (strcmp(reason, "TEST") == 0 ||
344d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(reason, "PREINIT") == 0 ||
345d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(reason, "CARRIER") == 0 ||
346d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(reason, "UNKNOWN") == 0)
347d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	{
348d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[9] = strdup("if_up=false");
349d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[10] = strdup("if_down=false");
350d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	} else if (1 == 2 /* appease ifdefs */
351d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
352d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    || (dhcp && state && state->new)
353d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
354d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
355d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    || (dhcp6 && d6_state && d6_state->new)
356d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    || (ra && ipv6nd_hasra(ifp))
357d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
358d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    )
359d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	{
360d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[9] = strdup("if_up=true");
361d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[10] = strdup("if_down=false");
362d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	} else {
363d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[9] = strdup("if_up=false");
364d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[10] = strdup("if_down=true");
365d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
366d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (env[9] == NULL || env[10] == NULL)
367d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		goto eexit;
368d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (dhcpcd_oneup(ifp->ctx))
369d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[11] = strdup("if_oneup=true");
370d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else
371d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[11] = strdup("if_oneup=false");
372d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (env[11] == NULL)
373d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		goto eexit;
374d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (dhcpcd_ipwaited(ifp->ctx))
375d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[12] = strdup("if_ipwaited=true");
376d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else
377d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[12] = strdup("if_ipwaited=false");
378d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (env[12] == NULL)
379d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		goto eexit;
380d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ifo->options & DHCPCD_DEBUG) {
381d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		e = strlen("syslog_debug=true") + 1;
382d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		EMALLOC(elen, e);
383d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		snprintf(env[elen++], e, "syslog_debug=true");
384d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
385d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (*ifp->profile) {
386d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		e = strlen("profile=") + strlen(ifp->profile) + 1;
387d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		EMALLOC(elen, e);
388d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		snprintf(env[elen++], e, "profile=%s", ifp->profile);
389d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
390d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ifp->wireless) {
391d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		static const char *pfx = "ifssid=";
392d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		size_t pfx_len;
393d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		ssize_t psl;
394d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
395d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		pfx_len = strlen(pfx);
396d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		psl = print_string(NULL, 0, ESCSTRING,
397d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    (const uint8_t *)ifp->ssid, ifp->ssid_len);
398d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (psl != -1) {
399d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			EMALLOC(elen, pfx_len + (size_t)psl + 1);
400d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			memcpy(env[elen], pfx, pfx_len);
401d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			print_string(env[elen] + pfx_len, (size_t)psl + 1,
402d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    ESCSTRING,
403d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    (const uint8_t *)ifp->ssid, ifp->ssid_len);
404d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen++;
405d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
406d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
407d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
408d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (dhcp && state && state->old) {
409d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		n = dhcp_env(NULL, NULL, state->old, ifp);
410d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (n == -1)
411d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto eexit;
412d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (n > 0) {
413d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			nenv = realloc(env, sizeof(char *) *
414d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    (elen + (size_t)n + 1));
415d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (nenv == NULL)
416d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
417d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			env = nenv;
418d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			n = dhcp_env(env + elen, "old", state->old, ifp);
419d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (n == -1)
420d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
421d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen += (size_t)n;
422d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
423d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (append_config(ifp->ctx, &env, &elen, "old",
424d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    (const char *const *)ifo->config) == -1)
425d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto eexit;
426d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
427d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
428d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
429d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (dhcp6 && d6_state && ifo->options & DHCPCD_PFXDLGONLY) {
430d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		nenv = realloc(env, sizeof(char *) * (elen + 2));
431d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (nenv == NULL)
432d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto eexit;
433d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env = nenv;
434d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[elen] = strdup("ifclass=pd");
435d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (env[elen] == NULL)
436d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto eexit;
437d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		elen++;
438d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
439d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (dhcp6 && d6_state && d6_state->old) {
440d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		n = dhcp6_env(NULL, NULL, ifp,
441d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    d6_state->old, d6_state->old_len);
442d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (n > 0) {
443d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			nenv = realloc(env, sizeof(char *) *
444d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    (elen + (size_t)n + 1));
445d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (nenv == NULL)
446d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
447d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			env = nenv;
448d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			n = dhcp6_env(env + elen, "old", ifp,
449d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    d6_state->old, d6_state->old_len);
450d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (n == -1)
451d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
452d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen += (size_t)n;
453d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
454d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
455d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
456d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
457d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandumplease:
458d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
459d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (dhcp && state && state->new) {
460d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		n = dhcp_env(NULL, NULL, state->new, ifp);
461d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (n > 0) {
462d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			nenv = realloc(env, sizeof(char *) *
463d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    (elen + (size_t)n + 1));
464d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (nenv == NULL)
465d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
466d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			env = nenv;
467d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			n = dhcp_env(env + elen, "new",
468d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    state->new, ifp);
469d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (n == -1)
470d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
471d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen += (size_t)n;
472d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
473d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (append_config(ifp->ctx, &env, &elen, "new",
474d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    (const char *const *)ifo->config) == -1)
475d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto eexit;
476d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
477d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
478d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
479d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (dhcp6 && D6_STATE_RUNNING(ifp)) {
480d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		n = dhcp6_env(NULL, NULL, ifp,
481d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    d6_state->new, d6_state->new_len);
482d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (n > 0) {
483d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			nenv = realloc(env, sizeof(char *) *
484d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    (elen + (size_t)n + 1));
485d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (nenv == NULL)
486d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
487d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			env = nenv;
488d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			n = dhcp6_env(env + elen, "new", ifp,
489d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    d6_state->new, d6_state->new_len);
490d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (n == -1)
491d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
492d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen += (size_t)n;
493d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
494d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
495d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ra) {
496d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		n = ipv6nd_env(NULL, NULL, ifp);
497d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (n > 0) {
498d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			nenv = realloc(env, sizeof(char *) *
499d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    (elen + (size_t)n + 1));
500d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (nenv == NULL)
501d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
502d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			env = nenv;
503d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			n = ipv6nd_env(env + elen, NULL, ifp);
504d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (n == -1)
505d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
506d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen += (size_t)n;
507d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
508d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
509d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
510d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
511d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Add our base environment */
512d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ifo->environ) {
513d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		e = 0;
514d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		while (ifo->environ[e++])
515d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			;
516d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		nenv = realloc(env, sizeof(char *) * (elen + e + 1));
517d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (nenv == NULL)
518d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto eexit;
519d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env = nenv;
520d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		e = 0;
521d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		while (ifo->environ[e]) {
522d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			env[elen + e] = strdup(ifo->environ[e]);
523d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (env[elen + e] == NULL)
524d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				goto eexit;
525d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			e++;
526d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
527d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		elen += e;
528d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
529d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	env[elen] = NULL;
530d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
531d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*argv = env;
532d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return (ssize_t)elen;
533d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
534d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneexit:
535d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
536d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (env) {
537d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		nenv = env;
538d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		while (*nenv)
539d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			free(*nenv++);
540d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		free(env);
541d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
542d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return -1;
543d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
544d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
545d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int
546d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tansend_interface1(struct fd_list *fd, const struct interface *iface,
547d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan    const char *reason)
548d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
549d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	char **env, **ep, *s;
550d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	size_t elen;
551d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	int retval;
552d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
553d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (make_env(iface, reason, &env) == -1)
554d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return -1;
555d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	s = NULL;
556d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	elen = (size_t)arraytostr((const char *const *)env, &s);
557d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if ((ssize_t)elen == -1) {
558d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		free(s);
559d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return -1;
560d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
561d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	retval = control_queue(fd, s, elen, 1);
562d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ep = env;
563d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	while (*ep)
564d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		free(*ep++);
565d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	free(env);
566d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return retval;
567d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
568d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
569d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint
570d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tansend_interface(struct fd_list *fd, const struct interface *ifp)
571d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
572d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const char *reason;
573d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	int retval = 0;
574d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
575d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const struct dhcp_state *d;
576d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
577d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
578d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const struct dhcp6_state *d6;
579d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
580d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
581d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	switch (ifp->carrier) {
582d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	case LINK_UP:
583d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		reason = "CARRIER";
584d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		break;
585d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	case LINK_DOWN:
586d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		reason = "NOCARRIER";
587d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		break;
588d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	default:
589d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		reason = "UNKNOWN";
590d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		break;
591d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
592d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (send_interface1(fd, ifp, reason) == -1)
593d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		retval = -1;
594d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET
595d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (D_STATE_RUNNING(ifp)) {
596d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		d = D_CSTATE(ifp);
597d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (send_interface1(fd, ifp, d->reason) == -1)
598d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			retval = -1;
599d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
600d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
601d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
602d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6
603d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (RS_STATE_RUNNING(ifp)) {
604d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (send_interface1(fd, ifp, "ROUTERADVERT") == -1)
605d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			retval = -1;
606d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
607d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (D6_STATE_RUNNING(ifp)) {
608d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		d6 = D6_CSTATE(ifp);
609d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (send_interface1(fd, ifp, d6->reason) == -1)
610d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			retval = -1;
611d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
612d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
613d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
614d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return retval;
615d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
616d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
617d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint
618d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanscript_runreason(const struct interface *ifp, const char *reason)
619d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
620d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	char *argv[2];
621d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	char **env = NULL, **ep;
622d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	char *svcname, *path, *bigenv;
623d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	size_t e, elen = 0;
624d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	pid_t pid;
625d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	int status = 0;
626d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct fd_list *fd;
627d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
628d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ifp->options->script &&
629d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    (ifp->options->script[0] == '\0' ||
630d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    strcmp(ifp->options->script, "/dev/null") == 0))
631d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return 0;
632d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
633d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	argv[0] = ifp->options->script ? ifp->options->script : UNCONST(SCRIPT);
634d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	argv[1] = NULL;
635d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	logger(ifp->ctx, LOG_DEBUG, "%s: executing `%s' %s",
636d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    ifp->name, argv[0], reason);
637d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
638d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Make our env */
639d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	elen = (size_t)make_env(ifp, reason, &env);
640d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (elen == (size_t)-1) {
641d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ifp->ctx, LOG_ERR, "%s: make_env: %m", ifp->name);
642d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return -1;
643d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
644d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Resize for PATH and RC_SVCNAME */
645d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	svcname = getenv(RC_SVCNAME);
646d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ep = realloc(env, sizeof(char *) * (elen + 2 + (svcname ? 1 : 0)));
647d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ep == NULL) {
648d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		elen = 0;
649d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		goto out;
650d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
651d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	env = ep;
652d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Add path to it */
653d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	path = getenv("PATH");
654d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (path) {
655d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		e = strlen("PATH") + strlen(path) + 2;
656d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[elen] = malloc(e);
657d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (env[elen] == NULL) {
658d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen = 0;
659d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto out;
660d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
661d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		snprintf(env[elen], e, "PATH=%s", path);
662d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	} else {
663d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[elen] = strdup(DEFAULT_PATH);
664d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (env[elen] == NULL) {
665d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen = 0;
666d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto out;
667d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
668d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
669d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (svcname) {
670d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		e = strlen(RC_SVCNAME) + strlen(svcname) + 2;
671d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		env[++elen] = malloc(e);
672d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (env[elen] == NULL) {
673d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen = 0;
674d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto out;
675d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
676d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		snprintf(env[elen], e, "%s=%s", RC_SVCNAME, svcname);
677d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
678d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	env[++elen] = NULL;
679d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
680d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	pid = exec_script(ifp->ctx, argv, env);
681d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (pid == -1)
682d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ifp->ctx, LOG_ERR, "%s: %s: %m", __func__, argv[0]);
683d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else if (pid != 0) {
684d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Wait for the script to finish */
685d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		while (waitpid(pid, &status, 0) == -1) {
686d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (errno != EINTR) {
687d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				logger(ifp->ctx, LOG_ERR, "waitpid: %m");
688d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				status = 0;
689d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				break;
690d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			}
691d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
692d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (WIFEXITED(status)) {
693d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (WEXITSTATUS(status))
694d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				logger(ifp->ctx, LOG_ERR,
695d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				    "%s: %s: WEXITSTATUS %d",
696d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				    __func__, argv[0], WEXITSTATUS(status));
697d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		} else if (WIFSIGNALED(status))
698d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			logger(ifp->ctx, LOG_ERR, "%s: %s: %s",
699d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    __func__, argv[0], strsignal(WTERMSIG(status)));
700d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
701d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
702d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Send to our listeners */
703d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	bigenv = NULL;
704d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	status = 0;
705d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	TAILQ_FOREACH(fd, &ifp->ctx->control_fds, next) {
706d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (!(fd->flags & FD_LISTEN))
707d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
708d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (bigenv == NULL) {
709d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			elen = (size_t)arraytostr((const char *const *)env,
710d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    &bigenv);
711d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if ((ssize_t)elen == -1) {
712d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				logger(ifp->ctx, LOG_ERR, "%s: arraytostr: %m",
713d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				    ifp->name);
714d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				    break;
715d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			}
716d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
717d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (control_queue(fd, bigenv, elen, 1) == -1)
718d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			logger(ifp->ctx, LOG_ERR,
719d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    "%s: control_queue: %m", __func__);
720d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		else
721d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			status = 1;
722d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
723d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (!status)
724d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		free(bigenv);
725d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
726d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanout:
727d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Cleanup */
728d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ep = env;
729d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	while (*ep)
730d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		free(*ep++);
731d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	free(env);
732d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (elen == 0)
733d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return -1;
734d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return WEXITSTATUS(status);
735d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
736