[BACK]Return to script.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / bsd / dhcpcd / dist / src

Annotation of src/external/bsd/dhcpcd/dist/src/script.c, Revision 1.1.1.10

1.1.1.8   roy         1: /* SPDX-License-Identifier: BSD-2-Clause */
1.1       roy         2: /*
                      3:  * dhcpcd - DHCP client daemon
1.1.1.5   roy         4:  * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
1.1       roy         5:  * All rights reserved
                      6:
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     19:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     26:  * SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include <sys/stat.h>
                     30: #include <sys/uio.h>
                     31: #include <sys/wait.h>
                     32:
                     33: #include <netinet/in.h>
                     34: #include <arpa/inet.h>
                     35:
                     36: #include <ctype.h>
                     37: #include <errno.h>
                     38: #include <signal.h>
                     39: #include <spawn.h>
1.1.1.8   roy        40: #include <stdarg.h>
1.1       roy        41: #include <stdlib.h>
                     42: #include <string.h>
                     43: #include <unistd.h>
                     44:
                     45: #include "config.h"
                     46: #include "common.h"
                     47: #include "dhcp.h"
                     48: #include "dhcp6.h"
                     49: #include "if.h"
                     50: #include "if-options.h"
                     51: #include "ipv4ll.h"
                     52: #include "ipv6nd.h"
1.1.1.2   roy        53: #include "logerr.h"
1.1       roy        54: #include "script.h"
                     55:
                     56: /* Allow the OS to define another script env var name */
                     57: #ifndef RC_SVCNAME
                     58: #define RC_SVCNAME "RC_SVCNAME"
                     59: #endif
                     60:
1.1.1.8   roy        61: #define DEFAULT_PATH   "/usr/bin:/usr/sbin:/bin:/sbin"
1.1       roy        62:
                     63: static const char * const if_params[] = {
                     64:        "interface",
1.1.1.3   roy        65:        "protocol",
1.1       roy        66:        "reason",
                     67:        "pid",
                     68:        "ifcarrier",
                     69:        "ifmetric",
                     70:        "ifwireless",
                     71:        "ifflags",
                     72:        "ssid",
                     73:        "profile",
                     74:        "interface_order",
                     75:        NULL
                     76: };
                     77:
                     78: void
                     79: if_printoptions(void)
                     80: {
                     81:        const char * const *p;
                     82:
                     83:        for (p = if_params; *p; p++)
                     84:                printf(" -  %s\n", *p);
                     85: }
                     86:
                     87: static int
                     88: exec_script(const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env)
                     89: {
                     90:        pid_t pid;
                     91:        posix_spawnattr_t attr;
                     92:        int r;
                     93: #ifdef USE_SIGNALS
                     94:        size_t i;
                     95:        short flags;
                     96:        sigset_t defsigs;
                     97: #else
                     98:        UNUSED(ctx);
                     99: #endif
                    100:
                    101:        /* posix_spawn is a safe way of executing another image
                    102:         * and changing signals back to how they should be. */
                    103:        if (posix_spawnattr_init(&attr) == -1)
                    104:                return -1;
                    105: #ifdef USE_SIGNALS
                    106:        flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF;
                    107:        posix_spawnattr_setflags(&attr, flags);
                    108:        sigemptyset(&defsigs);
                    109:        for (i = 0; i < dhcpcd_signals_len; i++)
                    110:                sigaddset(&defsigs, dhcpcd_signals[i]);
                    111:        posix_spawnattr_setsigdefault(&attr, &defsigs);
                    112:        posix_spawnattr_setsigmask(&attr, &ctx->sigset);
                    113: #endif
                    114:        errno = 0;
                    115:        r = posix_spawn(&pid, argv[0], NULL, &attr, argv, env);
                    116:        posix_spawnattr_destroy(&attr);
                    117:        if (r) {
                    118:                errno = r;
                    119:                return -1;
                    120:        }
                    121:        return pid;
                    122: }
                    123:
                    124: #ifdef INET
                    125: static int
