• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2001
4  *   Author: David L Stevens
5  *
6  *   This program is free software;  you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14  *   the GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program;  if not, write to the Free Software Foundation,
18  *   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 /*
21  *   Description:
22  *     Tests for name to index and index to name functions in IPv6
23  */
24 
25 #include <unistd.h>
26 #include <errno.h>
27 #include <sys/socket.h>
28 #include <net/if.h>
29 
30 #include "test.h"
31 
32 static struct {
33 	char *name;
34 	int nonzero;
35 } n2i[] = {
36 	{ "lo", 1 },
37 	{ "eth0", 1 },
38 	{ "hoser75", 0 },
39 	{ "6", 0 },
40 };
41 
42 #define N2I_COUNT (sizeof(n2i)/sizeof(n2i[0]))
43 #define I2N_RNDCOUNT	10	/* random ints */
44 #define I2N_LOWCOUNT	10	/* sequential from 0 */
45 
46 static void setup(void);
47 static void n2itest(void);
48 static void i2ntest(void);
49 static void initest(void);
50 
51 static void (*testfunc[])(void) = { n2itest,
52 	i2ntest, initest };
53 
54 char *TCID = "in6_02";
55 int TST_TOTAL = ARRAY_SIZE(testfunc);
56 
main(int argc,char * argv[])57 int main(int argc, char *argv[])
58 {
59 	int lc;
60 	int i;
61 
62 	tst_parse_opts(argc, argv, NULL, NULL);
63 
64 	setup();
65 
66 	for (lc = 0; TEST_LOOPING(lc); ++lc) {
67 		tst_count = 0;
68 
69 		for (i = 0; i < TST_TOTAL; i++)
70 			(*testfunc[i])();
71 	}
72 
73 	tst_exit();
74 }
75 
76 /* if_nametoindex tests */
n2itest(void)77 void n2itest(void)
78 {
79 	unsigned int i;
80 	char ifname[IF_NAMESIZE], *pifn;
81 
82 	for (i = 0; i < N2I_COUNT; ++i) {
83 		TEST(if_nametoindex(n2i[i].name));
84 		if (!TEST_RETURN != !n2i[i].nonzero) {
85 			tst_resm(TFAIL, "if_nametoindex(\"%s\") %ld "
86 				"[should be %szero]", n2i[i].name, TEST_RETURN,
87 				n2i[i].nonzero ? "non" : "");
88 			return;
89 		}
90 		if (TEST_RETURN) {
91 			pifn = if_indextoname(TEST_RETURN, ifname);
92 			if (!pifn || strcmp(n2i[i].name, pifn)) {
93 				tst_resm(TFAIL, "if_nametoindex(\"%s\") %ld "
94 					"doesn't match if_indextoname(%ld) "
95 					"\"%s\"", n2i[i].name, TEST_RETURN,
96 					TEST_RETURN, pifn ? pifn : "");
97 				return;
98 			}
99 		}
100 		tst_resm(TINFO, "if_nametoindex(\"%s\") %ld",
101 			n2i[i].name, TEST_RETURN);
102 	}
103 
104 	tst_resm(TPASS, "if_nametoindex() tests succeed");
105 }
106 
sub_i2ntest(unsigned int if_index)107 int sub_i2ntest(unsigned int if_index)
108 {
109 	char ifname[IF_NAMESIZE];
110 	unsigned int idx;
111 
112 	TEST((ifname == if_indextoname(if_index, ifname)));
113 	if (!TEST_RETURN) {
114 		if (TEST_ERRNO != ENXIO) {
115 			tst_resm(TFAIL, "if_indextoname(%d) returns %ld "
116 				 "but errno %d != ENXIO", if_index, TEST_RETURN,
117 				 TEST_ERRNO);
118 			return 0;
119 		}
120 		tst_resm(TINFO, "if_indextoname(%d) returns NULL", if_index);
121 		return 1;
122 	}
123 	/* else, a valid interface-- double check name */
124 	idx = if_nametoindex(ifname);
125 	if (idx != if_index) {
126 		tst_resm(TFAIL, "if_indextoname(%u) returns \"%s\" but "
127 			 "doesn't if_nametoindex(\"%s\") returns %u",
128 			 if_index, ifname, ifname, idx);
129 		return 0;
130 	}
131 	tst_resm(TINFO, "if_indextoname(%d) returns \"%s\"", if_index, ifname);
132 	return 1;
133 }
134 
135 /* if_indextoname tests */
i2ntest(void)136 void i2ntest(void)
137 {
138 	unsigned int i;
139 
140 	/* some low-numbered indexes-- likely to get valid interfaces here */
141 	for (i = 0; i < I2N_LOWCOUNT; ++i)
142 		if (!sub_i2ntest(i))
143 			return;	/* skip the rest, if broken */
144 	/* some random ints; should mostly fail */
145 	for (i = 0; i < I2N_RNDCOUNT; ++i)
146 		if (!sub_i2ntest(rand()))
147 			return;	/* skip the rest, if broken */
148 
149 	tst_resm(TPASS, "if_indextoname() tests succeed");
150 }
151 
152 /*
153  * This is an ugly, linux-only solution. getrusage() doesn't support the
154  * current data segment size, so we get it out of /proc
155  */
getdatasize(void)156 int getdatasize(void)
157 {
158 	char line[128], *p;
159 	int dsize = -1;
160 	FILE *fp;
161 
162 	fp = fopen("/proc/self/status", "r");
163 	if (fp == NULL)
164 		return -1;
165 	while (fgets(line, sizeof(line), fp)) {
166 		if (strncmp(line, "VmData:", 7) == 0) {
167 			dsize = strtol(line + 7, &p, 0);
168 			++p;	/* skip space */
169 			if (!strcmp(p, "kB"))
170 				return -1;	/* don't know units */
171 			dsize *= 1024;
172 			break;
173 		}
174 	}
175 	fclose(fp);
176 	return dsize;
177 }
178 
179 /* if_nameindex tests */
initest(void)180 void initest(void)
181 {
182 	struct if_nameindex *pini;
183 	int i;
184 	char buf[IF_NAMESIZE], *p;
185 	unsigned int idx;
186 	int freenicount;
187 	int dsize_before, dsize_after;
188 
189 	pini = if_nameindex();
190 	if (pini == NULL) {
191 		tst_resm(TFAIL, "if_nameindex() returns NULL, errno %d (%s)",
192 			 TEST_ERRNO, strerror(TEST_ERRNO));
193 		return;
194 	}
195 	for (i = 0; pini[i].if_index; ++i) {
196 		p = if_indextoname(pini[i].if_index, buf);
197 		if (!p || strcmp(p, pini[i].if_name)) {
198 			tst_resm(TFAIL, "if_nameindex idx %d name \"%s\" but "
199 				 "if_indextoname(%d) is \"%s\"",
200 				 pini[i].if_index, pini[i].if_name,
201 				 pini[i].if_index, p ? p : "");
202 			return;
203 		}
204 		idx = if_nametoindex(pini[i].if_name);
205 		if (idx != pini[i].if_index) {
206 			tst_resm(TFAIL, "if_nameindex idx %d name \"%s\" but "
207 				 "if_indextoname(\"%s\") is %d",
208 				 pini[i].if_index, pini[i].if_name,
209 				 pini[i].if_name, idx);
210 			return;
211 		}
212 		tst_resm(TINFO, "if_nameindex idx %d name \"%s\"",
213 			 pini[i].if_index, pini[i].if_name);
214 	}
215 	if_freenameindex(pini);
216 
217 	/* if_freenameindex() has no error conditions; see if we run
218 	 * out of memory if we do it a lot.
219 	 */
220 	dsize_before = getdatasize();
221 	if (dsize_before < 0) {
222 		tst_brkm(TBROK, NULL, "getdatasize failed: errno %d (%s)",
223 			errno, strerror(errno));
224 	}
225 	/* we need to leak at least a page to detect a leak; 1 byte per call
226 	 * will be detected with getpagesize() calls.
227 	 */
228 	freenicount = getpagesize();
229 	for (i = 0; i < freenicount; ++i) {
230 		pini = if_nameindex();
231 		if (pini == NULL) {
232 			tst_resm(TINFO, "if_freenameindex test failed "
233 				 "if_nameindex() iteration %d", i);
234 			break;
235 		}
236 		if_freenameindex(pini);
237 	}
238 	dsize_after = getdatasize();
239 	if (dsize_after < 0) {
240 		tst_brkm(TBROK, NULL, "getdatasize failed: errno %d (%s)",
241 			errno, strerror(errno));
242 	}
243 	if (dsize_after > dsize_before + getpagesize()) {
244 		tst_resm(TFAIL, "if_freenameindex leaking memory "
245 			 "(%d iterations) dsize before %d dsize after %d", i,
246 			 dsize_before, dsize_after);
247 		return;
248 	} else {
249 		tst_resm(TINFO, "if_freenameindex passed %d iterations", i);
250 	}
251 
252 	tst_resm(TPASS, "if_nameindex() tests succeed");
253 }
254 
setup(void)255 void setup(void)
256 {
257 	TEST_PAUSE;
258 
259 	tst_resm(TINFO, "get interface name from LHOST_IFACES var");
260 
261 	char *ifnames = getenv("LHOST_IFACES");
262 
263 	if (!ifnames) {
264 		tst_resm(TWARN, "LHOST_IFACES not defined, default to eth0");
265 		return;
266 	}
267 
268 	static char name[256];
269 
270 	sscanf(ifnames, "%255s", name);
271 
272 	if (!strcmp(name, n2i[1].name))
273 		return;
274 
275 	tst_resm(TINFO, "change default 'eth0' name to '%s'", name);
276 	n2i[1].name = name;
277 }
278