summaryrefslogtreecommitdiff
path: root/staging/cli_sequence.c
blob: 0a55251efe4ee9ded74184dc176e1cbb43aac703 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/*
 * Mausezahn - A fast versatile traffic generator
 * Copyright (C) 2010 Herbert Haas
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 as published by the 
 * Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with 
 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
 * 
*/


#include "mz.h"
#include "cli.h"
#include "mops.h"
#include "llist.h"

// PURPOSE: Enter sequence configuration mode 
// either a) create new or b) edit old or c) delete old sequence
// 
// # sequence MY_SEQUENCE
// # sequence OLD_SEQUENCE delete
// 
int conf_sequence (struct cli_def *cli, const char *command, char *argv[], int argc)
{
	struct mz_ll *cur;
	char str[512];
	int ret=0;
	
	if ( (strcmp(argv[argc-1],"?")==0) || (argc<1) || (argc>2)) {

		cli_print(cli, "Configure a sequence of packets.\n");
		cli_print(cli, "ARGUMENTS: <sequence_name> [delete]\n");
		
		cli_print(cli, "Current list of packet sequences:\n");
		while (mops_dump_sequence(str)) cli_print(cli, "%s\r", str);
		return CLI_OK;
	}

	switch (argc) {
	 case 1:
		cur = mz_ll_search_name (packet_sequences, argv[0]);
		if (cur==NULL) { // create NEW sequence
			cli_print(cli, "Sequence does not exist; creating new sequence named '%s'\n", argv[0]);
			cur = mops_create_sequence(argv[0]);
			if (cur==NULL) {
				cli_print(cli, "ERROR: Cannot allocate another sequence!\n");
				return CLI_OK;
			}
		} // else ENTER EXISTING (cur already points to it)
		cli_seq = cur;
		cli_set_configmode(cli, MZ_MODE_SEQUENCE, "config-seq");
		break;
		
	 case 2: // otherwise DELETE?
		if (mz_strcmp(argv[1], "delete", 3)==0) {
			ret = mops_delete_sequence(argv[0]);
			switch (ret) {
			 case 1:
				cli_print(cli, "Sequence '%s' does not exist\n", argv[0]);
				break;
			 case 2: 
				cli_print(cli, "Sequence '%s' is currently active! Cannot delete it.\n", argv[0]);
				break;
			 default:
				cli_print(cli, "Sequence '%s' deleted.\n", argv[0]);
			}
		}
		break;
	 default:
		// nothing
		break;
	}
	return CLI_OK;
}


// add packet to current sequence
int sequence_add (struct cli_def *cli, const char *command, char *argv[], int argc)
{
	struct mops *mp;
	int ret=0;
	
	if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1) ) {

		cli_print(cli, "Add a packet to the current sequence.\n");
		cli_print(cli, "ARGUMENT: <packet name> OR <packet-identifier>\n");
		return CLI_OK;
	}

	// first assume argument is a name
	mp = mops_search_name (mp_head, argv[0]); 
	if (mp==NULL) { // but packet name does not exist
		if (mz_strisnum(argv[0])!=0) // arg is really a number?
			mp = mops_search_id (mp_head, (int) str2int(argv[0]));
		if (mp==NULL) { // also packet ID not found
			cli_print(cli, "Packet does not exist!\n");
			return CLI_OK;
		}
	}
	
	// packet found, so add to current sequence
	ret = mops_add_packet_to_sequence (cli_seq, mp);
	if (ret==1) cli_print(cli, "Cannot add packet (unknown error, maybe report this)!\n");
	if (ret==-1) cli_print(cli, "Cannot add packet: sequence already full!\n");
	if (ret==-2) cli_print(cli, "Cannot add packet with infinite count!\n");
	return CLI_OK;
}