1.1.1.8   roy       126: append_config(FILE *fp, const char *prefix, const char *const *config)
1.1       roy       127: {
1.1.1.8   roy       128:        size_t i;
1.1       roy       129:
                    130:        if (config == NULL)
                    131:                return 0;
                    132:
1.1.1.8   roy       133:        /* Do we need to replace existing config rather than append? */
1.1       roy       134:        for (i = 0; config[i] != NULL; i++) {
1.1.1.8   roy       135:                if (efprintf(fp, "%s_%s", prefix, config[i]) == -1)
                    136:                        return -1;
1.1       roy       137:        }
1.1.1.8   roy       138:        return 1;
1.1       roy       139: }
                    140:
1.1.1.8   roy       141: #endif
1.1       roy       142:
1.1.1.4   roy       143: #define        PROTO_LINK      0
1.1.1.3   roy       144: #define        PROTO_DHCP      1
                    145: #define        PROTO_IPV4LL    2
                    146: #define        PROTO_RA        3
                    147: #define        PROTO_DHCP6     4
                    148: #define        PROTO_STATIC6   5
                    149: static const char *protocols[] = {
1.1.1.4   roy       150:        "link",
1.1.1.3   roy       151:        "dhcp",
                    152:        "ipv4ll",
                    153:        "ra",
                    154:        "dhcp6",
                    155:        "static6"
                    156: };
                    157:
1.1.1.8   roy       158: int
                    159: efprintf(FILE *fp, const char *fmt, ...)
                    160: {
                    161:        va_list args;
                    162:        int r;
                    163:
                    164:        va_start(args, fmt);
                    165:        r = vfprintf(fp, fmt, args);
                    166:        va_end(args);
                    167:        if (r == -1)
                    168:                return -1;
                    169:        /* Write a trailing NULL so we can easily create env strings. */
                    170:        if (fputc('\0', fp) == EOF)
                    171:                return -1;
                    172:        return r;
                    173: }
                    174:
