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 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