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@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#ifndef CONFDIR 27#define CONFDIR "/etc/iproute2" 28#endif 29 30struct rtnl_hash_entry { 31 struct rtnl_hash_entry *next; 32 char * name; 33 unsigned int id; 34}; 35 36static void 37rtnl_hash_initialize(char *file, struct rtnl_hash_entry **hash, int size) 38{ 39 struct rtnl_hash_entry *entry; 40 char buf[512]; 41 FILE *fp; 42 43 fp = fopen(file, "r"); 44 if (!fp) 45 return; 46 while (fgets(buf, sizeof(buf), fp)) { 47 char *p = buf; 48 int id; 49 char namebuf[512]; 50 51 while (*p == ' ' || *p == '\t') 52 p++; 53 if (*p == '#' || *p == '\n' || *p == 0) 54 continue; 55 if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 && 56 sscanf(p, "0x%x %s #", &id, namebuf) != 2 && 57 sscanf(p, "%d %s\n", &id, namebuf) != 2 && 58 sscanf(p, "%d %s #", &id, namebuf) != 2) { 59 fprintf(stderr, "Database %s is corrupted at %s\n", 60 file, p); 61 fclose(fp); 62 return; 63 } 64 65 if (id<0) 66 continue; 67 entry = malloc(sizeof(*entry)); 68 entry->id = id; 69 entry->name = strdup(namebuf); 70 entry->next = hash[id & (size - 1)]; 71 hash[id & (size - 1)] = entry; 72 } 73 fclose(fp); 74} 75 76static void rtnl_tab_initialize(char *file, char **tab, int size) 77{ 78 char buf[512]; 79 FILE *fp; 80 81 fp = fopen(file, "r"); 82 if (!fp) 83 return; 84 while (fgets(buf, sizeof(buf), fp)) { 85 char *p = buf; 86 int id; 87 char namebuf[512]; 88 89 while (*p == ' ' || *p == '\t') 90 p++; 91 if (*p == '#' || *p == '\n' || *p == 0) 92 continue; 93 if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 && 94 sscanf(p, "0x%x %s #", &id, namebuf) != 2 && 95 sscanf(p, "%d %s\n", &id, namebuf) != 2 && 96 sscanf(p, "%d %s #", &id, namebuf) != 2) { 97 fprintf(stderr, "Database %s is corrupted at %s\n", 98 file, p); 99 fclose(fp); 100 return; 101 } 102 103 if (id<0 || id>size) 104 continue; 105 106 tab[id] = strdup(namebuf); 107 } 108 fclose(fp); 109} 110 111static char * rtnl_rtprot_tab[256] = { 112 [RTPROT_UNSPEC] = "none", 113 [RTPROT_REDIRECT] ="redirect", 114 [RTPROT_KERNEL] = "kernel", 115 [RTPROT_BOOT] = "boot", 116 [RTPROT_STATIC] = "static", 117 118 [RTPROT_GATED] = "gated", 119 [RTPROT_RA] = "ra", 120 [RTPROT_MRT] = "mrt", 121 [RTPROT_ZEBRA] ="zebra", 122 [RTPROT_BIRD] = "bird", 123 [RTPROT_DNROUTED] = "dnrouted", 124 [RTPROT_XORP] = "xorp", 125 [RTPROT_NTK] = "ntk", 126 [RTPROT_DHCP] = "dhcp", 127}; 128 129 130 131static int rtnl_rtprot_init; 132 133static void rtnl_rtprot_initialize(void) 134{ 135 rtnl_rtprot_init = 1; 136 rtnl_tab_initialize(CONFDIR "/rt_protos", 137 rtnl_rtprot_tab, 256); 138} 139 140char * rtnl_rtprot_n2a(int id, char *buf, int len) 141{ 142 if (id<0 || id>=256) { 143 snprintf(buf, len, "%d", id); 144 return buf; 145 } 146 if (!rtnl_rtprot_tab[id]) { 147 if (!rtnl_rtprot_init) 148 rtnl_rtprot_initialize(); 149 } 150 if (rtnl_rtprot_tab[id]) 151 return rtnl_rtprot_tab[id]; 152 snprintf(buf, len, "%d", id); 153 return buf; 154} 155 156int rtnl_rtprot_a2n(__u32 *id, char *arg) 157{ 158 static char *cache = NULL; 159 static unsigned long res; 160 char *end; 161 int i; 162 163 if (cache && strcmp(cache, arg) == 0) { 164 *id = res; 165 return 0; 166 } 167 168 if (!rtnl_rtprot_init) 169 rtnl_rtprot_initialize(); 170 171 for (i=0; i<256; i++) { 172 if (rtnl_rtprot_tab[i] && 173 strcmp(rtnl_rtprot_tab[i], arg) == 0) { 174 cache = rtnl_rtprot_tab[i]; 175 res = i; 176 *id = res; 177 return 0; 178 } 179 } 180 181 res = strtoul(arg, &end, 0); 182 if (!end || end == arg || *end || res > 255) 183 return -1; 184 *id = res; 185 return 0; 186} 187 188 189 190static char * rtnl_rtscope_tab[256] = { 191 "global", 192}; 193 194static int rtnl_rtscope_init; 195 196static void rtnl_rtscope_initialize(void) 197{ 198 rtnl_rtscope_init = 1; 199 rtnl_rtscope_tab[255] = "nowhere"; 200 rtnl_rtscope_tab[254] = "host"; 201 rtnl_rtscope_tab[253] = "link"; 202 rtnl_rtscope_tab[200] = "site"; 203 rtnl_tab_initialize(CONFDIR "/rt_scopes", 204 rtnl_rtscope_tab, 256); 205} 206 207char * rtnl_rtscope_n2a(int id, char *buf, int len) 208{ 209 if (id<0 || id>=256) { 210 snprintf(buf, len, "%d", id); 211 return buf; 212 } 213 if (!rtnl_rtscope_tab[id]) { 214 if (!rtnl_rtscope_init) 215 rtnl_rtscope_initialize(); 216 } 217 if (rtnl_rtscope_tab[id]) 218 return rtnl_rtscope_tab[id]; 219 snprintf(buf, len, "%d", id); 220 return buf; 221} 222 223int rtnl_rtscope_a2n(__u32 *id, char *arg) 224{ 225 static char *cache = NULL; 226 static unsigned long res; 227 char *end; 228 int i; 229 230 if (cache && strcmp(cache, arg) == 0) { 231 *id = res; 232 return 0; 233 } 234 235 if (!rtnl_rtscope_init) 236 rtnl_rtscope_initialize(); 237 238 for (i=0; i<256; i++) { 239 if (rtnl_rtscope_tab[i] && 240 strcmp(rtnl_rtscope_tab[i], arg) == 0) { 241 cache = rtnl_rtscope_tab[i]; 242 res = i; 243 *id = res; 244 return 0; 245 } 246 } 247 248 res = strtoul(arg, &end, 0); 249 if (!end || end == arg || *end || res > 255) 250 return -1; 251 *id = res; 252 return 0; 253} 254 255 256 257static char * rtnl_rtrealm_tab[256] = { 258 "unknown", 259}; 260 261static int rtnl_rtrealm_init; 262 263static void rtnl_rtrealm_initialize(void) 264{ 265 rtnl_rtrealm_init = 1; 266 rtnl_tab_initialize(CONFDIR "/rt_realms", 267 rtnl_rtrealm_tab, 256); 268} 269 270char * rtnl_rtrealm_n2a(int id, char *buf, int len) 271{ 272 if (id<0 || id>=256) { 273 snprintf(buf, len, "%d", id); 274 return buf; 275 } 276 if (!rtnl_rtrealm_tab[id]) { 277 if (!rtnl_rtrealm_init) 278 rtnl_rtrealm_initialize(); 279 } 280 if (rtnl_rtrealm_tab[id]) 281 return rtnl_rtrealm_tab[id]; 282 snprintf(buf, len, "%d", id); 283 return buf; 284} 285 286 287int rtnl_rtrealm_a2n(__u32 *id, char *arg) 288{ 289 static char *cache = NULL; 290 static unsigned long res; 291 char *end; 292 int i; 293 294 if (cache && strcmp(cache, arg) == 0) { 295 *id = res; 296 return 0; 297 } 298 299 if (!rtnl_rtrealm_init) 300 rtnl_rtrealm_initialize(); 301 302 for (i=0; i<256; i++) { 303 if (rtnl_rtrealm_tab[i] && 304 strcmp(rtnl_rtrealm_tab[i], arg) == 0) { 305 cache = rtnl_rtrealm_tab[i]; 306 res = i; 307 *id = res; 308 return 0; 309 } 310 } 311 312 res = strtoul(arg, &end, 0); 313 if (!end || end == arg || *end || res > 255) 314 return -1; 315 *id = res; 316 return 0; 317} 318 319 320static struct rtnl_hash_entry dflt_table_entry = { .id = 253, .name = "default" }; 321static struct rtnl_hash_entry main_table_entry = { .id = 254, .name = "main" }; 322static struct rtnl_hash_entry local_table_entry = { .id = 255, .name = "local" }; 323 324static struct rtnl_hash_entry * rtnl_rttable_hash[256] = { 325 [253] = &dflt_table_entry, 326 [254] = &main_table_entry, 327 [255] = &local_table_entry, 328}; 329 330static int rtnl_rttable_init; 331 332static void rtnl_rttable_initialize(void) 333{ 334 rtnl_rttable_init = 1; 335 rtnl_hash_initialize(CONFDIR "/rt_tables", 336 rtnl_rttable_hash, 256); 337} 338 339char * rtnl_rttable_n2a(__u32 id, char *buf, int len) 340{ 341 struct rtnl_hash_entry *entry; 342 343 if (id > RT_TABLE_MAX) { 344 snprintf(buf, len, "%u", id); 345 return buf; 346 } 347 if (!rtnl_rttable_init) 348 rtnl_rttable_initialize(); 349 entry = rtnl_rttable_hash[id & 255]; 350 while (entry && entry->id != id) 351 entry = entry->next; 352 if (entry) 353 return entry->name; 354 snprintf(buf, len, "%u", id); 355 return buf; 356} 357 358int rtnl_rttable_a2n(__u32 *id, char *arg) 359{ 360 static char *cache = NULL; 361 static unsigned long res; 362 struct rtnl_hash_entry *entry; 363 char *end; 364 __u32 i; 365 366 if (cache && strcmp(cache, arg) == 0) { 367 *id = res; 368 return 0; 369 } 370 371 if (!rtnl_rttable_init) 372 rtnl_rttable_initialize(); 373 374 for (i=0; i<256; i++) { 375 entry = rtnl_rttable_hash[i]; 376 while (entry && strcmp(entry->name, arg)) 377 entry = entry->next; 378 if (entry) { 379 cache = entry->name; 380 res = entry->id; 381 *id = res; 382 return 0; 383 } 384 } 385 386 i = strtoul(arg, &end, 0); 387 if (!end || end == arg || *end || i > RT_TABLE_MAX) 388 return -1; 389 *id = i; 390 return 0; 391} 392 393 394static char * rtnl_rtdsfield_tab[256] = { 395 "0", 396}; 397 398static int rtnl_rtdsfield_init; 399 400static void rtnl_rtdsfield_initialize(void) 401{ 402 rtnl_rtdsfield_init = 1; 403 rtnl_tab_initialize(CONFDIR "/rt_dsfield", 404 rtnl_rtdsfield_tab, 256); 405} 406 407char * rtnl_dsfield_n2a(int id, char *buf, int len) 408{ 409 if (id<0 || id>=256) { 410 snprintf(buf, len, "%d", id); 411 return buf; 412 } 413 if (!rtnl_rtdsfield_tab[id]) { 414 if (!rtnl_rtdsfield_init) 415 rtnl_rtdsfield_initialize(); 416 } 417 if (rtnl_rtdsfield_tab[id]) 418 return rtnl_rtdsfield_tab[id]; 419 snprintf(buf, len, "0x%02x", id); 420 return buf; 421} 422 423 424int rtnl_dsfield_a2n(__u32 *id, char *arg) 425{ 426 static char *cache = NULL; 427 static unsigned long res; 428 char *end; 429 int i; 430 431 if (cache && strcmp(cache, arg) == 0) { 432 *id = res; 433 return 0; 434 } 435 436 if (!rtnl_rtdsfield_init) 437 rtnl_rtdsfield_initialize(); 438 439 for (i=0; i<256; i++) { 440 if (rtnl_rtdsfield_tab[i] && 441 strcmp(rtnl_rtdsfield_tab[i], arg) == 0) { 442 cache = rtnl_rtdsfield_tab[i]; 443 res = i; 444 *id = res; 445 return 0; 446 } 447 } 448 449 res = strtoul(arg, &end, 16); 450 if (!end || end == arg || *end || res > 255) 451 return -1; 452 *id = res; 453 return 0; 454} 455 456 457static struct rtnl_hash_entry dflt_group_entry = { .id = 0, .name = "default" }; 458 459static struct rtnl_hash_entry * rtnl_group_hash[256] = { 460 [0] = &dflt_group_entry, 461}; 462 463static int rtnl_group_init; 464 465static void rtnl_group_initialize(void) 466{ 467 rtnl_group_init = 1; 468 rtnl_hash_initialize("/etc/iproute2/group", 469 rtnl_group_hash, 256); 470} 471 472int rtnl_group_a2n(int *id, char *arg) 473{ 474 static char *cache = NULL; 475 static unsigned long res; 476 struct rtnl_hash_entry *entry; 477 char *end; 478 int i; 479 480 if (cache && strcmp(cache, arg) == 0) { 481 *id = res; 482 return 0; 483 } 484 485 if (!rtnl_group_init) 486 rtnl_group_initialize(); 487 488 for (i=0; i<256; i++) { 489 entry = rtnl_group_hash[i]; 490 while (entry && strcmp(entry->name, arg)) 491 entry = entry->next; 492 if (entry) { 493 cache = entry->name; 494 res = entry->id; 495 *id = res; 496 return 0; 497 } 498 } 499 500 i = strtol(arg, &end, 0); 501 if (!end || end == arg || *end || i < 0) 502 return -1; 503 *id = i; 504 return 0; 505} 506