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