/* 1200, Wed 3 Feb 99 FD_PARSE.C: Scanner/parser for fd_filter and fd_extract Copyright (C) 1992-2002 by Nevil Brownlee, CAIDA | University of Auckland */ /* * $Log: fd_parse.c,v $ * Revision 1.1.1.2.2.11 2002/02/23 01:57:17 nevil * Moving srl examples to examples/ directory. Modified examples/Makefile.in * * Revision 1.1.1.2.2.6 2000/08/08 19:44:42 nevil * 44b8 release * * Revision 1.1.1.2.2.4 2000/06/06 03:38:08 nevil * Combine NEW_ATR with TCP_ATR, various bug fixes * * Revision 1.1.1.2.2.1 2000/01/12 02:57:03 nevil * Implement 'packet pair matched' turnaroundtime distribution attributes. * Fix ASN-related bugs in NeTraMet, distribution-related bugs in fd_filter. * * Revision 1.1.1.2 1999/10/03 21:06:14 nevil * *** empty log message *** * * Revision 1.1.1.1.2.9 1999/09/22 05:38:34 nevil * Improve code to work properly on 64-bit machines * - Add OS=ALPHA handling to configure.in * - Clean up the Alpha compiler warnings * - Change all the snmp-related code to use Bit32 instead of unsigned long * * Revision 1.1.1.1.2.8 1999/09/14 00:46:46 nevil * 4.3 Release .. * - Implement -D option to run NeMaC as a daemon * - Tidy up the on-line help displays * - Make IPv4 the default PeerType for sfmt_attribute() * * Revision 1.1.1.1.2.7 1999/05/18 03:36:24 nevil * Implement IPv6 in NeTraMet, and its manager/collectors. * - This is controlled by the V6 #define * - NeTraMet recognises v6 packets and fishes through their extension * headers until it finds the actual payload. * - NeMaC et al display v6 addresses in the fom specified by RFC 2373 * - fd_util and fd_extract allow colons in addresses (for defining tags) * * Revision 1.1.1.1.2.6 1999/02/15 21:24:05 nevil * Distribution file for 4.3b9 * * Revision 1.1.1.1.2.5 1999/02/03 04:41:42 nevil * Implementation of TCP attributes, part 5 * * Revision 1.1.1.1.2.4 1999/01/27 04:26:12 nevil * Minor corrections to fix compiler warnings * * Revision 1.1.1.1.2.3 1999/01/20 04:01:32 nevil * Implementation of TCP attributes, part 4 * * Revision 1.1.1.1.2.2 1999/01/08 01:37:07 nevil * Implement TCPdata and DScodepoint attribute * * Revision 1.1.1.1.2.1 1998/11/26 04:13:49 nevil * Fix problems in fd_filter and fd_extract when dealing with 'new' * attributes, especially those used with NETFLOW. In particular: * - Make sure attribs[] is referred to via attr_ix[] * - Get the separators correctly from a #Format record (no quotes) * - fd_extract wasn't writing out its data for the last sample! * * Revision 1.1.1.1 1998/11/16 03:57:27 nevil * Import of NeTraMet 4.3b3 * * Revision 1.1.1.1 1998/11/16 03:22:00 nevil * Import of release 4.3b3 * * Revision 1.1.1.1.2.1 1998/11/11 23:14:36 nevil * Only include malloc.h if we HAVE_MALLOC_H * * Revision 1.1.1.1 1998/10/28 20:31:23 nevil * Import of NeTraMet 4.3b1 * * Revision 1.1.3.2 1998/10/18 23:44:04 nevil * Added Nicolai's patches, some 'tidying up' of the source * * Revision 1.1.3.1 1998/10/13 02:48:17 nevil * Import of Nicolai's 4.2.2 * * Revision 1.1.1.1 1998/08/24 12:09:28 nguba * NetraMet 4.2 Original Distribution * * Revision 1.4 1998/07/21 00:43:57 rtfm * Change attrib numbers for 'New Attribs' I-D * First release version of SRL * * Revision 1.3 1998/05/07 04:28:53 rtfm * Implement NetFlowMet, the Cisco NetFlow RTFM meter */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include #if HAVE_MALLOC_H # include #endif #include #include #include #include #include "ausnmp.h" #include "asn1.h" #include "fd_data.h" #include "nmc_c64.h" #if NEW_ATR #define TEST_DELTA 0 struct distribution *dl INIT(NULL); struct distribution *get_dist(void) /* Get an unused distribution */ { struct distribution *d; if (dl != NULL) { d = dl; dl = dl->next; } else { d = (struct distribution *)malloc(sizeof(struct distribution)); } return d; } void free_dist(struct distribution *d) /* Return distribution to free list */ { d->next = dl; dl = d; } #endif /* NEW_ATR */ char *gnbr(unsigned int *n,char *s) /* Get nbr from 's', */ { unsigned int v = 0, b = 10, d; while (*s == ' ') ++s; if (*s == 'x' || *s == 'X') { ++s; b = 16; } else if (*s == '0') { ++s; b = 8; } for (;;) { d = *s; if (b == 16) { if (!isxdigit(d)) break; } else { if (!isdigit(d)) break; if (b == 8 && d > '7') break; } if (d <= '9') d -= '0'; else if (d <= 'F') d -= ('A'-10); else d -= ('a'-10); v = v*b + d; ++s; } *n = v; return s; } char *gcstring(char *s, int *len) /* Get string from s */ { static char escin[] = { 'b', 'f', 'n', 'r', 't', 'v','\\','\'','\"','\?', 0 }; static char escout[] ={ '\b','\f','\n','\r','\t','\v','\\','\'','\"','\?' }; unsigned int c,j; char sbuf[80], *t = sbuf, *rp; while (*s) { if (*s == '\\') { ++s; c = *s; if (c == '0' || c == 'x' || c == 'X') { /* Octal or hex nbr */ s = gnbr(&c,s); *t++ = c; } else if (isdigit(c)) { /* Octal number */ --s; *s = '0'; /* Make gnbr use base 8 */ s = gnbr(&c,s); *t++ = c; } else { j = 0; do { if (c == escin[j]) break; } while (escin[++j] != 0); if (escin[j] != 0) { *t++ = escout[j]; ++s; } } } else *t++ = *s++; } *t = '\0'; *len = t-sbuf; rp = (char *)malloc(*len+1); strcpy(rp,sbuf); return rp; } int parse_open(char *fn) /* Open file and initialise parser */ { if ((rfp = fopen(fn, "r")) == NULL) return 0; rferrors = rule_line = 0; ic = '\n'; return 1; } void p_error(char *msg) { if (!iblisted) { fprintf(stderr,"line %d: %s\n", rule_line,inbuf); iblisted = 1; } fprintf(stderr,"%s !!!\n", msg); ++rferrors; } int nextchar(void) { char *p; lic = ic; for (;;) { if (lic == '\n') { if (fgets(inbuf, sizeof(inbuf), rfp) == NULL) return ic = EOF; iblisted = 0; ++rule_line; ibp = inbuf; } ic = *ibp++; if (ic == '#') lic = '\n'; /* Ignore comments */ else return ic; } } int nexttoken(void) { for (;;) { if (isalnum(ic) || ic == '_') return 1; if (ic == ';' || ic == EOF) return 0; nextchar(); } } int relop_next(void) { int op; for (;;) { if (isalnum(ic) || ic == '_' || ic == ';' || ic == EOF) return 0; if (ic == '=' || ic == '!') { op = ic; nextchar(); switch (op) { case '=': return OP_EQ; case '!': return OP_NE; } } nextchar(); } } void getfdstring(unsigned char *arg) { for (;;) { if (isxdigit(ic)) break; /* Addresses start with a (hex) digit */ #if V6 if (ic == ':') break; /* v6 addresses may start with a colon */ #endif nextchar(); } if (ic != EOF) do { *arg++ = toupper(ic); nextchar(); /* Addresses may include . (decimal) or - (hex) */ } while (isxdigit(ic) || ic == '.' || ic == '-' #if V6 || ic == ':' #endif ); *arg = '\0'; return; } int wordis(char *p, char *w) { if (strlen(p) != strlen(w)) return 0; /* Lengths differ */ return strcmp(p,w) == 0; } int getword(void) { char wbuf[50], *wp = wbuf; int j; for (;;) { *wp++ = tolower(ic); nextchar(); if (ic == EOF) return EOF; if (!isalnum(ic) && ic != '_') break; } *wp = '\0'; if (wordis(wbuf,"set")) return RF_SET; if (wordis(wbuf,"format")) return RF_FORMAT; if (wordis(wbuf,"tag")) return RF_TAG; if (wordis(wbuf,"statistics")) return RF_STATS; if (wordis(wbuf,"column")) return RF_COLUMN; if (wordis(wbuf,"time")) return RF_TIME; if (wordis(wbuf,"scale")) return EX_SCALE; if (wordis(wbuf,"kilo")) return EX_KILO; if (wordis(wbuf,"mega")) return EX_MEGA; if (wordis(wbuf,"elapsed")) return EX_ELAPSED; if (wordis(wbuf,"clock")) return EX_CLOCK; if (wordis(wbuf,"seconds")) return EX_SECS; if (wordis(wbuf,"minutes")) return EX_MINS; if (wordis(wbuf,"hours")) return EX_HOURS; if (wordis(wbuf,"days")) return EX_DAYS; if (wordis(wbuf,"ip")) return AT_IP4; if (wordis(wbuf,"clns")) return AT_CLNS; if (wordis(wbuf,"decnet")) return AT_DECNET; if (wordis(wbuf,"ipx")) return AT_NOVELL; if (wordis(wbuf,"novell")) return AT_NOVELL; if (wordis(wbuf,"ethertalk")) return AT_ETHERTALK; if (wordis(wbuf,"other")) return AT_OTHER; if (wordis(wbuf,"icmp")) return PT_ICMP; if (wordis(wbuf,"tcp")) return PT_TCP; if (wordis(wbuf,"udp")) return PT_UDP; if (wordis(wbuf,"ospf")) return PT_OSPF; if (wordis(wbuf,"ftpdata")) return WNP_FTPDATA; if (wordis(wbuf,"ftp")) return WNP_FTP; if (wordis(wbuf,"telnet")) return WNP_TELNET; if (wordis(wbuf,"smtp")) return WNP_SMTP; if (wordis(wbuf,"domain")) return WNP_DOMAIN; if (wordis(wbuf,"nntp")) return WNP_NNTP; if (wordis(wbuf,"ntp")) return WNP_NTP; if (wordis(wbuf,"snmp")) return WNP_SNMP; for (j = 0; j != SZ_ATTRIBS; ++j) { if (wordis(wbuf,attribs[j].name)) return attribs[j].index; } sprintf(ebuf, "Unknown word %s", wbuf); p_error(ebuf); return 0; } int getnbr(void) /* Words return negative numbers */ { int v = 0; for (;;) { if (ic == EOF) return EOF; if (isdigit(ic)) break; if (isalpha(ic)) return getword(); if (ic == '\'') { v = nextchar(); if (nextchar() != '\'') p_error("Missing closing quote"); return v; } nextchar(); } for (;;) { v = v*10 + ic-'0'; if (nextchar() == EOF) return EOF; if (!isdigit(ic)) break; } return v; } void scan_format(struct flow_stats *fs, int single_record, int list) { char sbuf[32], *sp; int a, n, len, x; memset (fs, 0, sizeof(struct flow_stats)); for (a = 0; ; ++a) { n = getnbr(); if (n < 0 || n > LASTATTRIB || attr_ix[n] == 0) { sprintf(ebuf, "Attribute %d not allowed in format",n); p_error(ebuf); } else { fs->format[a] = n; fs->required[n] = 1; #if NEW_ATR if (DISTRIB_ATTRIB(n)) fs->distrib_bits |= 1 << n-DISTRIB_BASE; else if (DELTA_ATTRIB(n)) fs->delta_bits |= 1 << n-DELTA_BASE; #endif } if (single_record) { for (sp = sbuf; ; ) { if (ic == '\n' || islower(ic)) break; /* Start of next attribute name */ *sp++ = ic; nextchar(); } *sp = '\0'; fs->separator[a] = (char *)malloc(strlen(sp)+1); strcpy(fs->separator[a],sbuf); if (ic == '\n') break; /* End of #Format record */ } else { fs->separator[a] = " "; /* Default */ while (isspace(ic)) nextchar(); /* Skip blanks */ if (ic == ';') break; /* End of format statement */ if (!isalnum(ic)) { /* Separator */ if (ic == '\"') { /* Separator string */ nextchar(); for (sp = sbuf; ; ) { if (ic == '\"') break; *sp++ = ic; nextchar(); } nextchar(); } else { sp = sbuf; *sp++ = ' '; for (;;) { if (isspace(ic)) break; *sp++ = ic; nextchar(); } *sp++ = ' '; } *sp = '\0'; fs->separator[a] = gcstring(sbuf, &len); while (isspace(ic)) nextchar(); /* Skip blanks */ } if (ic == ';') break; /* End of format statement */ } } fs->n_attr = a+1; if (list && !quiet) { fprintf(stderr,"Format: "); for (n = 0; n != fs->n_attr; ++n) { a = fs->format[n]; x = attr_ix[a]; /* Index into attribs[] */ fprintf(stderr,attribs[x].name); if (n != fs->n_attr-1 || strcmp(fs->separator[n]," ") != 0) fprintf(stderr, fs->separator[n]); } fprintf(stderr,"\n"); } } val attrib_ptr(struct flow_info *fip, int a) { val v; switch (a) { case FTFLOWINDEX: v.intval = &fip->FlowIndex; break; case FTLOWINTERFACE: v.intval = &fip->LowInterface; break; case FTLOWADJACENTTYPE: v.intval = &fip->LowAdjType; break; case FTLOWADJACENTADDRESS: v.charval = fip->LowAdjAddress; break; case FTLOWADJACENTMASK: v.charval = fip->LowAdjMask; break; case FTLOWPEERTYPE: v.intval = &fip->LowPeerType; break; case FTLOWPEERADDRESS: v.charval = fip->LowPeerAddress; break; case FTLOWPEERMASK: v.charval = fip->LowPeerMask; break; case FTLOWTRANSTYPE: v.intval = &fip->LowTransType; break; case FTLOWTRANSADDRESS: v.intval = &fip->LowTransAddress; break; case FTLOWTRANSMASK: v.intval = &fip->LowTransMask; break; case FTHIINTERFACE: v.intval = &fip->HighInterface; break; case FTHIADJACENTTYPE: v.intval = &fip->HighAdjType; break; case FTHIADJACENTADDRESS: v.charval = fip->HighAdjAddress; break; case FTHIADJACENTMASK: v.charval = fip->HighAdjMask; break; case FTHIPEERTYPE: v.intval = &fip->HighPeerType; break; case FTHIPEERADDRESS: v.charval = fip->HighPeerAddress; break; case FTHIPEERMASK: v.charval = fip->HighPeerMask; break; case FTHITRANSTYPE: v.intval = &fip->HighTransType; break; case FTHITRANSADDRESS: v.intval = &fip->HighTransAddress; break; case FTHITRANSMASK: v.intval = &fip->HighTransMask; break; case FTRULESET: v.intval = &fip->FlowRuleSet; break; case FTUPOCTETS: v.c64val = &fip->FwdBytes; break; case FTUPPDUS: v.c64val = &fip->FwdPackets; break; case FTDOWNOCTETS: v.c64val = &fip->BackBytes; break; case FTDOWNPDUS: v.c64val = &fip->BackPackets; break; case FTFIRSTTIME: v.intval = &fip->FirstTime; break; case FTLASTTIME: v.intval = &fip->LastTime; break; case FTSOURCECLASS: v.intval = &fip->LowClass; break; case FTDESTCLASS: v.intval = &fip->HighClass; break; case FTFLOWCLASS: v.intval = &fip->FlowClass; break; case FTSOURCEKIND: v.intval = &fip->LowKind; break; case FTDESTKIND: v.intval = &fip->HighKind; break; case FTFLOWKIND: v.intval = &fip->FlowKind; break; case FTDSCODEPOINT: v.intval = &fip->DSCodePoint; break; case FTUPOCTETS_D: v.c64val = &fip->upbci; break; case FTUPPDUS_D: v.c64val = &fip->uppci; break; case FTDOWNOCTETS_D: v.c64val = &fip->dnbci; break; case FTDOWNPDUS_D: v.c64val = &fip->dnpci; break; case FTTAGNBR: v.intval = &fip->TagNbr; break; #if defined(NETFLOW) case FTMETERID: v.intval = &fip->MeterId; break; case FTLOWROUTEASN: v.intval = &fip->LowRouteASN; break; case FTLOWROUTEPREFIX: v.intval = &fip->LowRoutePrefix; break; case FTHIROUTEASN: v.intval = &fip->HighRouteASN; break; case FTHIROUTEPREFIX: v.intval = &fip->HighRoutePrefix; break; #endif #if NEW_ATR case FTTCPDATA: v.sfval = &fip->sfd; break; case FTTCPDATA_D: v.sfval = &fip->sfd_rate; break; case FTTOLOSTPDUS: v.intval = &fip->ToLostPDUs; break; case FTFROMLOSTPDUS: v.intval = &fip->FromLostPDUs; break; case FTTOLOSTPDUS_D: v.intval = &fip->d_ToLostPDUs; break; case FTFROMLOSTPDUS_D: v.intval = &fip->d_FromLostPDUs; break; case FTTOPQOVERFLOWS: v.intval = &fip->ToPQOverflows; break; case FTFROMPQOVERFLOWS: v.intval = &fip->FromPQOverflows; break; case FTTOPQOVERFLOWS_D: v.intval = &fip->d_ToPQOverflows; break; case FTFROMPQOVERFLOWS_D: v.intval = &fip->d_FromPQOverflows; break; case FTTOPACKETSIZE: case FTFROMPACKETSIZE: case FTTOINTERARRIVALTIME: case FTFROMINTERARRIVALTIME: /* case FTTOTURNAROUNDTIME: case FTFROMTURNAROUNDTIME: */ case FTTOBITRATE: case FTFROMBITRATE: case FTTOPDURATE: case FTFROMPDURATE: case FTTOTCPSIZE: case FTFROMTCPSIZE: case FTTOTCPTIME: case FTFROMTCPTIME: case FTTOTCPRATE1: case FTFROMTCPRATE1: case FTTOTCPRATE2: case FTFROMTCPRATE2: case FTTOTURNAROUNDTIME1: case FTFROMTURNAROUNDTIME1: case FTTOTURNAROUNDTIME2: case FTFROMTURNAROUNDTIME2: case FTTOTURNAROUNDTIME3: case FTFROMTURNAROUNDTIME3: case FTTOTURNAROUNDTIME4: case FTFROMTURNAROUNDTIME4: case FTTOFLOWOCTETS: case FTFROMFLOWOCTETS: case FTTOFLOWPDUS: case FTFROMFLOWPDUS: case FTFLOWTIME: v.distval = &fip->dist; /* Start of flow's distrib chain */ break; case FTTOPACKETSIZE_D: case FTFROMPACKETSIZE_D: case FTTOINTERARRIVALTIME_D: case FTFROMINTERARRIVALTIME_D: /* case FTTOTURNAROUNDTIME_D: case FTFROMTURNAROUNDTIME_D: */ case FTTOBITRATE_D: case FTFROMBITRATE_D: case FTTOPDURATE_D: case FTFROMPDURATE_D: case FTTOTCPSIZE_D: case FTFROMTCPSIZE_D: case FTTOTCPTIME_D: case FTFROMTCPTIME_D: case FTTOTCPRATE1_D: case FTFROMTCPRATE1_D: case FTTOTCPRATE2_D: case FTFROMTCPRATE2_D: case FTTOTURNAROUNDTIME1_D: case FTFROMTURNAROUNDTIME1_D: case FTTOTURNAROUNDTIME2_D: case FTFROMTURNAROUNDTIME2_D: case FTTOTURNAROUNDTIME3_D: case FTFROMTURNAROUNDTIME3_D: case FTTOTURNAROUNDTIME4_D: case FTFROMTURNAROUNDTIME4_D: case FTTOFLOWOCTETS_D: case FTFROMFLOWOCTETS_D: case FTTOFLOWPDUS_D: case FTFROMFLOWPDUS_D: case FTFLOWTIME_D: v.distval = &fip->dist_rate; break; #endif /* NEW_ATR */ default: v.intval = NULL; break; } return v; } /* get_value() and put_value() are simplified routines for working with flow data files. Strings are delimited by blanks! */ char *get_value(val v, int a, char *pb) { unsigned long val; int j; unsigned char *p; #if NEW_ATR struct distribution *d, *ld; #endif /* NEW_ATR */ char buf[30]; /* ???????? */ if (*pb == '\0') return NULL; while (isspace(*pb)) pb++; switch (a) { /* counter64 attributes */ case FTUPOCTETS: case FTUPPDUS: case FTDOWNOCTETS: case FTDOWNPDUS: case FTUPOCTETS_D: case FTUPPDUS_D: case FTDOWNOCTETS_D: case FTDOWNPDUS_D: pb = getc64(v.c64val, pb); break; #if NEW_ATR case FTTCPDATA: case FTTCPDATA_D: sscanf(pb, "%u", &v.sfval->n_subflows); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; if (v.sfval->n_subflows == 0) break; /* No TCPdata values */ sscanf(pb, "%u", &v.sfval->mx_active_subflows); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; pb = getc64(&v.sfval->ToTCPLenOctets, pb); while (isspace(*pb)) ++pb; pb = getc64(&v.sfval->FromTCPLenOctets, pb); while (isspace(*pb)) ++pb; pb = getc64(&v.sfval->ToTCPSeqOctets, pb); while (isspace(*pb)) ++pb; pb = getc64(&v.sfval->FromTCPSeqOctets, pb); while (isspace(*pb)) ++pb; pb = getc64(&v.sfval->ToTCPAckOctets, pb); while (isspace(*pb)) ++pb; pb = getc64(&v.sfval->FromTCPAckOctets, pb); while (isspace(*pb)) ++pb; sscanf(pb, "%u", &v.sfval->ToTCPDecrSeq); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; sscanf(pb, "%u", &v.sfval->FromTCPDecrSeq); while (isdigit(*pb)) ++pb; break; case FTTOPACKETSIZE: case FTFROMPACKETSIZE: case FTTOINTERARRIVALTIME: case FTFROMINTERARRIVALTIME: /* case FTTOTURNAROUNDTIME: case FTFROMTURNAROUNDTIME: */ case FTTOBITRATE: case FTFROMBITRATE: case FTTOPDURATE: case FTFROMPDURATE: case FTTOTCPSIZE: case FTFROMTCPSIZE: case FTTOTCPTIME: case FTFROMTCPTIME: case FTTOTCPRATE1: case FTFROMTCPRATE1: case FTTOTCPRATE2: case FTFROMTCPRATE2: case FTTOTURNAROUNDTIME1: case FTFROMTURNAROUNDTIME1: case FTTOTURNAROUNDTIME2: case FTFROMTURNAROUNDTIME2: case FTTOTURNAROUNDTIME3: case FTFROMTURNAROUNDTIME3: case FTTOTURNAROUNDTIME4: case FTFROMTURNAROUNDTIME4: case FTTOFLOWOCTETS: case FTFROMFLOWOCTETS: case FTTOFLOWPDUS: case FTFROMFLOWPDUS: case FTFLOWTIME: case FTTOPACKETSIZE_D: case FTFROMPACKETSIZE_D: case FTTOINTERARRIVALTIME_D: case FTFROMINTERARRIVALTIME_D: /* case FTTOTURNAROUNDTIME_D: case FTFROMTURNAROUNDTIME_D: */ case FTTOBITRATE_D: case FTFROMBITRATE_D: case FTTOPDURATE_D: case FTFROMPDURATE_D: case FTTOTCPSIZE_D: case FTFROMTCPSIZE_D: case FTTOTCPTIME_D: case FTFROMTCPTIME_D: case FTTOTCPRATE1_D: case FTFROMTCPRATE1_D: case FTTOTCPRATE2_D: case FTFROMTCPRATE2_D: case FTTOTURNAROUNDTIME1_D: case FTFROMTURNAROUNDTIME1_D: case FTTOTURNAROUNDTIME2_D: case FTFROMTURNAROUNDTIME2_D: case FTTOTURNAROUNDTIME3_D: case FTFROMTURNAROUNDTIME3_D: case FTTOTURNAROUNDTIME4_D: case FTFROMTURNAROUNDTIME4_D: case FTTOFLOWOCTETS_D: case FTFROMFLOWOCTETS_D: case FTTOFLOWPDUS_D: case FTFROMFLOWPDUS_D: case FTFLOWTIME_D: if (*v.distval == NULL) { ld = d = NULL; } else for (d = *v.distval; ; ) { /* Find end of chain */ if (d->selector == a) break; ld = d; d = d->next; if (d == NULL) break; } if (d == NULL) { if ((d = get_dist()) == NULL) { fprintf(stderr, "Couldn't get space for distribution!\n"); exit(12); } #if TEST_DELTA fprintf(stderr, "get_val(0x%0lx, %d) -> 0x%0lx\n", v.distval,a, d); #endif if (ld == NULL) *v.distval = d; /* First dist in chain */ else ld->next = d; d->next = NULL; d->selector = a; /* Attribute number */ } sscanf(pb, "%u", &d->Transform); while (isdigit(*pb)) ++pb; if (d->Transform == 0) break; /* No data available */ while (isspace(*pb)) ++pb; sscanf(pb, "%u", &d->ScaleFactor); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; sscanf(pb, "%u", &d->LowerLimit); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; sscanf(pb, "%u", &d->UpperLimit); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; sscanf(pb, "%u", &d->Buckets); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; sscanf(pb, "%u", &d->Parameter1); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; sscanf(pb, "%u", &d->Parameter2); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; sscanf(pb, "%u", &d->Parameter3); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; for (j = 0; j != d->Buckets+1; ++j) { sscanf(pb, "%u", &d->counts[j]); while (isdigit(*pb)) ++pb; while (isspace(*pb)) ++pb; } break; #endif /* NEW_ATR */ default: if (string_value(a)) { for (j = 0, p = v.charval; *pb && *pb != ' ' && *pb != ';' && j < STR_LEN; ++j) *p++ = *pb++; *p = '\0'; } else { /* Unsigned int */ sscanf(pb, "%u", v.intval); while (isdigit(*pb)) ++pb; } } return pb; } void put_value(FILE *out, int a, val v) { char buf[30]; #if NEW_ATR struct distribution *d; int j; #endif /* NEW_ATR */ switch (a) { /* counter64 attributes */ case FTUPOCTETS: case FTUPPDUS: case FTDOWNOCTETS: case FTDOWNPDUS: case FTUPOCTETS_D: case FTUPPDUS_D: case FTDOWNOCTETS_D: case FTDOWNPDUS_D: putc64(buf, v.c64val); fprintf(out,"%s",buf); break; #if NEW_ATR case FTTCPDATA: case FTTCPDATA_D: if (v.sfval->n_subflows == 0) { /* No TCPdata values */ fprintf(out,"0 "); break; } fprintf(out,"%u %u ", v.sfval->n_subflows, v.sfval->mx_active_subflows); putc64(buf, &v.sfval->ToTCPLenOctets); fprintf(out,"%s ",buf); putc64(buf, &v.sfval->FromTCPLenOctets); fprintf(out,"%s ",buf); putc64(buf, &v.sfval->ToTCPSeqOctets); fprintf(out,"%s ",buf); putc64(buf, &v.sfval->FromTCPSeqOctets); fprintf(out,"%s ",buf); putc64(buf, &v.sfval->ToTCPAckOctets); fprintf(out,"%s ",buf); putc64(buf, &v.sfval->FromTCPAckOctets); fprintf(out,"%s ",buf); fprintf(out,"%u %u", v.sfval->ToTCPDecrSeq, v.sfval->FromTCPDecrSeq); break; case FTTOPACKETSIZE: case FTFROMPACKETSIZE: case FTTOINTERARRIVALTIME: case FTFROMINTERARRIVALTIME: /* case FTTOTURNAROUNDTIME: case FTFROMTURNAROUNDTIME: */ case FTTOBITRATE: case FTFROMBITRATE: case FTTOPDURATE: case FTFROMPDURATE: case FTTOTCPSIZE: case FTFROMTCPSIZE: case FTTOTCPTIME: case FTFROMTCPTIME: case FTTOTCPRATE1: case FTFROMTCPRATE1: case FTTOTCPRATE2: case FTFROMTCPRATE2: case FTTOTURNAROUNDTIME1: case FTFROMTURNAROUNDTIME1: case FTTOTURNAROUNDTIME2: case FTFROMTURNAROUNDTIME2: case FTTOTURNAROUNDTIME3: case FTFROMTURNAROUNDTIME3: case FTTOTURNAROUNDTIME4: case FTFROMTURNAROUNDTIME4: case FTTOFLOWOCTETS: case FTFROMFLOWOCTETS: case FTTOFLOWPDUS: case FTFROMFLOWPDUS: case FTFLOWTIME: case FTTOPACKETSIZE_D: case FTFROMPACKETSIZE_D: case FTTOINTERARRIVALTIME_D: case FTFROMINTERARRIVALTIME_D: /* case FTTOTURNAROUNDTIME_D: case FTFROMTURNAROUNDTIME_D: */ case FTTOBITRATE_D: case FTFROMBITRATE_D: case FTTOPDURATE_D: case FTFROMPDURATE_D: case FTTOTCPSIZE_D: case FTFROMTCPSIZE_D: case FTTOTCPTIME_D: case FTFROMTCPTIME_D: case FTTOTCPRATE1_D: case FTFROMTCPRATE1_D: case FTTOTCPRATE2_D: case FTFROMTCPRATE2_D: case FTTOTURNAROUNDTIME1_D: case FTFROMTURNAROUNDTIME1_D: case FTTOTURNAROUNDTIME2_D: case FTFROMTURNAROUNDTIME2_D: case FTTOTURNAROUNDTIME3_D: case FTFROMTURNAROUNDTIME3_D: case FTTOTURNAROUNDTIME4_D: case FTFROMTURNAROUNDTIME4_D: case FTTOFLOWOCTETS_D: case FTFROMFLOWOCTETS_D: case FTTOFLOWPDUS_D: case FTFROMFLOWPDUS_D: case FTFLOWTIME_D: for (d = *v.distval; d != NULL; d = d->next) { if (d->selector == a) break; } if (d == NULL) { fprintf(stderr, "Couldn't find distribution attrib %d\n", a); exit(12); } fprintf(out,"%u",d->Transform); if (d->Transform == 0) break; /* No data available */ fprintf(out," %u %u %u %u %u %u %u ", d->ScaleFactor, d->LowerLimit, d->UpperLimit, d->Buckets, d->Parameter1, d->Parameter2, d->Parameter3); for (j = 0; j != d->Buckets+1; ++j) fprintf(out," %u", d->counts[j]); break; #endif /* NEW_ATR */ default: if (string_value(a)) { fprintf(out,"%s",v.charval); } else { fprintf(out,"%u",*v.intval); } } }