utils.c revision 3c56ed5787481a06703ffb25561df3dd56b447bd
11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/* 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * lib/utils.c Utility Functions 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * This library is free software; you can redistribute it and/or 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * modify it under the terms of the GNU Lesser General Public 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * License as published by the Free Software Foundation version 2.1 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * of the License. 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @defgroup utils Utilities 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @{ 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <netlink-local.h> 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <netlink/netlink.h> 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <netlink/utils.h> 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <linux/socket.h> 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Debug level 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint nl_debug = 0; 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct nl_dump_params nl_debug_dp = { 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci .dp_type = NL_DUMP_FULL, 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic void __init nl_debug_init(void) 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{ 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci char *nldbg, *end; 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((nldbg = getenv("NLDBG"))) { 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci long level = strtol(nldbg, &end, 0); 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (nldbg != end) 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nl_debug = level; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nl_debug_dp.dp_fd = stderr; 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @name Error Code Helpers 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @{ 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic char *errbuf; 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic int nlerrno; 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** @cond SKIP */ 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint __nl_error(int err, const char *file, unsigned int line, const char *func, 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const char *fmt, ...) 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{ 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci char *user_err; 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci va_list args; 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (errbuf) { 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci free(errbuf); 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci errbuf = NULL; 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nlerrno = err; 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (fmt) { 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci va_start(args, fmt); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci vasprintf(&user_err, fmt, args); 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci va_end(args); 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#ifdef VERBOSE_ERRORS 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci asprintf(&errbuf, "%s:%u:%s: %s (errno = %s)", 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file, line, func, fmt ? user_err : "", strerror(err)); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci asprintf(&errbuf, "%s (errno = %s)", 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fmt ? user_err : "", strerror(err)); 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (fmt) 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci free(user_err); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return -err; 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{ 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FILE *fd; 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci char buf[128]; 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fd = fopen(path, "r"); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (fd == NULL) 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return nl_error(errno, "Unable to open file %s for reading", 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci path); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci while (fgets(buf, sizeof(buf), fd)) { 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int goodlen, err; 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci long num; 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci char *end; 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (*buf == '#' || *buf == '\n' || *buf == '\r') 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci num = strtol(buf, &end, 0); 105 if (end == buf) 106 return nl_error(EINVAL, "Parsing error"); 107 108 if (num == LONG_MIN || num == LONG_MAX) 109 return nl_error(errno, "Number of out range"); 110 111 while (*end == ' ' || *end == '\t') 112 end++; 113 114 goodlen = strcspn(end, "#\r\n\t "); 115 if (goodlen == 0) 116 return nl_error(EINVAL, "Empty string"); 117 118 end[goodlen] = '\0'; 119 120 err = cb(num, end); 121 if (err < 0) 122 return err; 123 } 124 125 fclose(fd); 126 127 return 0; 128} 129 130/** @endcond */ 131 132int nl_get_errno(void) 133{ 134 return nlerrno; 135} 136 137 138/** 139 * Return error message for an error code 140 * @return error message 141 */ 142char *nl_geterror(void) 143{ 144 if (errbuf) 145 return errbuf; 146 147 if (nlerrno) 148 return strerror(nlerrno); 149 150 return "Sucess\n"; 151} 152 153/** 154 * Print a libnl error message 155 * @arg s error message prefix 156 * 157 * Prints the error message of the call that failed last. 158 * 159 * If s is not NULL and *s is not a null byte the argument 160 * string is printed, followed by a colon and a blank. Then 161 * the error message and a new-line. 162 */ 163void nl_perror(const char *s) 164{ 165 if (s && *s) 166 fprintf(stderr, "%s: %s\n", s, nl_geterror()); 167 else 168 fprintf(stderr, "%s\n", nl_geterror()); 169} 170 171/** @} */ 172 173/** 174 * @name Unit Pretty-Printing 175 * @{ 176 */ 177 178/** 179 * Cancel down a byte counter 180 * @arg l byte counter 181 * @arg unit destination unit pointer 182 * 183 * Cancels down a byte counter until it reaches a reasonable 184 * unit. The chosen unit is assigned to \a unit. 185 * 186 * @return The cancelled down byte counter in the new unit. 187 */ 188double nl_cancel_down_bytes(unsigned long long l, char **unit) 189{ 190 if (l >= 1099511627776LL) { 191 *unit = "TiB"; 192 return ((double) l) / 1099511627776LL; 193 } else if (l >= 1073741824) { 194 *unit = "GiB"; 195 return ((double) l) / 1073741824; 196 } else if (l >= 1048576) { 197 *unit = "MiB"; 198 return ((double) l) / 1048576; 199 } else if (l >= 1024) { 200 *unit = "KiB"; 201 return ((double) l) / 1024; 202 } else { 203 *unit = "B"; 204 return (double) l; 205 } 206} 207 208/** 209 * Cancel down a bit counter 210 * @arg l bit counter 211 * @arg unit destination unit pointer 212 * 213 * Cancels downa bit counter until it reaches a reasonable 214 * unit. The chosen unit is assigned to \a unit. 215 * 216 * @return The cancelled down bit counter in the new unit. 217 */ 218double nl_cancel_down_bits(unsigned long long l, char **unit) 219{ 220 if (l >= 1099511627776ULL) { 221 *unit = "Tbit"; 222 return ((double) l) / 1099511627776ULL; 223 } else if (l >= 1073741824) { 224 *unit = "Gbit"; 225 return ((double) l) / 1073741824; 226 } else if (l >= 1048576) { 227 *unit = "Mbit"; 228 return ((double) l) / 1048576; 229 } else if (l >= 1024) { 230 *unit = "Kbit"; 231 return ((double) l) / 1024; 232 } else { 233 *unit = "bit"; 234 return (double) l; 235 } 236 237} 238 239/** 240 * Cancel down a micro second value 241 * @arg l micro seconds 242 * @arg unit destination unit pointer 243 * 244 * Cancels down a microsecond counter until it reaches a 245 * reasonable unit. The chosen unit is assigned to \a unit. 246 * 247 * @return The cancelled down microsecond in the new unit 248 */ 249double nl_cancel_down_us(uint32_t l, char **unit) 250{ 251 if (l >= 1000000) { 252 *unit = "s"; 253 return ((double) l) / 1000000; 254 } else if (l >= 1000) { 255 *unit = "ms"; 256 return ((double) l) / 1000; 257 } else { 258 *unit = "us"; 259 return (double) l; 260 } 261} 262 263/** @} */ 264 265/** 266 * @name Generic Unit Translations 267 * @{ 268 */ 269 270/** 271 * Convert a character string to a size 272 * @arg str size encoded as character string 273 * 274 * Converts the specified size as character to the corresponding 275 * number of bytes. 276 * 277 * Supported formats are: 278 * - b,kb/k,m/mb,gb/g for bytes 279 * - bit,kbit/mbit/gbit 280 * 281 * @return The number of bytes or -1 if the string is unparseable 282 */ 283long nl_size2int(const char *str) 284{ 285 char *p; 286 long l = strtol(str, &p, 0); 287 if (p == str) 288 return -1; 289 290 if (*p) { 291 if (!strcasecmp(p, "kb") || !strcasecmp(p, "k")) 292 l *= 1024; 293 else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g")) 294 l *= 1024*1024*1024; 295 else if (!strcasecmp(p, "gbit")) 296 l *= 1024*1024*1024/8; 297 else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m")) 298 l *= 1024*1024; 299 else if (!strcasecmp(p, "mbit")) 300 l *= 1024*1024/8; 301 else if (!strcasecmp(p, "kbit")) 302 l *= 1024/8; 303 else if (!strcasecmp(p, "bit")) 304 l /= 8; 305 else if (strcasecmp(p, "b") != 0) 306 return -1; 307 } 308 309 return l; 310} 311 312/** 313 * Convert a character string to a probability 314 * @arg str probability encoded as character string 315 * 316 * Converts the specified probability as character to the 317 * corresponding probability number. 318 * 319 * Supported formats are: 320 * - 0.0-1.0 321 * - 0%-100% 322 * 323 * @return The probability relative to NL_PROB_MIN and NL_PROB_MAX 324 */ 325long nl_prob2int(const char *str) 326{ 327 char *p; 328 double d = strtod(str, &p); 329 330 if (p == str) 331 return -1; 332 333 if (d > 1.0) 334 d /= 100.0f; 335 336 if (d > 1.0f || d < 0.0f) 337 return -1; 338 339 if (*p && strcmp(p, "%") != 0) 340 return -1; 341 342 return rint(d * NL_PROB_MAX); 343} 344 345/** @} */ 346 347/** 348 * @name Time Translations 349 * @{ 350 */ 351 352#ifdef USER_HZ 353static uint32_t user_hz = USER_HZ; 354#else 355static uint32_t user_hz = 100; 356#endif 357 358static double ticks_per_usec = 1.0f; 359 360/* Retrieves the configured HZ and ticks/us value in the kernel. 361 * The value is cached. Supported ways of getting it: 362 * 363 * 1) environment variable 364 * 2) /proc/net/psched and sysconf 365 * 366 * Supports the environment variables: 367 * PROC_NET_PSCHED - may point to psched file in /proc 368 * PROC_ROOT - may point to /proc fs */ 369static void __init get_psched_settings(void) 370{ 371 char name[FILENAME_MAX]; 372 FILE *fd; 373 int got_hz = 0, got_tick = 0; 374 375 if (getenv("HZ")) { 376 long hz = strtol(getenv("HZ"), NULL, 0); 377 378 if (LONG_MIN != hz && LONG_MAX != hz) { 379 user_hz = hz; 380 got_hz = 1; 381 } 382 } 383 384 if (!got_hz) 385 user_hz = sysconf(_SC_CLK_TCK); 386 387 if (getenv("TICKS_PER_USEC")) { 388 double t = strtod(getenv("TICKS_PER_USEC"), NULL); 389 390 ticks_per_usec = t; 391 got_tick = 1; 392 } 393 394 395 if (getenv("PROC_NET_PSCHED")) 396 snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED")); 397 else if (getenv("PROC_ROOT")) 398 snprintf(name, sizeof(name), "%s/net/psched", 399 getenv("PROC_ROOT")); 400 else 401 strncpy(name, "/proc/net/psched", sizeof(name) - 1); 402 403 if ((fd = fopen(name, "r"))) { 404 uint32_t tick, us, nom; 405 int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom); 406 407 if (4 == r && nom == 1000000 && !got_tick) 408 ticks_per_usec = (double)tick/(double)us; 409 410 fclose(fd); 411 } 412} 413 414 415/** 416 * Return the value of HZ 417 */ 418int nl_get_hz(void) 419{ 420 return user_hz; 421} 422 423 424/** 425 * Convert micro seconds to ticks 426 * @arg us micro seconds 427 * @return number of ticks 428 */ 429uint32_t nl_us2ticks(uint32_t us) 430{ 431 return us * ticks_per_usec; 432} 433 434 435/** 436 * Convert ticks to micro seconds 437 * @arg ticks number of ticks 438 * @return microseconds 439 */ 440uint32_t nl_ticks2us(uint32_t ticks) 441{ 442 return ticks / ticks_per_usec; 443} 444 445long nl_time2int(const char *str) 446{ 447 char *p; 448 long l = strtol(str, &p, 0); 449 if (p == str) 450 return -1; 451 452 if (*p) { 453 if (!strcasecmp(p, "min") == 0 || !strcasecmp(p, "m")) 454 l *= 60; 455 else if (!strcasecmp(p, "hour") || !strcasecmp(p, "h")) 456 l *= 60*60; 457 else if (!strcasecmp(p, "day") || !strcasecmp(p, "d")) 458 l *= 60*60*24; 459 else if (strcasecmp(p, "s") != 0) 460 return -1; 461 } 462 463 return l; 464} 465 466/** 467 * Convert milliseconds to a character string 468 * @arg msec number of milliseconds 469 * @arg buf destination buffer 470 * @arg len buffer length 471 * 472 * Converts milliseconds to a character string split up in days, hours, 473 * minutes, seconds, and milliseconds and stores it in the specified 474 * destination buffer. 475 * 476 * @return The destination buffer. 477 */ 478char * nl_msec2str(uint64_t msec, char *buf, size_t len) 479{ 480 int i, split[5]; 481 char *units[] = {"d", "h", "m", "s", "msec"}; 482 483#define _SPLIT(idx, unit) if ((split[idx] = msec / unit) > 0) msec %= unit 484 _SPLIT(0, 86400000); /* days */ 485 _SPLIT(1, 3600000); /* hours */ 486 _SPLIT(2, 60000); /* minutes */ 487 _SPLIT(3, 1000); /* seconds */ 488#undef _SPLIT 489 split[4] = msec; 490 491 memset(buf, 0, len); 492 493 for (i = 0; i < ARRAY_SIZE(split); i++) { 494 if (split[i] > 0) { 495 char t[64]; 496 snprintf(t, sizeof(t), "%s%d%s", 497 strlen(buf) ? " " : "", split[i], units[i]); 498 strncat(buf, t, len - strlen(buf) - 1); 499 } 500 } 501 502 return buf; 503} 504 505/** @} */ 506 507/** 508 * @name Link Layer Protocol Translations 509 * @{ 510 */ 511 512static struct trans_tbl llprotos[] = { 513 {0, "generic"}, 514 __ADD(ARPHRD_ETHER,ether) 515 __ADD(ARPHRD_EETHER,eether) 516 __ADD(ARPHRD_AX25,ax25) 517 __ADD(ARPHRD_PRONET,pronet) 518 __ADD(ARPHRD_CHAOS,chaos) 519 __ADD(ARPHRD_IEEE802,ieee802) 520 __ADD(ARPHRD_ARCNET,arcnet) 521 __ADD(ARPHRD_APPLETLK,atalk) 522 __ADD(ARPHRD_DLCI,dlci) 523 __ADD(ARPHRD_ATM,atm) 524 __ADD(ARPHRD_METRICOM,metricom) 525 __ADD(ARPHRD_IEEE1394,ieee1394) 526#ifdef ARPHRD_EUI64 527 __ADD(ARPHRD_EUI64,eui64) 528#endif 529 __ADD(ARPHRD_INFINIBAND,infiniband) 530 __ADD(ARPHRD_SLIP,slip) 531 __ADD(ARPHRD_CSLIP,cslip) 532 __ADD(ARPHRD_SLIP6,slip6) 533 __ADD(ARPHRD_CSLIP6,cslip6) 534 __ADD(ARPHRD_RSRVD,rsrvd) 535 __ADD(ARPHRD_ADAPT,adapt) 536 __ADD(ARPHRD_ROSE,rose) 537 __ADD(ARPHRD_X25,x25) 538#ifdef ARPHRD_HWX25 539 __ADD(ARPHRD_HWX25,hwx25) 540#endif 541 __ADD(ARPHRD_PPP,ppp) 542 __ADD(ARPHRD_HDLC,hdlc) 543 __ADD(ARPHRD_LAPB,lapb) 544 __ADD(ARPHRD_DDCMP,ddcmp) 545 __ADD(ARPHRD_RAWHDLC,rawhdlc) 546 __ADD(ARPHRD_TUNNEL,ipip) 547 __ADD(ARPHRD_TUNNEL6,tunnel6) 548 __ADD(ARPHRD_FRAD,frad) 549 __ADD(ARPHRD_SKIP,skip) 550 __ADD(ARPHRD_LOOPBACK,loopback) 551 __ADD(ARPHRD_LOCALTLK,localtlk) 552 __ADD(ARPHRD_FDDI,fddi) 553 __ADD(ARPHRD_BIF,bif) 554 __ADD(ARPHRD_SIT,sit) 555 __ADD(ARPHRD_IPDDP,ip/ddp) 556 __ADD(ARPHRD_IPGRE,gre) 557 __ADD(ARPHRD_PIMREG,pimreg) 558 __ADD(ARPHRD_HIPPI,hippi) 559 __ADD(ARPHRD_ASH,ash) 560 __ADD(ARPHRD_ECONET,econet) 561 __ADD(ARPHRD_IRDA,irda) 562 __ADD(ARPHRD_FCPP,fcpp) 563 __ADD(ARPHRD_FCAL,fcal) 564 __ADD(ARPHRD_FCPL,fcpl) 565 __ADD(ARPHRD_FCFABRIC,fcfb_0) 566 __ADD(ARPHRD_FCFABRIC+1,fcfb_1) 567 __ADD(ARPHRD_FCFABRIC+2,fcfb_2) 568 __ADD(ARPHRD_FCFABRIC+3,fcfb_3) 569 __ADD(ARPHRD_FCFABRIC+4,fcfb_4) 570 __ADD(ARPHRD_FCFABRIC+5,fcfb_5) 571 __ADD(ARPHRD_FCFABRIC+6,fcfb_6) 572 __ADD(ARPHRD_FCFABRIC+7,fcfb_7) 573 __ADD(ARPHRD_FCFABRIC+8,fcfb_8) 574 __ADD(ARPHRD_FCFABRIC+9,fcfb_9) 575 __ADD(ARPHRD_FCFABRIC+10,fcfb_10) 576 __ADD(ARPHRD_FCFABRIC+11,fcfb_11) 577 __ADD(ARPHRD_FCFABRIC+12,fcfb_12) 578 __ADD(ARPHRD_IEEE802_TR,tr) 579 __ADD(ARPHRD_IEEE80211,ieee802.11) 580#ifdef ARPHRD_IEEE80211_PRISM 581 __ADD(ARPHRD_IEEE80211_PRISM, ieee802.11_prism) 582#endif 583#ifdef ARPHRD_VOID 584 __ADD(ARPHRD_VOID,void) 585#endif 586}; 587 588char * nl_llproto2str(int llproto, char *buf, size_t len) 589{ 590 return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos)); 591} 592 593int nl_str2llproto(const char *name) 594{ 595 return __str2type(name, llprotos, ARRAY_SIZE(llprotos)); 596} 597 598/** @} */ 599 600 601/** 602 * @name Ethernet Protocol Translations 603 * @{ 604 */ 605 606static struct trans_tbl ether_protos[] = { 607 __ADD(ETH_P_LOOP,loop) 608 __ADD(ETH_P_PUP,pup) 609 __ADD(ETH_P_PUPAT,pupat) 610 __ADD(ETH_P_IP,ip) 611 __ADD(ETH_P_X25,x25) 612 __ADD(ETH_P_ARP,arp) 613 __ADD(ETH_P_BPQ,bpq) 614 __ADD(ETH_P_IEEEPUP,ieeepup) 615 __ADD(ETH_P_IEEEPUPAT,ieeepupat) 616 __ADD(ETH_P_DEC,dec) 617 __ADD(ETH_P_DNA_DL,dna_dl) 618 __ADD(ETH_P_DNA_RC,dna_rc) 619 __ADD(ETH_P_DNA_RT,dna_rt) 620 __ADD(ETH_P_LAT,lat) 621 __ADD(ETH_P_DIAG,diag) 622 __ADD(ETH_P_CUST,cust) 623 __ADD(ETH_P_SCA,sca) 624 __ADD(ETH_P_RARP,rarp) 625 __ADD(ETH_P_ATALK,atalk) 626 __ADD(ETH_P_AARP,aarp) 627#ifdef ETH_P_8021Q 628 __ADD(ETH_P_8021Q,802.1q) 629#endif 630 __ADD(ETH_P_IPX,ipx) 631 __ADD(ETH_P_IPV6,ipv6) 632#ifdef ETH_P_WCCP 633 __ADD(ETH_P_WCCP,wccp) 634#endif 635 __ADD(ETH_P_PPP_DISC,ppp_disc) 636 __ADD(ETH_P_PPP_SES,ppp_ses) 637 __ADD(ETH_P_MPLS_UC,mpls_uc) 638 __ADD(ETH_P_MPLS_MC,mpls_mc) 639 __ADD(ETH_P_ATMMPOA,atmmpoa) 640 __ADD(ETH_P_ATMFATE,atmfate) 641 __ADD(ETH_P_EDP2,edp2) 642 __ADD(ETH_P_802_3,802.3) 643 __ADD(ETH_P_AX25,ax25) 644 __ADD(ETH_P_ALL,all) 645 __ADD(ETH_P_802_2,802.2) 646 __ADD(ETH_P_SNAP,snap) 647 __ADD(ETH_P_DDCMP,ddcmp) 648 __ADD(ETH_P_WAN_PPP,wan_ppp) 649 __ADD(ETH_P_PPP_MP,ppp_mp) 650 __ADD(ETH_P_LOCALTALK,localtalk) 651 __ADD(ETH_P_PPPTALK,ppptalk) 652 __ADD(ETH_P_TR_802_2,tr_802.2) 653 __ADD(ETH_P_MOBITEX,mobitex) 654 __ADD(ETH_P_CONTROL,control) 655 __ADD(ETH_P_IRDA,irda) 656 __ADD(ETH_P_ECONET,econet) 657 __ADD(ETH_P_HDLC,hdlc) 658}; 659 660char *nl_ether_proto2str(int eproto, char *buf, size_t len) 661{ 662 return __type2str(eproto, buf, len, ether_protos, 663 ARRAY_SIZE(ether_protos)); 664} 665 666int nl_str2ether_proto(const char *name) 667{ 668 return __str2type(name, ether_protos, ARRAY_SIZE(ether_protos)); 669} 670 671/** @} */ 672 673/** 674 * @name IP Protocol Translations 675 * @{ 676 */ 677 678char *nl_ip_proto2str(int proto, char *buf, size_t len) 679{ 680 struct protoent *p = getprotobynumber(proto); 681 682 if (p) { 683 snprintf(buf, len, "%s", p->p_name); 684 return buf; 685 } 686 687 snprintf(buf, len, "0x%x", proto); 688 return buf; 689} 690 691int nl_str2ip_proto(const char *name) 692{ 693 struct protoent *p = getprotobyname(name); 694 unsigned long l; 695 char *end; 696 697 if (p) 698 return p->p_proto; 699 700 l = strtoul(name, &end, 0); 701 if (l == ULONG_MAX || *end != '\0') 702 return -1; 703 704 return (int) l; 705} 706 707/** @} */ 708 709/** 710 * @name Dumping Helpers 711 * @{ 712 */ 713 714/** 715 * Handle a new line while dumping 716 * @arg params Dumping parameters 717 * @arg line Number of lines dumped already. 718 * 719 * This function must be called before dumping any onto a 720 * new line. It will ensure proper prefixing as specified 721 * by the dumping parameters. 722 * 723 * @note This function will NOT dump any newlines itself 724 */ 725void nl_new_line(struct nl_dump_params *params, int line) 726{ 727 if (params->dp_prefix) { 728 int i; 729 for (i = 0; i < params->dp_prefix; i++) { 730 if (params->dp_fd) 731 fprintf(params->dp_fd, " "); 732 else if (params->dp_buf) 733 strncat(params->dp_buf, " ", 734 params->dp_buflen - 735 sizeof(params->dp_buf) - 1); 736 } 737 } 738 739 if (params->dp_nl_cb) 740 params->dp_nl_cb(params, line); 741} 742 743/** 744 * Dump a formatted character string 745 * @arg params Dumping parameters 746 * @arg fmt printf style formatting string 747 * @arg ... Arguments to formatting string 748 * 749 * Dumps a printf style formatting string to the output device 750 * as specified by the dumping parameters. 751 */ 752void nl_dump(struct nl_dump_params *params, const char *fmt, ...) 753{ 754 va_list args; 755 756 va_start(args, fmt); 757 __dp_dump(params, fmt, args); 758 va_end(args); 759} 760 761/** @} */ 762 763/** @} */ 764