// add a delay
int sequence_delay (struct cli_def *cli, const char *command, char *argv[], int argc)
{
	int ret=0, ret2=0;
	struct timespec t;
	char str[128];
	
	if ( (strcmp(argv[argc-1],"?")==0) || (argc<1) || (argc>2)) {
		cli_print(cli, "Add a delay to the current sequence.\n");
		cli_print(cli, "ARGUMENTS:  <delay> [hour | min | sec | msec | usec | nsec]\n");
		cli_print(cli, "The default unit is milliseconds (i. e. when no unit is given).\n");
		return CLI_OK;
	}
	
	switch (argc) {
	 case 1:  // only one argument, but may contain an unit (such as '314sec')
		ret = delay_parse(&t, argv[0], NULL);
		break;
		
	 case 2: // user specified two arguments such as '100 msec'
		ret = delay_parse(&t, argv[0], argv[1]);
		break;
	 default:
		cli_print(cli, "Too many arguments! Expected delay value and unit, such as '10 msec'\n");
		return CLI_OK;
	}
	
	switch (ret) {
	 case 1:
		cli_print(cli, "Invalid unit! Use one of {nsec, usec, msec, sec, min, hours}\n");
		return CLI_OK;
		break;
	 case 2:
		cli_print(cli, "Value too large! Supported range is from 0 to 999999999\n");
		return CLI_OK;
		break;
	}
	

	ret2 = mops_add_delay_to_sequence (cli_seq, &t);
	if (ret2==-1) { 
		cli_print(cli, "You must add a packet first.\n");
		return CLI_OK;
	}
	if (ret2==-2) { 
		cli_print(cli, "Cannot add delay (array full).\n");
		return CLI_OK;
	}
	
	sprintf(str, "Delay set to %lu sec and %lu nsec", 
		((struct pseq*) cli_seq->data)->gap[ret2].tv_sec,
		((struct pseq*) cli_seq->data)->gap[ret2].tv_nsec);
	cli_print(cli, "%s\n", str);
	
	return CLI_OK;
}


// remove one packet
int sequence_remove (struct cli_def *cli, const char *command, char *argv[], int argc)
{
	int ret=0;
	int i=0;
	
	if ( (strcmp(argv[argc-1],"?")==0) || (argc!=1)) {
		cli_print(cli, "Remove a packet (and any associated pause configuration) from the current sequence.\n");
		cli_print(cli, "ARGUMENT: <sequence-list-index> | last | all\n");
		cli_print(cli, "FYI: Use the 'show' command to see the current packet list with indexes.\n");
		return CLI_OK;
	}

	if (mz_strcmp(argv[0], "last", 1)==0) {
		 ret = mops_delete_packet_from_pseq (cli_seq, -1);
	} else if (mz_strcmp(argv[0], "all", 1)==0) {
		ret = mops_delete_all_packets_from_pseq (cli_seq);
		i=1;
	} else { // index number given
		if (mz_strisnum(argv[0])==0) {
			cli_print(cli, "Invalid parameter. Please specify a packet index number or 'last'\n");
			return CLI_OK;
		}
		ret = mops_delete_packet_from_pseq (cli_seq, (int) str2int(argv[0]));
	}
	switch (ret) {
	 case 0: 
		if (i) cli_print(cli, "Removed all entries.\n");
		else cli_print(cli, "Removed one entry.\n");
		break;
	 case 1:
		cli_print(cli, "List empty or invalid packet index.\n");
		break;
	 case 2:
		cli_print(cli, "Packet index too large.\n");
		break;

	}
	return CLI_OK;
}


// show packet list of that sequence
int sequence_show (struct cli_def *cli, const char *command, char *argv[], int argc)
{
	char str[512], name[32], layers[16], proto[16];
	struct pseq *seq;
	int i;
	
	if  (strcmp(argv[argc-1],"?")==0)  {
		cli_print(cli, "Shows all packets of the current sequence.\n");
		return CLI_OK;
	}

	if (argc>0) {
		cli_print(cli, "This command has currently no arguments!\n");
		return CLI_OK;
	}
	
	seq = (struct pseq*) cli_seq->data;
	
	if (seq->count==0) {
		cli_print(cli, "Current sequence '%s' has no entries.\n", cli_seq->name);
	}
	else { // show all packets in this sequence
		cli_print(cli, "%i sequence(s) defined.\r", packet_sequences->refcount-1);                 // total info
		snprintf(str,512, "Current sequence '%s' has %i entries:", cli_seq->name, seq->count);    // num entries here
		cli_print(cli, "%s\n", str);
		cli_print(cli, "Nr  PId  PktName          Layers  Protocol  Device");
		for (i=0; i<seq->count; i++) { 
			strncpy (name, seq->packet[i]->packet_name, 13); // only show first 13 chars
			if (strnlen(seq->packet[i]->packet_name, MAX_MOPS_PACKET_NAME_LEN)>13) {
				name[13]=0x00;        
				strcat(name, "...");
			}
			mops_get_proto_info(seq->packet[i], layers, proto);
			snprintf(str,512, "%2i %4i  %-16s %s  %-8s  %-6s", i+1, seq->packet[i]->id, name, layers, proto, seq->packet[i]->device);
			cli_print(cli, "%s\r", str);
			if ((seq->gap[i].tv_sec !=0) || (seq->gap[i].tv_nsec !=0)) { // gap also defined?
				timespec2str(&seq->gap[i], str);
				cli_print(cli, "  \\___ %s pause ___/\r", str);
			}
		}
	}
	return CLI_OK;
}