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 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 */ 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 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 */ 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 */ 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 */ 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 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