1.1       roy       175: static ssize_t
1.1.1.8   roy       176: make_env(const struct interface *ifp, const char *reason)
1.1       roy       177: {
1.1.1.8   roy       178:        struct dhcpcd_ctx *ctx = ifp->ctx;
                    179:        FILE *fp;
                    180:        char **env, **envp, *buf, *bufp, *endp, *path;
                    181:        size_t nenv;
                    182:        long buf_pos, i;
1.1.1.9   roy       183:        int protocol = PROTO_LINK;
1.1       roy       184:        const struct if_options *ifo = ifp->options;
                    185:        const struct interface *ifp2;
                    186:        int af;
                    187: #ifdef INET
                    188:        const struct dhcp_state *state;
                    189: #ifdef IPV4LL
                    190:        const struct ipv4ll_state *istate;
                    191: #endif
                    192: #endif
1.1.1.6   roy       193: #ifdef DHCP6
1.1       roy       194:        const struct dhcp6_state *d6_state;
                    195: #endif
                    196:
1.1.1.8   roy       197: #ifdef HAVE_OPEN_MEMSTREAM
                    198:        if (ctx->script_fp == NULL) {
                    199:                fp = open_memstream(&ctx->script_buf, &ctx->script_buflen);
                    200:                if (fp == NULL)
                    201:                        goto eexit;
                    202:                ctx->script_fp = fp;
                    203:        } else {
                    204:                fp = ctx->script_fp;
                    205:                rewind(fp);
                    206:        }
                    207: #else
                    208:        char tmpfile[] = "/tmp/dhcpcd-script-env-XXXXXX";
                    209:        int tmpfd;
                    210:
                    211:        fp = NULL;
                    212:        tmpfd = mkstemp(tmpfile);
                    213:        if (tmpfd == -1)
                    214:                goto eexit;
                    215:        unlink(tmpfile);
1.1.1.10! roy       216:        fp = fdopen(tmpfd, "w+");
        !           217:        if (fp == NULL) {
        !           218:                close(tmpfd);
1.1.1.8   roy       219:                goto eexit;
1.1.1.10! roy       220:        }
1.1.1.8   roy       221: #endif
                    222:
1.1       roy       223: #ifdef INET
                    224:        state = D_STATE(ifp);
                    225: #ifdef IPV4LL
                    226:        istate = IPV4LL_CSTATE(ifp);
                    227: #endif
                    228: #endif
1.1.1.6   roy       229: #ifdef DHCP6
1.1       roy       230:        d6_state = D6_CSTATE(ifp);
                    231: #endif
                    232:        if (strcmp(reason, "TEST") == 0) {
                    233:                if (1 == 2) {}
                    234: #ifdef INET6
1.1.1.6   roy       235: #ifdef DHCP6
1.1       roy       236:                else if (d6_state && d6_state->new)
1.1.1.3   roy       237:                        protocol = PROTO_DHCP6;
1.1.1.6   roy       238: #endif
1.1       roy       239:                else if (ipv6nd_hasra(ifp))
1.1.1.3   roy       240:                        protocol = PROTO_RA;
1.1       roy       241: #endif
                    242: #ifdef INET
                    243: #ifdef IPV4LL
                    244:                else if (istate && istate->addr != NULL)
1.1.1.3   roy       245:                        protocol = PROTO_IPV4LL;
1.1       roy       246: #endif
                    247:                else
1.1.1.3   roy       248:                        protocol = PROTO_DHCP;
1.1       roy       249: #endif
                    250:        }
                    251: #ifdef INET6
                    252:        else if (strcmp(reason, "STATIC6") == 0)
1.1.1.3   roy       253:                protocol = PROTO_STATIC6;
1.1.1.6   roy       254: #ifdef DHCP6
1.1       roy       255:        else if (reason[strlen(reason) - 1] == '6')
1.1.1.3   roy       256:                protocol = PROTO_DHCP6;
1.1.1.6   roy       257: #endif
1.1       roy       258:        else if (strcmp(reason, "ROUTERADVERT") == 0)
1.1.1.3   roy       259:                protocol = PROTO_RA;
1.1       roy       260: #endif
                    261:        else if (strcmp(reason, "PREINIT") == 0 ||
                    262:            strcmp(reason, "CARRIER") == 0 ||
                    263:            strcmp(reason, "NOCARRIER") == 0 ||
                    264:            strcmp(reason, "UNKNOWN") == 0 ||
                    265:            strcmp(reason, "DEPARTED") == 0 ||
                    266:            strcmp(reason, "STOPPED") == 0)
1.1.1.4   roy       267:                protocol = PROTO_LINK;
1.1       roy       268: #ifdef INET
                    269: #ifdef IPV4LL
                    270:        else if (strcmp(reason, "IPV4LL") == 0)
1.1.1.3   roy       271:                protocol = PROTO_IPV4LL;
1.1       roy       272: #endif
                    273:        else
1.1.1.3   roy       274:                protocol = PROTO_DHCP;
1.1       roy       275: #endif
                    276:
1.1.1.8   roy       277:        /* Needed for scripts */
                    278:        path = getenv("PATH");
                    279:        if (efprintf(fp, "PATH=%s", path == NULL ? DEFAULT_PATH:path) == -1)
                    280:                goto eexit;
1.1       roy       281:
1.1.1.8   roy       282:        if (efprintf(fp, "interface=%s", ifp->name) == -1)
                    283:                goto eexit;
                    284:        if (efprintf(fp, "reason=%s", reason) == -1)
                    285:                goto eexit;
1.1       roy       286:        if (ifp->ctx->options & DHCPCD_DUMPLEASE)
                    287:                goto dumplease;
1.1.1.8   roy       288:        if (efprintf(fp, "pid=%d", getpid()) == -1)
                    289:                goto eexit;
                    290:        if (efprintf(fp, "ifcarrier=%s",
1.1       roy       291:            ifp->carrier == LINK_UNKNOWN ? "unknown" :
1.1.1.8   roy       292:            ifp->carrier == LINK_UP ? "up" : "down") == -1)
                    293:                goto eexit;
                    294:        if (efprintf(fp, "ifmetric=%d", ifp->metric) == -1)
                    295:                goto eexit;
                    296:        if (efprintf(fp, "ifwireless=%d", ifp->wireless) == -1)
                    297:                goto eexit;
                    298:        if (efprintf(fp, "ifflags=%u", ifp->flags) == -1)
                    299:                goto eexit;
                    300:        if (efprintf(fp, "ifmtu=%d", if_getmtu(ifp)) == -1)
                    301:                goto eexit;
                    302:
                    303:        if (fprintf(fp, "interface_order=") == -1)
                    304:                goto eexit;
1.1       roy       305:        TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
1.1.1.8   roy       306:                if (ifp2 != TAILQ_FIRST(ifp->ctx->ifaces)) {
                    307:                        if (fputc(' ', fp) == EOF)
                    308:                                return -1;
                    309:                }
                    310:                if (fprintf(fp, "%s", ifp2->name) == -1)
                    311:                        return -1;
1.1       roy       312:        }
1.1.1.8   roy       313:        if (fputc('\0', fp) == EOF)
                    314:                return -1;
                    315:
