00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <netlink-local.h>
00019 #include <netlink/netlink.h>
00020 #include <netlink/utils.h>
00021 #include <linux/socket.h>
00022
00023
00024
00025
00026 int nl_debug = 0;
00027
00028 struct nl_dump_params nl_debug_dp = {
00029 .dp_type = NL_DUMP_DETAILS,
00030 };
00031
00032 static void __init nl_debug_init(void)
00033 {
00034 char *nldbg, *end;
00035
00036 if ((nldbg = getenv("NLDBG"))) {
00037 long level = strtol(nldbg, &end, 0);
00038 if (nldbg != end)
00039 nl_debug = level;
00040 }
00041
00042 nl_debug_dp.dp_fd = stderr;
00043 }
00044
00045 int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *))
00046 {
00047 FILE *fd;
00048 char buf[128];
00049
00050 fd = fopen(path, "r");
00051 if (fd == NULL)
00052 return -nl_syserr2nlerr(errno);
00053
00054 while (fgets(buf, sizeof(buf), fd)) {
00055 int goodlen, err;
00056 long num;
00057 char *end;
00058
00059 if (*buf == '#' || *buf == '\n' || *buf == '\r')
00060 continue;
00061
00062 num = strtol(buf, &end, 0);
00063 if (end == buf)
00064 return -NLE_INVAL;
00065
00066 if (num == LONG_MIN || num == LONG_MAX)
00067 return -NLE_RANGE;
00068
00069 while (*end == ' ' || *end == '\t')
00070 end++;
00071
00072 goodlen = strcspn(end, "#\r\n\t ");
00073 if (goodlen == 0)
00074 return -NLE_INVAL;
00075
00076 end[goodlen] = '\0';
00077
00078 err = cb(num, end);
00079 if (err < 0)
00080 return err;
00081 }
00082
00083 fclose(fd);
00084
00085 return 0;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 double nl_cancel_down_bytes(unsigned long long l, char **unit)
00104 {
00105 if (l >= 1099511627776LL) {
00106 *unit = "TiB";
00107 return ((double) l) / 1099511627776LL;
00108 } else if (l >= 1073741824) {
00109 *unit = "GiB";
00110 return ((double) l) / 1073741824;
00111 } else if (l >= 1048576) {
00112 *unit = "MiB";
00113 return ((double) l) / 1048576;
00114 } else if (l >= 1024) {
00115 *unit = "KiB";
00116 return ((double) l) / 1024;
00117 } else {
00118 *unit = "B";
00119 return (double) l;
00120 }
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 double nl_cancel_down_bits(unsigned long long l, char **unit)
00134 {
00135 if (l >= 1099511627776ULL) {
00136 *unit = "Tbit";
00137 return ((double) l) / 1099511627776ULL;
00138 } else if (l >= 1073741824) {
00139 *unit = "Gbit";
00140 return ((double) l) / 1073741824;
00141 } else if (l >= 1048576) {
00142 *unit = "Mbit";
00143 return ((double) l) / 1048576;
00144 } else if (l >= 1024) {
00145 *unit = "Kbit";
00146 return ((double) l) / 1024;
00147 } else {
00148 *unit = "bit";
00149 return (double) l;
00150 }
00151
00152 }
00153
00154 int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len)
00155 {
00156 char *unit;
00157 double frac;
00158
00159 switch (type) {
00160 case NL_BYTE_RATE:
00161 frac = nl_cancel_down_bytes(rate, &unit);
00162 break;
00163
00164 case NL_BIT_RATE:
00165 frac = nl_cancel_down_bits(rate, &unit);
00166 break;
00167
00168 default:
00169 BUG();
00170 }
00171
00172 return snprintf(buf, len, "%.2f%s/s", frac, unit);
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 double nl_cancel_down_us(uint32_t l, char **unit)
00186 {
00187 if (l >= 1000000) {
00188 *unit = "s";
00189 return ((double) l) / 1000000;
00190 } else if (l >= 1000) {
00191 *unit = "ms";
00192 return ((double) l) / 1000;
00193 } else {
00194 *unit = "us";
00195 return (double) l;
00196 }
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 long nl_size2int(const char *str)
00220 {
00221 char *p;
00222 long l = strtol(str, &p, 0);
00223 if (p == str)
00224 return -NLE_INVAL;
00225
00226 if (*p) {
00227 if (!strcasecmp(p, "kb") || !strcasecmp(p, "k"))
00228 l *= 1024;
00229 else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g"))
00230 l *= 1024*1024*1024;
00231 else if (!strcasecmp(p, "gbit"))
00232 l *= 1024*1024*1024/8;
00233 else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m"))
00234 l *= 1024*1024;
00235 else if (!strcasecmp(p, "mbit"))
00236 l *= 1024*1024/8;
00237 else if (!strcasecmp(p, "kbit"))
00238 l *= 1024/8;
00239 else if (!strcasecmp(p, "bit"))
00240 l /= 8;
00241 else if (strcasecmp(p, "b") != 0)
00242 return -NLE_INVAL;
00243 }
00244
00245 return l;
00246 }
00247
00248 static const struct {
00249 double limit;
00250 const char *unit;
00251 } size_units[] = {
00252 { 1024. * 1024. * 1024. * 1024. * 1024., "EiB" },
00253 { 1024. * 1024. * 1024. * 1024., "TiB" },
00254 { 1024. * 1024. * 1024., "GiB" },
00255 { 1024. * 1024., "MiB" },
00256 { 1024., "KiB" },
00257 { 0., "B" },
00258 };
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 char *nl_size2str(const size_t size, char *buf, const size_t len)
00283 {
00284 int i;
00285
00286 for (i = 0; i < ARRAY_SIZE(size_units); i++) {
00287 if (size >= size_units[i].limit) {
00288 snprintf(buf, len, "%.2g%s",
00289 (double) size / size_units[i].limit,
00290 size_units[i].unit);
00291 return buf;
00292 }
00293 }
00294
00295 BUG();
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 long nl_prob2int(const char *str)
00312 {
00313 char *p;
00314 double d = strtod(str, &p);
00315
00316 if (p == str)
00317 return -NLE_INVAL;
00318
00319 if (d > 1.0)
00320 d /= 100.0f;
00321
00322 if (d > 1.0f || d < 0.0f)
00323 return -NLE_RANGE;
00324
00325 if (*p && strcmp(p, "%") != 0)
00326 return -NLE_INVAL;
00327
00328 return rint(d * NL_PROB_MAX);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338 #ifdef USER_HZ
00339 static uint32_t user_hz = USER_HZ;
00340 #else
00341 static uint32_t user_hz = 100;
00342 #endif
00343
00344 static double ticks_per_usec = 1.0f;
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 static void __init get_psched_settings(void)
00356 {
00357 char name[FILENAME_MAX];
00358 FILE *fd;
00359 int got_hz = 0;
00360
00361 if (getenv("HZ")) {
00362 long hz = strtol(getenv("HZ"), NULL, 0);
00363
00364 if (LONG_MIN != hz && LONG_MAX != hz) {
00365 user_hz = hz;
00366 got_hz = 1;
00367 }
00368 }
00369
00370 if (!got_hz)
00371 user_hz = sysconf(_SC_CLK_TCK);
00372
00373 if (getenv("TICKS_PER_USEC")) {
00374 double t = strtod(getenv("TICKS_PER_USEC"), NULL);
00375 ticks_per_usec = t;
00376 }
00377 else {
00378 if (getenv("PROC_NET_PSCHED"))
00379 snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED"));
00380 else if (getenv("PROC_ROOT"))
00381 snprintf(name, sizeof(name), "%s/net/psched",
00382 getenv("PROC_ROOT"));
00383 else
00384 strncpy(name, "/proc/net/psched", sizeof(name) - 1);
00385
00386 if ((fd = fopen(name, "r"))) {
00387 uint32_t ns_per_usec, ns_per_tick;
00388
00389
00390 fscanf(fd, "%08x %08x", &ns_per_usec, &ns_per_tick);
00391
00392 ticks_per_usec = (double) ns_per_usec /
00393 (double) ns_per_tick;
00394
00395
00396 fclose(fd);
00397 }
00398 }
00399 }
00400
00401
00402
00403
00404
00405 int nl_get_user_hz(void)
00406 {
00407 return user_hz;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416 uint32_t nl_us2ticks(uint32_t us)
00417 {
00418 return us * ticks_per_usec;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427 uint32_t nl_ticks2us(uint32_t ticks)
00428 {
00429 return ticks / ticks_per_usec;
00430 }
00431
00432 int nl_str2msec(const char *str, uint64_t *result)
00433 {
00434 uint64_t total = 0, l;
00435 int plen;
00436 char *p;
00437
00438 do {
00439 l = strtoul(str, &p, 0);
00440 if (p == str)
00441 return -NLE_INVAL;
00442 else if (*p) {
00443 plen = strcspn(p, " \t");
00444
00445 if (!plen)
00446 total += l;
00447 else if (!strncasecmp(p, "sec", plen))
00448 total += (l * 1000);
00449 else if (!strncasecmp(p, "min", plen))
00450 total += (l * 1000*60);
00451 else if (!strncasecmp(p, "hour", plen))
00452 total += (l * 1000*60*60);
00453 else if (!strncasecmp(p, "day", plen))
00454 total += (l * 1000*60*60*24);
00455 else
00456 return -NLE_INVAL;
00457
00458 str = p + plen;
00459 } else
00460 total += l;
00461 } while (*str && *p);
00462
00463 *result = total;
00464
00465 return 0;
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 char * nl_msec2str(uint64_t msec, char *buf, size_t len)
00481 {
00482 int i, split[5];
00483 char *units[] = {"d", "h", "m", "s", "msec"};
00484
00485 #define _SPLIT(idx, unit) if ((split[idx] = msec / unit) > 0) msec %= unit
00486 _SPLIT(0, 86400000);
00487 _SPLIT(1, 3600000);
00488 _SPLIT(2, 60000);
00489 _SPLIT(3, 1000);
00490 #undef _SPLIT
00491 split[4] = msec;
00492
00493 memset(buf, 0, len);
00494
00495 for (i = 0; i < ARRAY_SIZE(split); i++) {
00496 if (split[i] > 0) {
00497 char t[64];
00498 snprintf(t, sizeof(t), "%s%d%s",
00499 strlen(buf) ? " " : "", split[i], units[i]);
00500 strncat(buf, t, len - strlen(buf) - 1);
00501 }
00502 }
00503
00504 return buf;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514 static const struct trans_tbl nlfamilies[] = {
00515 __ADD(NETLINK_ROUTE,route)
00516 __ADD(NETLINK_USERSOCK,usersock)
00517 __ADD(NETLINK_FIREWALL,firewall)
00518 __ADD(NETLINK_INET_DIAG,inetdiag)
00519 __ADD(NETLINK_NFLOG,nflog)
00520 __ADD(NETLINK_XFRM,xfrm)
00521 __ADD(NETLINK_SELINUX,selinux)
00522 __ADD(NETLINK_ISCSI,iscsi)
00523 __ADD(NETLINK_AUDIT,audit)
00524 __ADD(NETLINK_FIB_LOOKUP,fib_lookup)
00525 __ADD(NETLINK_CONNECTOR,connector)
00526 __ADD(NETLINK_NETFILTER,netfilter)
00527 __ADD(NETLINK_IP6_FW,ip6_fw)
00528 __ADD(NETLINK_DNRTMSG,dnrtmsg)
00529 __ADD(NETLINK_KOBJECT_UEVENT,kobject_uevent)
00530 __ADD(NETLINK_GENERIC,generic)
00531 __ADD(NETLINK_SCSITRANSPORT,scsitransport)
00532 __ADD(NETLINK_ECRYPTFS,ecryptfs)
00533 };
00534
00535 char * nl_nlfamily2str(int family, char *buf, size_t size)
00536 {
00537 return __type2str(family, buf, size, nlfamilies,
00538 ARRAY_SIZE(nlfamilies));
00539 }
00540
00541 int nl_str2nlfamily(const char *name)
00542 {
00543 return __str2type(name, nlfamilies, ARRAY_SIZE(nlfamilies));
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 static const struct trans_tbl llprotos[] = {
00556 {0, "generic"},
00557 __ADD(ARPHRD_ETHER,ether)
00558 __ADD(ARPHRD_EETHER,eether)
00559 __ADD(ARPHRD_AX25,ax25)
00560 __ADD(ARPHRD_PRONET,pronet)
00561 __ADD(ARPHRD_CHAOS,chaos)
00562 __ADD(ARPHRD_IEEE802,ieee802)
00563 __ADD(ARPHRD_ARCNET,arcnet)
00564 __ADD(ARPHRD_APPLETLK,atalk)
00565 __ADD(ARPHRD_DLCI,dlci)
00566 __ADD(ARPHRD_ATM,atm)
00567 __ADD(ARPHRD_METRICOM,metricom)
00568 __ADD(ARPHRD_IEEE1394,ieee1394)
00569 #ifdef ARPHRD_EUI64
00570 __ADD(ARPHRD_EUI64,eui64)
00571 #endif
00572 __ADD(ARPHRD_INFINIBAND,infiniband)
00573 __ADD(ARPHRD_SLIP,slip)
00574 __ADD(ARPHRD_CSLIP,cslip)
00575 __ADD(ARPHRD_SLIP6,slip6)
00576 __ADD(ARPHRD_CSLIP6,cslip6)
00577 __ADD(ARPHRD_RSRVD,rsrvd)
00578 __ADD(ARPHRD_ADAPT,adapt)
00579 __ADD(ARPHRD_ROSE,rose)
00580 __ADD(ARPHRD_X25,x25)
00581 #ifdef ARPHRD_HWX25
00582 __ADD(ARPHRD_HWX25,hwx25)
00583 #endif
00584 __ADD(ARPHRD_CAN,can)
00585 __ADD(ARPHRD_PPP,ppp)
00586 __ADD(ARPHRD_HDLC,hdlc)
00587 __ADD(ARPHRD_LAPB,lapb)
00588 __ADD(ARPHRD_DDCMP,ddcmp)
00589 __ADD(ARPHRD_RAWHDLC,rawhdlc)
00590 __ADD(ARPHRD_TUNNEL,ipip)
00591 __ADD(ARPHRD_TUNNEL6,tunnel6)
00592 __ADD(ARPHRD_FRAD,frad)
00593 __ADD(ARPHRD_SKIP,skip)
00594 __ADD(ARPHRD_LOOPBACK,loopback)
00595 __ADD(ARPHRD_LOCALTLK,localtlk)
00596 __ADD(ARPHRD_FDDI,fddi)
00597 __ADD(ARPHRD_BIF,bif)
00598 __ADD(ARPHRD_SIT,sit)
00599 __ADD(ARPHRD_IPDDP,ip/ddp)
00600 __ADD(ARPHRD_IPGRE,gre)
00601 __ADD(ARPHRD_PIMREG,pimreg)
00602 __ADD(ARPHRD_HIPPI,hippi)
00603 __ADD(ARPHRD_ASH,ash)
00604 __ADD(ARPHRD_ECONET,econet)
00605 __ADD(ARPHRD_IRDA,irda)
00606 __ADD(ARPHRD_FCPP,fcpp)
00607 __ADD(ARPHRD_FCAL,fcal)
00608 __ADD(ARPHRD_FCPL,fcpl)
00609 __ADD(ARPHRD_FCFABRIC,fcfb_0)
00610 __ADD(ARPHRD_FCFABRIC+1,fcfb_1)
00611 __ADD(ARPHRD_FCFABRIC+2,fcfb_2)
00612 __ADD(ARPHRD_FCFABRIC+3,fcfb_3)
00613 __ADD(ARPHRD_FCFABRIC+4,fcfb_4)
00614 __ADD(ARPHRD_FCFABRIC+5,fcfb_5)
00615 __ADD(ARPHRD_FCFABRIC+6,fcfb_6)
00616 __ADD(ARPHRD_FCFABRIC+7,fcfb_7)
00617 __ADD(ARPHRD_FCFABRIC+8,fcfb_8)
00618 __ADD(ARPHRD_FCFABRIC+9,fcfb_9)
00619 __ADD(ARPHRD_FCFABRIC+10,fcfb_10)
00620 __ADD(ARPHRD_FCFABRIC+11,fcfb_11)
00621 __ADD(ARPHRD_FCFABRIC+12,fcfb_12)
00622 __ADD(ARPHRD_IEEE802_TR,tr)
00623 __ADD(ARPHRD_IEEE80211,ieee802.11)
00624 __ADD(ARPHRD_PHONET,phonet)
00625 __ADD(ARPHRD_CAIF, caif)
00626 #ifdef ARPHRD_IEEE80211_PRISM
00627 __ADD(ARPHRD_IEEE80211_PRISM, ieee802.11_prism)
00628 #endif
00629 #ifdef ARPHRD_VOID
00630 __ADD(ARPHRD_VOID,void)
00631 #endif
00632 #ifdef ARPHRD_NONE
00633 __ADD(ARPHRD_NONE,nohdr)
00634 #endif
00635 };
00636
00637 char * nl_llproto2str(int llproto, char *buf, size_t len)
00638 {
00639 return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos));
00640 }
00641
00642 int nl_str2llproto(const char *name)
00643 {
00644 return __str2type(name, llprotos, ARRAY_SIZE(llprotos));
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655 static const struct trans_tbl ether_protos[] = {
00656 __ADD(ETH_P_LOOP,loop)
00657 __ADD(ETH_P_PUP,pup)
00658 __ADD(ETH_P_PUPAT,pupat)
00659 __ADD(ETH_P_IP,ip)
00660 __ADD(ETH_P_X25,x25)
00661 __ADD(ETH_P_ARP,arp)
00662 __ADD(ETH_P_BPQ,bpq)
00663 __ADD(ETH_P_IEEEPUP,ieeepup)
00664 __ADD(ETH_P_IEEEPUPAT,ieeepupat)
00665 __ADD(ETH_P_DEC,dec)
00666 __ADD(ETH_P_DNA_DL,dna_dl)
00667 __ADD(ETH_P_DNA_RC,dna_rc)
00668 __ADD(ETH_P_DNA_RT,dna_rt)
00669 __ADD(ETH_P_LAT,lat)
00670 __ADD(ETH_P_DIAG,diag)
00671 __ADD(ETH_P_CUST,cust)
00672 __ADD(ETH_P_SCA,sca)
00673 __ADD(ETH_P_TEB,teb)
00674 __ADD(ETH_P_RARP,rarp)
00675 __ADD(ETH_P_ATALK,atalk)
00676 __ADD(ETH_P_AARP,aarp)
00677 #ifdef ETH_P_8021Q
00678 __ADD(ETH_P_8021Q,802.1q)
00679 #endif
00680 __ADD(ETH_P_IPX,ipx)
00681 __ADD(ETH_P_IPV6,ipv6)
00682 __ADD(ETH_P_PAUSE,pause)
00683 __ADD(ETH_P_SLOW,slow)
00684 #ifdef ETH_P_WCCP
00685 __ADD(ETH_P_WCCP,wccp)
00686 #endif
00687 __ADD(ETH_P_PPP_DISC,ppp_disc)
00688 __ADD(ETH_P_PPP_SES,ppp_ses)
00689 __ADD(ETH_P_MPLS_UC,mpls_uc)
00690 __ADD(ETH_P_MPLS_MC,mpls_mc)
00691 __ADD(ETH_P_ATMMPOA,atmmpoa)
00692 __ADD(ETH_P_LINK_CTL,link_ctl)
00693 __ADD(ETH_P_ATMFATE,atmfate)
00694 __ADD(ETH_P_PAE,pae)
00695 __ADD(ETH_P_AOE,aoe)
00696 __ADD(ETH_P_TIPC,tipc)
00697 __ADD(ETH_P_1588,ieee1588)
00698 __ADD(ETH_P_FCOE,fcoe)
00699 __ADD(ETH_P_FIP,fip)
00700 __ADD(ETH_P_EDSA,edsa)
00701 __ADD(ETH_P_EDP2,edp2)
00702 __ADD(ETH_P_802_3,802.3)
00703 __ADD(ETH_P_AX25,ax25)
00704 __ADD(ETH_P_ALL,all)
00705 __ADD(ETH_P_802_2,802.2)
00706 __ADD(ETH_P_SNAP,snap)
00707 __ADD(ETH_P_DDCMP,ddcmp)
00708 __ADD(ETH_P_WAN_PPP,wan_ppp)
00709 __ADD(ETH_P_PPP_MP,ppp_mp)
00710 __ADD(ETH_P_LOCALTALK,localtalk)
00711 __ADD(ETH_P_CAN,can)
00712 __ADD(ETH_P_PPPTALK,ppptalk)
00713 __ADD(ETH_P_TR_802_2,tr_802.2)
00714 __ADD(ETH_P_MOBITEX,mobitex)
00715 __ADD(ETH_P_CONTROL,control)
00716 __ADD(ETH_P_IRDA,irda)
00717 __ADD(ETH_P_ECONET,econet)
00718 __ADD(ETH_P_HDLC,hdlc)
00719 __ADD(ETH_P_ARCNET,arcnet)
00720 __ADD(ETH_P_DSA,dsa)
00721 __ADD(ETH_P_TRAILER,trailer)
00722 __ADD(ETH_P_PHONET,phonet)
00723 __ADD(ETH_P_IEEE802154,ieee802154)
00724 __ADD(ETH_P_CAIF,caif)
00725 };
00726
00727 char *nl_ether_proto2str(int eproto, char *buf, size_t len)
00728 {
00729 return __type2str(eproto, buf, len, ether_protos,
00730 ARRAY_SIZE(ether_protos));
00731 }
00732
00733 int nl_str2ether_proto(const char *name)
00734 {
00735 return __str2type(name, ether_protos, ARRAY_SIZE(ether_protos));
00736 }
00737
00738
00739
00740
00741
00742
00743
00744
00745 char *nl_ip_proto2str(int proto, char *buf, size_t len)
00746 {
00747 struct protoent *p = getprotobynumber(proto);
00748
00749 if (p) {
00750 snprintf(buf, len, "%s", p->p_name);
00751 return buf;
00752 }
00753
00754 snprintf(buf, len, "0x%x", proto);
00755 return buf;
00756 }
00757
00758 int nl_str2ip_proto(const char *name)
00759 {
00760 struct protoent *p = getprotobyname(name);
00761 unsigned long l;
00762 char *end;
00763
00764 if (p)
00765 return p->p_proto;
00766
00767 l = strtoul(name, &end, 0);
00768 if (l == ULONG_MAX || *end != '\0')
00769 return -NLE_OBJ_NOTFOUND;
00770
00771 return (int) l;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 void nl_new_line(struct nl_dump_params *params)
00792 {
00793 params->dp_line++;
00794
00795 if (params->dp_prefix) {
00796 int i;
00797 for (i = 0; i < params->dp_prefix; i++) {
00798 if (params->dp_fd)
00799 fprintf(params->dp_fd, " ");
00800 else if (params->dp_buf)
00801 strncat(params->dp_buf, " ",
00802 params->dp_buflen -
00803 sizeof(params->dp_buf) - 1);
00804 }
00805 }
00806
00807 if (params->dp_nl_cb)
00808 params->dp_nl_cb(params, params->dp_line);
00809 }
00810
00811 static void dump_one(struct nl_dump_params *parms, const char *fmt,
00812 va_list args)
00813 {
00814 if (parms->dp_fd)
00815 vfprintf(parms->dp_fd, fmt, args);
00816 else if (parms->dp_buf || parms->dp_cb) {
00817 char *buf = NULL;
00818 if (vasprintf(&buf, fmt, args) >= 0) {
00819 if (parms->dp_cb)
00820 parms->dp_cb(parms, buf);
00821 else
00822 strncat(parms->dp_buf, buf,
00823 parms->dp_buflen - strlen(parms->dp_buf) - 1);
00824 free(buf);
00825 }
00826 }
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839 void nl_dump(struct nl_dump_params *params, const char *fmt, ...)
00840 {
00841 va_list args;
00842
00843 va_start(args, fmt);
00844 dump_one(params, fmt, args);
00845 va_end(args);
00846 }
00847
00848 void nl_dump_line(struct nl_dump_params *parms, const char *fmt, ...)
00849 {
00850 va_list args;
00851
00852 nl_new_line(parms);
00853
00854 va_start(args, fmt);
00855 dump_one(parms, fmt, args);
00856 va_end(args);
00857 }
00858
00859
00860
00861
00862
00863
00864 int __trans_list_add(int i, const char *a, struct nl_list_head *head)
00865 {
00866 struct trans_list *tl;
00867
00868 tl = calloc(1, sizeof(*tl));
00869 if (!tl)
00870 return -NLE_NOMEM;
00871
00872 tl->i = i;
00873 tl->a = strdup(a);
00874
00875 nl_list_add_tail(&tl->list, head);
00876
00877 return 0;
00878 }
00879
00880 void __trans_list_clear(struct nl_list_head *head)
00881 {
00882 struct trans_list *tl, *next;
00883
00884 nl_list_for_each_entry_safe(tl, next, head, list) {
00885 free(tl->a);
00886 free(tl);
00887 }
00888
00889 nl_init_list_head(head);
00890 }
00891
00892 char *__type2str(int type, char *buf, size_t len,
00893 const struct trans_tbl *tbl, size_t tbl_len)
00894 {
00895 int i;
00896 for (i = 0; i < tbl_len; i++) {
00897 if (tbl[i].i == type) {
00898 snprintf(buf, len, "%s", tbl[i].a);
00899 return buf;
00900 }
00901 }
00902
00903 snprintf(buf, len, "0x%x", type);
00904 return buf;
00905 }
00906
00907 char *__list_type2str(int type, char *buf, size_t len,
00908 struct nl_list_head *head)
00909 {
00910 struct trans_list *tl;
00911
00912 nl_list_for_each_entry(tl, head, list) {
00913 if (tl->i == type) {
00914 snprintf(buf, len, "%s", tl->a);
00915 return buf;
00916 }
00917 }
00918
00919 snprintf(buf, len, "0x%x", type);
00920 return buf;
00921 }
00922
00923 char *__flags2str(int flags, char *buf, size_t len,
00924 const struct trans_tbl *tbl, size_t tbl_len)
00925 {
00926 int i;
00927 int tmp = flags;
00928
00929 memset(buf, 0, len);
00930
00931 for (i = 0; i < tbl_len; i++) {
00932 if (tbl[i].i & tmp) {
00933 tmp &= ~tbl[i].i;
00934 strncat(buf, tbl[i].a, len - strlen(buf) - 1);
00935 if ((tmp & flags))
00936 strncat(buf, ",", len - strlen(buf) - 1);
00937 }
00938 }
00939
00940 return buf;
00941 }
00942
00943 int __str2type(const char *buf, const struct trans_tbl *tbl, size_t tbl_len)
00944 {
00945 unsigned long l;
00946 char *end;
00947 int i;
00948
00949 if (*buf == '\0')
00950 return -NLE_INVAL;
00951
00952 for (i = 0; i < tbl_len; i++)
00953 if (!strcasecmp(tbl[i].a, buf))
00954 return tbl[i].i;
00955
00956 l = strtoul(buf, &end, 0);
00957 if (l == ULONG_MAX || *end != '\0')
00958 return -NLE_OBJ_NOTFOUND;
00959
00960 return (int) l;
00961 }
00962
00963 int __list_str2type(const char *buf, struct nl_list_head *head)
00964 {
00965 struct trans_list *tl;
00966 unsigned long l;
00967 char *end;
00968
00969 if (*buf == '\0')
00970 return -NLE_INVAL;
00971
00972 nl_list_for_each_entry(tl, head, list) {
00973 if (!strcasecmp(tl->a, buf))
00974 return tl->i;
00975 }
00976
00977 l = strtoul(buf, &end, 0);
00978 if (l == ULONG_MAX || *end != '\0')
00979 return -NLE_OBJ_NOTFOUND;
00980
00981 return (int) l;
00982 }
00983
00984 int __str2flags(const char *buf, const struct trans_tbl *tbl, size_t tbl_len)
00985 {
00986 int i, flags = 0, len;
00987 char *p = (char *) buf, *t;
00988
00989 for (;;) {
00990 if (*p == ' ')
00991 p++;
00992
00993 t = strchr(p, ',');
00994 len = t ? t - p : strlen(p);
00995 for (i = 0; i < tbl_len; i++)
00996 if (!strncasecmp(tbl[i].a, p, len))
00997 flags |= tbl[i].i;
00998
00999 if (!t)
01000 return flags;
01001
01002 p = ++t;
01003 }
01004
01005 return 0;
01006 }
01007
01008 void dump_from_ops(struct nl_object *obj, struct nl_dump_params *params)
01009 {
01010 int type = params->dp_type;
01011
01012 if (type < 0 || type > NL_DUMP_MAX)
01013 BUG();
01014
01015 params->dp_line = 0;
01016
01017 if (params->dp_dump_msgtype) {
01018 #if 0
01019
01020 char buf[64];
01021
01022 dp_dump_line(params, 0, "%s ",
01023 nl_cache_mngt_type2name(obj->ce_ops,
01024 obj->ce_ops->co_protocol,
01025 obj->ce_msgtype,
01026 buf, sizeof(buf)));
01027 #endif
01028 params->dp_pre_dump = 1;
01029 }
01030
01031 if (params->dp_buf)
01032 memset(params->dp_buf, 0, params->dp_buflen);
01033
01034 if (obj->ce_ops->oo_dump[type])
01035 obj->ce_ops->oo_dump[type](obj, params);
01036 }
01037
01038
01039
01040