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