1.1       roy       316:        if (strcmp(reason, "STOPPED") == 0) {
1.1.1.8   roy       317:                if (efprintf(fp, "if_up=false") == -1)
                    318:                        goto eexit;
                    319:                if (efprintf(fp, "if_down=%s",
                    320:                    ifo->options & DHCPCD_RELEASE ? "true" : "false") == -1)
                    321:                        goto eexit;
1.1       roy       322:        } else if (strcmp(reason, "TEST") == 0 ||
                    323:            strcmp(reason, "PREINIT") == 0 ||
                    324:            strcmp(reason, "CARRIER") == 0 ||
                    325:            strcmp(reason, "UNKNOWN") == 0)
                    326:        {
1.1.1.8   roy       327:                if (efprintf(fp, "if_up=false") == -1)
                    328:                        goto eexit;
                    329:                if (efprintf(fp, "if_down=false") == -1)
                    330:                        goto eexit;
1.1       roy       331:        } else if (1 == 2 /* appease ifdefs */
                    332: #ifdef INET
1.1.1.3   roy       333:            || (protocol == PROTO_DHCP && state && state->new)
1.1       roy       334: #ifdef IPV4LL
1.1.1.3   roy       335:            || (protocol == PROTO_IPV4LL && IPV4LL_STATE_RUNNING(ifp))
1.1       roy       336: #endif
                    337: #endif
                    338: #ifdef INET6
1.1.1.3   roy       339:            || (protocol == PROTO_STATIC6 && IPV6_STATE_RUNNING(ifp))
1.1.1.6   roy       340: #ifdef DHCP6
1.1.1.3   roy       341:            || (protocol == PROTO_DHCP6 && d6_state && d6_state->new)
1.1.1.6   roy       342: #endif
1.1.1.3   roy       343:            || (protocol == PROTO_RA && ipv6nd_hasra(ifp))
1.1       roy       344: #endif
                    345:            )
                    346:        {
1.1.1.8   roy       347:                if (efprintf(fp, "if_up=true") == -1)
                    348:                        goto eexit;
                    349:                if (efprintf(fp, "if_down=false") == -1)
                    350:                        goto eexit;
1.1       roy       351:        } else {
1.1.1.8   roy       352:                if (efprintf(fp, "if_up=false") == -1)
                    353:                        goto eexit;
                    354:                if (efprintf(fp, "if_down=true") == -1)
                    355:                        goto eexit;
1.1       roy       356:        }
1.1.1.3   roy       357:        if (protocols[protocol] != NULL) {
1.1.1.8   roy       358:                if (efprintf(fp, "protocol=%s", protocols[protocol]) == -1)
1.1.1.3   roy       359:                        goto eexit;
                    360:        }
1.1       roy       361:        if ((af = dhcpcd_ifafwaiting(ifp)) != AF_MAX) {
1.1.1.8   roy       362:                if (efprintf(fp, "if_afwaiting=%d", af) == -1)
                    363:                        goto eexit;
1.1       roy       364:        }
                    365:        if ((af = dhcpcd_afwaiting(ifp->ctx)) != AF_MAX) {
                    366:                TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
                    367:                        if ((af = dhcpcd_ifafwaiting(ifp2)) != AF_MAX)
                    368:                                break;
                    369:                }
                    370:        }
                    371:        if (af != AF_MAX) {
1.1.1.8   roy       372:                if (efprintf(fp, "af_waiting=%d", af) == -1)
                    373:                        goto eexit;
1.1       roy       374:        }
                    375:        if (ifo->options & DHCPCD_DEBUG) {
1.1.1.8   roy       376:                if (efprintf(fp, "syslog_debug=true") == -1)
                    377:                        goto eexit;
1.1       roy       378:        }
                    379:        if (*ifp->profile) {
1.1.1.8   roy       380:                if (efprintf(fp, "profile=%s", ifp->profile) == -1)
                    381:                        goto eexit;
1.1       roy       382:        }
                    383:        if (ifp->wireless) {
1.1.1.8   roy       384:                char pssid[IF_SSIDLEN * 4];
                    385:
                    386:                if (print_string(pssid, sizeof(pssid), OT_ESCSTRING,
                    387:                    ifp->ssid, ifp->ssid_len) != -1)
                    388:                {
                    389:                        if (efprintf(fp, "ifssid=%s", pssid) == -1)
                    390:                                goto eexit;
1.1       roy       391:                }
                    392:        }
                    393: #ifdef INET
