00001
00008 #include <net-snmp/net-snmp-config.h>
00009 #include <sys/types.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <ctype.h>
00013 #if HAVE_STRING_H
00014 #include <string.h>
00015 #else
00016 #include <strings.h>
00017 #endif
00018 #if HAVE_WINSOCK_H
00019 #include <winsock.h>
00020 #endif
00021
00022 #include <net-snmp/types.h>
00023 #include <net-snmp/library/int64.h>
00024 #include <net-snmp/library/snmp_assert.h>
00025 #include <net-snmp/library/snmp_debug.h>
00026 #include <net-snmp/library/snmp_logging.h>
00027
00028 #define TRUE 1
00029 #define FALSE 0
00030
00039 void
00040 divBy10(U64 u64, U64 * pu64Q, unsigned int *puR)
00041 {
00042 unsigned long ulT;
00043 unsigned long ulQ;
00044 unsigned long ulR;
00045
00046
00047
00048
00049
00050 ulT = (u64.high >> 16) & 0x0ffff;
00051 ulQ = ulT / 10;
00052 ulR = ulT % 10;
00053 pu64Q->high = ulQ << 16;
00054
00055
00056
00057
00058 ulT = (u64.high & 0x0ffff);
00059 ulT += (ulR << 16);
00060 ulQ = ulT / 10;
00061 ulR = ulT % 10;
00062 pu64Q->high = pu64Q->high | ulQ;
00063
00064
00065
00066
00067 ulT = ((u64.low >> 16) & 0x0ffff) + (ulR << 16);
00068 ulQ = ulT / 10;
00069 ulR = ulT % 10;
00070 pu64Q->low = ulQ << 16;
00071
00072
00073
00074
00075 ulT = (u64.low & 0x0ffff);
00076 ulT += (ulR << 16);
00077 ulQ = ulT / 10;
00078 ulR = ulT % 10;
00079 pu64Q->low = pu64Q->low | ulQ;
00080
00081 *puR = (unsigned int) (ulR);
00082
00083
00084 }
00085
00086
00094 void
00095 multBy10(U64 u64, U64 * pu64P)
00096 {
00097 unsigned long ulT;
00098 unsigned long ulP;
00099 unsigned long ulK;
00100
00101
00102
00103
00104
00105 ulT = u64.low & 0x0ffff;
00106 ulP = ulT * 10;
00107 ulK = ulP >> 16;
00108 pu64P->low = ulP & 0x0ffff;
00109
00110
00111
00112
00113 ulT = (u64.low >> 16) & 0x0ffff;
00114 ulP = (ulT * 10) + ulK;
00115 ulK = ulP >> 16;
00116 pu64P->low = (ulP & 0x0ffff) << 16 | pu64P->low;
00117
00118
00119
00120
00121 ulT = u64.high & 0x0ffff;
00122 ulP = (ulT * 10) + ulK;
00123 ulK = ulP >> 16;
00124 pu64P->high = ulP & 0x0ffff;
00125
00126
00127
00128
00129 ulT = (u64.high >> 16) & 0x0ffff;
00130 ulP = (ulT * 10) + ulK;
00131 ulK = ulP >> 16;
00132 pu64P->high = (ulP & 0x0ffff) << 16 | pu64P->high;
00133
00134
00135 }
00136
00137
00145 void
00146 incrByU16(U64 * pu64, unsigned int u16)
00147 {
00148 unsigned long ulT1;
00149 unsigned long ulT2;
00150 unsigned long ulR;
00151 unsigned long ulK;
00152
00153
00154
00155
00156
00157 ulT1 = pu64->low;
00158 ulT2 = ulT1 & 0x0ffff;
00159 ulR = ulT2 + u16;
00160 ulK = ulR >> 16;
00161 if (ulK == 0) {
00162 pu64->low = ulT1 + u16;
00163 return;
00164 }
00165
00166
00167
00168
00169 ulT2 = (ulT1 >> 16) & 0x0ffff;
00170 ulR = ulT2 + 1;
00171 ulK = ulR >> 16;
00172 if (ulK == 0) {
00173 pu64->low = ulT1 + u16;
00174 return;
00175 }
00176
00177
00178
00179
00180 pu64->low = (ulT1 + u16) & 0x0FFFFFFFFL;
00181 pu64->high++;
00182 #if SIZEOF_LONG != 4
00183 pu64->high &= 0xffffffff;
00184 #endif
00185 }
00186
00187 void
00188 incrByU32(U64 * pu64, unsigned int u32)
00189 {
00190 unsigned int tmp;
00191 tmp = pu64->low;
00192 pu64->low += u32;
00193 #if SIZEOF_LONG != 4
00194 pu64->low &= 0xffffffff;
00195 #endif
00196 if (pu64->low < tmp) {
00197 pu64->high++;
00198 #if SIZEOF_LONG != 4
00199 pu64->high &= 0xffffffff;
00200 #endif
00201 }
00202 }
00203
00207 void
00208 u64Subtract(const U64 * pu64one, const U64 * pu64two, U64 * pu64out)
00209 {
00210 if (pu64one->low < pu64two->low) {
00211 pu64out->low = 0xffffffff - pu64two->low + pu64one->low + 1;
00212 pu64out->high = pu64one->high - pu64two->high - 1;
00213 } else {
00214 pu64out->low = pu64one->low - pu64two->low;
00215 pu64out->high = pu64one->high - pu64two->high;
00216 }
00217 }
00218
00222 void
00223 u64Incr(U64 * pu64out, const U64 * pu64one)
00224 {
00225 pu64out->high += pu64one->high;
00226 #if SIZEOF_LONG != 4
00227 pu64out->high &= 0xffffffff;
00228 #endif
00229 incrByU32(pu64out, pu64one->low);
00230 }
00231
00235 void
00236 u64UpdateCounter(U64 * pu64out, const U64 * pu64one, const U64 * pu64two)
00237 {
00238 U64 tmp;
00239 u64Subtract(pu64one, pu64two, &tmp);
00240 u64Incr(pu64out, &tmp);
00241 }
00242
00246 void
00247 u64Copy(U64 * pu64one, const U64 * pu64two)
00248 {
00249 pu64one->high = pu64two->high;
00250 pu64one->low = pu64two->low;
00251 }
00252
00259 void
00260 zeroU64(U64 * pu64)
00261 {
00262 pu64->low = 0;
00263 pu64->high = 0;
00264 }
00265
00266
00273 int
00274 isZeroU64(const U64 * pu64)
00275 {
00276
00277 if ((pu64->low == 0) && (pu64->high == 0))
00278 return (TRUE);
00279 else
00280 return (FALSE);
00281
00282 }
00283
00307 int
00308 netsnmp_c64_check_for_32bit_wrap(struct counter64 *old_val,
00309 struct counter64 *new_val,
00310 int adjust)
00311 {
00312 if( (NULL == old_val) || (NULL == new_val) )
00313 return -1;
00314
00315 DEBUGMSGTL(("9:c64:check_wrap", "check wrap 0x%0x.0x%0x 0x%0x.0x%0x\n",
00316 old_val->high, old_val->low, new_val->high, new_val->low));
00317
00318
00319
00320
00321 if ((new_val->low >= old_val->low) &&
00322 (new_val->high == old_val->high)) {
00323 DEBUGMSGTL(("9:c64:check_wrap", "no wrap\n"));
00324 return 0;
00325 }
00326
00327
00328
00329
00330 if (new_val->high == old_val->high) {
00331 DEBUGMSGTL(("c64:check_wrap", "32 bit wrap\n"));
00332 if (adjust) {
00333 ++new_val->high;
00334 #if SIZEOF_LONG != 4
00335 new_val->high &= 0xffffffff;
00336 #endif
00337 }
00338 return 32;
00339 }
00340 else if ((new_val->high == (old_val->high + 1)) ||
00341 ((0 == new_val->high) && (0xffffffff == old_val->high))) {
00342 DEBUGMSGTL(("c64:check_wrap", "64 bit wrap\n"));
00343 return 64;
00344 }
00345
00346 return -2;
00347 }
00348
00384 int
00385 netsnmp_c64_check32_and_update(struct counter64 *prev_val, struct counter64 *new_val,
00386 struct counter64 *old_prev_val, int *need_wrap_check)
00387 {
00388 int rc;
00389
00390
00391
00392
00393
00394
00395
00396 if ((NULL == need_wrap_check) || (0 != *need_wrap_check)) {
00397 rc = netsnmp_c64_check_for_32bit_wrap(old_prev_val,new_val, 1);
00398 if (rc < 0) {
00399 snmp_log(LOG_ERR,"c64 32 bit check failed\n");
00400 return -1;
00401 }
00402 }
00403 else
00404 rc = 0;
00405
00406
00407
00408
00409 (void) u64UpdateCounter(prev_val, new_val, old_prev_val);
00410
00411
00412
00413
00414 if (32 == rc) {
00415
00416
00417
00418
00419 netsnmp_assert(1 == new_val->high);
00420 new_val->high = 0;
00421 }
00422 else if (64 == rc) {
00423
00424
00425
00426
00427 if ((prev_val->low != new_val->low) ||
00428 (prev_val->high != new_val->high)) {
00429 snmp_log(LOG_ERR, "looks like a 64bit wrap, but prev!=new\n");
00430 return -2;
00431 }
00432 else if (NULL != need_wrap_check)
00433 *need_wrap_check = 0;
00434 }
00435
00436 return 0;
00437 }
00438
00439 void
00440 printU64(char *buf,
00441 const U64 * pu64) {
00442 U64 u64a;
00443 U64 u64b;
00444
00445 char aRes[I64CHARSZ + 1];
00446 unsigned int u;
00447 int j;
00448
00449 u64a.high = pu64->high;
00450 u64a.low = pu64->low;
00451 aRes[I64CHARSZ] = 0;
00452 for (j = 0; j < I64CHARSZ; j++) {
00453 divBy10(u64a, &u64b, &u);
00454 aRes[(I64CHARSZ - 1) - j] = (char) ('0' + u);
00455 u64a.high = u64b.high;
00456 u64a.low = u64b.low;
00457 if (isZeroU64(&u64a))
00458 break;
00459 }
00460 strcpy(buf, &aRes[(I64CHARSZ - 1) - j]);
00461 }
00462
00463 void
00464 printI64(char *buf,
00465 const U64 * pu64) {
00466 U64 u64a;
00467 U64 u64b;
00468
00469 char aRes[I64CHARSZ + 1];
00470 unsigned int u;
00471 int j, sign = 0;
00472
00473 if (pu64->high & 0x80000000) {
00474 u64a.high = ~pu64->high;
00475 u64a.low = ~pu64->low;
00476 sign = 1;
00477 incrByU32(&u64a, 1);
00478 } else {
00479 u64a.high = pu64->high;
00480 u64a.low = pu64->low;
00481 }
00482
00483 aRes[I64CHARSZ] = 0;
00484 for (j = 0; j < I64CHARSZ; j++) {
00485 divBy10(u64a, &u64b, &u);
00486 aRes[(I64CHARSZ - 1) - j] = (char) ('0' + u);
00487 u64a.high = u64b.high;
00488 u64a.low = u64b.low;
00489 if (isZeroU64(&u64a))
00490 break;
00491 }
00492 if (sign == 1) {
00493 aRes[(I64CHARSZ - 1) - j - 1] = '-';
00494 strcpy(buf, &aRes[(I64CHARSZ - 1) - j - 1]);
00495 return;
00496 }
00497 strcpy(buf, &aRes[(I64CHARSZ - 1) - j]);
00498 }
00499
00500 int
00501 read64(U64 * i64, const char *str)
00502 {
00503 U64 i64p;
00504 unsigned int u;
00505 int sign = 0;
00506 int ok = 0;
00507
00508 zeroU64(i64);
00509 if (*str == '-') {
00510 sign = 1;
00511 str++;
00512 }
00513
00514 while (*str && isdigit(*str)) {
00515 ok = 1;
00516 u = *str - '0';
00517 multBy10(*i64, &i64p);
00518 memcpy(i64, &i64p, sizeof(i64p));
00519 incrByU16(i64, u);
00520 str++;
00521 }
00522 if (sign) {
00523 i64->high = ~i64->high;
00524 i64->low = ~i64->low;
00525 incrByU16(i64, 1);
00526 }
00527 return ok;
00528 }
00529
00530
00531
00532
00533 #ifdef TESTING
00534 void
00535 main(int argc, char *argv[])
00536 {
00537 int i;
00538 int j;
00539 int l;
00540 unsigned int u;
00541 U64 u64a;
00542 U64 u64b;
00543 #define MXSZ 20
00544 char aRes[MXSZ + 1];
00545
00546
00547 if (argc < 2) {
00548 printf("This program takes numbers from the command line\n"
00549 "and prints them out.\n" "Usage: test <unsignedInt>...\n");
00550 exit(1);
00551 }
00552
00553 aRes[MXSZ] = 0;
00554
00555 for (i = 1; i < argc; i++) {
00556 l = strlen(argv[i]);
00557 zeroU64(&u64a);
00558 for (j = 0; j < l; j++) {
00559 if (!isdigit(argv[i][j])) {
00560 printf("Argument is not a number \"%s\"\n", argv[i]);
00561 exit(1);
00562 }
00563 u = argv[i][j] - '0';
00564 multBy10(u64a, &u64b);
00565 u64a = u64b;
00566 incrByU16(&u64a, u);
00567 }
00568
00569 printf("number \"%s\" in hex is '%08x%08x'h\n",
00570 argv[i], u64a.high, u64a.low);
00571
00572 printf("number is \"%s\"\n", printU64(&u64a));
00573 for (j = 0; j < MXSZ; j++) {
00574 divBy10(u64a, &u64b, &u);
00575 aRes[(MXSZ - 1) - j] = (char) ('0' + u);
00576 u64a = u64b;
00577 if (isZeroU64(&u64a))
00578 break;
00579 }
00580
00581 printf("number is \"%s\"\n", &aRes[(MXSZ - 1) - j]);
00582 }
00583 exit(0);
00584 }
00585 #endif
00586
00587
00588
00589