1 /* 2 * rt_names.c rtnetlink names DB. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Alexey Kuznetsov, <kuznet (at) ms2.inr.ac.ru> 10 */ 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <unistd.h> 15 #include <syslog.h> 16 #include <fcntl.h> 17 #include <string.h> 18 #include <sys/time.h> 19 #include <sys/socket.h> 20 21 #include <asm/types.h> 22 #include <linux/rtnetlink.h> 23 24 #include "rt_names.h" 25 26 struct rtnl_hash_entry { 27 struct rtnl_hash_entry *next; 28 char * name; 29 unsigned int id; 30 }; 31 32 static void 33 rtnl_hash_initialize(char *file, struct rtnl_hash_entry **hash, int size) 34 { 35 struct rtnl_hash_entry *entry; 36 char buf[512]; 37 FILE *fp; 38 39 fp = fopen(file, "r"); 40 if (!fp) 41 return; 42 while (fgets(buf, sizeof(buf), fp)) { 43 char *p = buf; 44 int id; 45 char namebuf[512]; 46 47 while (*p == ' ' || *p == '\t') 48 p++; 49 if (*p == '#' || *p == '\n' || *p == 0) 50 continue; 51 if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 && 52 sscanf(p, "0x%x %s #", &id, namebuf) != 2 && 53 sscanf(p, "%d %s\n", &id, namebuf) != 2 && 54 sscanf(p, "%d %s #", &id, namebuf) != 2) { 55 fprintf(stderr, "Database %s is corrupted at %s\n", 56 file, p); 57 return; 58 } 59 60 if (id<0) 61 continue; 62 entry = malloc(sizeof(*entry)); 63 entry->id = id; 64 entry->name = strdup(namebuf); 65 entry->next = hash[id & (size - 1)]; 66 hash[id & (size - 1)] = entry; 67 } 68 fclose(fp); 69 } 70 71 static void rtnl_tab_initialize(char *file, char **tab, int size) 72 { 73 char buf[512]; 74 FILE *fp; 75 76 fp = fopen(file, "r"); 77 if (!fp) 78 return; 79 while (fgets(buf, sizeof(buf), fp)) { 80 char *p = buf; 81 int id; 82 char namebuf[512]; 83 84 while (*p == ' ' || *p == '\t') 85 p++; 86 if (*p == '#' || *p == '\n' || *p == 0) 87 continue; 88 if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 && 89 sscanf(p, "0x%x %s #", &id, namebuf) != 2 && 90 sscanf(p, "%d %s\n", &id, namebuf) != 2 && 91 sscanf(p, "%d %s #", &id, namebuf) != 2) { 92 fprintf(stderr, "Database %s is corrupted at %s\n", 93 file, p); 94 return; 95 } 96 97 if (id<0 || id>size) 98 continue; 99 100 tab[id] = strdup(namebuf); 101 } 102 fclose(fp); 103 } 104 105 static char * rtnl_rtprot_tab[256] = { 106 [RTPROT_UNSPEC] = "none", 107 [RTPROT_REDIRECT] ="redirect", 108 [RTPROT_KERNEL] = "kernel", 109 [RTPROT_BOOT] = "boot", 110 [RTPROT_STATIC] = "static", 111 112 [RTPROT_GATED] = "gated", 113 [RTPROT_RA] = "ra", 114 [RTPROT_MRT] = "mrt", 115 [RTPROT_ZEBRA] ="zebra", 116 [RTPROT_BIRD] = "bird", 117 [RTPROT_DNROUTED] = "dnrouted", 118 [RTPROT_XORP] = "xorp", 119 [RTPROT_NTK] = "ntk", 120 [RTPROT_DHCP] = "dhcp", 121 }; 122 123 124 125 static int rtnl_rtprot_init; 126 127 static void rtnl_rtprot_initialize(void) 128 { 129 rtnl_rtprot_init = 1; 130 rtnl_tab_initialize("/etc/iproute2/rt_protos", 131 rtnl_rtprot_tab, 256); 132 } 133 134 char * rtnl_rtprot_n2a(int id, char *buf, int len) 135 { 136 if (id<0 || id>=256) { 137 snprintf(buf, len, "%d", id); 138 return buf; 139 } 140 if (!rtnl_rtprot_tab[id]) { 141 if (!rtnl_rtprot_init) 142 rtnl_rtprot_initialize(); 143 } 144 if (rtnl_rtprot_tab[id]) 145 return rtnl_rtprot_tab[id]; 146 snprintf(buf, len, "%d", id); 147 return buf; 148 } 149 150 int rtnl_rtprot_a2n(__u32 *id, char *arg) 151 { 152 static char *cache = NULL; 153 static unsigned long res; 154 char *end; 155 int i; 156 157 if (cache && strcmp(cache, arg) == 0) { 158 *id = res; 159 return 0; 160 } 161 162 if (!rtnl_rtprot_init) 163 rtnl_rtprot_initialize(); 164 165 for (i=0; i<256; i++) { 166 if (rtnl_rtprot_tab[i] && 167 strcmp(rtnl_rtprot_tab[i], arg) == 0) { 168 cache = rtnl_rtprot_tab[i]; 169 res = i; 170 *id = res; 171 return 0; 172 } 173 } 174 175 res = strtoul(arg, &end, 0); 176 if (!end || end == arg || *end || res > 255) 177 return -1; 178 *id = res; 179 return 0; 180 } 181 182 183 184 static char * rtnl_rtscope_tab[256] = { 185 "global", 186 }; 187 188 static int rtnl_rtscope_init; 189 190 static void rtnl_rtscope_initialize(void) 191 { 192 rtnl_rtscope_init = 1; 193 rtnl_rtscope_tab[255] = "nowhere"; 194 rtnl_rtscope_tab[254] = "host"; 195 rtnl_rtscope_tab[253] = "link"; 196 rtnl_rtscope_tab[200] = "site"; 197 rtnl_tab_initialize("/etc/iproute2/rt_scopes", 198 rtnl_rtscope_tab, 256); 199 } 200 201 char * rtnl_rtscope_n2a(int id, char *buf, int len) 202 { 203 if (id<0 || id>=256) { 204 snprintf(buf, len, "%d", id); 205 return buf; 206 } 207 if (!rtnl_rtscope_tab[id]) { 208 if (!rtnl_rtscope_init) 209 rtnl_rtscope_initialize(); 210 } 211 if (rtnl_rtscope_tab[id]) 212 return rtnl_rtscope_tab[id]; 213 snprintf(buf, len, "%d", id); 214 return buf; 215 } 216 217 int rtnl_rtscope_a2n(__u32 *id, char *arg) 218 { 219 static char *cache = NULL; 220 static unsigned long res; 221 char *end; 222 int i; 223 224 if (cache && strcmp(cache, arg) == 0) { 225 *id = res; 226 return 0; 227 } 228 229 if (!rtnl_rtscope_init) 230 rtnl_rtscope_initialize(); 231 232 for (i=0; i<256; i++) { 233 if (rtnl_rtscope_tab[i] && 234 strcmp(rtnl_rtscope_tab[i], arg) == 0) { 235 cache = rtnl_rtscope_tab[i]; 236 res = i; 237 *id = res; 238 return 0; 239 } 240 } 241 242 res = strtoul(arg, &end, 0); 243 if (!end || end == arg || *end || res > 255) 244 return -1; 245 *id = res; 246 return 0; 247 } 248 249 250 251 static char * rtnl_rtrealm_tab[256] = { 252 "unknown", 253 }; 254 255 static int rtnl_rtrealm_init; 256 257 static void rtnl_rtrealm_initialize(void) 258 { 259 rtnl_rtrealm_init = 1; 260 rtnl_tab_initialize("/etc/iproute2/rt_realms", 261 rtnl_rtrealm_tab, 256); 262 } 263 264 char * rtnl_rtrealm_n2a(int id, char *buf, int len) 265 { 266 if (id<0 || id>=256) { 267 snprintf(buf, len, "%d", id); 268 return buf; 269 } 270 if (!rtnl_rtrealm_tab[id]) { 271 if (!rtnl_rtrealm_init) 272 rtnl_rtrealm_initialize(); 273 } 274 if (rtnl_rtrealm_tab[id]) 275 return rtnl_rtrealm_tab[id]; 276 snprintf(buf, len, "%d", id); 277 return buf; 278 } 279 280 281 int rtnl_rtrealm_a2n(__u32 *id, char *arg) 282 { 283 static char *cache = NULL; 284 static unsigned long res; 285 char *end; 286 int i; 287 288 if (cache && strcmp(cache, arg) == 0) { 289 *id = res; 290 return 0; 291 } 292 293 if (!rtnl_rtrealm_init) 294 rtnl_rtrealm_initialize(); 295 296 for (i=0; i<256; i++) { 297 if (rtnl_rtrealm_tab[i] && 298 strcmp(rtnl_rtrealm_tab[i], arg) == 0) { 299 cache = rtnl_rtrealm_tab[i]; 300 res = i; 301 *id = res; 302 return 0; 303 } 304 } 305 306 res = strtoul(arg, &end, 0); 307 if (!end || end == arg || *end || res > 255) 308 return -1; 309 *id = res; 310 return 0; 311 } 312 313 314 static struct rtnl_hash_entry dflt_table_entry = { .id = 253, .name = "default" }; 315 static struct rtnl_hash_entry main_table_entry = { .id = 254, .name = "main" }; 316 static struct rtnl_hash_entry local_table_entry = { .id = 255, .name = "local" }; 317 318 static struct rtnl_hash_entry * rtnl_rttable_hash[256] = { 319 [253] = &dflt_table_entry, 320 [254] = &main_table_entry, 321 [255] = &local_table_entry, 322 }; 323 324 static int rtnl_rttable_init; 325 326 static void rtnl_rttable_initialize(void) 327 { 328 rtnl_rttable_init = 1; 329 rtnl_hash_initialize("/etc/iproute2/rt_tables", 330 rtnl_rttable_hash, 256); 331 } 332 333 char * rtnl_rttable_n2a(__u32 id, char *buf, int len) 334 { 335 struct rtnl_hash_entry *entry; 336 337 if (id > RT_TABLE_MAX) { 338 snprintf(buf, len, "%u", id); 339 return buf; 340 } 341 if (!rtnl_rttable_init) 342 rtnl_rttable_initialize(); 343 entry = rtnl_rttable_hash[id & 255]; 344 while (entry && entry->id != id) 345 entry = entry->next; 346 if (entry) 347 return entry->name; 348 snprintf(buf, len, "%u", id); 349 return buf; 350 } 351 352 int rtnl_rttable_a2n(__u32 *id, char *arg) 353 { 354 static char *cache = NULL; 355 static unsigned long res; 356 struct rtnl_hash_entry *entry; 357 char *end; 358 __u32 i; 359 360 if (cache && strcmp(cache, arg) == 0) { 361 *id = res; 362 return 0; 363 } 364 365 if (!rtnl_rttable_init) 366 rtnl_rttable_initialize(); 367 368 for (i=0; i<256; i++) { 369 entry = rtnl_rttable_hash[i]; 370 while (entry && strcmp(entry->name, arg)) 371 entry = entry->next; 372 if (entry) { 373 cache = entry->name; 374 res = entry->id; 375 *id = res; 376 return 0; 377 } 378 } 379 380 i = strtoul(arg, &end, 0); 381 if (!end || end == arg || *end || i > RT_TABLE_MAX) 382 return -1; 383 *id = i; 384 return 0; 385 } 386 387 388 static char * rtnl_rtdsfield_tab[256] = { 389 "0", 390 }; 391 392 static int rtnl_rtdsfield_init; 393 394 static void rtnl_rtdsfield_initialize(void) 395 { 396 rtnl_rtdsfield_init = 1; 397 rtnl_tab_initialize("/etc/iproute2/rt_dsfield", 398 rtnl_rtdsfield_tab, 256); 399 } 400 401 char * rtnl_dsfield_n2a(int id, char *buf, int len) 402 { 403 if (id<0 || id>=256) { 404 snprintf(buf, len, "%d", id); 405 return buf; 406 } 407 if (!rtnl_rtdsfield_tab[id]) { 408 if (!rtnl_rtdsfield_init) 409 rtnl_rtdsfield_initialize(); 410 } 411 if (rtnl_rtdsfield_tab[id]) 412 return rtnl_rtdsfield_tab[id]; 413 snprintf(buf, len, "0x%02x", id); 414 return buf; 415 } 416 417 418 int rtnl_dsfield_a2n(__u32 *id, char *arg) 419 { 420 static char *cache = NULL; 421 static unsigned long res; 422 char *end; 423 int i; 424 425 if (cache && strcmp(cache, arg) == 0) { 426 *id = res; 427 return 0; 428 } 429 430 if (!rtnl_rtdsfield_init) 431 rtnl_rtdsfield_initialize(); 432 433 for (i=0; i<256; i++) { 434 if (rtnl_rtdsfield_tab[i] && 435 strcmp(rtnl_rtdsfield_tab[i], arg) == 0) { 436 cache = rtnl_rtdsfield_tab[i]; 437 res = i; 438 *id = res; 439 return 0; 440 } 441 } 442 443 res = strtoul(arg, &end, 16); 444 if (!end || end == arg || *end || res > 255) 445 return -1; 446 *id = res; 447 return 0; 448 } 449 450