netsniff-ng: nlmsg: Drop dissection of GENL_ID_GENERATE type
[netsniff-ng.git] / staging / cli_cmds.c
blob5e0babd41307d7fe09fb282d4f9081e6a7eea19d
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, const 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, const 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, const 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, const 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, const 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 int show_system(struct cli_def *cli, const char *command, char *argv[], int argc)
157 cli_print(cli, "Not supported in this version\n");
158 return CLI_OK;
164 ////////////////////////////////////////////////////////////////////////////////
165 // Run through packet list and print some details about existing packets.
166 // SYNTAX:
168 // show packet
169 // show packet MyPacket
171 int show_packets(struct cli_def *cli, const char *command, char *argv[], int argc)
173 int a=0, i, j=0, k, v, active_only=0;
174 u_int32_t t;
175 char c,T;
176 char name[32], ds[16], pr[16], ps[16];
177 char myframe[MAX_MOPS_FRAME_SIZE*3];
178 char mystate[32];
179 char line[150], line2[150], line3[150];
180 char delay_str[64];
181 unsigned char *x0, *x1, *x2, *x3;
183 struct mops *head = mp_head;
184 struct mops *mp = mp_head;
187 if (strncmp(argv[argc-1], "?", 2)==0) {
188 cli_print(cli, "<CR> Show list of all defined packets\r");
189 cli_print(cli, "active Only show active packets\r");
190 cli_print(cli, "<PKT_ID> Show detailed info about given packet\r");
191 //TODO cli_print(cli, "type <proto> Only list packets r");
192 cli_print(cli, "\n");
193 return CLI_OK;
196 if (argc==1) {
197 if (mz_strcmp(argv[0], "active", 1)==0) {
198 active_only=1;
202 if ((argc==0) || (active_only)) // show packet summary
204 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");
205 cli_print(cli, "PktID PktName Layers Proto Size State Device Delay Count/CntX\n");
209 if (active_only) {
210 if (mp->state < MOPS_STATE_ACTIVE) {
211 mp = mp->next;
212 j++;
213 continue;
217 ds[0]='\0';
218 ps[0]='\0';
219 pr[0]='\0';
221 if (mp->use_ETHER) strcat(ds,"E"); else strcat(ds,"-");
222 if (mp->use_SNAP) strcat(ds,"S"); else strcat(ds,"-");
223 if (mp->use_dot1Q) strcat(ds,"Q"); else strcat(ds,"-");
224 if (mp->use_MPLS) strcat(ds,"M"); else strcat(ds,"-");
225 if (mp->use_IP) {
226 if (mp->auto_delivery_off)
227 strcat(ds,"i");
228 else
229 strcat(ds,"I");
230 } else strcat(ds,"-");
232 if (mp->use_UDP)
233 strcat(ds,"U");
234 else if
235 (mp->use_TCP) strcat(ds,"T");
236 else strcat(ds,"-");
240 switch (mp->p_desc_type)
242 case MOPS_ARP:
243 strncpy(pr, "ARP", 8);
244 break;
245 case MOPS_BPDU:
246 strncpy(pr, "BPDU", 8);
247 break;
248 case MOPS_CDP:
249 strncpy(pr, "CDP", 8);
250 break;
251 case MOPS_DNS:
252 strncpy(pr, "DNS", 8);
253 break;
254 case MOPS_ICMP:
255 strncpy(pr, "ICMP", 8);
256 break;
257 case MOPS_IGMP:
258 strncpy(pr, "IGMP", 8);
259 break;
260 case MOPS_LLDP:
261 strncpy(pr, "LLDP", 8);
262 break;
263 case MOPS_RTP:
264 strncpy(pr, "RTP", 8);
265 break;
266 case MOPS_SYSLOG:
267 strncpy(pr, "SYSLOG", 8);
268 break;
269 default:
270 break;
274 switch (mops_state(mp))
276 case MOPS_STATE_NULL:
277 strcat(ps, "NULL"); // should never happen!
278 break;
279 case MOPS_STATE_INIT:
280 strcat(ps, "init");
281 break;
282 case MOPS_STATE_CONFIG:
283 strcat(ps, "config");
284 break;
285 case MOPS_STATE_ACTIVE:
286 strcat(ps, "active");
287 a++;
288 break;
289 case MOPS_STATE_SEQACT:
290 strcat(ps, "actseq");
291 a++;
292 break;
293 default:
294 strcat(ps, "unknown");
295 break;
298 switch (mp->interval_used) {
299 case 1: // interval only configured, not started
300 strncat(ps, "-i", 2);
301 break;
303 case 2:
304 strncat(ps, "+I", 2);
305 break;
306 default:
307 break;
311 strncpy (name, mp->packet_name, 13); // only show first 13 chars
313 if (strnlen(mp->packet_name, MAX_MOPS_PACKET_NAME_LEN)>13)
315 name[13]=0x00;
316 strcat(name, "...");
319 // To determine the actual packet length ***
320 // we must reassemble everything: ***
321 mops_ext_update (mp);
322 mops_update (mp);
324 timespec2str(&mp->ndelay, delay_str);
326 // ID name lrs prot size state dev del count/cntx/%
327 sprintf(line, "%5i %-16s %s %-8s %4i %-9s %-6s %10s%9lu/%lu (%i%%)\r",
328 mp->id, // ID
329 name, // packet_name
330 ds, // layers
331 pr, // protocol
332 mp->frame_s, // size
333 ps, // state
334 mp->device, // device
335 delay_str, // delay
336 mp->count, // Configured count value
337 mp->cntx, // Current count
338 (mp->count) ? (int) (100 * (mp->count - mp->cntx)/mp->count) : 0 );
339 cli_print(cli, "%s\r", line);
340 mp = mp->next;
341 j++;
343 while (head != mp);
345 cli_print(cli, "\r");
346 cli_print(cli, "%i packets defined, %i active.\n", j, a);
348 //////////////////////////////////////////////////////////////////////////////////////////////////////////
350 //////////////////////////////////////////////////////////////////////////////////////////////////////////
351 else if (argc == 1) // show details about a specific packet **********************************************
353 if ( (mp = mops_search_name (mp_head, argv[0])) == NULL)// not found
355 if ( (mp = mops_search_id (mp_head, (int) str2int(argv[0]))) == NULL)// not found
357 cli_print (cli, "Packet not in list.\n");
358 return CLI_OK;
362 // To determine the actual packet length ***
363 // we must reassemble everything: ***
364 mops_ext_update (mp);
365 mops_update (mp);
367 cli_print(cli, "Packet [%i] %s\r", mp->id, mp->packet_name);
368 cli_print(cli, " Description: %s \r",
369 (strnlen(mp->description, MAX_MOPS_DESCRIPTION_LEN)) ? mp->description : "(no description)");
371 switch(mp->state)
373 case MOPS_STATE_NULL:
374 sprintf(mystate, "NULL");
375 break;
376 case MOPS_STATE_INIT:
377 sprintf(mystate, "init");
378 break;
379 case MOPS_STATE_CONFIG:
380 sprintf(mystate, "config");
381 break;
382 case MOPS_STATE_ACTIVE:
383 sprintf(mystate, "active(tx)");
384 break;
385 default:
386 sprintf(mystate, "unknown");
389 timespec2str(&mp->ndelay, delay_str);
390 if (mp->interval_used)
391 timespec2str(&mp->interval, line2);
392 else
393 sprintf(line2, "(undefined)");
395 sprintf(line, "State: %s, Count=%lu, delay=%s (%lu s %lu nsec), interval= %s\r",
396 mystate,
397 mp->count,
398 delay_str,
399 mp->ndelay.tv_sec,
400 mp->ndelay.tv_nsec,
401 line2);
402 cli_print(cli, " %s\r", line);
404 cli_print(cli, " Headers:\r");
405 i=0;
406 if (mp->use_ETHER)
408 if (mp->eth_src_israndom)
410 cli_print(cli, " Ethernet: *** RANDOMIZED SMAC *** => %02x-%02x-%02x-%02x-%02x-%02x [%04x%s]\r",
411 mp->eth_dst[0],mp->eth_dst[1],mp->eth_dst[2],mp->eth_dst[3],mp->eth_dst[4],mp->eth_dst[5],
412 mp->eth_type, (mp->use_dot1Q) ? " after 802.1Q tag" : "");
414 else
416 cli_print(cli, " Ethernet: %02x-%02x-%02x-%02x-%02x-%02x => %02x-%02x-%02x-%02x-%02x-%02x [%04x%s]\r",
417 mp->eth_src[0],mp->eth_src[1],mp->eth_src[2],mp->eth_src[3],mp->eth_src[4],mp->eth_src[5],
418 mp->eth_dst[0],mp->eth_dst[1],mp->eth_dst[2],mp->eth_dst[3],mp->eth_dst[4],mp->eth_dst[5],
419 mp->eth_type, (mp->use_dot1Q) ? " after 802.1Q tag" : "");
422 if (mp->use_IP) {
423 if (mp->auto_delivery_off)
424 cli_print(cli, " NOTE: Auto-delivery is OFF (that is, the destination MAC is fixed)\r");
425 else
426 cli_print(cli, " Auto-delivery is ON (that is, the actual MAC is determined upon transmission)\r");
428 i++;
430 if (mp->use_SNAP)
432 bs2str(clipkt->eth_snap, line, clipkt->eth_snap_s);
433 cli_print(cli, " LLC/SNAP: %s\r", line);
434 i++;
436 if (mp->use_dot1Q)
438 k = clipkt->dot1Q_s/4; // number of tags
439 sprintf(line, "%i tag(s); ", k);
440 for (j=0; j<k; j++)
441 { // tag format = 0x81 0x00 cosTvvvv vvvvvvvv
442 // x0 x1
443 x0 = (unsigned char*) &clipkt->dot1Q[(j*4)+2];
444 x1 = (unsigned char*) &clipkt->dot1Q[(j*4)+3];
445 v = (*x0 & 0x0f)*256 + *x1; // VLAN
446 // c = *x0 & 0xe0; // CoS e0=11100000
447 c = *x0 >> 5;
448 sprintf(ds, "%i:%i%s",
450 (unsigned char) c,
451 (*x0 & 0x10) ? "[CFI]" : ""); // CFI
452 strncat(line, ds, 14);
453 if (j<(k-1)) strcat(line, ", ");
456 cli_print(cli, " 802.1Q: %s (VLAN:CoS)\r", line);
457 i++;
459 if (mp->use_MPLS)
461 k = clipkt->mpls_s/4; // number of tags
462 sprintf(line, "%i tag(s); ", k);
463 for (j=0; j<k; j++)
464 { // tag format = llllllll llllllll llllcccB TTTTTTTT
465 x0 = (unsigned char*) &clipkt->mpls[(j*4)+0];
466 x1 = (unsigned char*) &clipkt->mpls[(j*4)+1];
467 x2 = (unsigned char*) &clipkt->mpls[(j*4)+2];
468 x3 = (unsigned char*) &clipkt->mpls[(j*4)+3];
469 t = *x0;
470 t <<= 12;
471 t += *x1 * 16;
472 t += (*x2 & 0xf0) >> 4;
473 c = (*x2 & 0x0e) >> 1;
474 T = *x3;
475 sprintf(ds, "%i:%i:%i%s",
477 (unsigned char) c,
478 (unsigned char) T,
479 (*x2 & 0x01) ? "[BoS]" : ""); // Bottom of Stack?
480 strncat(line, ds, 20);
481 if (j<(k-1)) strcat(line, ", ");
484 cli_print(cli, " MPLS: %s (Label:CoS:TTL)\r", line);
486 i++;
488 if (mp->use_IP)
490 // Source IP settings:
491 x0 = (unsigned char*) & clipkt->ip_src;
492 line2[0]=0x00;
493 if (clipkt->ip_src_isrange)
495 x1 = (unsigned char*) & clipkt->ip_src_start;
496 x2 = (unsigned char*) & clipkt->ip_src_stop;
497 sprintf(line2, "%u.%u.%u.%u-%u.%u.%u.%u",
498 (unsigned char) *(x1+3), (unsigned char) *(x1+2), (unsigned char) *(x1+1) , (unsigned char) *x1,
499 (unsigned char) *(x2+3), (unsigned char) *(x2+2), (unsigned char) *(x2+1) , (unsigned char) *x2);
501 sprintf(line, "SA=%u.%u.%u.%u %s %s %s",
502 (unsigned char) *(x0+3), (unsigned char) *(x0+2), (unsigned char) *(x0+1) , (unsigned char) *x0,
503 (clipkt->ip_src_israndom) ? "RANDOM" : "(not random)",
504 (clipkt->ip_src_isrange) ? "RANGE:" : "(no range)",
505 line2);
507 cli_print(cli, " IP: %s\r", line);
508 //Destination IP settings:
509 x0 = (unsigned char*) & clipkt->ip_dst;
510 line2[0]=0x00;
511 if (clipkt->ip_dst_isrange)
513 x1 = (unsigned char*) & clipkt->ip_dst_start;
514 x2 = (unsigned char*) & clipkt->ip_dst_stop;
515 sprintf(line2, "%u.%u.%u.%u-%u.%u.%u.%u",
516 (unsigned char) *(x1+3), (unsigned char) *(x1+2), (unsigned char) *(x1+1) , (unsigned char) *x1,
517 (unsigned char) *(x2+3), (unsigned char) *(x2+2), (unsigned char) *(x2+1) , (unsigned char) *x2);
520 sprintf(line, "DA=%u.%u.%u.%u %s %s",
521 (unsigned char) *(x0+3), (unsigned char) *(x0+2), (unsigned char) *(x0+1) , (unsigned char) *x0,
522 (clipkt->ip_dst_isrange) ? "RANGE:" : "(no range)",
523 line2);
524 cli_print(cli, " %s\r", line);
526 sprintf(line, "ToS=0x%02x proto=%u TTL=%u ID=%u offset=%u flags: %s|%s|%s",
527 clipkt->ip_tos, clipkt->ip_proto, clipkt->ip_ttl, clipkt->ip_id, clipkt->ip_frag_offset,
528 (clipkt->ip_flags_RS) ? "RS" : "-",
529 (clipkt->ip_flags_DF) ? "DF" : "-",
530 (clipkt->ip_flags_MF) ? "MF" : "-");
532 cli_print(cli, " %s\r", line);
534 if (clipkt->ip_fragsize) {
535 sprintf(line, "NOTE: Auto-fragmentation is ON! Fragment size %u bytes, overlap %u",
536 clipkt->ip_fragsize,
537 clipkt->ip_frag_overlap);
538 cli_print(cli, " %s\r", line);
541 sprintf(line, "len=%u(%s) checksum=0x%02x%02x(%s)",
542 clipkt->frame[clipkt->begin_IP+2]*256+clipkt->frame[clipkt->begin_IP+3],
543 (clipkt->ip_len_false) ? "false" : "correct",
544 clipkt->frame[clipkt->begin_IP+10],
545 clipkt->frame[clipkt->begin_IP+11],
546 (clipkt->ip_sum_false) ? "false" : "correct");
548 cli_print(cli, " %s\r", line);
550 i++;
552 if (mp->use_UDP)
554 if (clipkt->sp_isrange)
555 sprintf(line2, "RANGE: %u-%u", clipkt->sp_start, clipkt->sp_stop);
556 else
557 sprintf(line2, "(norange)");
558 if (clipkt->dp_isrange)
559 sprintf(line3, "RANGE: %u-%u", clipkt->dp_start, clipkt->dp_stop);
560 else
561 sprintf(line3, "(norange)");
562 sprintf(line, "SP=%i %s %s, DP=%i %s %s\r",
563 clipkt->sp,
564 line2,
565 (clipkt->sp_isrand) ? "RANDOM" : "(not random)",
566 clipkt->dp,
567 line3,
568 (clipkt->dp_isrand) ? "RANDOM" : "(not random)");
569 cli_print(cli, " UDP: %s\r", line);
570 sprintf(line, "checksum= %04x (%s), length= %u (%s)",
571 clipkt->udp_sum, (clipkt->udp_sum_false) ? "false" : "correct",
572 clipkt->udp_len, (clipkt->udp_len_false) ? "false" : "correct");
573 cli_print(cli, " %s\r", line);
574 i++;
576 if (mp->use_TCP)
578 sprintf(line, "%u bytes segment size (including TCP header)", mp->tcp_len);
579 cli_print(cli, " TCP: %s\r", line);
580 if (clipkt->sp_isrange)
581 sprintf(line2, "RANGE: %u-%u", clipkt->sp_start, clipkt->sp_stop);
582 else
583 sprintf(line2, "(norange)");
584 if (clipkt->dp_isrange)
585 sprintf(line3, "RANGE: %u-%u", clipkt->dp_start, clipkt->dp_stop);
586 else
587 sprintf(line3, "(norange)");
588 sprintf(line, "SP=%i %s %s, DP=%i %s %s\r",
589 clipkt->sp,
590 line2,
591 (clipkt->sp_isrand) ? "RANDOM" : "(not random)",
592 clipkt->dp,
593 line3,
594 (clipkt->dp_isrand) ? "RANDOM" : "(not random)");
595 cli_print(cli, " %s\r", line);
596 sprintf(line, "SQNR=%u (start %u, stop %u, delta %u) -- ACKNR=%u %s",
597 clipkt->tcp_seq,
598 clipkt->tcp_seq_start,
599 clipkt->tcp_seq_stop,
600 clipkt->tcp_seq_delta,
601 clipkt->tcp_ack,
602 (clipkt->tcp_ctrl_ACK) ? "(valid)" : "(invalid)");
603 cli_print(cli, " %s\r", line);
604 mops_tcp_flags2str(clipkt,line2);
605 sprintf(line, "Flags: %s, reserved field is %02x, urgent pointer= %u",
606 line2,
607 clipkt->tcp_res,
608 clipkt->tcp_urg);
609 cli_print(cli, " %s\r", line);
610 sprintf(line, "Announced window size= %u", clipkt->tcp_win);
611 cli_print(cli, " %s\r", line);
612 sprintf(line, "Offset= %u (times 32 bit; value is %s), checksum= %04x (%s)",
613 clipkt->tcp_offset,
614 (clipkt->tcp_offset_false) ? "FALSE" : "valid",
615 clipkt->tcp_sum,
616 (clipkt->tcp_sum_false) ? "FALSE" : "valid");
617 cli_print(cli, " %s\r", line);
618 sprintf(line, "%s - %u bytes defined",
619 (clipkt->tcp_option_used) ? "TCP options attached" : "(No TCP options attached)",
620 clipkt->tcp_option_s);
621 cli_print(cli, " %s\r", line);
622 i++;
625 if (!i) cli_print(cli, " No headers defined.\r");
627 if (mp->msg_s) {
628 cli_print(cli, " Payload size: %i bytes\r", mp->msg_s);
631 cli_print(cli, " Frame size: %i bytes\n", mp->frame_s);
633 mops_print_frame(mp, myframe);
634 cli_print(cli, "%s\n", myframe);
637 return CLI_OK;
641 ////////////////////////////////////////////////////////////////////////////////
642 int show_interfaces (struct cli_def *cli, const char *command, char *argv[], int argc)
644 int i, j=0;
645 char line[100];
646 char ip[20];
649 if (strncmp(argv[argc-1], "?", 2)==0) {
650 cli_print(cli, "<CR> Show summary list of all interfaces found\r");
651 cli_print(cli, "detailed Additionally show network, mask, default gatway, and MTU\r");
652 cli_print(cli, "\n");
653 return CLI_OK;
656 // Some safety checks
657 if (argc>1) return CLI_OK;
658 if (argc==1) {
659 if (mz_strcmp(argv[0], "detailed", 1)!=0) {
660 cli_print(cli, "invalid keyword (use ?)\n");
661 return CLI_OK;
665 /* Refresh interface data */
667 lookupdev();
669 for (i=0; i<device_list_entries; i++) {
670 get_dev_params(device_list[i].dev);
675 /* No additional keyword */
676 if (argc==0) {
677 cli_print(cli, "Available network interfaces:\n");
678 cli_print(cli, " real real used (fake) used (fake)\r");
679 cli_print(cli, " device IPv4 address MAC address IPv4 address MAC address\r");
680 cli_print(cli, "---------------------------------------------------------------------------------------\r");
681 for (i=0; i<device_list_entries; i++) {
682 sprintf(ip,"%u.%u.%u.%u",
683 device_list[i].ip_mops[0],
684 device_list[i].ip_mops[1],
685 device_list[i].ip_mops[2],
686 device_list[i].ip_mops[3]);
688 sprintf(line, "%-10s %-15s %02x:%02x:%02x:%02x:%02x:%02x %-15s %02x:%02x:%02x:%02x:%02x:%02x",
689 device_list[i].dev, device_list[i].ip_str,
690 device_list[i].mac[0],
691 device_list[i].mac[1],
692 device_list[i].mac[2],
693 device_list[i].mac[3],
694 device_list[i].mac[4],
695 device_list[i].mac[5],
697 device_list[i].mac_mops[0],
698 device_list[i].mac_mops[1],
699 device_list[i].mac_mops[2],
700 device_list[i].mac_mops[3],
701 device_list[i].mac_mops[4],
702 device_list[i].mac_mops[5]
706 if (strncmp(device_list[i].dev, tx.device, 16)==0) {
707 cli_print(cli, "%s%s> %s\r",
708 (device_list[i].cli) ? "C" : " ",
709 (device_list[i].mgmt_only) ? "!" : "",
710 line);
711 j=i;
713 else
714 cli_print(cli, "%s%s %s\r",
715 (device_list[i].cli) ? "C" : " ",
716 (device_list[i].mgmt_only) ? "M" : "",
717 line);
720 /////////////////////////
721 else
723 /* keyword detailed used */
724 if (mz_strcmp(argv[0], "detailed", 1)==0) {
725 cli_print(cli, "Detailed interface list:\n");
726 for (i=0; i<device_list_entries; i++) {
727 sprintf(line, "interface %s [%i] %s%stype %s, MTU=%i bytes", // general HW info
728 device_list[i].dev,
729 device_list[i].index,
730 (device_list[i].cli) ? "[cli] " : "",
731 (device_list[i].mgmt_only) ? "[management-only] " : "",
732 (device_list[i].phy) ? "physical" : "software",
733 device_list[i].mtu);
734 cli_print(cli,"%s\r",line);
735 sprintf(line, "MAC bia: %02x:%02x:%02x:%02x:%02x:%02x\n MAC fake: %02x:%02x:%02x:%02x:%02x:%02x",
736 device_list[i].mac[0],
737 device_list[i].mac[1],
738 device_list[i].mac[2],
739 device_list[i].mac[3],
740 device_list[i].mac[4],
741 device_list[i].mac[5],
742 device_list[i].mac_mops[0],
743 device_list[i].mac_mops[1],
744 device_list[i].mac_mops[2],
745 device_list[i].mac_mops[3],
746 device_list[i].mac_mops[4],
747 device_list[i].mac_mops[5]);
748 cli_print(cli," %s\r",line);
749 sprintf(line,"IP addr: %s mask %u.%u.%u.%u (net %u.%u.%u.%u)",
750 device_list[i].ip_str,
751 device_list[i].mask[0],
752 device_list[i].mask[1],
753 device_list[i].mask[2],
754 device_list[i].mask[3],
755 device_list[i].net[0],
756 device_list[i].net[1],
757 device_list[i].net[2],
758 device_list[i].net[3]);
759 cli_print(cli," %s\r",line);
760 sprintf(line,"IP fake: %u.%u.%u.%u",
761 device_list[i].ip_mops[0],
762 device_list[i].ip_mops[1],
763 device_list[i].ip_mops[2],
764 device_list[i].ip_mops[3]);
765 cli_print(cli, " %s\r", line);
766 sprintf(line,"GW addr: %u.%u.%u.%u (%02x:%02x:%02x:%02x:%02x:%02x)",
767 device_list[i].ip_gw[0],
768 device_list[i].ip_gw[1],
769 device_list[i].ip_gw[2],
770 device_list[i].ip_gw[3],
771 device_list[i].mac_gw[0],
772 device_list[i].mac_gw[1],
773 device_list[i].mac_gw[2],
774 device_list[i].mac_gw[3],
775 device_list[i].mac_gw[4],
776 device_list[i].mac_gw[5]);
777 cli_print(cli," %s\n",line);
781 /* In any case, print final summary line: */
782 cli_print(cli, "\n%i interfaces found.\nDefault interface is %s.\n",
783 device_list_entries, device_list[j].dev);
785 return CLI_OK;
790 ////////////////////////////////////////////////////////////////////////////////
791 int show_set(struct cli_def *cli, const char *command, char *argv[], int argc)
793 unsigned char *x;
794 char hexload[3*MAX_PAYLOAD_SIZE];
796 cli_print(cli, "----- Packet parameters: ------ -------- Value: ----------\r");
797 cli_print(cli, "Source MAC address (sa) %02x:%02x:%02x:%02x:%02x:%02x [%s]\r",
798 tx.eth_src[0], tx.eth_src[1], tx.eth_src[2],
799 tx.eth_src[3], tx.eth_src[4], tx.eth_src[5],
800 (tx.eth_src_rand) ? "rand" : "spec");
801 cli_print(cli, "Basic MAC address %02x:%02x:%02x:%02x:%02x:%02x\r",
802 tx.eth_mac_own[0], tx.eth_mac_own[1], tx.eth_mac_own[2],
803 tx.eth_mac_own[3], tx.eth_mac_own[4], tx.eth_mac_own[5]);
804 cli_print(cli, "Destination MAC address (da) %02x:%02x:%02x:%02x:%02x:%02x [%s]\r",
805 tx.eth_dst[0], tx.eth_dst[1], tx.eth_dst[2],
806 tx.eth_dst[3], tx.eth_dst[4], tx.eth_dst[5],
807 (tx.eth_dst_rand) ? "rand" : "spec");
808 cli_print(cli, "\r");
809 x = (unsigned char *) &tx.ip_src;
810 cli_print(cli, "Source IP address (SA) %i.%i.%i.%i [%s]\r",
811 *x,*(x+1),*(x+2),*(x+3),
812 (tx.ip_src_rand) ? "rand" : "spec");
814 if (tx.ip_src_isrange)
816 x = (unsigned char *) &tx.ip_src_start;
817 cli_print(cli, "Source IP range start: %i.%i.%i.%i\r",
818 *(x+3), *(x+2), *(x+1), *x);
819 x = (unsigned char *) &tx.ip_src_stop;
820 cli_print(cli, "Source IP range stop: %i.%i.%i.%i\r",
821 *(x+3), *(x+2), *(x+1), *x);
823 else
825 cli_print(cli, "No source IP range specified\r");
827 x = (unsigned char *) &tx.ip_dst;
828 cli_print(cli, "Destination IP address (DA) %i.%i.%i.%i\r",
829 *x,*(x+1),*(x+2),*(x+3));
831 if (tx.ip_dst_isrange)
833 x = (unsigned char *) &tx.ip_dst_start;
834 cli_print(cli, "Destination IP range start: %i.%i.%i.%i\r",
835 *(x+3), *(x+2), *(x+1), *x);
836 x = (unsigned char *) &tx.ip_dst_stop;
837 cli_print(cli, "Destination IP range stop: %i.%i.%i.%i\r",
838 *(x+3), *(x+2), *(x+1), *x);
840 else
842 cli_print(cli, "No destination IP range specified\r");
845 if (tx.dot1Q)
847 cli_print(cli, "802.1Q tags specified: %s\r", tx.dot1Q_txt);
850 if (tx.mpls)
852 cli_print(cli, "MPLS labels specified: %s\r", tx.mpls_txt);
855 if (tx.ascii)
856 { cli_print(cli, "\r");
857 cli_print(cli, "---- ASCII payload is set: ----- \r");
858 cli_print(cli, ">>>%s<<<\r", tx.ascii_payload);
859 cli_print(cli, "-------------------------------- \n");
862 if (tx.hex_payload_s)
863 { cli_print(cli, "\r");
864 cli_print(cli, "---- Hexadecimal payload is set: ----- \r");
865 bs2str(tx.hex_payload, hexload, tx.hex_payload_s);
866 cli_print(cli, "%s\r", hexload);
867 cli_print(cli, "-------------------------------------- \n");
870 if (tx.padding)
872 cli_print(cli, "Configured padding: %u\r", tx.padding);
875 cli_print(cli, "\r");
876 cli_print(cli, "Packet count value %u\r", tx.count);
877 cli_print(cli, "Interpacket delay (usec) %u\r", tx.delay);
878 cli_print(cli, "\r");
879 cli_print(cli, "Used network device(s): %s\r", tx.device);
880 cli_print(cli, "\n");
881 return CLI_OK;
890 ////////////////////////////////////////////////////////////////////////////////
891 int stop_mausezahn (struct cli_def *cli, const char *command, char *argv[], int argc)
893 if (strncmp(argv[argc-1], "?", 2)==0) {
894 cli_print(cli, "now Terminate the mausezahn server! BEWARE!\n");
895 return CLI_OK;
898 if (argc!=1) {
899 cli_print(cli, "The only allowed argument is 'now' -- anything else is ignored\n");
900 return CLI_OK;
903 if (mz_strcmp(argv[0], "now", 3)==0) {
904 cli_print(cli, "Good bye...\n");
905 cli_done(cli);
906 clean_up(0);
907 return CLI_OK;
908 } else {
909 cli_print(cli, "Invalid argument. If you want to stop the Mausezahn server then\r");
910 cli_print(cli, "enter 'terminate now'. You cannot abbreviate the argument 'now'. \n");
913 return CLI_OK;
919 int cmd_run_id (struct cli_def *cli, const char *command, char *argv[], int argc)
921 int i, slot;
922 struct mops *mp;
924 if (argc == 0) {
925 cli_print(cli, "Specify one or more packet identifiers to run.\n");
926 return CLI_OK;
929 if ( strncmp(argv[argc-1], "?", 1) == 0) {
930 cli_print(cli, "Run packet transmission processes for given list of packet identifiers\n");
931 return CLI_OK;
934 // User provided packet id numbers
935 if (argc > 0) {
936 for (i=0; i<argc; i++) {
937 slot = (int) str2int(argv[i]);
938 if ( (mp = mops_search_id (mp_head, slot)) == NULL) { // not found
939 cli_print (cli, "Packet %i not in list.\n", slot );
940 return CLI_OK;
942 else {
943 switch (mops_tx_simple (mp)) {
944 case 1:
945 cli_print(cli, "Cannot create sending process.\r");
946 return CLI_OK;
947 break;
948 case 3:
949 cli_print(cli, "Packet [%i] has already an active sending process\r", mp->id);
950 return CLI_OK;
951 break;
952 default:
953 cli_print (cli, "Activate [%i] ", slot );
954 break;
958 cli_print (cli, "\n");
960 return CLI_OK;
964 int cmd_run_name (struct cli_def *cli, const char *command, char *argv[], int argc)
966 int i;
967 struct mops *mp;
969 if (argc == 0) {
970 cli_print(cli, "Specify one or more packet name(s) to run.\n");
971 return CLI_OK;
974 if ( strncmp(argv[argc-1], "?", 1) == 0) {
975 cli_print(cli, "Run packet transmission processes for specified packet name(s).\n");
976 return CLI_OK;
979 if (argc > 0) {
980 for (i=0; i<argc; i++) {
981 if ( (mp = mops_search_name (mp_head, argv[i])) == NULL) { // not found
982 cli_print (cli, "Packet %s not in list.\n", argv[i]);
983 return CLI_OK;
985 else {
986 switch (mops_tx_simple (mp)) {
987 case 1:
988 cli_print(cli, "Cannot create sending process.\r");
989 return CLI_OK;
990 break;
991 case 3:
992 cli_print(cli, "Packet [%i] has already an active sending process\r", mp->id);
993 return CLI_OK;
994 break;
995 default:
996 cli_print (cli, "Activate [%i] ", mp->id );
997 break;
1001 cli_print (cli, "\n");
1003 return CLI_OK;
1007 int cmd_run_sequence (struct cli_def *cli, const char *command, char *argv[], int argc)
1009 struct mz_ll *cur;
1010 int ret=0;
1011 if (argc != 1) {
1012 cli_print(cli, "Specify one (and only one) packet sequence name to run.\n");
1013 return CLI_OK;
1016 if ( strncmp(argv[argc-1], "?", 1) == 0) {
1017 cli_print(cli, "Run sequence transmission processes for specified sequence name.\n");
1018 return CLI_OK;
1021 cur = mz_ll_search_name (packet_sequences, argv[0]);
1022 if (cur==NULL) { // NOT FOUND !!!
1023 cli_print(cli, "Sequence %s does not exist.", argv[0]);
1024 return CLI_OK;
1026 ret = mops_tx_sequence(cur);
1027 switch (ret) {
1028 case 0: cli_print(cli, "Sequence %s is running\n", cur->name);
1029 break;
1030 case 1: cli_print(cli, "Cannot run sequence: All packets must be in config state!\n");
1031 break;
1032 case 2: cli_print(cli, "Cannot run sequence: All packets must have a finite count!\n");
1033 break;
1034 case 3: cli_print(cli, "Cannot run sequence: Unable to start sequence transmission process.\n");
1035 break;
1037 return CLI_OK;
1042 int cmd_run_all (struct cli_def *cli, const char *command, char *argv[], int argc)
1044 int i;
1045 struct mops *mp;
1046 struct mops *head;
1048 if ( strncmp(argv[argc-1], "?", 1) == 0) {
1049 cli_print(cli, "Run all user-specified packets.\n");
1050 return CLI_OK;
1053 if (argc>0) {
1054 cli_print(cli, "No arguments expected!\n");
1055 return CLI_OK;
1058 // Send all valid packets
1059 i=0;
1060 head = mp_head;
1061 mp = mp_head;
1062 do {
1063 if ((mp->mz_system==0) && (mops_state(mp) == MOPS_STATE_CONFIG)) {
1064 switch (mops_tx_simple (mp)) {
1065 case 1:
1066 cli_print(cli, "Cannot create sending process.\r");
1067 return CLI_OK;
1068 break;
1069 case 3:
1070 cli_print(cli, "Packet [%i] has already an active sending process\r", mp->id);
1071 return CLI_OK;
1072 break;
1073 default:
1074 break;
1076 i++;
1077 cli_print (cli, "Activate [%i] %s\r", mp->id, mp->packet_name );
1079 mp = mp->next;
1081 while (head != mp);
1082 if (i==0) {
1083 cli_print (cli, "No valid packets found\n");
1084 } else {
1085 cli_print (cli, "\r");
1086 cli_print (cli, "Activated %i packets \n", i);
1088 return CLI_OK;
1093 int cmd_stop (struct cli_def *cli, const char *command, char *argv[], int argc)
1095 struct mops *mp;
1096 int i, ret=0, slot=0;
1098 struct mops *head = mp_head;
1099 struct mops *cur = mp_head;
1101 if ((strncmp(argv[argc-1], "?", 2)==0) || (argc==0)) {
1102 cli_print(cli, "Stop transmission process(es) or an active sequence.\r");
1103 cli_print(cli, "SYNTAX: 1) Either specify one or more packet-ids or packet names of active packets\r");
1104 cli_print(cli, " 2) Or enter 'sequence <seq-name>' to stop an active sequence and its associated packets.\n");
1105 return CLI_OK;
1108 // Did the user specify a sequence? (ONE SEQUENCE ONLY)
1109 if ((mz_strcmp(argv[0], "sequence", 3)==0) && (argc==2)) {
1110 ret = stop_sequence (argv[1]);
1111 switch (ret) {
1112 case 0:
1113 cli_print(cli, "Sequence '%s' stopped.\n", argv[1]);
1114 break;
1116 case 1:
1117 cli_print(cli, "Sequence '%s' does not exist!\n", argv[1]);
1118 break;
1119 case 2:
1120 cli_print(cli, "Sequence '%s' is not active. Nothing to stop.\n", argv[1]);
1121 break;
1123 return CLI_OK;
1127 if (((mz_strcmp(argv[0], "all", 3)==0) || (mz_strcmp(argv[0], "*", 1)==0)) && (argc==1)) {
1128 i=0;
1129 cli_print(cli, "Stopping ");
1130 do {
1131 if (mops_destroy_thread (cur)==0) {
1132 i++;
1133 cli_print(cli, "[%i] %s", cur->id, cur->packet_name);
1135 cur = cur->next;
1137 while (head != cur);
1138 cli_print(cli, "\n");
1139 if (i) {
1140 cli_print(cli, "Stopped %i transmission processe(s)\r", i);
1142 else {
1143 cli_print(cli, "No active transmission processes found.\r");
1146 i = stop_all_sequences ();
1147 if (i) {
1148 cli_print(cli, "Stopped %i sequence(s)\n", i);
1150 else {
1151 cli_print(cli, "No active sequences found.\n");
1154 return CLI_OK;
1157 // Stop all specified packets:
1159 for (i=0; i<argc; i++) {
1160 mp = NULL;
1161 // is argv[i] a numerical pkt-id?
1162 if (mz_strisnum(argv[i])) {
1163 slot = (int) str2int(argv[i]);
1164 mp = mops_search_id (mp_head, slot);
1166 // still not found? Is it a name?
1167 if (mp==NULL) mp = mops_search_name (mp_head, argv[i]);
1168 if (mp==NULL) cli_print(cli, "Packet '%s' not in list!\r",argv[i]);
1169 else { // packet found:
1170 if (mops_destroy_thread (mp)) {
1171 cli_print(cli, "Packet [%i] '%s' has no associated transmission process (nothing to stop).\r", mp->id, mp->packet_name);
1172 } else
1173 cli_print (cli, "Stopped transission process for packet [%i] '%s'.\r", mp->id, mp->packet_name);
1177 cli_print(cli, "\r");
1178 return CLI_OK;
1183 int show_mops(struct cli_def *cli, const char *command, char *argv[], int argc)
1185 char tmp[120];
1187 if (strncmp(argv[argc-1], "?", 2)==0) {
1188 cli_print(cli, "<ENTER> Check MOPS version and details\n");
1189 return CLI_OK;
1192 cli_print(cli, "-----------------------------------------------------\r");
1193 cli_print(cli, "Mops version %s [%s]\n", MOPS_VERSION, MOPS_CODENAME);
1194 cli_print(cli, "Maximum packet sequence length is %i packets\r", MAX_PACKET_SEQUENCE_LEN);
1195 cli_print(cli, "Maximum frame size is %i bytes\r", MAX_MOPS_FRAME_SIZE);
1196 cli_print(cli, "Minimum frame size is %i bytes\r", MIN_MOPS_FRAME_SIZE);
1197 cli_print(cli, "PCAP readout delay is %i msec\r", PCAP_READ_TIMEOUT_MSEC);
1198 cli_print(cli, "Maximum payload size is %i bytes\r", MAX_MOPS_MSG_SIZE);
1199 cli_print(cli, "Maximum chunk size is %i bytes\r", MAX_MOPS_MSG_CHUNK_SIZE);
1200 cli_print(cli, "Maximum counters per packet is %i\r", MAX_MOPS_COUNTERS_PER_PACKET);
1201 cli_print(cli, "Maximum number of 802.1Q tags is %i\r", MAX_MOPS_DOT1Q_TAGS);
1202 cli_print(cli, "Maximum number of MPLS tags is %i\r", MAX_MOPS_MPLS_TAGS);
1203 cli_print(cli, "Maximum length of packet names is %i characters\r", MAX_MOPS_PACKET_NAME_LEN);
1204 cli_print(cli, "Maximum length of packet descriptions is %i characters\r", MAX_MOPS_DESCRIPTION_LEN);
1205 cli_print(cli, "Bytes per line for formatted frame output %i\r", MAX_CLI_LINE_BYTES);
1206 cli_print(cli, "Maximum LLDP optional section length is %i bytes\r", MAX_LLDP_OPT_TLVS);
1207 if (AUTOMOPS_ENABLED) {
1208 cli_print(cli, "Auto-MOPS subsystem is enabled\r");
1209 cli_print(cli, " Maximum nesting depth is %i\r", XN_MAX_STACK);
1210 cli_print(cli, " Maximum file size for protocol definitions is %i\r", AUTOMOPS_MAX_FILE_SIZE);
1211 cli_print(cli, " Maximum names length is %i\r", AUTOMOPS_MAX_NAME_LEN);
1212 cli_print(cli, " Maximum short description length is %i\r", AUTOMOPS_MAX_SHORTDESC_LEN);
1213 cli_print(cli, " Maximum XML tag length is %i\r", XML_MAX_TAG_LEN);
1214 } else cli_print(cli, "Auto-MOPS subsystem is disabled\r");
1216 if (mops_dump_all(mp_head, tmp)) {
1217 cli_print(cli, "No mopses found.\n"); // keine Möpse gefunden ;-)
1218 } else {
1219 cli_print(cli, "%s\n", tmp);
1222 return CLI_OK;
1228 int cmd_reset_interface (struct cli_def *cli, const char *command, char *argv[], int argc)
1230 int i;
1232 if (strncmp(argv[argc-1], "?", 2)==0) {
1233 cli_print(cli, "<ENTER> Check MOPS version and details\n");
1234 return CLI_OK;
1237 if (argc>0) {
1238 cli_print(cli, "Unknown parameter\n");
1239 return CLI_OK;
1242 lookupdev();
1244 for (i=0; i<device_list_entries; i++) {
1245 get_dev_params(device_list[i].dev);
1246 // refresh ARP table i. e. MAC addresses of default GWs
1247 service_arp(device_list[i].dev, device_list[i].ip_gw, device_list[i].mac_gw);
1250 return CLI_OK;
1256 int conf_frame_limit (struct cli_def *cli, const char *command, char *argv[], int argc)
1258 unsigned int tmp;
1260 if (strncmp(argv[argc-1], "?", 2)==0)
1262 cli_print(cli, "Configure global frame size limits:\n");
1263 cli_print(cli, " <min-frame-size> [max-frame-size]\n");
1264 return CLI_OK;
1267 if (argc>2)
1269 cli_print(cli, "Two arguments allowed: <min-frame-size> [max-frame-size]\n");
1270 return CLI_OK;
1273 tmp = (unsigned int) str2int (argv[0]);
1274 if (tmp < MIN_MOPS_FRAME_SIZE)
1276 cli_print(cli, "This Mausezahn requires that the minimum frame size is at least %i bytes\n", MIN_MOPS_FRAME_SIZE);
1277 return CLI_OK;
1280 if (tmp>(max_frame_s-2))
1282 cli_print(cli, "The minimum frame size must be below %i bytes\n", max_frame_s-1);
1283 return CLI_OK;
1286 min_frame_s = tmp;
1288 if (argc==2)
1290 tmp = (unsigned int) str2int (argv[1]);
1292 if (tmp > MAX_MOPS_FRAME_SIZE-MOPS_SIZE_MARGIN)
1294 cli_print(cli, "This Mausezahn requires that the maximum frame size is not greater than %i bytes\n",
1295 MAX_MOPS_FRAME_SIZE-MOPS_SIZE_MARGIN);
1296 return CLI_OK;
1299 if (tmp<(min_frame_s+2))
1301 cli_print(cli, "The maximum frame size must be greater than %i bytes\n", min_frame_s+1);
1302 return CLI_OK;
1305 max_frame_s = tmp;
1308 return CLI_OK;
1314 int cmd_load (struct cli_def *cli, const char *command, char *argv[], int argc)
1316 int i;
1317 FILE *fp;
1319 if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) ) {
1320 cli_print(cli, "Load commands from one or more specified file(s)\r");
1321 cli_print(cli, "\n");
1322 return CLI_OK;
1325 if (!argc){
1326 cli_print(cli, "Specify one or more configuration files\n");
1327 return CLI_OK;
1330 for (i=0; i<argc; i++) {
1331 fp = fopen(argv[i], "r");
1332 if (fp==NULL) {
1333 cli_print(cli, "Warning: Cannot read %s\n", argv[i]);
1334 continue;
1336 cli_print(cli, "Read commands from %s...\n", argv[i]);
1337 cli_file (cli, fp, PRIVILEGE_PRIVILEGED, MODE_EXEC);
1338 if (fclose(fp) == EOF)
1340 cli_print(cli, "Warning: problems closing %s (errno=%i)\n", argv[i],errno);
1344 return CLI_OK;
1348 int show_arp (struct cli_def *cli, const char *command, char *argv[], int argc)
1350 int i;
1351 struct arp_table_struct *cur;
1352 char s[128], ip[20], uc[16], bc[16], ch[16];
1353 struct mz_timestamp now, prev, result;
1357 if (strcmp(argv[argc-1],"?")==0) {
1358 cli_print(cli, "<CR> shows the advanced Mausezahn ARP table\n");
1359 return CLI_OK;
1362 if (argc>0) {
1363 cli_print(cli, "Unknown parameter\n");
1364 return CLI_OK;
1368 cli_print(cli, "Intf Index IP address MAC address last Ch UCast BCast Info\r");
1369 cli_print(cli, "----------------------------------------------------------------------------------\r");
1370 // ------------------------------------------------------------------------------
1371 // wlan0 [1] DL 192.168.0.1 at 00:09:5b:9a:15:84 3'42'' 1
1373 for (i=0; i<device_list_entries; i++) {
1374 cur=device_list[i].arp_table;
1375 while(cur!=NULL) {
1376 sprintf(ip,"%i.%i.%i.%i",cur->sip[0],cur->sip[1],cur->sip[2],cur->sip[3]);
1377 if (cur->changed>99999) mz_strncpy(ch,"ALERT",6); else sprintf(ch,"%lu", cur->changed);
1378 if (cur->uni_resp>99999) mz_strncpy(uc,"ALERT",6); else sprintf(uc,"%lu", cur->uni_resp);
1379 if (cur->bc_resp>99999) mz_strncpy(bc,"ALERT",6); else sprintf(bc,"%lu", cur->bc_resp);
1380 sprintf(s, "%-7s [%i] %s%s %15s %02x:%02x:%02x:%02x:%02x:%02x %8s %5s %5s %5s %04x",
1381 device_list[i].dev,
1382 cur->index,
1383 (cur->dynamic) ? "D" : "U",
1384 (cur->locked) ? "L" : "",
1386 cur->smac[0],
1387 cur->smac[1],
1388 cur->smac[2],
1389 cur->smac[3],
1390 cur->smac[4],
1391 cur->smac[5],
1392 cur->when,
1396 cur->flags);
1397 cli_print(cli, "%s\r", s);
1398 if (cur->changed>1) {
1399 now.sec = cur->sec;
1400 now.nsec = cur->nsec;
1401 prev.sec = cur->sec_prev;
1402 prev.nsec= cur->nsec_prev;
1403 printf("sec=%u nsec=%u sec=%u nsec=%u\n", cur->sec, cur->nsec, cur->sec_prev, cur->nsec_prev);
1404 timestamp_subtract(&now, &prev, &result);
1405 sprintf(s," previous MAC was: %02x:%02x:%02x:%02x:%02x:%02x time delta: %u sec %u msec",
1406 cur->smac_prev[0],
1407 cur->smac_prev[1],
1408 cur->smac_prev[2],
1409 cur->smac_prev[3],
1410 cur->smac_prev[4],
1411 cur->smac_prev[5],
1412 (unsigned int) result.sec, (unsigned int) result.nsec/1000000);
1413 cli_print(cli, " %s\r", s);
1415 cur=cur->next;
1419 return CLI_OK;
1423 // general 'end' command to return to global config mode
1424 int cmd_end_to_config(struct cli_def *cli, const char *command, char *argv[], int argc)
1426 cli_set_configmode(cli, MODE_CONFIG, NULL);
1427 return CLI_OK;