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 #ifndef CONFDIR 27 #define CONFDIR "/etc/iproute2" 28 #endif 29 30 struct rtnl_hash_entry { 31 struct rtnl_hash_entry *next; 32 char * name; 33 unsigned int id; 34 }; 35 36 static void 37 rtnl_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 76 static 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 111 static 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 131 static int rtnl_rtprot_init; 132 133 static 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 140 char * 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 156 int 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 190 static char * rtnl_rtscope_tab[256] = { 191 "global", 192 }; 193 194 static int rtnl_rtscope_init; 195 196 static 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 207 char * 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 223 int 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 257 static char * rtnl_rtrealm_tab[256] = { 258 "unknown", 259 }; 260 261 static int rtnl_rtrealm_init; 262 263 static 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 270 char * 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 287 int 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 320 static struct rtnl_hash_entry dflt_table_entry = { .id = 253, .name = "default" }; 321 static struct rtnl_hash_entry main_table_entry = { .id = 254, .name = "main" }; 322 static struct rtnl_hash_entry local_table_entry = { .id = 255, .name = "local" }; 323 324 static 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 330 static int rtnl_rttable_init; 331 332 static 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 339 char * 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 358 int 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 394 static char * rtnl_rtdsfield_tab[256] = { 395 "0", 396 }; 397 398 static int rtnl_rtdsfield_init; 399 400 static 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 407 char * 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 424 int 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 457 static struct rtnl_hash_entry dflt_group_entry = { .id = 0, .name = "default" }; 458 459 static struct rtnl_hash_entry * rtnl_group_hash[256] = { 460 [0] = &dflt_group_entry, 461 }; 462 463 static int rtnl_group_init; 464 465 static 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 472 int 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