Ejemplo n.º 1
0
/* Very, very minimal hangup function.  This just attempts to hang up a device
 * that should already be hung up, so it does not need to be bulletproof.  */
static void
hangup(shvarFile *ifcfg) {
    int fd;
    char *line;
    struct termios original_ts, ts;

    line = svGetValue(ifcfg, "MODEMPORT");
    if (line == NULL)
	return;

    fd = open(line, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd != -1) {
        if (tcgetattr(fd, &ts) != -1) {
            original_ts = ts;
            write(fd, "\r", 1); /* tickle modems that do not like dropped DTR */
            usleep(1000);
            cfsetospeed(&ts, B0);
            tcsetattr(fd, TCSANOW, &ts);
            usleep(100000);
            tcsetattr(fd, TCSANOW, &original_ts);
	}
	close(fd);
    }
    free(line);
}
static char *
plugin_get_hostname (SCPluginIfcfg *plugin)
{
	shvarFile *network;
	char *hostname;
	gboolean ignore_localhost;

	if (g_file_get_contents (HOSTNAME_FILE, &hostname, NULL, NULL)) {
		g_strchomp (hostname);
		return hostname;
	}

	network = svOpenFile (SC_NETWORK_FILE, NULL);
	if (!network) {
		_LOGW ("Could not get hostname: failed to read " SC_NETWORK_FILE);
		return NULL;
	}

	hostname = svGetValue (network, "HOSTNAME", FALSE);
	ignore_localhost = svTrueValue (network, "NM_IGNORE_HOSTNAME_LOCALHOST", FALSE);
	if (ignore_localhost) {
		/* Ignore a default hostname ('localhost[6]' or 'localhost[6].localdomain[6]')
		 * to preserve 'network' service behavior.
		 */
		if (hostname && !nm_utils_is_specific_hostname (hostname)) {
			g_free (hostname);
			hostname = NULL;
		}
	}

	svCloseFile (network);
	return hostname;
}
Ejemplo n.º 3
0
int
main(int argc, char **argv) {
    int status;
    pid_t waited;
    char *device, *real_device, *physicalDevice = NULL;
    char *boot = NULL;
    shvarFile *ifcfg;
    sigset_t blockedsigs, unblockedsigs;
    int pppdPid = 0;
    int timeout = 30;
    char *temp;
    gboolean dying = FALSE;
    int sendsig;
    gboolean connectedOnce = FALSE;
    int maxfail = 0;		// MAXFAIL Patch <*****@*****.**>

    if (argc < 2) {
	fprintf (stderr, "usage: ppp-watch <interface-name> [boot]\n");
	exit(30);
    }

    if (strncmp(argv[1], "ifcfg-", 6) == 0) {
	device = argv[1] + 6;
    } else {
	device = argv[1];
    }

    detach(device); /* Prepare a child process to monitor pppd.  When we
		       return, we'll be in the child. */

    if ((argc > 2) && (strcmp("boot", argv[2]) == 0)) {
	boot = argv[2];
    }

    ifcfg = shvarfilesGet(device);
    if (ifcfg == NULL)
	failureExit(28);

    real_device = svGetValue(ifcfg, "DEVICE");
    if (real_device == NULL)
	real_device = device;

    doPidFile(real_device);

    /* We'll want to know which signal interrupted our sleep below, so
     * attach a signal handler to these. */
    set_signal(SIGTERM, signal_tracker);
    set_signal(SIGINT, signal_tracker);
    set_signal(SIGHUP, signal_tracker);
    set_signal(SIGIO, signal_tracker);
    set_signal(SIGCHLD, signal_tracker);

    /* We time out only if we're being run at boot-time. */
    if (boot) {
	temp = svGetValue(ifcfg, "BOOTTIMEOUT");
	if (temp) {
	    timeout = atoi(temp);
	    if (timeout < 1) timeout = 1;
	    free(temp);
	} else {
	    timeout = 30;
	}
	set_signal(SIGALRM, signal_tracker);
	alarm(timeout);
    }

    /* Register us to get a signal when something changes. Yes, that's vague. */
    fork_exec(TRUE, "/sbin/netreport", NULL, NULL, NULL);

    /* Reset theSigchld, which should have been triggered by netreport. */
    theSigchld = 0;

    /* We don't set up the procmask until after we have received the netreport
     * signal.  Do so now. */
    sigemptyset(&blockedsigs);
    sigaddset(&blockedsigs, SIGTERM);
    sigaddset(&blockedsigs, SIGINT);
    sigaddset(&blockedsigs, SIGHUP);
    sigaddset(&blockedsigs, SIGIO);
    sigaddset(&blockedsigs, SIGCHLD);
    if (boot) {
	sigaddset(&blockedsigs, SIGALRM);
    }
    sigprocmask(SIG_BLOCK, &blockedsigs, NULL);

    sigfillset(&unblockedsigs);
    sigdelset(&unblockedsigs, SIGTERM);
    sigdelset(&unblockedsigs, SIGINT);
    sigdelset(&unblockedsigs, SIGHUP);
    sigdelset(&unblockedsigs, SIGIO);
    sigdelset(&unblockedsigs, SIGCHLD);
    if (boot) {
	sigdelset(&unblockedsigs, SIGALRM);
    }
    sigprocmask(SIG_UNBLOCK, &unblockedsigs, NULL);

    /* Initialize the retry timeout using the RETRYTIMEOUT setting. */
    temp = svGetValue(ifcfg, "RETRYTIMEOUT");
    if (temp) {
	timeout = atoi(temp);
	free(temp);
    } else {
	timeout = 30;
    }

    /* Start trying to bring the interface up. */
    fork_exec(FALSE, IFUP_PPP, "daemon", device, boot);

    while (TRUE) {
	/* Wait for a signal. */
	if (!theSigterm &&
	    !theSigint &&
	    !theSighup &&
	    !theSigio &&
	    !theSigchld &&
	    !theSigalrm) {
	    sigsuspend(&unblockedsigs);
	}

	/* If we got SIGTERM or SIGINT, give up and hang up. */
	if (theSigterm || theSigint) {
	    theSigterm = theSigint = 0;

	    /* If we've already tried to exit this way, use SIGKILL instead
	     * of SIGTERM, because pppd's just being stubborn. */
	    if (dying) {
		sendsig = SIGKILL;
	    } else {
		sendsig = SIGTERM;
	    }
	    dying = TRUE;

	    /* Get the pid of our child pppd. */
	    pppLogicalToPhysical(&pppdPid, device, NULL);

	    /* We don't know what our child pid is.  This is very confusing. */
	    if (!pppdPid) {
		failureExit(35);
	    }

	    /* Die, pppd, die. */
	    kill(pppdPid, sendsig);
	    if (sendsig == SIGKILL) {
		kill(-pppdPid, SIGTERM); /* Give it a chance to die nicely, then
					    kill its whole process group. */
		usleep(2500000);
		kill(-pppdPid, sendsig);
		hangup(ifcfg);
		failureExit(32);
	    }
	}

	/* If we got SIGHUP, reload and redial. */
	if (theSighup) {
	    theSighup = 0;

	    /* Free and reload the configuration structure. */
	    if (ifcfg->parent)
		svCloseFile(ifcfg->parent);
	    svCloseFile(ifcfg);
	    ifcfg = shvarfilesGet(device);

	    /* Get the PID of our child pppd. */
	    pppLogicalToPhysical(&pppdPid, device, NULL);
	    kill(pppdPid, SIGTERM);

	    /* We'll redial when the SIGCHLD arrives, even if PERSIST is
	     * not set (the latter handled by clearing the "we've connected
	     * at least once" flag). */
	    connectedOnce = FALSE;

 	    /* We don't want to delay before redialing, either, so cut
	     * the retry timeout to zero. */
	    timeout = 0;
	}

	/* If we got a SIGIO (from netreport, presumably), check if the
	 * interface is up and return zero (via our parent) if it is. */
	if (theSigio) {
	    theSigio = 0;

	    pppLogicalToPhysical(NULL, device, &physicalDevice);
	    if (physicalDevice) {
		if (interfaceIsUp(physicalDevice)) {
		    /* The interface is up, so report a success to a parent if
		     * we have one.  Any errors after this we just swallow. */
		    relay_exitcode(0);
		    connectedOnce = TRUE;
		    alarm(0);
		}
		free(physicalDevice);
	    }
	}

	/* If we got a SIGCHLD, then pppd died (possibly because we killed it),
	 * and we need to restart it after timeout seconds. */
	if (theSigchld) {
	    theSigchld = 0;

	    /* Find its pid, which is also its process group ID. */
	    waited = waitpid(-1, &status, 0);
	    if (waited == -1) {
		continue;
	    }

	    /* Now, we need to kill any children of pppd still in pppd's
	     * process group, in case they are hanging around.
	     * pppd is dead (we just waited for it) but there is no
	     * guarantee that its children are dead, and they will
	     * hold the modem if we do not get rid of them.
	     * We have kept the old pid/pgrp around in pppdPid.  */
	    if (pppdPid) {
		kill(-pppdPid, SIGTERM); /* give it a chance to die nicely */
		usleep(2500000);
		kill(-pppdPid, SIGKILL);
		hangup(ifcfg);
	    }
	    pppdPid = 0;

	    /* Bail if the child exitted abnormally or we were already
	     * signalled to kill it. */
	    if (!WIFEXITED(status)) {
		failureExit(29);
	    }
	    if (dying) {
		failureExit(WEXITSTATUS(status));
	    }

	    /* Error conditions from which we do not expect to recover
	     * without user intervention -- do not fill up the logs.  */
	    switch (WEXITSTATUS(status)) {
	    case 1: case 2: case 3: case 4: case 6:
	    case 7: case 9: case 14: case 17:
		failureExit(WEXITSTATUS(status));
		break;
	    default:
		break;
	    }

            /* PGB 08/20/02: We no longer retry connecting MAXFAIL
	       times on a failed connect script unless RETRYCONNECT is
	       true. */
	    if ((WEXITSTATUS(status) == 8) &&
		!svTrueValue(ifcfg, "RETRYCONNECT", FALSE)) {
                failureExit(WEXITSTATUS(status));
            }

	    /* If we've never connected, or PERSIST is set, dial again, up
	     * to MAXFAIL times. */
	    if ((WEXITSTATUS(status) == 8) ||
	        !connectedOnce ||
		svTrueValue(ifcfg, "PERSIST", FALSE)) {
		/* If we've been connected (i.e., if we didn't force a redial,
		 * but the connection went down) wait for DISCONNECTTIMEOUT
		 * seconds before redialing. */
		if (connectedOnce) {
		    connectedOnce = FALSE;
		    temp = svGetValue(ifcfg, "DISCONNECTTIMEOUT");
		    if (temp) {
			timeout = atoi(temp);
			free(temp);
		    } else {
			timeout = 2;
		    }
		}
		sigprocmask(SIG_UNBLOCK, &blockedsigs, NULL);
		sleep(timeout);
		sigprocmask(SIG_BLOCK, &blockedsigs, NULL);
		if (!theSigterm &&
		    !theSigint &&
		    !theSighup &&
		    !theSigio &&
		    !theSigchld &&
		    !theSigalrm) {
		    fork_exec(FALSE, IFUP_PPP, "daemon", device, boot);
		}
		/* Reinitialize the retry timeout. */
		temp = svGetValue(ifcfg, "RETRYTIMEOUT");
		if (temp) {
		    timeout = atoi(temp);
		    free(temp);
		} else {
		    timeout = 30;
		}
// Scott Sharkey <*****@*****.**>
// MAXFAIL Patch...
		temp = svGetValue(ifcfg, "MAXFAIL");
		if (temp) {
		    maxfail = atoi(temp);
		    free(temp);
		} else {
		    maxfail = 0;
		}
		if ( maxfail != 0 ) {
		    dialCount++;
		    if ( dialCount >= maxfail )
			failureExit(WEXITSTATUS(status));
		} 
	    } else {
		failureExit(WEXITSTATUS(status));
	    }
	}

	/* We timed out, and we're running at boot-time. */
	if (theSigalrm) {
	    failureExit(34);
	}
    }
}