1*63d1fd59SEnji Cooper /*	$NetBSD: t_swwdog.c,v 1.7 2017/01/13 21:30:39 christos Exp $	*/
257718be8SEnji Cooper 
357718be8SEnji Cooper /*
457718be8SEnji Cooper  * Copyright (c) 2010 Antti Kantee.  All Rights Reserved.
557718be8SEnji Cooper  *
657718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
757718be8SEnji Cooper  * modification, are permitted provided that the following conditions
857718be8SEnji Cooper  * are met:
957718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1057718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1157718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1257718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1357718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1457718be8SEnji Cooper  *
1557718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
1657718be8SEnji Cooper  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1757718be8SEnji Cooper  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1857718be8SEnji Cooper  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1957718be8SEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2057718be8SEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2157718be8SEnji Cooper  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2257718be8SEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2357718be8SEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2457718be8SEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2557718be8SEnji Cooper  * SUCH DAMAGE.
2657718be8SEnji Cooper  */
2757718be8SEnji Cooper 
2857718be8SEnji Cooper #include <sys/types.h>
2957718be8SEnji Cooper #include <sys/wait.h>
3057718be8SEnji Cooper #include <sys/wdog.h>
3157718be8SEnji Cooper 
3257718be8SEnji Cooper #include <assert.h>
3357718be8SEnji Cooper #include <atf-c.h>
3457718be8SEnji Cooper #include <err.h>
3557718be8SEnji Cooper #include <errno.h>
3657718be8SEnji Cooper #include <fcntl.h>
3757718be8SEnji Cooper #include <stdio.h>
3857718be8SEnji Cooper #include <stdlib.h>
3957718be8SEnji Cooper #include <string.h>
4057718be8SEnji Cooper #include <unistd.h>
4157718be8SEnji Cooper #include <signal.h>
4257718be8SEnji Cooper 
4357718be8SEnji Cooper #include <rump/rump.h>
4457718be8SEnji Cooper #include <rump/rump_syscalls.h>
4557718be8SEnji Cooper 
46*63d1fd59SEnji Cooper #include "h_macros.h"
4757718be8SEnji Cooper 
4857718be8SEnji Cooper static volatile sig_atomic_t tcount;
4957718be8SEnji Cooper 
5057718be8SEnji Cooper static void
sigcount(int sig)5157718be8SEnji Cooper sigcount(int sig)
5257718be8SEnji Cooper {
5357718be8SEnji Cooper 
5457718be8SEnji Cooper 	assert(sig == SIGUSR1);
5557718be8SEnji Cooper 	tcount++;
5657718be8SEnji Cooper }
5757718be8SEnji Cooper 
5857718be8SEnji Cooper /*
5957718be8SEnji Cooper  * Since we are testing for swwdog's ability to reboot/panic, we need
6057718be8SEnji Cooper  * to fork and monitor the exit status from the parent and report
6157718be8SEnji Cooper  * something sensible back to atf.
6257718be8SEnji Cooper  */
6357718be8SEnji Cooper static int
testbody(int max)6457718be8SEnji Cooper testbody(int max)
6557718be8SEnji Cooper {
6657718be8SEnji Cooper 	char wname[WDOG_NAMESIZE];
6757718be8SEnji Cooper 	struct wdog_conf wc;
6857718be8SEnji Cooper 	struct wdog_mode wm;
6957718be8SEnji Cooper 	pid_t p1, p2;
7057718be8SEnji Cooper 	int status;
7157718be8SEnji Cooper 	int fd;
7257718be8SEnji Cooper 
7357718be8SEnji Cooper 	signal(SIGUSR1, sigcount);
7457718be8SEnji Cooper 
7557718be8SEnji Cooper 	switch ((p1 = fork())) {
7657718be8SEnji Cooper 	case 0:
7757718be8SEnji Cooper 		break;
7857718be8SEnji Cooper 	case -1:
7957718be8SEnji Cooper 		atf_tc_fail_errno("fork");
8057718be8SEnji Cooper 		break;
8157718be8SEnji Cooper 	default:
8257718be8SEnji Cooper 		p2 = wait(&status);
8357718be8SEnji Cooper 		ATF_REQUIRE_EQ(p1, p2);
8457718be8SEnji Cooper 		ATF_REQUIRE_EQ(tcount, max);
8557718be8SEnji Cooper 		return status;
8657718be8SEnji Cooper 	}
8757718be8SEnji Cooper 
8857718be8SEnji Cooper 	rump_init();
8957718be8SEnji Cooper 
9057718be8SEnji Cooper 	fd = rump_sys_open("/dev/watchdog", O_RDWR);
9157718be8SEnji Cooper 	if (fd == -1)
9257718be8SEnji Cooper 		err(1, "open watchdog");
9357718be8SEnji Cooper 
9457718be8SEnji Cooper 	wc.wc_count = 1;
9557718be8SEnji Cooper 	wc.wc_names = wname;
9657718be8SEnji Cooper 
9757718be8SEnji Cooper 	if (rump_sys_ioctl(fd, WDOGIOC_GWDOGS, &wc) == -1)
9857718be8SEnji Cooper 		err(1, "can't fetch watchdog names");
9957718be8SEnji Cooper 
10057718be8SEnji Cooper 	if (wc.wc_count) {
10157718be8SEnji Cooper 		assert(wc.wc_count == 1);
10257718be8SEnji Cooper 
10357718be8SEnji Cooper 		strlcpy(wm.wm_name, wc.wc_names, sizeof(wm.wm_name));
10457718be8SEnji Cooper 		wm.wm_mode = WDOG_MODE_ETICKLE;
10557718be8SEnji Cooper 		wm.wm_period = 1;
10657718be8SEnji Cooper 		if (rump_sys_ioctl(fd, WDOGIOC_SMODE, &wm) == -1)
10757718be8SEnji Cooper 			atf_tc_fail_errno("failed to set tickle");
10857718be8SEnji Cooper 
10957718be8SEnji Cooper 		usleep(400000);
11057718be8SEnji Cooper 		if (max == 1)
11157718be8SEnji Cooper 			rump_sys_ioctl(fd, WDOGIOC_TICKLE);
11257718be8SEnji Cooper 		else {
11357718be8SEnji Cooper 			wm.wm_mode = WDOG_MODE_DISARMED;
11457718be8SEnji Cooper 			rump_sys_ioctl(fd, WDOGIOC_SMODE, &wm);
11557718be8SEnji Cooper 		}
11657718be8SEnji Cooper 		kill(getppid(), SIGUSR1);
11757718be8SEnji Cooper 
11857718be8SEnji Cooper 		sleep(2);
11957718be8SEnji Cooper 		printf("staying alive\n");
12057718be8SEnji Cooper 		kill(getppid(), SIGUSR1);
12157718be8SEnji Cooper 		_exit(2);
12257718be8SEnji Cooper 	}
12357718be8SEnji Cooper 	/* fail */
124640235e2SEnji Cooper 	printf("no watchdog registered!\n");
12557718be8SEnji Cooper 	_exit(1);
12657718be8SEnji Cooper }
12757718be8SEnji Cooper 
12857718be8SEnji Cooper ATF_TC(reboot);
ATF_TC_HEAD(reboot,tc)12957718be8SEnji Cooper ATF_TC_HEAD(reboot, tc)
13057718be8SEnji Cooper {
13157718be8SEnji Cooper 
13257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "check swwdog reboot capability");
13357718be8SEnji Cooper }
13457718be8SEnji Cooper 
ATF_TC_BODY(reboot,tc)13557718be8SEnji Cooper ATF_TC_BODY(reboot, tc)
13657718be8SEnji Cooper {
13757718be8SEnji Cooper 	extern bool rumpns_swwdog_reboot;
13857718be8SEnji Cooper 	int status;
13957718be8SEnji Cooper 
14057718be8SEnji Cooper 	/* XXX: should use sysctl */
14157718be8SEnji Cooper 	rumpns_swwdog_reboot = true;
14257718be8SEnji Cooper 	status = testbody(1);
14357718be8SEnji Cooper 
14457718be8SEnji Cooper 	ATF_REQUIRE(WIFEXITED(status));
14557718be8SEnji Cooper 	ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);
14657718be8SEnji Cooper }
14757718be8SEnji Cooper 
14857718be8SEnji Cooper ATF_TC(panic);
ATF_TC_HEAD(panic,tc)14957718be8SEnji Cooper ATF_TC_HEAD(panic, tc)
15057718be8SEnji Cooper {
15157718be8SEnji Cooper 
15257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "check swwdog panic capability");
15357718be8SEnji Cooper }
15457718be8SEnji Cooper 
ATF_TC_BODY(panic,tc)15557718be8SEnji Cooper ATF_TC_BODY(panic, tc)
15657718be8SEnji Cooper {
15757718be8SEnji Cooper 	extern bool rumpns_swwdog_reboot;
15857718be8SEnji Cooper 	int status;
15957718be8SEnji Cooper 
16057718be8SEnji Cooper 	/* XXX: should use sysctl */
16157718be8SEnji Cooper 	rumpns_swwdog_reboot = false;
16257718be8SEnji Cooper 	status = testbody(1);
16357718be8SEnji Cooper 
16457718be8SEnji Cooper 	ATF_REQUIRE(WIFSIGNALED(status));
16557718be8SEnji Cooper 	ATF_REQUIRE_EQ(WTERMSIG(status), SIGABRT);
16657718be8SEnji Cooper }
16757718be8SEnji Cooper 
16857718be8SEnji Cooper ATF_TC(disarm);
ATF_TC_HEAD(disarm,tc)16957718be8SEnji Cooper ATF_TC_HEAD(disarm, tc)
17057718be8SEnji Cooper {
17157718be8SEnji Cooper 
17257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "check swwdog disarm capability");
17357718be8SEnji Cooper }
17457718be8SEnji Cooper 
ATF_TC_BODY(disarm,tc)17557718be8SEnji Cooper ATF_TC_BODY(disarm, tc)
17657718be8SEnji Cooper {
17757718be8SEnji Cooper 	int status;
17857718be8SEnji Cooper 
17957718be8SEnji Cooper 	status = testbody(2);
18057718be8SEnji Cooper 
18157718be8SEnji Cooper 	ATF_REQUIRE(WIFEXITED(status));
18257718be8SEnji Cooper 	ATF_REQUIRE_EQ(WEXITSTATUS(status), 2);
18357718be8SEnji Cooper }
18457718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)18557718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
18657718be8SEnji Cooper {
18757718be8SEnji Cooper 
18857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, panic);
18957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, reboot);
19057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, disarm);
19157718be8SEnji Cooper 
19257718be8SEnji Cooper 	return atf_no_error();
19357718be8SEnji Cooper }
194