flowtop: make function nested
[netsniff-ng.git] / src / cli_cmds.c
blobcc9edb10c334a6f9b0a82976c5c67246974efdfa
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
21 #include "mz.h"
22 #include "cli.h"
23 #include "mops.h"
24 #include "llist.h"
26 // Callback functions for the commands.
27 // __FUNCTION__ contains the name of the current callback function (for troubleshootig)
30 ////////////////////////////////////////////////////////////////////////////////
31 int cmd_test(struct cli_def *cli, char *command, char *argv[], int argc)
33 cli_print(cli, "called %s with %s\r\n", __FUNCTION__, command);
34 return CLI_OK;
39 ////////////////////////////////////////////////////////////////////////////////
40 int debug_all (struct cli_def *cli, char *command, char *argv[], int argc)
42 if ( strncmp(argv[argc-1], "?", 1) == 0)
44 cli_print(cli, "Will debug everything. (Be careful!)\n");
45 return CLI_OK;
49 cli_debug = 0x7fff;
50 cli_print(cli, "Debug all enabled - stop with undebug all\r");
51 cli_print(cli, "Note: _Already_ active packets will not be omitted!\n");
53 if (mz_strcmp(argv[argc-1], "dev", 3)==0)
55 cli_print(cli, "*** Developer mode debugging enabled ***\n");
56 cli_debug = 0xffff;
59 return CLI_OK;
65 ////////////////////////////////////////////////////////////////////////////////
66 // Clear all _legacy_ Mausezahn settings (reinitialize anything)
67 int clear_all(struct cli_def *cli, char *command, char *argv[], int argc)
69 if (argc) {
70 cli_print(cli, "No argument required! Try again.\n");
71 return CLI_OK;
74 reset();
75 cli_print(cli, "All legacy Mausezahn parts have been reinitialized.\r");
76 mops_delete_all(mp_head);
77 mops_reset_packet (mp_head);
78 cli_print(cli, "MOPS has been reinitialized.\n");
79 return CLI_OK;
83 int clear_packet(struct cli_def *cli, char *command, char *argv[], int argc)
86 struct mops *cur;
87 u_int32_t i;
89 if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) )
91 cli_print(cli, "Delete a single packet (i. e. MOPS entry).\r");
92 cli_print(cli, "Expects a single argument which is either a packet's ID or name.\r");
93 cli_print(cli, "NOTE: If the name matches an ID then the name has higher preference.\n");
94 return CLI_OK;
98 if (argc!=1) {
99 cli_print(cli, "Please specify only the packets ID or name\n");
100 return CLI_OK;
103 cur = mops_search_name (mp_head, argv[0]);
104 if (cur==NULL) {
105 i = (u_int32_t) str2int (argv[0]);
106 cur = mops_search_id (mp_head, i);
107 if (cur==NULL) {
108 cli_print(cli, "No packet found with that ID or name!\n");
109 return CLI_OK;
112 clipkt = mops_delete_packet(cur);
113 cli_print(cli, "Packet deleted.\n");
114 return CLI_OK;
118 int cmd_reset_packet(struct cli_def *cli, char *command, char *argv[], int argc)
120 struct mops *cur;
121 u_int32_t i;
123 if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) )
125 cli_print(cli, "Resets a single packet (i. e. MOPS entry).\r");
126 cli_print(cli, "Expects a single argument which is either a packet's ID or name.\r");
127 cli_print(cli, "NOTE: If the name matches an ID then the name has higher preference.\n");
128 return CLI_OK;
132 if (argc!=1) {
133 cli_print(cli, "Please specify only the packets ID or name\n");
134 return CLI_OK;
137 cur = mops_search_name (mp_head, argv[0]);
138 if (cur==NULL) {
139 i = (u_int32_t) str2int (argv[0]);
140 cur = mops_search_id (mp_head, i);
141 if (cur==NULL) {
142 cli_print(cli, "No packet found with that ID or name!\n");
143 return CLI_OK;
147 mops_reset_packet(cur);
148 cli_print(cli, "New packet name: %s\n", cur->packet_name);
149 return CLI_OK;
155 ////////////////////////////////////////////////////////////////////////////////
156 int warranty(struct cli_def *cli, char *command, char *argv[], int argc)
158 cli_print(cli, MZ_WARRANTY_TEXT);
159 return CLI_OK;
163 int show_system(struct cli_def *cli, char *command, char *argv[], int argc)
165 cli_print(cli, "Not supported in this version\n");
166 return CLI_OK;
172 ////////////////////////////////////////////////////////////////////////////////
173 // Run through packet list and print some details about existing packets.
174 // SYNTAX:
176 // show packet
177 // show packet MyPacket
179 int show_packets(struct cli_def *cli, char *command, char *argv[], int argc)
181 int a=0, i, j=0, k, v, active_only=0;
182 u_int32_t t;
183 char c,T;
184 char name[32], ds[16], pr[16], ps[16];
185 char myframe[MAX_MOPS_FRAME_SIZE*3];
186 char mystate[32];
187 char line[150], line2[150], line3[150];
188 char delay_str[64];
189 unsigned char *x0, *x1, *x2, *x3;
191 struct mops *head = mp_head;
192 struct mops *mp = mp_head;
195 if (strncmp(argv[argc-1], "?", 2)==0) {
196 cli_print(cli, "<CR> Show list of all defined packets\r");
197 cli_print(cli, "active Only show active packets\r");
198 cli_print(cli, "<PKT_ID> Show detailed info about given packet\r");
199 //TODO cli_print(cli, "type <proto> Only list packets r");
200 cli_print(cli, "\n");
201 return CLI_OK;
204 if (argc==1) {
205 if (mz_strcmp(argv[0], "active", 1)==0) {
206 active_only=1;
210 if ((argc==0) || (active_only)) // show packet summary
212 cli_print(cli, "Packet layer flags: E=Ethernet, S=SNAP, Q=802.1Q, M=MPLS, I/i=IP/delivery_off, U=UDP, T=TCP\n");
213 cli_print(cli, "PktID PktName Layers Proto Size State Device Delay Count/CntX\n");
217 if (active_only) {
218 if (mp->state < MOPS_STATE_ACTIVE) {
219 mp = mp->next;
220 j++;
221 continue;
225 ds[0]='\0';
226 ps[0]='\0';
227 pr[0]='\0';
229 if (mp->use_ETHER) strcat(ds,"E"); else strcat(ds,"-");
230 if (mp->use_SNAP) strcat(ds,"S"); else strcat(ds,"-");
231 if (mp->use_dot1Q) strcat(ds,"Q"); else strcat(ds,"-");
232 if (mp->use_MPLS) strcat(ds,"M"); else strcat(ds,"-");
233 if (mp->use_IP) {
234 if (mp->auto_delivery_off)
235 strcat(ds,"i");
236 else
237 strcat(ds,"I");
238 } else strcat(ds,"-");
240 if (mp->use_UDP)
241 strcat(ds,"U");
242 else if
243 (mp->use_TCP) strcat(ds,"T");
244 else strcat(ds,"-");
248 switch (mp->p_desc_type)
250 case MOPS_ARP:
251 strncpy(pr, "ARP", 8);
252 break;
253 case MOPS_BPDU:
254 strncpy(pr, "BPDU", 8);
255 break;
256 case MOPS_CDP:
257 strncpy(pr, "CDP", 8);
258 break;
259 case MOPS_DNS:
260 strncpy(pr, "DNS", 8);
261 break;
262 case MOPS_ICMP:
263 strncpy(pr, "ICMP", 8);
264 break;
265 case MOPS_IGMP:
266 strncpy(pr, "IGMP", 8);
267 break;
268 case MOPS_LLDP:
269 strncpy(pr, "LLDP", 8);
270 break;
271 case MOPS_RTP:
272 strncpy(pr, "RTP", 8);
273 break;
274 case MOPS_SYSLOG:
275 strncpy(pr, "SYSLOG", 8);
276 break;
277 default:
278 break;
282 switch (mops_state(mp))
284 case MOPS_STATE_NULL:
285 strcat(ps, "NULL"); // should never happen!
286 break;
287 case MOPS_STATE_INIT:
288 strcat(ps, "init");
289 break;
290 case MOPS_STATE_CONFIG:
291 strcat(ps, "config");
292 break;
293 case MOPS_STATE_ACTIVE:
294 strcat(ps, "active");
295 a++;
296 break;
297 case MOPS_STATE_SEQACT:
298 strcat(ps, "actseq");
299 a++;
300 break;
301 default:
302 strcat(ps, "unknown");
303 break;
306 switch (mp->interval_used) {
307 case 1: // interval only configured, not started
308 strncat(ps, "-i", 2);
309 break;
311 case 2:
312 strncat(ps, "+I", 2);
313 break;
314 default:
315 break;
319 strncpy (name, mp->packet_name, 13); // only show first 13 chars
321 if (strnlen(mp->packet_name, MAX_MOPS_PACKET_NAME_LEN)>13)
323 name[13]=0x00;
324 strcat(name, "...");
327 // To determine the actual packet length ***
328 // we must reassemble everything: ***
329 mops_ext_update (mp);
330 mops_update (mp);
332 timespec2str(&mp->ndelay, delay_str);
334 // ID name lrs prot size state dev del count/cntx/%
335 sprintf(line, "%5i %-16s %s %-8s %4i %-9s %-6s %10s%9lu/%lu (%i%%)\r",
336 mp->id, // ID
337 name, // packet_name
338 ds, // layers
339 pr, // protocol
340 mp->frame_s, // size
341 ps, // state
342 mp->device, // device
343 delay_str, // delay
344 mp->count, // Configured count value
345 mp->cntx, // Current count
346 (mp->count) ? (int) (100 * (mp->count - mp->cntx)/mp->count) : 0 );
347 cli_print(cli, "%s\r", line);
348 mp = mp->next;
349 j++;
351 while (head != mp);
353 cli_print(cli, "\r");
354 cli_print(cli, "%i packets defined, %i active.\n", j, a);
356 //////////////////////////////////////////////////////////////////////////////////////////////////////////
358 //////////////////////////////////////////////////////////////////////////////////////////////////////////
359 else if (argc == 1) // show details about a specific packet **********************************************
361 if ( (mp = mops_search_name (mp_head, argv[0])) == NULL)// not found
363 if ( (mp = mops_search_id (mp_head, (int) str2int(argv[0]))) == NULL)// not found
365 cli_print (cli, "Packet not in list.\n");
366 return CLI_OK;
370 // To determine the actual packet length ***
371 // we must reassemble everything: ***
372 mops_ext_update (mp);
373 mops_update (mp);
375 cli_print(cli, "Packet [%i] %s\r", mp->id, mp->packet_name);
376 cli_print(cli, " Description: %s \r",
377 (strnlen(mp->description, MAX_MOPS_DESCRIPTION_LEN)) ? mp->description : "(no description)");
379 switch(mp->state)
381 case MOPS_STATE_NULL:
382 sprintf(mystate, "NULL");
383 break;
384 case MOPS_STATE_INIT:
385 sprintf(mystate, "init");
386 break;
387 case MOPS_STATE_CONFIG:
388 sprintf(mystate, "config");
389 break;
390 case MOPS_STATE_ACTIVE:
391 sprintf(mystate, "active(tx)");
392 break;
393 default:
394 sprintf(mystate, "unknown");
397 timespec2str(&mp->ndelay, delay_str);
398 if (mp->interval_used)
399 timespec2str(&mp->interval, line2);
400 else
401 sprintf(line2, "(undefined)");
403 sprintf(line, "State: %s, Count=%lu, delay=%s (%lu s %lu nsec), interval= %s\r",
404 mystate,
405 mp->count,
406 delay_str,
407 mp->ndelay.tv_sec,
408 mp->ndelay.tv_nsec,
409 line2);
410 cli_print(cli, " %s\r", line);
412 cli_print(cli, " Headers:\r");
413 i=0;
414 if (mp->use_ETHER)
416 if (mp->eth_src_israndom)
418 cli_print(cli, " Ethernet: *** RANDOMIZED SMAC *** => %02x-%02x-%02x-%02x-%02x-%02x [%04x%s]\r",
419 mp->eth_dst[0],mp->eth_dst[1],mp->eth_dst[2],mp->eth_dst[3],mp->eth_dst[4],mp->eth_dst[5],
420 mp->eth_type, (mp->use_dot1Q) ? " after 802.1Q tag" : "");
422 else
424 cli_print(cli, " Ethernet: %02x-%02x-%02x-%02x-%02x-%02x => %02x-%02x-%02x-%02x-%02x-%02x [%04x%s]\r",
425 mp->eth_src[0],mp->eth_src[1],mp->eth_src[2],mp->eth_src[3],mp->eth_src[4],mp->eth_src[5],
426 mp->eth_dst[0],mp->eth_dst[1],mp->eth_dst[2],mp->eth_dst[3],mp->eth_dst[4],mp->eth_dst[5],
427 mp->eth_type, (mp->use_dot1Q) ? " after 802.1Q tag" : "");
430 if (mp->use_IP) {
431 if (mp->auto_delivery_off)
432 cli_print(cli, " NOTE: Auto-delivery is OFF (that is, the destination MAC is fixed)\r");
433 else
434 cli_print(cli, " Auto-delivery is ON (that is, the actual MAC is determined upon transmission)\r");
436 i++;
438 if (mp->use_SNAP)
440 bs2str(clipkt->eth_snap, line, clipkt->eth_snap_s);
441 cli_print(cli, " LLC/SNAP: %s\r", line);
442 i++;
444 if (mp->use_dot1Q)
446 k = clipkt->dot1Q_s/4; // number of tags
447 sprintf(line, "%i tag(s); ", k);
448 for (j=0; j<k; j++)
449 { // tag format = 0x81 0x00 cosTvvvv vvvvvvvv
450 // x0 x1
451 x0 = (unsigned char*) &clipkt->dot1Q[(j*4)+2];
452 x1 = (unsigned char*) &clipkt->dot1Q[(j*4)+3];
453 v = (*x0 & 0x0f)*256 + *x1; // VLAN
454 // c = *x0 & 0xe0; // CoS e0=11100000
455 c = *x0 >> 5;
456 sprintf(ds, "%i:%i%s",
458 (unsigned char) c,
459 (*x0 & 0x10) ? "[CFI]" : ""); // CFI
460 strncat(line, ds, 14);
461 if (j<(k-1)) strcat(line, ", ");
464 cli_print(cli, " 802.1Q: %s (VLAN:CoS)\r", line);
465 i++;
467 if (mp->use_MPLS)
469 k = clipkt->mpls_s/4; // number of tags
470 sprintf(line, "%i tag(s); ", k);
471 for (j=0; j<k; j++)
472 { // tag format = llllllll llllllll llllcccB TTTTTTTT
473 x0 = (unsigned char*) &clipkt->mpls[(j*4)+0];
474 x1 = (unsigned char*) &clipkt->mpls[(j*4)+1];
475 x2 = (unsigned char*) &clipkt->mpls[(j*4)+2];
476 x3 = (unsigned char*) &clipkt->mpls[(j*4)+3];
477 t = *x0;
478 t <<= 12;
479 t += *x1 * 16;
480 t += (*x2 & 0xf0) >> 4;
481 c = (*x2 & 0x0e) >> 1;
482 T = *x3;
483 sprintf(ds, "%i:%i:%i%s",
485 (unsigned char) c,
486 (unsigned char) T,
487 (*x2 & 0x01) ? "[BoS]" : ""); // Bottom of Stack?
488 strncat(line, ds, 20);
489 if (j<(k-1)) strcat(line, ", ");
492 cli_print(cli, " MPLS: %s (Label:CoS:TTL)\r", line);
494 i++;
496 if (mp->use_IP)
498 // Source IP settings:
499 x0 = (unsigned char*) & clipkt->ip_src;
500 line2[0]=0x00;
501 if (clipkt->ip_src_isrange)
503 x1 = (unsigned char*) & clipkt->ip_src_start;
504 x2 = (unsigned char*) & clipkt->ip_src_stop;
505 sprintf(line2, "%u.%u.%u.%u-%u.%u.%u.%u",
506 (unsigned char) *(x1+3), (unsigned char) *(x1+2), (unsigned char) *(x1+1) , (unsigned char) *x1,
507 (unsigned char) *(x2+3), (unsigned char) *(x2+2), (unsigned char) *(x2+1) , (unsigned char) *x2);
509 sprintf(line, "SA=%u.%u.%u.%u %s %s %s",
510 (unsigned char) *(x0+3), (unsigned char) *(x0+2), (unsigned char) *(x0+1) , (unsigned char) *x0,
511 (clipkt->ip_src_israndom) ? "RANDOM" : "(not random)",
512 (clipkt->ip_src_isrange) ? "RANGE:" : "(no range)",
513 line2);
515 cli_print(cli, " IP: %s\r", line);
516 //Destination IP settings:
517 x0 = (unsigned char*) & clipkt->ip_dst;
518 line2[0]=0x00;
519 if (clipkt->ip_dst_isrange)
521 x1 = (unsigned char*) & clipkt->ip_dst_start;
522 x2 = (unsigned char*) & clipkt->ip_dst_stop;
523 sprintf(line2, "%u.%u.%u.%u-%u.%u.%u.%u",
524 (unsigned char) *(x1+3), (unsigned char) *(x1+2), (unsigned char) *(x1+1) , (unsigned char) *x1,
525 (unsigned char) *(x2+3), (unsigned char) *(x2+2), (unsigned char) *(x2+1) , (unsigned char) *x2);
528 sprintf(line, "DA=%u.%u.%u.%u %s %s",
529 (unsigned char) *(x0+3), (unsigned char) *(x0+2), (unsigned char) *(x0+1) , (unsigned char) *x0,
530 (clipkt->ip_dst_isrange) ? "RANGE:" : "(no range)",
531 line2);
532 cli_print(cli, " %s\r", line);
534 sprintf(line, "ToS=0x%02x proto=%u TTL=%u ID=%u offset=%u flags: %s|%s|%s",
535 clipkt->ip_tos, clipkt->ip_proto, clipkt->ip_ttl, clipkt->ip_id, clipkt->ip_frag_offset,
536 (clipkt->ip_flags_RS) ? "RS" : "-",
537 (clipkt->ip_flags_DF) ? "DF" : "-",
538 (clipkt->ip_flags_MF) ? "MF" : "-");
540 cli_print(cli, " %s\r", line);
542 if (clipkt->ip_fragsize) {
543 sprintf(line, "NOTE: Auto-fragmentation is ON! Fragment size %u bytes, overlap %u",
544 clipkt->ip_fragsize,
545 clipkt->ip_frag_overlap);
546 cli_print(cli, " %s\r", line);
549 sprintf(line, "len=%u(%s) checksum=0x%02x%02x(%s)",
550 clipkt->frame[clipkt->begin_IP+2]*256+clipkt->frame[clipkt->begin_IP+3],
551 (clipkt->ip_len_false) ? "false" : "correct",
552 clipkt->frame[clipkt->begin_IP+10],
553 clipkt->frame[clipkt->begin_IP+11],
554 (clipkt->ip_sum_false) ? "false" : "correct");
556 cli_print(cli, " %s\r", line);
558 i++;
560 if (mp->use_UDP)
562 if (clipkt->sp_isrange)
563 sprintf(line2, "RANGE: %u-%u", clipkt->sp_start, clipkt->sp_stop);
564 else
565 sprintf(line2, "(norange)");
566 if (clipkt->dp_isrange)
567 sprintf(line3, "RANGE: %u-%u", clipkt->dp_start, clipkt->dp_stop);
568 else
569 sprintf(line3, "(norange)");
570 sprintf(line, "SP=%i %s %s, DP=%i %s %s\r",
571 clipkt->sp,
572 line2,
573 (clipkt->sp_isrand) ? "RANDOM" : "(not random)",
574 clipkt->dp,
575 line3,
576 (clipkt->dp_isrand) ? "RANDOM" : "(not random)");
577 cli_print(cli, " UDP: %s\r", line);
578 sprintf(line, "checksum= %04x (%s), length= %u (%s)",
579 clipkt->udp_sum, (clipkt->udp_sum_false) ? "false" : "correct",
580 clipkt->udp_len, (clipkt->udp_len_false) ? "false" : "correct");
581 cli_print(cli, " %s\r", line);
582 i++;
584 if (mp->use_TCP)
586 sprintf(line, "%u bytes segment size (including TCP header)", mp->tcp_len);
587 cli_print(cli, " TCP: %s\r", line);
588 if (clipkt->sp_isrange)
589 sprintf(line2, "RANGE: %u-%u", clipkt->sp_start, clipkt->sp_stop);
590 else
591 sprintf(line2, "(norange)");
592 if (clipkt->dp_isrange)
593 sprintf(line3, "RANGE: %u-%u", clipkt->dp_start, clipkt->dp_stop);
594 else
595 sprintf(line3, "(norange)");
596 sprintf(line, "SP=%i %s %s, DP=%i %s %s\r",
597 clipkt->sp,
598 line2,
599 (clipkt->sp_isrand) ? "RANDOM" : "(not random)",
600 clipkt->dp,
601 line3,
602 (clipkt->dp_isrand) ? "RANDOM" : "(not random)");
603 cli_print(cli, " %s\r", line);
604 sprintf(line, "SQNR=%u (start %u, stop %u, delta %u) -- ACKNR=%u %s",
605 clipkt->tcp_seq,
606 clipkt->tcp_seq_start,
607 clipkt->tcp_seq_stop,
608 clipkt->tcp_seq_delta,
609 clipkt->tcp_ack,
610 (clipkt->tcp_ctrl_ACK) ? "(valid)" : "(invalid)");
611 cli_print(cli, " %s\r", line);
612 mops_tcp_flags2str(clipkt,line2);
613 sprintf(line, "Flags: %s, reserved field is %02x, urgent pointer= %u",
614 line2,
615 clipkt->tcp_res,
616 clipkt->tcp_urg);
617 cli_print(cli, " %s\r", line);
618 sprintf(line, "Announced window size= %u", clipkt->tcp_win);
619 cli_print(cli, " %s\r", line);
620 sprintf(line, "Offset= %u (times 32 bit; value is %s), checksum= %04x (%s)",
621 clipkt->tcp_offset,
622 (clipkt->tcp_offset_false) ? "FALSE" : "valid",
623 clipkt->tcp_sum,
624 (clipkt->tcp_sum_false) ? "FALSE" : "valid");
625 cli_print(cli, " %s\r", line);
626 sprintf(line, "%s - %u bytes defined",
627 (clipkt->tcp_option_used) ? "TCP options attached" : "(No TCP options attached)",
628 clipkt->tcp_option_s);
629 cli_print(cli, " %s\r", line);
630 i++;
633 if (!i) cli_print(cli, " No headers defined.\r");
635 if (mp->msg_s) {
636 cli_print(cli, " Payload size: %i bytes\r", mp->msg_s);
639 cli_print(cli, " Frame size: %i bytes\n", mp->frame_s);
641 mops_print_frame(mp, myframe);
642 cli_print(cli, "%s\n", myframe);
645 return CLI_OK;
649 ////////////////////////////////////////////////////////////////////////////////
650 int show_interfaces (struct cli_def *cli, char *command, char *argv[], int argc)
652 int i, j=0;
653 char line[100];
654 char ip[20];
657 if (strncmp(argv[argc-1], "?", 2)==0) {
658 cli_print(cli, "<CR> Show summary list of all interfaces found\r");
659 cli_print(cli, "detailed Additionally show network, mask, default gatway, and MTU\r");
660 cli_print(cli, "\n");
661 return CLI_OK;
664 // Some safety checks
665 if (argc>1) return CLI_OK;
666 if (argc==1) {
667 if (mz_strcmp(argv[0], "detailed", 1)!=0) {
668 cli_print(cli, "invalid keyword (use ?)\n");
669 return CLI_OK;
673 /* Refresh interface data */
675 lookupdev();
677 for (i=0; i<device_list_entries; i++) {
678 get_dev_params(device_list[i].dev);
683 /* No additional keyword */
684 if (argc==0) {
685 cli_print(cli, "Available network interfaces:\n");
686 cli_print(cli, " real real used (fake) used (fake)\r");
687 cli_print(cli, " device IPv4 address MAC address IPv4 address MAC address\r");
688 cli_print(cli, "---------------------------------------------------------------------------------------\r");
689 for (i=0; i<device_list_entries; i++) {
690 sprintf(ip,"%u.%u.%u.%u",
691 device_list[i].ip_mops[0],
692 device_list[i].ip_mops[1],
693 device_list[i].ip_mops[2],
694 device_list[i].ip_mops[3]);
696 sprintf(line, "%-10s %-15s %02x:%02x:%02x:%02x:%02x:%02x %-15s %02x:%02x:%02x:%02x:%02x:%02x",
697 device_list[i].dev, device_list[i].ip_str,
698 device_list[i].mac[0],
699 device_list[i].mac[1],
700 device_list[i].mac[2],
701 device_list[i].mac[3],
702 device_list[i].mac[4],
703 device_list[i].mac[5],
705 device_list[i].mac_mops[0],
706 device_list[i].mac_mops[1],
707 device_list[i].mac_mops[2],
708 device_list[i].mac_mops[3],
709 device_list[i].mac_mops[4],
710 device_list[i].mac_mops[5]
714 if (strncmp(device_list[i].dev, tx.device, 16)==0) {
715 cli_print(cli, "%s%s> %s\r",
716 (device_list[i].cli) ? "C" : " ",
717 (device_list[i].mgmt_only) ? "!" : "",
718 line);
719 j=i;
721 else
722 cli_print(cli, "%s%s %s\r",
723 (device_list[i].cli) ? "C" : " ",
724 (device_list[i].mgmt_only) ? "M" : "",
725 line);
728 /////////////////////////
729 else
731 /* keyword detailed used */
732 if (mz_strcmp(argv[0], "detailed", 1)==0) {
733 cli_print(cli, "Detailed interface list:\n");
734 for (i=0; i<device_list_entries; i++) {
735 sprintf(line, "interface %s [%i] %s%stype %s, MTU=%i bytes", // general HW info
736 device_list[i].dev,
737 device_list[i].index,
738 (device_list[i].cli) ? "[cli] " : "",
739 (device_list[i].mgmt_only) ? "[management-only] " : "",
740 (device_list[i].phy) ? "physical" : "software",
741 device_list[i].mtu);
742 cli_print(cli,"%s\r",line);
743 sprintf(line, "MAC bia: %02x:%02x:%02x:%02x:%02x:%02x\n MAC fake: %02x:%02x:%02x:%02x:%02x:%02x",
744 device_list[i].mac[0],
745 device_list[i].mac[1],
746 device_list[i].mac[2],
747 device_list[i].mac[3],
748 device_list[i].mac[4],
749 device_list[i].mac[5],
750 device_list[i].mac_mops[0],
751 device_list[i].mac_mops[1],
752 device_list[i].mac_mops[2],
753 device_list[i].mac_mops[3],
754 device_list[i].mac_mops[4],
755 device_list[i].mac_mops[5]);
756 cli_print(cli," %s\r",line);
757 sprintf(line,"IP addr: %s mask %u.%u.%u.%u (net %u.%u.%u.%u)",
758 device_list[i].ip_str,
759 device_list[i].mask[0],
760 device_list[i].mask[1],
761 device_list[i].mask[2],
762 device_list[i].mask[3],
763 device_list[i].net[0],
764 device_list[i].net[1],
765 device_list[i].net[2],
766 device_list[i].net[3]);
767 cli_print(cli," %s\r",line);
768 sprintf(line,"IP fake: %u.%u.%u.%u",
769 device_list[i].ip_mops[0],
770 device_list[i].ip_mops[1],
771 device_list[i].ip_mops[2],
772 device_list[i].ip_mops[3]);
773 cli_print(cli, " %s\r", line);
774 sprintf(line,"GW addr: %u.%u.%u.%u (%02x:%02x:%02x:%02x:%02x:%02x)",
775 device_list[i].ip_gw[0],
776 device_list[i].ip_gw[1],
777 device_list[i].ip_gw[2],
778 device_list[i].ip_gw[3],
779 device_list[i].mac_gw[0],
780 device_list[i].mac_gw[1],
781 device_list[i].mac_gw[2],
782 device_list[i].mac_gw[3],
783 device_list[i].mac_gw[4],
784 device_list[i].mac_gw[5]);
785 cli_print(cli," %s\n",line);
789 /* In any case, print final summary line: */
790 cli_print(cli, "\n%i interfaces found.\nDefault interface is %s.\n",
791 device_list_entries, device_list[j].dev);
793 return CLI_OK;
798 ////////////////////////////////////////////////////////////////////////////////
799 int show_set(struct cli_def *cli, char *command, char *argv[], int argc)
801 unsigned char *x;
802 char hexload[3*MAX_PAYLOAD_SIZE];
804 cli_print(cli, "----- Packet parameters: ------ -------- Value: ----------\r");
805 cli_print(cli, "Source MAC address (sa) %02x:%02x:%02x:%02x:%02x:%02x [%s]\r",
806 tx.eth_src[0], tx.eth_src[1], tx.eth_src[2],
807 tx.eth_src[3], tx.eth_src[4], tx.eth_src[5],
808 (tx.eth_src_rand) ? "rand" : "spec");
809 cli_print(cli, "Basic MAC address %02x:%02x:%02x:%02x:%02x:%02x\r",
810 tx.eth_mac_own[0], tx.eth_mac_own[1], tx.eth_mac_own[2],
811 tx.eth_mac_own[3], tx.eth_mac_own[4], tx.eth_mac_own[5]);
812 cli_print(cli, "Destination MAC address (da) %02x:%02x:%02x:%02x:%02x:%02x [%s]\r",
813 tx.eth_dst[0], tx.eth_dst[1], tx.eth_dst[2],
814 tx.eth_dst[3], tx.eth_dst[4], tx.eth_dst[5],
815 (tx.eth_dst_rand) ? "rand" : "spec");
816 cli_print(cli, "\r");
817 x = (unsigned char *) &tx.ip_src;
818 cli_print(cli, "Source IP address (SA) %i.%i.%i.%i [%s]\r",
819 *x,*(x+1),*(x+2),*(x+3),
820 (tx.ip_src_rand) ? "rand" : "spec");
822 if (tx.ip_src_isrange)
824 x = (unsigned char *) &tx.ip_src_start;
825 cli_print(cli, "Source IP range start: %i.%i.%i.%i\r",
826 *(x+3), *(x+2), *(x+1), *x);
827 x = (unsigned char *) &tx.ip_src_stop;
828 cli_print(cli, "Source IP range stop: %i.%i.%i.%i\r",
829 *(x+3), *(x+2), *(x+1), *x);
831 else
833 cli_print(cli, "No source IP range specified\r");
835 x = (unsigned char *) &tx.ip_dst;
836 cli_print(cli, "Destination IP address (DA) %i.%i.%i.%i\r",
837 *x,*(x+1),*(x+2),*(x+3));
839 if (tx.ip_dst_isrange)
841 x = (unsigned char *) &tx.ip_dst_start;
842 cli_print(cli, "Destination IP range start: %i.%i.%i.%i\r",
843 *(x+3), *(x+2), *(x+1), *x);
844 x = (unsigned char *) &tx.ip_dst_stop;
845 cli_print(cli, "Destination IP range stop: %i.%i.%i.%i\r",
846 *(x+3), *(x+2), *(x+1), *x);
848 else
850 cli_print(cli, "No destination IP range specified\r");
853 if (tx.dot1Q)
855 cli_print(cli, "802.1Q tags specified: %s\r", tx.dot1Q_txt);
858 if (tx.mpls)
860 cli_print(cli, "MPLS labels specified: %s\r", tx.mpls_txt);
863 if (tx.ascii)
864 { cli_print(cli, "\r");
865 cli_print(cli, "---- ASCII payload is set: ----- \r");
866 cli_print(cli, ">>>%s<<<\r", tx.ascii_payload);
867 cli_print(cli, "-------------------------------- \n");
870 if (tx.hex_payload_s)
871 { cli_print(cli, "\r");
872 cli_print(cli, "---- Hexadecimal payload is set: ----- \r");
873 bs2str(tx.hex_payload, hexload, tx.hex_payload_s);
874 cli_print(cli, "%s\r", hexload);
875 cli_print(cli, "-------------------------------------- \n");
878 if (tx.padding)
880 cli_print(cli, "Configured padding: %u\r", tx.padding);
883 cli_print(cli, "\r");
884 cli_print(cli, "Packet count value %u\r", tx.count);
885 cli_print(cli, "Interpacket delay (usec) %u\r", tx.delay);
886 cli_print(cli, "\r");
887 cli_print(cli, "Used network device(s): %s\r", tx.device);
888 cli_print(cli, "\n");
889 return CLI_OK;
898 ////////////////////////////////////////////////////////////////////////////////
899 int stop_mausezahn (struct cli_def *cli, char *command, char *argv[], int argc)
901 if (strncmp(argv[argc-1], "?", 2)==0) {
902 cli_print(cli, "now Terminate the mausezahn server! BEWARE!\n");
903 return CLI_OK;
906 if (argc!=1) {
907 cli_print(cli, "The only allowed argument is 'now' -- anything else is ignored\n");
908 return CLI_OK;
911 if (mz_strcmp(argv[0], "now", 3)==0) {
912 cli_print(cli, "Good bye...\n");
913 cli_done(cli);
914 clean_up(0);
915 return CLI_OK;
916 } else {
917 cli_print(cli, "Invalid argument. If you want to stop the Mausezahn server then\r");
918 cli_print(cli, "enter 'terminate now'. You cannot abbreviate the argument 'now'. \n");
921 return CLI_OK;
927 int cmd_run_id (struct cli_def *cli, char *command, char *argv[], int argc)
929 int i, slot;
930 struct mops *mp;
932 if (argc == 0) {
933 cli_print(cli, "Specify one or more packet identifiers to run.\n");
934 return CLI_OK;
937 if ( strncmp(argv[argc-1], "?", 1) == 0) {
938 cli_print(cli, "Run packet transmission processes for given list of packet identifiers\n");
939 return CLI_OK;
942 // User provided packet id numbers
943 if (argc > 0) {
944 for (i=0; i<argc; i++) {
945 slot = (int) str2int(argv[i]);
946 if ( (mp = mops_search_id (mp_head, slot)) == NULL) { // not found
947 cli_print (cli, "Packet %i not in list.\n", slot );
948 return CLI_OK;
950 else {
951 switch (mops_tx_simple (mp)) {
952 case 1:
953 cli_print(cli, "Cannot create sending process.\r");
954 return CLI_OK;
955 break;
956 case 3:
957 cli_print(cli, "Packet [%i] has already an active sending process\r", mp->id);
958 return CLI_OK;
959 break;
960 default:
961 cli_print (cli, "Activate [%i] ", slot );
962 break;
966 cli_print (cli, "\n");
968 return CLI_OK;
972 int cmd_run_name (struct cli_def *cli, char *command, char *argv[], int argc)
974 int i;
975 struct mops *mp;
977 if (argc == 0) {
978 cli_print(cli, "Specify one or more packet name(s) to run.\n");
979 return CLI_OK;
982 if ( strncmp(argv[argc-1], "?", 1) == 0) {
983 cli_print(cli, "Run packet transmission processes for specified packet name(s).\n");
984 return CLI_OK;
987 if (argc > 0) {
988 for (i=0; i<argc; i++) {
989 if ( (mp = mops_search_name (mp_head, argv[i])) == NULL) { // not found
990 cli_print (cli, "Packet %s not in list.\n", argv[i]);
991 return CLI_OK;
993 else {
994 switch (mops_tx_simple (mp)) {
995 case 1:
996 cli_print(cli, "Cannot create sending process.\r");
997 return CLI_OK;
998 break;
999 case 3:
1000 cli_print(cli, "Packet [%i] has already an active sending process\r", mp->id);
1001 return CLI_OK;
1002 break;
1003 default:
1004 cli_print (cli, "Activate [%i] ", mp->id );
1005 break;
1009 cli_print (cli, "\n");
1011 return CLI_OK;
1015 int cmd_run_sequence (struct cli_def *cli, char *command, char *argv[], int argc)
1017 struct mz_ll *cur;
1018 int ret=0;
1019 if (argc != 1) {
1020 cli_print(cli, "Specify one (and only one) packet sequence name to run.\n");
1021 return CLI_OK;
1024 if ( strncmp(argv[argc-1], "?", 1) == 0) {
1025 cli_print(cli, "Run sequence transmission processes for specified sequence name.\n");
1026 return CLI_OK;
1029 cur = mz_ll_search_name (packet_sequences, argv[0]);
1030 if (cur==NULL) { // NOT FOUND !!!
1031 cli_print(cli, "Sequence %s does not exist.", argv[0]);
1032 return CLI_OK;
1034 ret = mops_tx_sequence(cur);
1035 switch (ret) {
1036 case 0: cli_print(cli, "Sequence %s is runnning\n", cur->name);
1037 break;
1038 case 1: cli_print(cli, "Cannot run sequence: All packets must be in config state!\n");
1039 break;
1040 case 2: cli_print(cli, "Cannot run sequence: All packets must have a finite count!\n");
1041 break;
1042 case 3: cli_print(cli, "Cannot run sequence: Unable to start sequence transmission process.\n");
1043 break;
1045 return CLI_OK;
1050 int cmd_run_all (struct cli_def *cli, char *command, char *argv[], int argc)
1052 int i;
1053 struct mops *mp;
1054 struct mops *head;
1056 if ( strncmp(argv[argc-1], "?", 1) == 0) {
1057 cli_print(cli, "Run all user-specified packets.\n");
1058 return CLI_OK;
1061 if (argc>0) {
1062 cli_print(cli, "No arguments expected!\n");
1063 return CLI_OK;
1066 // Send all valid packets
1067 i=0;
1068 head = mp_head;
1069 mp = mp_head;
1070 do {
1071 if ((mp->mz_system==0) && (mops_state(mp) == MOPS_STATE_CONFIG)) {
1072 switch (mops_tx_simple (mp)) {
1073 case 1:
1074 cli_print(cli, "Cannot create sending process.\r");
1075 return CLI_OK;
1076 break;
1077 case 3:
1078 cli_print(cli, "Packet [%i] has already an active sending process\r", mp->id);
1079 return CLI_OK;
1080 break;
1081 default:
1082 break;
1084 i++;
1085 cli_print (cli, "Activate [%i] %s\r", mp->id, mp->packet_name );
1087 mp = mp->next;
1089 while (head != mp);
1090 if (i==0) {
1091 cli_print (cli, "No valid packets found\n");
1092 } else {
1093 cli_print (cli, "\r");
1094 cli_print (cli, "Activated %i packets \n", i);
1096 return CLI_OK;
1101 int cmd_stop (struct cli_def *cli, char *command, char *argv[], int argc)
1103 struct mops *mp;
1104 int i, ret=0, slot=0;
1106 struct mops *head = mp_head;
1107 struct mops *cur = mp_head;
1109 if ((strncmp(argv[argc-1], "?", 2)==0) || (argc==0)) {
1110 cli_print(cli, "Stop transmission process(es) or an active sequence.\r");
1111 cli_print(cli, "SYNTAX: 1) Either specify one or more packet-ids or packet names of active packets\r");
1112 cli_print(cli, " 2) Or enter 'sequence <seq-name>' to stop an active sequence and its associated packets.\n");
1113 return CLI_OK;
1116 // Did the user specify a sequence? (ONE SEQUENCE ONLY)
1117 if ((mz_strcmp(argv[0], "sequence", 3)==0) && (argc==2)) {
1118 ret = stop_sequence (argv[1]);
1119 switch (ret) {
1120 case 0:
1121 cli_print(cli, "Sequence '%s' stopped.\n", argv[1]);
1122 break;
1124 case 1:
1125 cli_print(cli, "Sequence '%s' does not exist!\n", argv[1]);
1126 break;
1127 case 2:
1128 cli_print(cli, "Sequence '%s' is not active. Nothing to stop.\n", argv[1]);
1129 break;
1131 return CLI_OK;
1135 if (((mz_strcmp(argv[0], "all", 3)==0) || (mz_strcmp(argv[0], "*", 1)==0)) && (argc==1)) {
1136 i=0;
1137 cli_print(cli, "Stopping ");
1138 do {
1139 if (mops_destroy_thread (cur)==0) {
1140 i++;
1141 cli_print(cli, "[%i] %s", cur->id, cur->packet_name);
1143 cur = cur->next;
1145 while (head != cur);
1146 cli_print(cli, "\n");
1147 if (i) {
1148 cli_print(cli, "Stopped %i transmission processe(s)\r", i);
1150 else {
1151 cli_print(cli, "No active transmission processes found.\r");
1154 i = stop_all_sequences ();
1155 if (i) {
1156 cli_print(cli, "Stopped %i sequence(s)\n", i);
1158 else {
1159 cli_print(cli, "No active sequences found.\n");
1162 return CLI_OK;
1165 // Stop all specified packets:
1167 for (i=0; i<argc; i++) {
1168 mp = NULL;
1169 // is argv[i] a numerical pkt-id?
1170 if (mz_strisnum(argv[i])) {
1171 slot = (int) str2int(argv[i]);
1172 mp = mops_search_id (mp_head, slot);
1174 // still not found? Is it a name?
1175 if (mp==NULL) mp = mops_search_name (mp_head, argv[i]);
1176 if (mp==NULL) cli_print(cli, "Packet '%s' not in list!\r",argv[i]);
1177 else { // packet found:
1178 if (mops_destroy_thread (mp)) {
1179 cli_print(cli, "Packet [%i] '%s' has no associated transmission process (nothing to stop).\r", mp->id, mp->packet_name);
1180 } else
1181 cli_print (cli, "Stopped transission process for packet [%i] '%s'.\r", mp->id, mp->packet_name);
1185 cli_print(cli, "\r");
1186 return CLI_OK;
1191 int show_mops(struct cli_def *cli, char *command, char *argv[], int argc)
1193 char tmp[120];
1195 if (strncmp(argv[argc-1], "?", 2)==0) {
1196 cli_print(cli, "<ENTER> Check MOPS version and details\n");
1197 return CLI_OK;
1200 cli_print(cli, "-----------------------------------------------------\r");
1201 cli_print(cli, "Mops version %s [%s]\n", MOPS_VERSION, MOPS_CODENAME);
1202 cli_print(cli, "Maximum packet sequence length is %i packets\r", MAX_PACKET_SEQUENCE_LEN);
1203 cli_print(cli, "Maximum frame size is %i bytes\r", MAX_MOPS_FRAME_SIZE);
1204 cli_print(cli, "Minimum frame size is %i bytes\r", MIN_MOPS_FRAME_SIZE);
1205 cli_print(cli, "PCAP readout delay is %i msec\r", PCAP_READ_TIMEOUT_MSEC);
1206 cli_print(cli, "Maximum payload size is %i bytes\r", MAX_MOPS_MSG_SIZE);
1207 cli_print(cli, "Maximum chunk size is %i bytes\r", MAX_MOPS_MSG_CHUNK_SIZE);
1208 cli_print(cli, "Maximum counters per packet is %i\r", MAX_MOPS_COUNTERS_PER_PACKET);
1209 cli_print(cli, "Maximum number of 802.1Q tags is %i\r", MAX_MOPS_DOT1Q_TAGS);
1210 cli_print(cli, "Maximum number of MPLS tags is %i\r", MAX_MOPS_MPLS_TAGS);
1211 cli_print(cli, "Maximum length of packet names is %i characters\r", MAX_MOPS_PACKET_NAME_LEN);
1212 cli_print(cli, "Maximum length of packet descriptions is %i characters\r", MAX_MOPS_DESCRIPTION_LEN);
1213 cli_print(cli, "Bytes per line for formatted frame output %i\r", MAX_CLI_LINE_BYTES);
1214 cli_print(cli, "Maximum LLDP optional section length is %i bytes\r", MAX_LLDP_OPT_TLVS);
1215 if (AUTOMOPS_ENABLED) {
1216 cli_print(cli, "Auto-MOPS subsystem is enabled\r");
1217 cli_print(cli, " Maximum nesting depth is %i\r", XN_MAX_STACK);
1218 cli_print(cli, " Maximum file size for protocol definitions is %i\r", AUTOMOPS_MAX_FILE_SIZE);
1219 cli_print(cli, " Maximum names length is %i\r", AUTOMOPS_MAX_NAME_LEN);
1220 cli_print(cli, " Maximum short description length is %i\r", AUTOMOPS_MAX_SHORTDESC_LEN);
1221 cli_print(cli, " Maximum XML tag length is %i\r", XML_MAX_TAG_LEN);
1222 } else cli_print(cli, "Auto-MOPS subsystem is disabled\r");
1224 if (mops_dump_all(mp_head, tmp)) {
1225 cli_print(cli, "No mopses found.\n"); // keine Möpse gefunden ;-)
1226 } else {
1227 cli_print(cli, "%s\n", tmp);
1230 return CLI_OK;
1236 int cmd_reset_interface (struct cli_def *cli, char *command, char *argv[], int argc)
1238 int i;
1240 if (strncmp(argv[argc-1], "?", 2)==0) {
1241 cli_print(cli, "<ENTER> Check MOPS version and details\n");
1242 return CLI_OK;
1245 if (argc>0) {
1246 cli_print(cli, "Unknown parameter\n");
1247 return CLI_OK;
1250 lookupdev();
1252 for (i=0; i<device_list_entries; i++) {
1253 get_dev_params(device_list[i].dev);
1254 // refresh ARP table i. e. MAC addresses of default GWs
1255 service_arp(device_list[i].dev, device_list[i].ip_gw, device_list[i].mac_gw);
1258 return CLI_OK;
1264 int conf_frame_limit (struct cli_def *cli, char *command, char *argv[], int argc)
1266 unsigned int tmp;
1268 if (strncmp(argv[argc-1], "?", 2)==0)
1270 cli_print(cli, "Configure global frame size limits:\n");
1271 cli_print(cli, " <min-frame-size> [max-frame-size]\n");
1272 return CLI_OK;
1275 if (argc>2)
1277 cli_print(cli, "Two arguments allowed: <min-frame-size> [max-frame-size]\n");
1278 return CLI_OK;
1281 tmp = (unsigned int) str2int (argv[0]);
1282 if (tmp < MIN_MOPS_FRAME_SIZE)
1284 cli_print(cli, "This Mausezahn requires that the minimum frame size is at least %i bytes\n", MIN_MOPS_FRAME_SIZE);
1285 return CLI_OK;
1288 if (tmp>(max_frame_s-2))
1290 cli_print(cli, "The minimum frame size must be below %i bytes\n", max_frame_s-1);
1291 return CLI_OK;
1294 min_frame_s = tmp;
1296 if (argc==2)
1298 tmp = (unsigned int) str2int (argv[1]);
1300 if (tmp > MAX_MOPS_FRAME_SIZE-MOPS_SIZE_MARGIN)
1302 cli_print(cli, "This Mausezahn requires that the maximum frame size is not greater than %i bytes\n",
1303 MAX_MOPS_FRAME_SIZE-MOPS_SIZE_MARGIN);
1304 return CLI_OK;
1307 if (tmp<(min_frame_s+2))
1309 cli_print(cli, "The maximum frame size must be greater than %i bytes\n", min_frame_s+1);
1310 return CLI_OK;
1313 max_frame_s = tmp;
1316 return CLI_OK;
1322 int cmd_load (struct cli_def *cli, char *command, char *argv[], int argc)
1324 int i;
1325 FILE *fp;
1327 if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) ) {
1328 cli_print(cli, "Load commands from one or more specified file(s)\r");
1329 cli_print(cli, "\n");
1330 return CLI_OK;
1333 if (!argc){
1334 cli_print(cli, "Specify one or more configuration files\n");
1335 return CLI_OK;
1338 for (i=0; i<argc; i++) {
1339 fp = fopen(argv[i], "r");
1340 if (fp==NULL) {
1341 cli_print(cli, "Warning: Cannot read %s\n", argv[i]);
1342 continue;
1344 cli_print(cli, "Read commands from %s...\n", argv[i]);
1345 cli_file (cli, fp, PRIVILEGE_PRIVILEGED, MODE_EXEC);
1346 if (fclose(fp) == EOF)
1348 cli_print(cli, "Warning: problems closing %s (errno=%i)\n", argv[i],errno);
1352 return CLI_OK;
1356 int show_arp (struct cli_def *cli, char *command, char *argv[], int argc)
1358 int i;
1359 struct arp_table_struct *cur;
1360 char s[128], ip[20], uc[16], bc[16], ch[16];
1361 struct mz_timestamp now, prev, result;
1365 if (strcmp(argv[argc-1],"?")==0) {
1366 cli_print(cli, "<CR> shows the advanced Mausezahn ARP table\n");
1367 return CLI_OK;
1370 if (argc>0) {
1371 cli_print(cli, "Unknown parameter\n");
1372 return CLI_OK;
1376 cli_print(cli, "Intf Index IP address MAC address last Ch UCast BCast Info\r");
1377 cli_print(cli, "----------------------------------------------------------------------------------\r");
1378 // ------------------------------------------------------------------------------
1379 // wlan0 [1] DL 192.168.0.1 at 00:09:5b:9a:15:84 3'42'' 1
1381 for (i=0; i<device_list_entries; i++) {
1382 cur=device_list[i].arp_table;
1383 while(cur!=NULL) {
1384 sprintf(ip,"%i.%i.%i.%i",cur->sip[0],cur->sip[1],cur->sip[2],cur->sip[3]);
1385 if (cur->changed>99999) mz_strncpy(ch,"ALERT",6); else sprintf(ch,"%lu", cur->changed);
1386 if (cur->uni_resp>99999) mz_strncpy(uc,"ALERT",6); else sprintf(uc,"%lu", cur->uni_resp);
1387 if (cur->bc_resp>99999) mz_strncpy(bc,"ALERT",6); else sprintf(bc,"%lu", cur->bc_resp);
1388 sprintf(s, "%-7s [%i] %s%s %15s %02x:%02x:%02x:%02x:%02x:%02x %8s %5s %5s %5s %04x",
1389 device_list[i].dev,
1390 cur->index,
1391 (cur->dynamic) ? "D" : "U",
1392 (cur->locked) ? "L" : "",
1394 cur->smac[0],
1395 cur->smac[1],
1396 cur->smac[2],
1397 cur->smac[3],
1398 cur->smac[4],
1399 cur->smac[5],
1400 cur->when,
1404 cur->flags);
1405 cli_print(cli, "%s\r", s);
1406 if (cur->changed>1) {
1407 now.sec = cur->sec;
1408 now.nsec = cur->nsec;
1409 prev.sec = cur->sec_prev;
1410 prev.nsec= cur->nsec_prev;
1411 printf("sec=%u nsec=%u sec=%u nsec=%u\n", cur->sec, cur->nsec, cur->sec_prev, cur->nsec_prev);
1412 timestamp_subtract(&now, &prev, &result);
1413 sprintf(s," previous MAC was: %02x:%02x:%02x:%02x:%02x:%02x time delta: %u sec %u msec",
1414 cur->smac_prev[0],
1415 cur->smac_prev[1],
1416 cur->smac_prev[2],
1417 cur->smac_prev[3],
1418 cur->smac_prev[4],
1419 cur->smac_prev[5],
1420 (unsigned int) result.sec, (unsigned int) result.nsec/1000000);
1421 cli_print(cli, " %s\r", s);
1423 cur=cur->next;
1427 return CLI_OK;
1431 // general 'end' command to return to global config mode
1432 int cmd_end_to_config(struct cli_def *cli, char *command, char *argv[], int argc)
1434 cli_set_configmode(cli, MODE_CONFIG, NULL);
1435 return CLI_OK;