/* pkt_test.c - a minimal test program for the pkt driver interafce */ #include #include #include #include #include #include #include #include #include "..\snmplib\ausnmp.h" #include "..\wattcp\wattcp.h" #include "..\types\types.h" #include "..\wattcp\pktdrv.h" #define PKT_DEBUG 0 #define TEST_IP 1 #define PKT_TRACE 1 #define TIME_TEST 1 #pragma inline static void swrite(int c) /* Write char to screen */ { _AH = 14; _AL = c; geninterrupt(0x10); } void scpos(int x, int y) /* Set Cursor Position */ { } void w_roll(int tx,int ty, int bx,int by, int n) { } struct pkt { unsigned int p_len; unsigned int p_lah_len, p_int; unsigned char hdr[14]; }; /* Declared in wattcp\src\pcpkt.c .. */ extern unsigned char eth_addr[6]; extern unsigned long npackets,nbytes; #define MAXPKTLEN 1526 struct pkt far *pkts; unsigned short maxpkt, /* Must be a power of 2 */ pktmask, /* maxpkt-1 */ prcv, /* Index of next pkt to be received (i.e. next empty pkt) */ pproc; /* Index of next pkt to be processed (i.e. next full pkt) */ udp_Socket udpsock; static udp_Socket *s; int status; /* For socket */ word _pktdevclass = 1; /* Ethernet = 1, SLIP = 6 */ /* forward declarations */ void accept_pkt(unsigned int len, unsigned char far *buff, unsigned int i_face, unsigned int lah_len); int our_packet(unsigned char far *buff); void receive(void); void snmp_read(int length); unsigned long tot; void accept_pkt(unsigned int len, unsigned char far *buff, unsigned int i_face, unsigned int lah_len) { struct pkt huge *pp; int j; #if PKT_DEBUG swrite(':'); #endif if (((pproc - prcv) & pktmask) == 1) { /* No pkts free, ignore the data */ } else { pp = &pkts[prcv]; pp->p_len = len; pp->p_int = i_face; pp->p_lah_len = lah_len; for (j = 0; j != 14; ++j) pp->hdr[j] = buff[j]; prcv = (prcv+1) & pktmask; } } #define SNAPSIZE 54 /* Matches meter_ux.c */ int our_packet(unsigned char 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 *pkt_rcv_call1(Bit16 len, Bit16 lah_len, Bit8 *buff, Bit16 if_nbr) { int if_type = en_table[if_nbr].type; #if PKT_DEBUG swrite('|'); #endif if (if_type & EN_HP) { if (if_type & EN_MT) accept_pkt(len, buff, if_nbr, lah_len); /* Pass attribute info to meter buffer */ if (if_type & EN_IP) { if (our_packet(buff)) return get_pktbuf(len); } return (unsigned char 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('@'); return last_buf; #else return get_pktbuf(len); #endif } void pkt_rcv_call2(Bit16 len, Bit8 *buff, Bit16 if_nbr) { int if_type = en_table[if_nbr].type; struct pbuf *bp; int ip_pkt = 0; #if PKT_DEBUG if (buff != last_buf) swrite('X'); else swrite('='); #endif if (if_type & EN_HP) ip_pkt = 1; /* IP pkt ready for tcp/ip */ else { if (if_type & EN_MT) { accept_pkt(len, buff, if_nbr, 0); /* Pass attribute info to meter buffer */ if (if_type & EN_IP) ip_pkt = our_packet(buff) ? 1 : 0; else ip_pkt = 0; } else if (if_type & EN_IP) ip_pkt = 1; /* Unicast/broadcast mode */ else ip_pkt = 0; /* Not our packet, free the buffer */ } bp = (struct pbuf *)(buff - BUF_HDR_LEN); #if PKT_DEBUG swrite('0' + bp->unused); swrite(ip_pkt ? 'I' : '#'); #endif #if TEST_IP if (ip_pkt) { bp->state = 2; enqueue(&readyq, bp); } else { bp->state = 0; enqueue(&freeq, bp); } #else bp->state = 0; enqueue(&freeq, bp); #endif return; } int snmp_dump_packet = 0; int main(int argc, char *argv[]) { int arg, a, c; char cbuf[20], *ap; int n_interfaces, IP_int; n_interfaces = 0; IP_int = -1; for (c = 0, arg = 1; arg < argc; ++arg) { if (argv[arg][0] == '-') { ap = argv[arg]+2; switch (a = argv[arg][1]) { #if TEST_IP case 'd': snmp_dump_packet++; break; #endif case 'I': /* IP only - no metering */ IP_int = n_interfaces; case 'i': /* Just plain metering */ case 'h': /* Metering with high-performance driver */ if (*ap == NULL) ap = argv[++arg]; if (arg == argc) c = 0; /* No more args */ else c = isdigit(*ap) ? atoi(ap) : 0; /* -h means -h0 */ en_table[n_interfaces].int_nbr = c; if (a != 'I') en_table[n_interfaces].type = a == 'h' ? EN_MT|EN_HP : EN_MT; ++n_interfaces; 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 TEST_IP if (IP_int == -1) IP_int = 0; en_table[IP_int].type |= EN_IP; #endif // maxpkt = 1024; maxpkt = 256; pktmask = maxpkt-1; pkts = (struct pkt far *)farmalloc((maxpkt+1) * sizeof(struct pkt)); pproc = prcv = 0; #if TEST_IP sock_init(); /* Initialise full TCP/IP stack */ #else if (pkt_init()) /* Initialise just the packet driver(s) */ exit(1); /* Problems in starting one of the packet driver(s) */ #endif #if TEST_IP s = &udpsock; /* myport hisadr hisport */ if (!udp_open( s, 161, 0, 0, 0 )) { puts("udp_open failed!\n"); exit(1); } #endif receive(); } void receive() { unsigned short k, n, npkts = 0; struct pkt huge *pp; unsigned char ch; unsigned long save_tot, same_count; save_tot = tot = set_timeout(0); same_count = 0; pproc = prcv; /* Discard packets collected during initialisation */ for (;;) { #if TEST_IP sock_tick(s, &status); /* Keep WATTCP alive */ if ((n = sock_dataready(s)) != 0) { snmp_read(n); sock_close(s); if (!udp_open( s, 161, 0, 0, 0 )) { puts("udp_open failed!\n"); exit(1); } } #endif k = (prcv-pproc) & pktmask; if (k != 0) { /* We have received some packets */ for (; k != 0; --k) { pp = &pkts[pproc]; #if PKT_DEBUG swrite('.'); #endif #if PKT_TRACE printf("%5u: %5u |%u #%u ", ++npkts, pp->p_len, pp->p_lah_len, pp->p_int); for (n = 0; n != 6; ++n) printf(" %02X", pp->hdr[n]); printf(" "); for (n = 6; n != 12; ++n) printf(" %02X", pp->hdr[n]); printf(" %02x%02X\n", pp->hdr[12],pp->hdr[13]); pproc = (pproc+1) & pktmask; #endif } } if (tot == save_tot) ++same_count; #if TIME_TEST else swrite('?'); #endif if (chk_timeout(tot)) { #if TIME_TEST printf("count=%lu, tot=%lu, save_tot=%lu", same_count, tot,save_tot); #endif save_tot = tot = set_timeout(1); /* 1 second */ same_count = 0; #if TIME_TEST printf(": tot+1s = %lu\n", tot); #endif if (kbhit()) { if ((ch = getch()) == 27) { /* ESC */ printf("\nShutting down\n"); #if TEST_IP // no effort required to stop whole TCP/IP stack // because it has an atexit() handler // #else // shut down access to packet driver // pkt_release(); #endif exit(0); } } } } #if TEST_IP 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); } #endif } #if TEST_IP void snmp_read(int length) { int out_length; unsigned char packet[1500]; int count; sock_read(s, packet,length); if (snmp_dump_packet) { printf("received %d bytes:\n", length); for (count = 0; count < length; count++) { printf("%02X ", packet[count]); if ((count % 16) == 15) printf("\n"); } printf("\n\n"); } sock_write(s, packet,length); /* Just echo the SNMP packet */ } #endif void au_send_mon(int length, unsigned char far *buffer) { return; } /* Default version, never used */