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