Home | History | Annotate | Download | only in lib
      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