1/*
2 *
3 *   Copyright (c) Wipro Technologies, 2002. All Rights Reserved.
4 *
5 *   This program is free software;  you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13 *   the GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with this program;  if not, write to the Free Software
17 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/****************************************************************************
21 *
22 *    TEST IDENTIFIER	: sethostname02
23 *
24 *    EXECUTED BY	: root / superuser
25 *
26 *    TEST TITLE	: test for checking error conditions for sethostname(2)
27 *
28 *    TEST CASE TOTAL	: 3
29 *
30 *    AUTHOR		: Suresh Babu V. <suresh.babu@wipro.com>
31 *
32 *    SIGNALS
33 *      Uses SIGUSR1 to pause before test if option set.
34 *      (See the parse_opts(3) man page).
35 *
36 * DESCRIPTION
37 *      Verify that,
38 *   1) sethostname(2) returns -1 and sets errno to EINVAL if the parameter,
39 *	len is less than zero.
40 *   2) sethostname(2) returns -1 and sets errno to EINVAL if len is greater
41 *	than the maximum allowed size.
42 *   3) sethostname(2) returns -1 and sets errno to EFAULT if an invalid
43 *	address is given for name.
44 *
45 * Setup:
46 *   Setup signal handling.
47 *   Save current hostname
48 *   Pause for SIGUSR1 if option specified.
49 *
50 *  Test:
51 *   Loop if the proper options are given.
52 *   Execute system call
53 *   Check return code, if system call failed and errno set == expected errno
54 *		Issue sys call fails with expected return value and errno.
55 *      Otherwise,
56 *		Issue sys call failed to produce expected error.
57 *
58 *   Cleanup:
59 *	Restore old hostname.
60 *	Print errno log and/or timing stats if options given
61 *
62 *   Side Effects :
63 *	sethostname() is resetting value to NULL, if an invalid address
64 *	is given for name. So, to overcome this problem, hostname is
65 *	resetting to original value as part of cleanup() routine.
66 *
67 * USAGE:  <for command-line>
68 *  sethostname02 [-c n] [-e] [-i n] [-I x] [-P x] [-p] [-t] [-h]
69 *     where,  -c n  : Run n copies concurrently.
70 *		-e   : Turn on errno logging.
71 *		-i n : Execute test n times.
72 *		-I x : Execute test for x seconds.
73 *		-P x : Pause for x seconds between iterations.
74 *		-p   : Pause for SIGUSR1 before startingt
75 *		-t   : Turn on syscall timing.
76 *		-h   : Display usage information.
77 *
78 ***************************************************************************/
79#include <stdio.h>
80#include <string.h>
81#include <errno.h>
82#include <sys/utsname.h>
83#include "test.h"
84
85#define LARGE_LENGTH MAX_LENGTH + 1
86#define MAX_LENGTH _UTSNAME_LENGTH - 1
87
88static void cleanup(void);
89static void setup(void);
90
91char *TCID = "sethostname02";
92static char hostname[MAX_LENGTH];
93static char hname[MAX_LENGTH];
94static char largehost[LARGE_LENGTH];
95static struct test_case_t {
96	char *err_desc;		/* error description            */
97	int exp_errno;		/* Expected error no            */
98	char *exp_errval;	/* Expected error value string  */
99	char *name;		/* hostname                     */
100	int len;		/* length                       */
101} testcases[] = {
102	{
103	"Length is -ve", EINVAL, "EINVAL", hostname, -1}, {
104	"Length > max allowed size", EINVAL, "EINVAL", largehost,
105		    sizeof(largehost)}
106	,
107#ifndef UCLINUX
108	    /* Skip since uClinux does not implement memory protection */
109	{
110	"Invalid address ", EFAULT, "EFAULT", (void *)-1,
111		    sizeof(hostname)}
112#endif
113};
114
115int TST_TOTAL = ARRAY_SIZE(testcases);
116
117int main(int ac, char **av)
118{
119	int i;
120	int lc;
121
122	tst_parse_opts(ac, av, NULL, NULL);
123
124	/* Do initial setup */
125	setup();
126
127	/* check for looping state if -i option is given */
128	for (lc = 0; TEST_LOOPING(lc); lc++) {
129		tst_count = 0;
130
131		for (i = 0; i < TST_TOTAL; ++i) {
132
133			/*
134			 * Test the system call.
135			 */
136			TEST(sethostname(testcases[i].name, testcases[i].len));
137
138			if ((TEST_RETURN == -1) &&
139			    (TEST_ERRNO == testcases[i].exp_errno)) {
140				tst_resm(TPASS, "expected failure; Got %s",
141					 testcases[i].exp_errval);
142			} else {
143				tst_resm(TFAIL, "call failed to produce "
144					 "expected error;  errno: %d : %s",
145					 TEST_ERRNO, strerror(TEST_ERRNO));
146			}
147		}
148	}
149	/* do cleanup and exit */
150	cleanup();
151
152	tst_exit();
153}
154
155/*
156 * setup() - performs all one time setup for this test.
157 */
158void setup(void)
159{
160	int ret;
161
162	tst_require_root();
163
164	/* capture the signals */
165	tst_sig(NOFORK, DEF_HANDLER, cleanup);
166
167	/* Keep the host name before starting the test */
168	if ((ret = gethostname(hname, sizeof(hname))) < 0) {
169		tst_brkm(TBROK, NULL, "gethostname() failed while"
170			 " getting current host name");
171	}
172
173	/* Pause if the option was specified */
174	TEST_PAUSE;
175}
176
177/*
178 * cleanup()  - performs all one time cleanup for this test
179 *		completion or premature exit.
180 */
181void cleanup(void)
182{
183	int ret;
184
185	/* Set the host name back to original name */
186	if ((ret = sethostname(hname, strlen(hname))) < 0) {
187		tst_resm(TWARN, "sethostname() failed while restoring"
188			 " hostname to \"%s\"", hname);
189	}
190
191}
192