00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <netlink-local.h>
00018 #include <netlink/netlink.h>
00019 #include <netlink/utils.h>
00020 #include <linux/socket.h>
00021
00022
00023
00024
00025 int nl_debug = 0;
00026
00027 struct nl_dump_params nl_debug_dp = {
00028 .dp_type = NL_DUMP_FULL,
00029 };
00030
00031 static void __init nl_debug_init(void)
00032 {
00033 char *nldbg, *end;
00034
00035 if ((nldbg = getenv("NLDBG"))) {
00036 long level = strtol(nldbg, &end, 0);
00037 if (nldbg != end)
00038 nl_debug = level;
00039 }
00040
00041 nl_debug_dp.dp_fd = stderr;
00042 }
00043
00044
00045
00046
00047
00048
00049 static __thread char *errbuf;
00050 static __thread int nlerrno;
00051
00052
00053 int __nl_error(int err, const char *file, unsigned int line, const char *func,
00054 const char *fmt, ...)
00055 {
00056 char *user_err;
00057 va_list args;
00058
00059 if (errbuf) {
00060 free(errbuf);
00061 errbuf = NULL;
00062 }
00063
00064 nlerrno = err;
00065
00066 if (fmt) {
00067 va_start(args, fmt);
00068 vasprintf(&user_err, fmt, args);
00069 va_end(args);
00070 }
00071
00072 #ifdef VERBOSE_ERRORS
00073 asprintf(&errbuf, "%s:%u:%s: %s (errno = %s)",
00074 file, line, func, fmt ? user_err : "", strerror(err));
00075 #else
00076 asprintf(&errbuf, "%s (errno = %s)",
00077 fmt ? user_err : "", strerror(err));
00078 #endif
00079
00080 if (fmt)
00081 free(user_err);
00082
00083 return -err;
00084 }
00085
00086 int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *))
00087 {
00088 FILE *fd;
00089 char buf[128];
00090
00091 fd = fopen(path, "r");
00092 if (fd == NULL)
00093 return nl_error(errno, "Unable to open file %s for reading",
00094 path);
00095
00096 while (fgets(buf, sizeof(buf), fd)) {
00097 int goodlen, err;
00098 long num;
00099 char *end;
00100
00101 if (*buf == '#' || *buf == '\n' || *buf == '\r')
00102 continue;
00103
00104 num = strtol(buf, &end, 0);
00105 if (end == buf)
00106 return nl_error(EINVAL, "Parsing error");
00107
00108 if (num == LONG_MIN || num == LONG_MAX)
00109 return nl_error(errno, "Number of out range");
00110
00111 while (*end == ' ' || *end == '\t')
00112 end++;
00113
00114 goodlen = strcspn(end, "#\r\n\t ");
00115 if (goodlen == 0)
00116 return nl_error(EINVAL, "Empty string");
00117
00118 end[goodlen] = '\0';
00119
00120 err = cb(num, end);
00121 if (err < 0)
00122 return err;
00123 }
00124
00125 fclose(fd);
00126
00127 return 0;
00128 }
00129
00130
00131
00132 int nl_get_errno(void)
00133 {
00134 return nlerrno;
00135 }
00136
00137
00138
00139
00140
00141
00142 char *nl_geterror(void)
00143 {
00144 if (errbuf)
00145 return errbuf;
00146
00147 if (nlerrno)
00148 return strerror(nlerrno);
00149
00150 return "Sucess\n";
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 void nl_perror(const char *s)
00164 {
00165 if (s && *s)
00166 fprintf(stderr, "%s: %s\n", s, nl_geterror());
00167 else
00168 fprintf(stderr, "%s\n", nl_geterror());
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 double nl_cancel_down_bytes(unsigned long long l, char **unit)
00190 {
00191 if (l >= 1099511627776LL) {
00192 *unit = "TiB";
00193 return ((double) l) / 1099511627776LL;
00194 } else if (l >= 1073741824) {
00195 *unit = "GiB";
00196 return ((double) l) / 1073741824;
00197 } else if (l >= 1048576) {
00198 *unit = "MiB";
00199 return ((double) l) / 1048576;
00200 } else if (l >= 1024) {
00201 *unit = "KiB";
00202 return ((double) l) / 1024;
00203 } else {
00204 *unit = "B";
00205 return (double) l;
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 double nl_cancel_down_bits(unsigned long long l, char **unit)
00221 {
00222 if (l >= 1000000000000ULL) {
00223 *unit = "Tbit";
00224 return ((double) l) / 1000000000000ULL;
00225 }
00226
00227 if (l >= 1000000000) {
00228 *unit = "Gbit";
00229 return ((double) l) / 1000000000;
00230 }
00231
00232 if (l >= 1000000) {
00233 *unit = "Mbit";
00234 return ((double) l) / 1000000;
00235 }
00236
00237 if (l >= 1000) {
00238 *unit = "Kbit";
00239 return ((double) l) / 1000;
00240 }
00241
00242 *unit = "bit";
00243 return (double) l;
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 double nl_cancel_down_us(uint32_t l, char **unit)
00257 {
00258 if (l >= 1000000) {
00259 *unit = "s";
00260 return ((double) l) / 1000000;
00261 } else if (l >= 1000) {
00262 *unit = "ms";
00263 return ((double) l) / 1000;
00264 } else {
00265 *unit = "us";
00266 return (double) l;
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 long nl_size2int(const char *str)
00294 {
00295 char *p;
00296 long l = strtol(str, &p, 0);
00297 if (p == str)
00298 return -1;
00299
00300 if (*p) {
00301 if (!strcasecmp(p, "kb") || !strcasecmp(p, "k"))
00302 l *= 1024;
00303 else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g"))
00304 l *= 1024*1024*1024;
00305 else if (!strcasecmp(p, "gbit"))
00306 l *= 1000000000L/8;
00307 else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m"))
00308 l *= 1024*1024;
00309 else if (!strcasecmp(p, "mbit"))
00310 l *= 1000000/8;
00311 else if (!strcasecmp(p, "kbit"))
00312 l *= 1000/8;
00313 else if (!strcasecmp(p, "bit"))
00314 l /= 8;
00315 else if (strcasecmp(p, "b") != 0)
00316 return -1;
00317 }
00318
00319 return l;
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 long nl_prob2int(const char *str)
00336 {
00337 char *p;
00338 double d = strtod(str, &p);
00339
00340 if (p == str)
00341 return -1;
00342
00343 if (d > 1.0)
00344 d /= 100.0f;
00345
00346 if (d > 1.0f || d < 0.0f)
00347 return -1;
00348
00349 if (*p && strcmp(p, "%") != 0)
00350 return -1;
00351
00352 return rint(d * NL_PROB_MAX);
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362 #ifdef USER_HZ
00363 static uint32_t user_hz = USER_HZ;
00364 #else
00365 static uint32_t user_hz = 100;
00366 #endif
00367
00368 static double ticks_per_usec = 1.0f;
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 static void __init get_psched_settings(void)
00380 {
00381 char name[FILENAME_MAX];
00382 FILE *fd;
00383 int got_hz = 0, got_tick = 0;
00384
00385 if (getenv("HZ")) {
00386 long hz = strtol(getenv("HZ"), NULL, 0);
00387
00388 if (LONG_MIN != hz && LONG_MAX != hz) {
00389 user_hz = hz;
00390 got_hz = 1;
00391 }
00392 }
00393
00394 if (!got_hz)
00395 user_hz = sysconf(_SC_CLK_TCK);
00396
00397 if (getenv("TICKS_PER_USEC")) {
00398 double t = strtod(getenv("TICKS_PER_USEC"), NULL);
00399
00400 ticks_per_usec = t;
00401 got_tick = 1;
00402 }
00403
00404
00405 if (getenv("PROC_NET_PSCHED"))
00406 snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED"));
00407 else if (getenv("PROC_ROOT"))
00408 snprintf(name, sizeof(name), "%s/net/psched",
00409 getenv("PROC_ROOT"));
00410 else
00411 strncpy(name, "/proc/net/psched", sizeof(name) - 1);
00412
00413 if ((fd = fopen(name, "r"))) {
00414 uint32_t tick, us, nom;
00415 int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom);
00416
00417 if (4 == r && nom == 1000000 && !got_tick)
00418 ticks_per_usec = (double)tick/(double)us;
00419
00420 fclose(fd);
00421 }
00422 }
00423
00424
00425
00426
00427
00428 int nl_get_hz(void)
00429 {
00430 return user_hz;
00431 }
00432
00433
00434
00435
00436
00437
00438
00439 uint32_t nl_us2ticks(uint32_t us)
00440 {
00441 return us * ticks_per_usec;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450 uint32_t nl_ticks2us(uint32_t ticks)
00451 {
00452 return ticks / ticks_per_usec;
00453 }
00454
00455 long nl_time2int(const char *str)
00456 {
00457 char *p;
00458 long l = strtol(str, &p, 0);
00459 if (p == str)
00460 return -1;
00461
00462 if (*p) {
00463 if (!strcasecmp(p, "min") == 0 || !strcasecmp(p, "m"))
00464 l *= 60;
00465 else if (!strcasecmp(p, "hour") || !strcasecmp(p, "h"))
00466 l *= 60*60;
00467 else if (!strcasecmp(p, "day") || !strcasecmp(p, "d"))
00468 l *= 60*60*24;
00469 else if (strcasecmp(p, "s") != 0)
00470 return -1;
00471 }
00472
00473 return l;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 char * nl_msec2str(uint64_t msec, char *buf, size_t len)
00489 {
00490 int i, split[5];
00491 char *units[] = {"d", "h", "m", "s", "msec"};
00492
00493 #define _SPLIT(idx, unit) if ((split[idx] = msec / unit) > 0) msec %= unit
00494 _SPLIT(0, 86400000);
00495 _SPLIT(1, 3600000);
00496 _SPLIT(2, 60000);
00497 _SPLIT(3, 1000);
00498 #undef _SPLIT
00499 split[4] = msec;
00500
00501 memset(buf, 0, len);
00502
00503 for (i = 0; i < ARRAY_SIZE(split); i++) {
00504 if (split[i] > 0) {
00505 char t[64];
00506 snprintf(t, sizeof(t), "%s%d%s",
00507 strlen(buf) ? " " : "", split[i], units[i]);
00508 strncat(buf, t, len - strlen(buf) - 1);
00509 }
00510 }
00511
00512 return buf;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522 static struct trans_tbl llprotos[] = {
00523 {0, "generic"},
00524 __ADD(ARPHRD_ETHER,ether)
00525 __ADD(ARPHRD_EETHER,eether)
00526 __ADD(ARPHRD_AX25,ax25)
00527 __ADD(ARPHRD_PRONET,pronet)
00528 __ADD(ARPHRD_CHAOS,chaos)
00529 __ADD(ARPHRD_IEEE802,ieee802)
00530 __ADD(ARPHRD_ARCNET,arcnet)
00531 __ADD(ARPHRD_APPLETLK,atalk)
00532 __ADD(ARPHRD_DLCI,dlci)
00533 __ADD(ARPHRD_ATM,atm)
00534 __ADD(ARPHRD_METRICOM,metricom)
00535 __ADD(ARPHRD_IEEE1394,ieee1394)
00536 #ifdef ARPHRD_EUI64
00537 __ADD(ARPHRD_EUI64,eui64)
00538 #endif
00539 __ADD(ARPHRD_INFINIBAND,infiniband)
00540 __ADD(ARPHRD_SLIP,slip)
00541 __ADD(ARPHRD_CSLIP,cslip)
00542 __ADD(ARPHRD_SLIP6,slip6)
00543 __ADD(ARPHRD_CSLIP6,cslip6)
00544 __ADD(ARPHRD_RSRVD,rsrvd)
00545 __ADD(ARPHRD_ADAPT,adapt)
00546 __ADD(ARPHRD_ROSE,rose)
00547 __ADD(ARPHRD_X25,x25)
00548 #ifdef ARPHRD_HWX25
00549 __ADD(ARPHRD_HWX25,hwx25)
00550 #endif
00551 __ADD(ARPHRD_PPP,ppp)
00552 __ADD(ARPHRD_HDLC,hdlc)
00553 __ADD(ARPHRD_LAPB,lapb)
00554 __ADD(ARPHRD_DDCMP,ddcmp)
00555 __ADD(ARPHRD_RAWHDLC,rawhdlc)
00556 __ADD(ARPHRD_TUNNEL,ipip)
00557 __ADD(ARPHRD_TUNNEL6,tunnel6)
00558 __ADD(ARPHRD_FRAD,frad)
00559 __ADD(ARPHRD_SKIP,skip)
00560 __ADD(ARPHRD_LOOPBACK,loopback)
00561 __ADD(ARPHRD_LOCALTLK,localtlk)
00562 __ADD(ARPHRD_FDDI,fddi)
00563 __ADD(ARPHRD_BIF,bif)
00564 __ADD(ARPHRD_SIT,sit)
00565 __ADD(ARPHRD_IPDDP,ip/ddp)
00566 __ADD(ARPHRD_IPGRE,gre)
00567 __ADD(ARPHRD_PIMREG,pimreg)
00568 __ADD(ARPHRD_HIPPI,hippi)
00569 __ADD(ARPHRD_ASH,ash)
00570 __ADD(ARPHRD_ECONET,econet)
00571 __ADD(ARPHRD_IRDA,irda)
00572 __ADD(ARPHRD_FCPP,fcpp)
00573 __ADD(ARPHRD_FCAL,fcal)
00574 __ADD(ARPHRD_FCPL,fcpl)
00575 __ADD(ARPHRD_FCFABRIC,fcfb_0)
00576 __ADD(ARPHRD_FCFABRIC+1,fcfb_1)
00577 __ADD(ARPHRD_FCFABRIC+2,fcfb_2)
00578 __ADD(ARPHRD_FCFABRIC+3,fcfb_3)
00579 __ADD(ARPHRD_FCFABRIC+4,fcfb_4)
00580 __ADD(ARPHRD_FCFABRIC+5,fcfb_5)
00581 __ADD(ARPHRD_FCFABRIC+6,fcfb_6)
00582 __ADD(ARPHRD_FCFABRIC+7,fcfb_7)
00583 __ADD(ARPHRD_FCFABRIC+8,fcfb_8)
00584 __ADD(ARPHRD_FCFABRIC+9,fcfb_9)
00585 __ADD(ARPHRD_FCFABRIC+10,fcfb_10)
00586 __ADD(ARPHRD_FCFABRIC+11,fcfb_11)
00587 __ADD(ARPHRD_FCFABRIC+12,fcfb_12)
00588 __ADD(ARPHRD_IEEE802_TR,tr)
00589 __ADD(ARPHRD_IEEE80211,ieee802.11)
00590 #ifdef ARPHRD_IEEE80211_PRISM
00591 __ADD(ARPHRD_IEEE80211_PRISM, ieee802.11_prism)
00592 #endif
00593 #ifdef ARPHRD_VOID
00594 __ADD(ARPHRD_VOID,void)
00595 #endif
00596 };
00597
00598 char * nl_llproto2str(int llproto, char *buf, size_t len)
00599 {
00600 return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos));
00601 }
00602
00603 int nl_str2llproto(const char *name)
00604 {
00605 return __str2type(name, llprotos, ARRAY_SIZE(llprotos));
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 static struct trans_tbl ether_protos[] = {
00617 __ADD(ETH_P_LOOP,loop)
00618 __ADD(ETH_P_PUP,pup)
00619 __ADD(ETH_P_PUPAT,pupat)
00620 __ADD(ETH_P_IP,ip)
00621 __ADD(ETH_P_X25,x25)
00622 __ADD(ETH_P_ARP,arp)
00623 __ADD(ETH_P_BPQ,bpq)
00624 __ADD(ETH_P_IEEEPUP,ieeepup)
00625 __ADD(ETH_P_IEEEPUPAT,ieeepupat)
00626 __ADD(ETH_P_DEC,dec)
00627 __ADD(ETH_P_DNA_DL,dna_dl)
00628 __ADD(ETH_P_DNA_RC,dna_rc)
00629 __ADD(ETH_P_DNA_RT,dna_rt)
00630 __ADD(ETH_P_LAT,lat)
00631 __ADD(ETH_P_DIAG,diag)
00632 __ADD(ETH_P_CUST,cust)
00633 __ADD(ETH_P_SCA,sca)
00634 __ADD(ETH_P_RARP,rarp)
00635 __ADD(ETH_P_ATALK,atalk)
00636 __ADD(ETH_P_AARP,aarp)
00637 #ifdef ETH_P_8021Q
00638 __ADD(ETH_P_8021Q,802.1q)
00639 #endif
00640 __ADD(ETH_P_IPX,ipx)
00641 __ADD(ETH_P_IPV6,ipv6)
00642 #ifdef ETH_P_WCCP
00643 __ADD(ETH_P_WCCP,wccp)
00644 #endif
00645 __ADD(ETH_P_PPP_DISC,ppp_disc)
00646 __ADD(ETH_P_PPP_SES,ppp_ses)
00647 __ADD(ETH_P_MPLS_UC,mpls_uc)
00648 __ADD(ETH_P_MPLS_MC,mpls_mc)
00649 __ADD(ETH_P_ATMMPOA,atmmpoa)
00650 __ADD(ETH_P_ATMFATE,atmfate)
00651 __ADD(ETH_P_EDP2,edp2)
00652 __ADD(ETH_P_802_3,802.3)
00653 __ADD(ETH_P_AX25,ax25)
00654 __ADD(ETH_P_ALL,all)
00655 __ADD(ETH_P_802_2,802.2)
00656 __ADD(ETH_P_SNAP,snap)
00657 __ADD(ETH_P_DDCMP,ddcmp)
00658 __ADD(ETH_P_WAN_PPP,wan_ppp)
00659 __ADD(ETH_P_PPP_MP,ppp_mp)
00660 __ADD(ETH_P_LOCALTALK,localtalk)
00661 __ADD(ETH_P_PPPTALK,ppptalk)
00662 __ADD(ETH_P_TR_802_2,tr_802.2)
00663 __ADD(ETH_P_MOBITEX,mobitex)
00664 __ADD(ETH_P_CONTROL,control)
00665 __ADD(ETH_P_IRDA,irda)
00666 __ADD(ETH_P_ECONET,econet)
00667 __ADD(ETH_P_HDLC,hdlc)
00668 };
00669
00670 char *nl_ether_proto2str(int eproto, char *buf, size_t len)
00671 {
00672 return __type2str(eproto, buf, len, ether_protos,
00673 ARRAY_SIZE(ether_protos));
00674 }
00675
00676 int nl_str2ether_proto(const char *name)
00677 {
00678 return __str2type(name, ether_protos, ARRAY_SIZE(ether_protos));
00679 }
00680
00681
00682
00683
00684
00685
00686
00687
00688 char *nl_ip_proto2str(int proto, char *buf, size_t len)
00689 {
00690 struct protoent *p = getprotobynumber(proto);
00691
00692 if (p) {
00693 snprintf(buf, len, "%s", p->p_name);
00694 return buf;
00695 }
00696
00697 snprintf(buf, len, "0x%x", proto);
00698 return buf;
00699 }
00700
00701 int nl_str2ip_proto(const char *name)
00702 {
00703 struct protoent *p = getprotobyname(name);
00704 unsigned long l;
00705 char *end;
00706
00707 if (p)
00708 return p->p_proto;
00709
00710 l = strtoul(name, &end, 0);
00711 if (l == ULONG_MAX || *end != '\0')
00712 return -1;
00713
00714 return (int) l;
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 void nl_new_line(struct nl_dump_params *params, int line)
00736 {
00737 if (params->dp_prefix) {
00738 int i;
00739 for (i = 0; i < params->dp_prefix; i++) {
00740 if (params->dp_fd)
00741 fprintf(params->dp_fd, " ");
00742 else if (params->dp_buf)
00743 strncat(params->dp_buf, " ",
00744 params->dp_buflen -
00745 sizeof(params->dp_buf) - 1);
00746 }
00747 }
00748
00749 if (params->dp_nl_cb)
00750 params->dp_nl_cb(params, line);
00751 }
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 void nl_dump(struct nl_dump_params *params, const char *fmt, ...)
00763 {
00764 va_list args;
00765
00766 va_start(args, fmt);
00767 __dp_dump(params, fmt, args);
00768 va_end(args);
00769 }
00770
00771
00772
00773