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