1.1.1.3   roy       394:        if (protocol == PROTO_DHCP && state && state->old) {
1.1.1.8   roy       395:                if (dhcp_env(fp, "old", ifp,
                    396:                    state->old, state->old_len) == -1)
1.1       roy       397:                        goto eexit;
1.1.1.8   roy       398:                if (append_config(fp, "old",
1.1       roy       399:                    (const char *const *)ifo->config) == -1)
                    400:                        goto eexit;
                    401:        }
                    402: #endif
1.1.1.6   roy       403: #ifdef DHCP6
1.1.1.3   roy       404:        if (protocol == PROTO_DHCP6 && d6_state && d6_state->old) {
1.1.1.8   roy       405:                if (dhcp6_env(fp, "old", ifp,
                    406:                    d6_state->old, d6_state->old_len) == -1)
                    407:                        goto eexit;
1.1       roy       408:        }
                    409: #endif
                    410:
                    411: dumplease:
                    412: #ifdef INET
                    413: #ifdef IPV4LL
1.1.1.3   roy       414:        if (protocol == PROTO_IPV4LL) {
1.1.1.8   roy       415:                if (ipv4ll_env(fp, istate->down ? "old" : "new", ifp) == -1)
                    416:                        goto eexit;
1.1       roy       417:        }
                    418: #endif
1.1.1.3   roy       419:        if (protocol == PROTO_DHCP && state && state->new) {
1.1.1.8   roy       420:                if (dhcp_env(fp, "new", ifp,
                    421:                    state->new, state->new_len) == -1)
                    422:                        goto eexit;
                    423:                if (append_config(fp, "new",
1.1       roy       424:                    (const char *const *)ifo->config) == -1)
                    425:                        goto eexit;
                    426:        }
                    427: #endif
                    428: #ifdef INET6
1.1.1.3   roy       429:        if (protocol == PROTO_STATIC6) {
1.1.1.8   roy       430:                if (ipv6_env(fp, "new", ifp) == -1)
                    431:                        goto eexit;
1.1       roy       432:        }
1.1.1.6   roy       433: #ifdef DHCP6
1.1.1.3   roy       434:        if (protocol == PROTO_DHCP6 && D6_STATE_RUNNING(ifp)) {
1.1.1.8   roy       435:                if (dhcp6_env(fp, "new", ifp,
                    436:                    d6_state->new, d6_state->new_len) == -1)
                    437:                        goto eexit;
1.1       roy       438:        }
1.1.1.6   roy       439: #endif
1.1.1.3   roy       440:        if (protocol == PROTO_RA) {
1.1.1.8   roy       441:                if (ipv6nd_env(fp, ifp) == -1)
                    442:                        goto eexit;
1.1       roy       443:        }
                    444: #endif
                    445:
                    446:        /* Add our base environment */
                    447:        if (ifo->environ) {
1.1.1.8   roy       448:                for (i = 0; ifo->environ[i] != NULL; i++)
                    449:                        if (efprintf(fp, "%s", ifo->environ[i]) == -1)
1.1       roy       450:                                goto eexit;
                    451:        }
                    452:
