/* 1500, Fri 21 May 99 METER_PC.C: The AU accounting meter mainline; based on CMU's snmpd, PCIP's packet monitoring and Waterloo's TCP/IP. Copyright (C) 1992-2002 by Nevil Brownlee, ITSS Technology Development, The University of Auckland */ /* * $Log: meter_pc.c,v $ * Revision 1.1.1.2.2.8 2002/02/23 01:57:32 nevil * Moving srl examples to examples/ directory. Modified examples/Makefile.in * * Revision 1.1.1.2.2.6 2001/05/24 02:19:55 nevil * LfapMet implemented by Remco Poortinga. * MinPDUs implemented by Nevil. * * Revision 1.1.1.2.2.4 2000/06/06 03:38:21 nevil * Combine NEW_ATR with TCP_ATR, various bug fixes * * Revision 1.1.1.2.2.1 2000/01/12 02:57:12 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:25 nevil * *** empty log message *** * * Revision 1.1.1.1.2.5 1999/09/29 02:42:49 nevil * Fix problems discovered on PC meters * - Use NETRAMET compile-time variable to leave out C++ declarations * - Clean up mistakes in porting OCX_BGP code from meter_pc to meter_oc * * Revision 1.1.1.1.2.4 1999/09/24 02:58:41 nevil * Polish up code to get rid of warning messages from Borland (DOS) compiler. * Make manager PeerAddress buffers NSAP_ADDR_LEN bytes long. * Add asn_lookup variable - only call FindSubnet if ruleset uses ASNs. * * Revision 1.1.1.1.2.1 1999/01/08 01:31:55 nevil * Implementation of TCP attributes, part 3 * * Revision 1.1.1.1 1998/11/16 03:57:29 nevil * Import of NeTraMet 4.3b3 * * Revision 1.1.1.1 1998/11/16 03:22:01 nevil * Import of release 4.3b3 * * Revision 1.1.1.1 1998/10/28 20:31:28 nevil * Import of NeTraMet 4.3b1 * * Revision 1.1.3.1.2.2 1998/10/19 22:32:48 nevil * Meter improvements, mostly arising from developments for the * OCxMON meter. These are documented in notes_oc.txt * * Revision 1.1.3.1.2.1 1998/10/18 20:51:26 nevil * Added Nicolai's patches, some 'tidying up' of the source * * Revision 1.1.3.1 1998/10/13 02:48:40 nevil * Import of Nicolai's 4.2.2 * * Revision 1.1 1998/05/07 04:13:44 rtfm * Initial revision */ #pragma inline #define UPTIME_DBG 1 #define PKT_DEBUG 0 #define PC_BGP_TEST 0 #define LOW_PRIORITY_ARP 1 #define MIN_IP_BUFFERS 10 /* Ignore ARP packets if less IP buffers than this */ extern char version_descr[]; /* In met_vars.c */ extern char *communities[]; /* In snmp/snmpagnt.c */ char interface_name[10]; /* Device name for metered interface */ #include #include #include #include #include #include #if defined(__LARGE__) extern unsigned _stklen = 16000; /* Default stack size is only 4K !! */ #endif #include #include #include #define EXTSNMP #include "ausnmp.h" #include "asn1.h" #include "..\wattcp\wattcp.h" #include "snmp.h" #include "snmpimpl.h" #include "snmpapi.h" #include "..\wattcp\pktdrv.h" #define PKTSNAP #include "pktsnap.h" #include "flowhash.h" #include "met_vars.h" #if FLAT_MEM /* Use flat memory for flows */ extern void flat_init(int verbose); /* In flat.cpp */ #endif #if NF_OCX_BGP #include "..\integrat\readbgp.h" #include "..\integrat\subnet.h" #endif extern int errno; int snmp_dump_packet = 0; udp_Socket udpsock; static udp_Socket *s; int status; /* For socket */ Bit32 gethostid(void); /* In wattcp\pcbsd.c */ void init_snmp(void); /* In snmp\snmpapi.c */ void zero_pkt_stats(void); /* meter_pc function prototypes */ void receive(void); void meter_snmp_read(int length); #if UPTIME_DBG void print_uptime_log(void); /* In chart.cpp */ #endif int n_interfaces, IP_int; void accept_pkt(int len, #if OCX_NTM || OC3_NTM double at, #else counter64 at, #endif unsigned char huge *buff, int b_len, int if_nbr) { Bit16 ether_type, lsap; Bit8 huge *p; struct pkt huge *pp; int pkt_ix; if (--en_table[if_nbr].sample_count == 0) { /* Process only 1 pkt per SampleRate */ en_table[if_nbr].sample_count = en_table[if_nbr].SampleRate; ++en_table[if_nbr].npackets; en_table[if_nbr].nbytes += len; if (buff[12] <= 5) { /* 802.3 (5FF hex = 1535 decimal) */ lsap = buff[14] << 8 | buff[15]; if (lsap == 0xAAAA) { /* SNAP packet */ ether_type = buff[20] << 8 | buff[21]; p = &buff[22]; b_len -= 22; } else { ether_type = 0; p = &buff[14]; b_len -= 14; } } else { /* Blue book */ lsap = 0; ether_type = buff[12] << 8 | buff[13]; p = &buff[14]; b_len -= 14; } asm pushf; /* Save flags (especially int flag) */ asm cli; /* Disable interrupts */ if (free_n_pkt == 0) pkt_ix = 0; else { pp = &pkts[pkt_ix = free_head]; free_head = pp->next; --free_n_pkt; } asm popf; /* Restore flags */ if (pkt_ix == 0) { /* No pkts free, ignore the data */ ++lostpackets; ++en_table[if_nbr].lostpackets; } else { /* We have a buffer */ pp->p_len = len; pp->Low.Interface = pp->High.Interface = if_nbr+1; /* 1-org */ pp->Low.AdjType = pp->High.AdjType = AT_ETHERNET; pp->arrival_time = at; if (handle_pkt(pp, ether_type,lsap, buff, p,b_len)) { pp->next = 0; asm pushf; /* Save flags (especially int flag) */ asm cli; /* Disable interrupts */ if (proc_n_pkt == 0) proc_head = pkt_ix; else pkts[proc_tail].next = pkt_ix; proc_tail = pkt_ix; ++proc_n_pkt; asm popf; /* Restore flags */ } else { /* No ruleset wants this packet; just free it */ asm pushf; /* Save flags (especially int flag) */ asm cli; /* Disable interrupts */ if (free_n_pkt == 0) free_head = pkt_ix; else pkts[free_tail].next = pkt_ix; free_tail = pkt_ix; ++free_n_pkt; asm popf; /* Restore flags */ } } } } int our_packet(Bit8 far *buff) { if (buff[0] == 0xFF) { /* Broadcast */ if (buff[13] == 0x06 && buff[12] == 0x08) /* ARP */ return 1; } else if (buff[5] == eth_addr[5] && buff[4] == eth_addr[4] && buff[3] == eth_addr[3] && buff[2] == eth_addr[2] && buff[1] == eth_addr[1] && buff[0] == eth_addr[0]) { if (buff[12] == 0x08 && (buff[13] == 0x00 || buff[13] == 0x06 )) { /* IP or ARP */ return 1; } } return 0; /* Only want our IP & ARP pkts */ } #if PKT_DEBUG Bit8 *last_buf, *buf; #endif Bit8 far *pkt_rcv_call1(Bit16 len, /* Nevil, 15 Jul 96 */ Bit16 lah_len, Bit8 far *buff, Bit16 if_nbr) { Bit8 far *ipbuf; struct pbuf *bp; int if_type = en_table[if_nbr].type; if (if_type & EN_HP) { if (if_type & EN_MT) accept_pkt(len,uptime(), buff,lah_len, if_nbr); /* Pass attrib info to meter buffer */ if (if_type & EN_IP) { if (our_packet(buff)) { #if LOW_PRIORITY_ARP if (buff[13] == 0x06) { /* ARP */ if (freeq.len < MIN_IP_BUFFERS) return (Bit8 far *)NULL; } #endif return get_pktbuf(len); } } return (Bit8 far *)NULL; /* Don't bother with call2 */ } else { /* Can't see packet contents until call2 */ #if PKT_DEBUG last_buf = get_pktbuf(len); if (last_buf == NULL) swrite('#'); else { bp = (struct pbuf *)(last_buf - BUF_HDR_LEN); # if OCX_NTM || OC3_NTM bp->d.arrival_time.d = uptime(); # else bp->d.arrival_time.c = uptime(); # endif } return last_buf; #else if ((ipbuf = get_pktbuf(len)) == NULL) return ipbuf; /* No free IP buffers */ bp = (struct pbuf *)(ipbuf - BUF_HDR_LEN); # if OCX_NTM || OC3_NTM bp->d.arrival_time.d = uptime(); # else bp->d.arrival_time.c = uptime(); # endif return ipbuf; #endif } } void pkt_rcv_call2(Bit16 len, Bit8 far *buff, Bit16 if_nbr) { struct pbuf *bp = (struct pbuf *)(buff - BUF_HDR_LEN); int if_type = en_table[if_nbr].type; #if PKT_DEBUG if (buff != last_buf) swrite('X'); #endif if (if_type & EN_HP) { bp->state = 2; /* IP pkt ready for tcp/ip */ enqueue(&readyq, bp); return; } else { if (if_type & EN_MT) { # if OCX_NTM || OC3_NTM accept_pkt(len,bp->d.arrival_time.d, buff,len, if_nbr); #else accept_pkt(len,bp->d.arrival_time.c, buff,len, if_nbr); #endif /* Pass attribute info to meter buffer */ if (if_type & EN_IP) { if (our_packet(buff)) { bp->state = 2; /* IP pkt ready for tcp/ip */ enqueue(&readyq, bp); return; } } } else if (if_type & EN_IP) { /* IP only on this interface */ bp->state = 2; /* Unicast/broadcast mode */ enqueue(&readyq, bp); return; } } bp->state = 0; /* Unicast/broadcast mode */ enqueue(&freeq, bp); } void au_send_mon(int length, Bit8 far *buffer) { /* Invoked by pkt_send in src/pcpkt.c (if monitoring on IP interface) */ accept_pkt(length,uptime(), buffer,length, IP_int); /* Only sending on IP interface */ } void bump_noflowpkts(int if_nbr) { ++noflowpackets; ++en_table[if_nbr-1].noflowpackets; /* 1-org */ } void startup_screen() { char cbuf[60]; sclear(); scpos(0,0); printf(version_descr); scpos(0,1); printf("Running on %s",inet_ntoa(cbuf,gethostid())); } #if PC_BGP_TEST void bgp_lookup_test(void); void bgp_lookup_test() { Subnet *my_subnet; Bit32 my_address; char my_address_string[50]; char temp[20]; strcpy(my_address_string,"130.216.4.32"); /* convert the dotted-decimal string into binary */ my_address = inet_addr("130.216.4.32"); /* find the subnet record that corresponds to the IP address */ my_subnet = FindSubnet( htonl(my_address)); if (!my_subnet) { fprintf( stdout, "IP=%s not found in routing table\n", inet_ntoa(temp,my_address) ); // continue; } else { fprintf( stdout, "\nIP=%s, AS_path='%s'\n", my_subnet->as_path, my_address_string ); fprintf( stdout, "net=%s/%d ", inet_ntoa(temp,ntohl(my_subnet->addr)), bits_in_mask(my_subnet->mask) ); fprintf( stdout, "nexthop_ip=%s\n", inet_ntoa(temp,my_subnet->nexthop_addr) ); } } #endif int main(int argc, char *argv[]) { int arg, a, c, s_n, bgp_result; char *ap; struct en_info *enp; scinit(); sclear(); maxpkt = 1024; s_n = 1; n_interfaces = 0; IP_int = -1; for (c = 0; c != MAX_PD; ++c) { memset(&en_table[c], 0, sizeof(struct en_info)); en_table[c].sample_count = en_table[c].SampleRate = 1; } display_enabled = kb_enabled = 1; /* Enabled by default */ chart_interface = 0; mxflows = DFMXFLOWS; mxrules = DFMXRULES; mxstreams = DFMXSTREAMS; mxstr_blocks = DFMXSTRBLOCKS; mxdistribs = DFMXDISTRIBS; mxdistevents = DFMXDISTEVENTS; mxpktdatas = DFMXPKTDATS; /* Default (CMU) communities are: 0 = "public", 1 = "proxy", 2 = "private", 3 = "regional", 4 = "core" We only allow "public" and "private" by default */ communities[1] = communities[3] = communities[4] = ""; for (arg = 1; arg < argc; ++arg) { if (argv[arg][0] == '-') { ap = argv[arg]+2; switch (a = argv[arg][1]) { case 'a': if (*ap == '\0') ap = argv[++arg]; mxpktdatas = atoi(ap); break; case 'b': if (*ap == '\0') ap = argv[++arg]; mxstr_blocks = atoi(ap); break; case 'd': snmp_dump_packet++; break; case 'f': if (*ap == '\0') ap = argv[++arg]; mxflows = atoi(ap); break; case 'I': /* IP only, no metering */ case 'i': /* Metering (and perhaps IP) */ if (a == 'I') IP_int = n_interfaces; else if (IP_int < 0) IP_int = n_interfaces; case 'h': /* Metering with high-performance driver */ c = 0; if (*ap == '\0') ap = argv[++arg]; if (arg != argc) { /* There is another arg */ if (*ap == '-') --arg; /* -h -.. means -h0 */ else if(isdigit(*ap)) c = atoi(ap); } en_table[n_interfaces].int_nbr = c; if (a != 'I') en_table[n_interfaces].type = a == 'h' ? EN_HP|EN_MT : EN_MT; else en_table[n_interfaces].type = 0; ++n_interfaces; break; case 'k': kb_enabled = 0; /* -k to disable keyboard */ break; case 'l': /* Use 'Total Length' field from IP datagrams */ use_ip_length = 1; break; case 'm': if (*ap == '\0') ap = argv[++arg]; au_snmp_port = atoi(ap); break; case 'n': if (*ap == '\0') ap = argv[++arg]; s_n = atoi(ap); if (s_n < 1) s_n = 1; break; #if NF_OCX_BGP case 'o': use_owner_asns++; break; #endif case 'p': if (*ap == '\0') ap = argv[++arg]; maxpkt = atoi(ap); break; case 'r': if (*ap == '\0') ap = argv[++arg]; communities[0] = ap; /* -r to set read community */ break; case 's': display_enabled = 0; /* -s to disable screen */ break; case 't': if (*ap == '\0') ap = argv[++arg]; mxstreams = atoi(ap); break; case 'u': if (*ap == '\0') ap = argv[++arg]; mxrules = atoi(ap); break; case 'v': if (*ap == '\0') ap = argv[++arg]; mxdistribs = atoi(ap); break; case 'w': if (*ap == '\0') ap = argv[++arg]; communities[2] = ap; /* -w to set write community */ break; default: printf("Invalid option: -%c\n", argv[arg][1]); exit(0); } } } if (n_interfaces == 0) { en_table[0].type= EN_MT; n_interfaces = 1; } if (IP_int == -1) IP_int = 0; en_table[IP_int].type |= EN_IP; for (c = 0; c != n_interfaces; ++c) en_table[c].SampleRate = en_table[c].sample_count = s_n; pkts = (struct pkt far *)farmalloc((maxpkt+1) * sizeof(struct pkt)); pkts[0].next = 0; for (c = 1; c <= maxpkt; ++c) /* pkt[0] used for dummy packets */ pkts[c].next = c-1; free_head = maxpkt; free_tail = 1; free_n_pkt = maxpkt; proc_head = proc_tail = proc_n_pkt = 0; sock_init(); sprintf(interface_name, "et%d",en_table[0].int_nbr); startup_screen(); s = &udpsock; /* myport hisadr hisport */ if (!udp_open( s, SNMP_PORT, 0, 0, 0 )) { puts("udp_open failed!\n"); exit(1); } init_snmp(); #if FLAT_MEM && !(OCX_NTM || OC3_NTM) flat_init(1); /* Verbose flat init (for ntm32) */ # endif #if NF_OCX_BGP InitSubnet(); bgp_result = read_bgp_file("bgp.txt"); if (bgp_result) { log_msg(LOG_ERR, 1, "read_bgp_file failed, bgp_result=%d\n", bgp_result); } #endif init_monitor(n_interfaces); receive(); } void show_meter_time() { char msg[60]; sprintf(msg,"%lu seconds since %02d%02d:%02d", elapsed_sec, s_tod_h,s_tod_m,s_tod_s); display_msg(0,msg); } void set_chart_interface(int int_nbr) { chart_interface = int_nbr; spackets = en_table[chart_interface].npackets; sbytes = en_table[chart_interface].nbytes; zero_pkt_stats(); printf("Charting interface %d", int_nbr+1); } int mxmonpkts = 200; /* Max nbr packets per pkt_monitor call */ /* 400 was a little bit too high! Nevil, 22 Oct 96 */ int bkgi; /* Seconds before next run of backgound process */ #define BKG_INTERVAL 30 /* 30 seconds */ extern Bit32 pc_noflowpkts; /* Declared in met_vars.c */ void zero_pkt_stats() { int j; struct en_info *eip; pc_noflowpkts = noflowpackets; badpackets = nobufpackets = lostpackets = stats_time = t_backlog = spackets = sbytes = kilodummypackets = dummypacketrate = 0L; mindummyrate = 100000000L; pkt_backlog = max_pkt_backlog = max_pkt_rate = dummypackets = mdpacketrate = 0; zpackets = en_table[chart_interface].npackets; clear_pkt_stats = 0; } void receive() { int startup, ch, gci, p, k, pkt_ix, n, x, sumx, minx, maxx, samples, ax; char msg[60]; char l_tod_s; /* Last tod_s displayed on chart */ struct pkt huge *pp; struct en_info *eip; struct mgr_rec *mip; struct rdr_rec *cip; unsigned long pd,bd; long tot = set_timeout(1); char huge *cp; unsigned char half_scale = 0; startup = 1; for (;;) { sock_tick((sock_type *)s, &status); if ((n = sock_dataready((sock_type *)s)) != 0) { meter_snmp_read(n); sock_close((sock_type *)s); if (!udp_open( s, SNMP_PORT, 0, 0, 0 )) { puts("udp_open failed!\n"); exit(1); } } if (proc_n_pkt == 0) { /* No queued packets - build a dummy one */ cp = (char far *)&pkts[0]; for (k = 0; k != sizeof(struct pkt); ++k) cp[k] = 0; pkts[0].PeerAddrType = AT_DUMMY; pkt_monitor(&pkts[0]); } else { if (proc_n_pkt > pkt_backlog) pkt_backlog = proc_n_pkt; for (k = mxmonpkts; proc_n_pkt != 0 && k != 0; --k) { asm pushf; /* Save flags (especially int flag) */ asm cli; /* Disable interrupts */ pp = &pkts[pkt_ix = proc_head]; proc_head = pp->next; --proc_n_pkt; asm popf; /* Restore flags */ pkt_monitor(pp); asm pushf; /* Save flags (especially int flag) */ asm cli; /* Disable interrupts */ if (free_n_pkt == 0) free_head = pkt_ix; else pkts[free_tail].next = pkt_ix; free_tail = pkt_ix; ++free_n_pkt; asm popf; /* Restore flags */ } } if (chk_timeout(tot)) { tot = set_timeout(1); /* 1 second */ ++elapsed_sec; set_tod(); eip = &en_table[chart_interface]; if (startup) { /* Running now, initialise counters etc. */ clear_pkt_stats = 1; minx = 100; sumx = samples = maxx = 0; spackets = eip->npackets; sbytes= eip->nbytes; l_tod_s = -1; gci = gc_interval; /* Garbage collect interval */ bkgi = BKG_INTERVAL; /* Background interval */ gc_f = mxflows/100; /* Flow indexes to check */ if (gc_f < 4) gc_f = 4; startup = 0; } else { #ifdef NEW_ATR check_rates(uptime_s()); #endif if (--gci == 0) { garbage_collect(1); /* Routine incremental collection */ gci = gc_interval; } if (--bkgi == 0) { /* Check % of flows active */ p = (unsigned long)active_flows()*100/mxflows; if (display_enabled) { scpos(12,3); printf("a=%3u",p); } if (p > FloodMark && FloodMode != TV_TRUE && FloodMark > 0 && FloodMark < 100) { FloodMode = TV_TRUE; /* Stop creating new flow records */ display_msg(1,"Meter in Flood mode"); } else for (x = 0; x != sizeof(mi)/sizeof(struct mgr_rec); ++x) { mip = &mi[x]; if (mip->mi_Status != RS_ACTIVE || mip->mi_RunningStandby == TV_TRUE) continue; else if (p > mip->mi_HighWaterMark && mip->mi_HighWaterMark > 0 && mip->mi_HighWaterMark < 100 && mip->mi_StandbyRuleSet != mip->mi_CurrentRuleSet && (mip->mi_StandbyRuleSet != 0 && ri[mip->mi_StandbyRuleSet-1].ri_Status == RS_ACTIVE) ) { open_rule_set(mip->mi_CurrentRuleSet, 0); /* Close */ open_rule_set(mip->mi_StandbyRuleSet, 1); /* Open */ mip->mi_RunningStandby = TV_TRUE; sprintf(msg,"Manager %d running Standby", x+1); display_msg(1,msg); } else if (p > HighWaterMark*2/3) more_garbage(); } pd = uptime_cs(); for (x = 0; x != sizeof(ci)/sizeof(struct rdr_rec); ++x) { cip = &ci[x]; if (cip->ci_Status != RS_ACTIVE || cip->ci_Timeout == 0) continue; if ((pd - cip->ci_LastTime)/100 > cip->ci_Timeout) cip->ci_Status = RS_UNUSED; /* Timed out */ } bkgi = BKG_INTERVAL; } npackets = eip->npackets - zpackets; /* For 'stats' display */ pd = (eip->npackets-spackets)*eip->SampleRate; bd = (eip->nbytes-sbytes)*eip->SampleRate; if (display_enabled) { scpos(0,3); printf("q=%4d",pkt_backlog); scpos(23,3); printf("%02d%02d:%02d", tod_h,tod_m,tod_s); scpos(0,5); x = util_pc(pd,bd); /* % utilisation */ printf("p=%6lu, b=%10lu, u=%4d", pd,bd, x); sumx += x; ++samples; if (x < minx) minx = x; if (x > maxx) maxx = x; if (tod_s != l_tod_s && tod_s%10 == 0) { if (samples) { /* 30% in col 79 */ ax = (sumx+(samples>>1))/samples; if (half_scale) chart(scr_chrtcol,0, scr_lcol,scr_lrow, minx>>1,ax>>1,maxx>>1); else chart(scr_chrtcol,0, scr_lcol,scr_lrow, minx,ax,maxx); l_tod_s = tod_s; } minx = 100; sumx = samples = maxx = 0; } } } if (clear_pkt_stats) zero_pkt_stats(); else { ++stats_time; if (pd > max_pkt_rate) max_pkt_rate = pd; t_backlog += (unsigned long)pkt_backlog; if (pkt_backlog > max_pkt_backlog) max_pkt_backlog = pkt_backlog; if (dummypacketrate < mindummyrate) { mindummyrate = dummypacketrate; mdpacketrate = pd; } } pkt_backlog = 0; dummypacketrate = 0; spackets = eip->npackets; sbytes = eip->nbytes; if (kb_enabled && kbhit()) { if ((ch = getch()) == 27) { /* ESC */ scpos(0,scr_lrow); printf("\nShutting down\n"); exit(0); } w_clear(0,scr_lrow, scr_chrtcol-1,scr_lrow); /* Status area */ scpos(0,scr_lrow); switch (k = tolower(ch)) { case 'b': printf("bad=%lu, nobuf=%lu, lost=%lu", badpackets,nobufpackets,lostpackets); break; case 'h': half_scale = !half_scale; printf("Chart scale 0..%d \%", half_scale ? 60 : 30); break; case 'i': printf("Ethernet %d, type %d, sw int %d", chart_interface+1, en_table[chart_interface].type, en_table[chart_interface].int_nbr); break; case 'v': printf(version_descr); break; case '1': case '2': case '3': case '4': set_chart_interface(k - '1'); break; case '=': startup_screen(); /* Clear the clutter off the screen */ break; case '\t': printf("uptime = %.3f seconds", uptime_cs()/100.0); break; #if UPTIME_DBG case '-': start_uptime_clock(); /* Caution: CLK_386 doesn't use this */ printf("uptime clock reset"); break; case '`': biostime(1, 1573040L - 91L); /* Midnight - 5s */ break; case '\\': print_uptime_log(); break; case '\'': // printf("last_tod = %lu, tod= %lu", // last_tod, *bios_tick_counter); break; #endif #if PC_BGP_TEST case '?': /* Test bgp lookup */ bgp_lookup_test(); break; #endif case '.': quack(313); /* For a debugger breakpoint */ break; default: handle_kb(ch); break; } } } } sock_err: switch (status) { case 1 : /* Foreign host closed */ exit(0); case -1: /* Timeout */ printf("\nConnection timed out!"); exit(1); default: printf("Aborting"); exit(1); } } static Bit32 snmp_peer_addr; void snmp_error(char *msg) { char snmp_peer_name[30], buf[80]; inet_ntoa(snmp_peer_name, snmp_peer_addr); sprintf(buf, "%s: %s", snmp_peer_name,msg); display_msg(1, buf); } void meter_snmp_read(int length) { int out_length; Bit8 packet[1520], outpacket[1550]; /* Leave some space just in case */ int count; struct sockaddr from; int fromlen = sizeof(struct sockaddr); char snmp_peer_name[30]; /* Name of host which sent the SNMP request */ getpeername((tcp_Socket *)s, &from,&fromlen); snmp_peer_addr = from.s_ip; sock_read((sock_type *)s, packet,length); if (snmp_dump_packet) { inet_ntoa(snmp_peer_name,from.s_ip); printf("received %d bytes from %s:\n", length, snmp_peer_name); for (count = 0; count < length; count++) { printf("%02X ", packet[count]); if ((count % 16) == 15) printf("\n"); else if ((count % 4) == 3) printf(" "); } printf("\n\n"); } out_length = 1500; if (snmp_agent_parse(packet, length, outpacket, &out_length, from.s_ip)) { if (snmp_dump_packet) { printf("sent %d bytes to %s:\n", out_length, snmp_peer_name); for (count = 0; count < out_length; count++) { printf("%02X ", outpacket[count]); if ((count % 16) == 15) printf("\n"); else if ((count % 4) == 3) printf(" "); } printf("\n\n"); } sock_write((sock_type *)s, (char *)outpacket, out_length); } }