1.1.1.8   roy       453:        /* Convert buffer to argv */
                    454:        fflush(fp);
                    455:
                    456:        buf_pos = ftell(fp);
                    457:        if (buf_pos == -1) {
                    458:                logerr(__func__);
                    459:                goto eexit;
                    460:        }
                    461: #ifdef HAVE_OPEN_MEMSTREAM
                    462:        buf = ctx->script_buf;
                    463: #else
                    464:        size_t buf_len = (size_t)buf_pos;
                    465:        if (ctx->script_buflen < buf_len) {
                    466:                buf = realloc(ctx->script_buf, buf_len);
                    467:                if (buf == NULL)
                    468:                        goto eexit;
                    469:                ctx->script_buf = buf;
                    470:                ctx->script_buflen = buf_len;
                    471:        }
                    472:        buf = ctx->script_buf;
                    473:        rewind(fp);
                    474:        if (fread(buf, sizeof(char), buf_len, fp) != buf_len)
                    475:                goto eexit;
                    476:        fclose(fp);
                    477:        fp = NULL;
                    478: #endif
                    479:
                    480:        nenv = 0;
                    481:        endp = buf + buf_pos;
                    482:        for (bufp = buf; bufp < endp; bufp++) {
                    483:                if (*bufp == '\0')
                    484:                        nenv++;
                    485:        }
                    486:        if (ctx->script_envlen < nenv) {
                    487:                env = reallocarray(ctx->script_env, nenv + 1, sizeof(*env));
                    488:                if (env == NULL)
                    489:                        goto eexit;
                    490:                ctx->script_env = env;
                    491:                ctx->script_envlen = nenv;
                    492:        }
                    493:        bufp = buf;
                    494:        envp = ctx->script_env;
                    495:        *envp++ = bufp++;
                    496:        endp--; /* Avoid setting the last \0 to an invalid pointer */
                    497:        for (; bufp < endp; bufp++) {
                    498:                if (*bufp == '\0')
                    499:                        *envp++ = bufp + 1;
                    500:        }
                    501:        *envp = NULL;
                    502:
                    503:        return (ssize_t)nenv;
1.1       roy       504:
                    505: eexit:
1.1.1.2   roy       506:        logerr(__func__);
1.1.1.8   roy       507: #ifndef HAVE_OPEN_MEMSTREAM
                    508:        if (fp != NULL)
                    509:                fclose(fp);
                    510: #endif
1.1       roy       511:        return -1;
                    512: }
                    513:
                    514: static int
1.1.1.8   roy       515: send_interface1(struct fd_list *fd, const struct interface *ifp,
1.1       roy       516:     const char *reason)
                    517: {
1.1.1.8   roy       518:        struct dhcpcd_ctx *ctx = ifp->ctx;
1.1       roy       519:
1.1.1.8   roy       520:        if (make_env(ifp, reason) == -1)
1.1       roy       521:                return -1;
1.1.1.8   roy       522:        return control_queue(fd, ctx->script_buf, ctx->script_buflen, 1);
1.1       roy       523: }
                    524:
                    525: int
                    526: send_interface(struct fd_list *fd, const struct interface *ifp)
                    527: {
                    528:        const char *reason;
                    529:        int retval = 0;
                    530: #ifdef INET
                    531:        const struct dhcp_state *d;
                    532: #endif
1.1.1.6   roy       533: #ifdef DHCP6
1.1       roy       534:        const struct dhcp6_state *d6;
                    535: #endif
                    536:
                    537:        switch (ifp->carrier) {
                    538:        case LINK_UP:
                    539:                reason = "CARRIER";
                    540:                break;
                    541:        case LINK_DOWN:
1.1.1.6   roy       542:        case LINK_DOWN_IFFUP:
1.1       roy       543:                reason = "NOCARRIER";
                    544:                break;
                    545:        default:
                    546:                reason = "UNKNOWN";
                    547:                break;
                    548:        }
                    549:        if (send_interface1(fd, ifp, reason) == -1)
                    550:                retval = -1;
                    551: #ifdef INET
                    552:        if (D_STATE_RUNNING(ifp)) {
                    553:                d = D_CSTATE(ifp);
                    554:                if (send_interface1(fd, ifp, d->reason) == -1)
                    555:                        retval = -1;
                    556:        }
                    557: #ifdef IPV4LL
                    558:        if (IPV4LL_STATE_RUNNING(ifp)) {
                    559:                if (send_interface1(fd, ifp, "IPV4LL") == -1)
                    560:                        retval = -1;
                    561:        }
                    562: #endif
                    563: #endif
                    564:
                    565: #ifdef INET6
                    566:        if (IPV6_STATE_RUNNING(ifp)) {
                    567:                if (send_interface1(fd, ifp, "STATIC6") == -1)
                    568:                        retval = -1;
                    569:        }
                    570:        if (RS_STATE_RUNNING(ifp)) {
                    571:                if (send_interface1(fd, ifp, "ROUTERADVERT") == -1)
                    572:                        retval = -1;
                    573:        }
1.1.1.6   roy       574: #ifdef DHCP6
1.1       roy       575:        if (D6_STATE_RUNNING(ifp)) {
                    576:                d6 = D6_CSTATE(ifp);
                    577:                if (send_interface1(fd, ifp, d6->reason) == -1)
                    578:                        retval = -1;
                    579:        }
                    580: #endif
1.1.1.6   roy       581: #endif
1.1       roy       582:
                    583:        return retval;
                    584: }
                    585:
                    586: int
                    587: script_runreason(const struct interface *ifp, const char *reason)
                    588: {
1.1.1.8   roy       589:        struct dhcpcd_ctx *ctx = ifp->ctx;
1.1       roy       590:        char *argv[2];
                    591:        pid_t pid;
                    592:        int status = 0;
                    593:        struct fd_list *fd;
                    594:
1.1.1.7   roy       595:        if (ifp->options->script == NULL &&
1.1       roy       596:            TAILQ_FIRST(&ifp->ctx->control_fds) == NULL)
                    597:                return 0;
                    598:
                    599:        /* Make our env */
1.1.1.8   roy       600:        if (make_env(ifp, reason) == -1) {
1.1.1.2   roy       601:                logerr(__func__);
1.1       roy       602:                return -1;
                    603:        }
                    604:
1.1.1.7   roy       605:        if (ifp->options->script == NULL)
1.1       roy       606:                goto send_listeners;
                    607:
1.1.1.7   roy       608:        argv[0] = ifp->options->script;
1.1       roy       609:        argv[1] = NULL;
1.1.1.2   roy       610:        logdebugx("%s: executing `%s' %s", ifp->name, argv[0], reason);
1.1       roy       611:
1.1.1.8   roy       612:        pid = exec_script(ctx, argv, ctx->script_env);
1.1       roy       613:        if (pid == -1)
1.1.1.2   roy       614:                logerr("%s: %s", __func__, argv[0]);
1.1       roy       615:        else if (pid != 0) {
                    616:                /* Wait for the script to finish */
                    617:                while (waitpid(pid, &status, 0) == -1) {
                    618:                        if (errno != EINTR) {
1.1.1.2   roy       619:                                logerr("%s: waitpid", __func__);
1.1       roy       620:                                status = 0;
                    621:                                break;
                    622:                        }
                    623:                }
                    624:                if (WIFEXITED(status)) {
                    625:                        if (WEXITSTATUS(status))
1.1.1.2   roy       626:                                logerrx("%s: %s: WEXITSTATUS %d",
1.1       roy       627:                                    __func__, argv[0], WEXITSTATUS(status));
                    628:                } else if (WIFSIGNALED(status))
1.1.1.2   roy       629:                        logerrx("%s: %s: %s",
1.1       roy       630:                            __func__, argv[0], strsignal(WTERMSIG(status)));
                    631:        }
                    632:
                    633: send_listeners:
                    634:        /* Send to our listeners */
                    635:        status = 0;
1.1.1.8   roy       636:        TAILQ_FOREACH(fd, &ctx->control_fds, next) {
1.1       roy       637:                if (!(fd->flags & FD_LISTEN))
                    638:                        continue;
1.1.1.8   roy       639:                if (control_queue(fd, ctx->script_buf, ctx->script_buflen, 1)
                    640:                    == -1)
1.1.1.2   roy       641:                        logerr("%s: control_queue", __func__);
1.1       roy       642:                else
                    643:                        status = 1;
                    644:        }
                    645:
                    646:        return WEXITSTATUS(status);
                    647: }

CVSweb <webmaster@jp.NetBSD.org>