Browse Source

Skeleton version: contains device driver (connecting to network via

hijack daemon) and a functional but very ugly and very primitive
wrapper around uIP.

This passes proof-of-concept testing; it successfully initiates a TCP
connection and responds to pings.
tags/v0.9.3
Michael Brown 19 years ago
parent
commit
c32e83ad8d
1 changed files with 338 additions and 0 deletions
  1. 338
    0
      src/util/prototester.c

+ 338
- 0
src/util/prototester.c View File

@@ -0,0 +1,338 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include <unistd.h>
4
+#include <string.h>
5
+#include <errno.h>
6
+#include <time.h>
7
+#include <sys/socket.h>
8
+#include <sys/un.h>
9
+#include <net/if.h>
10
+#include <net/ethernet.h>
11
+#include <netinet/in.h>
12
+#include <getopt.h>
13
+
14
+typedef int irq_action_t;
15
+
16
+struct nic {
17
+	struct nic_operations	*nic_op;
18
+	unsigned char		*node_addr;
19
+	unsigned char		*packet;
20
+	unsigned int		packetlen;
21
+	void			*priv_data;	/* driver private data */
22
+};
23
+
24
+struct nic_operations {
25
+	int ( *connect ) ( struct nic * );
26
+	int ( *poll ) ( struct nic *, int retrieve );
27
+	void ( *transmit ) ( struct nic *, const char *,
28
+			     unsigned int, unsigned int, const char * );
29
+	void ( *irq ) ( struct nic *, irq_action_t );
30
+};
31
+
32
+/*****************************************************************************
33
+ *
34
+ * Hijack device interface
35
+ *
36
+ * This requires a hijack daemon to be running
37
+ *
38
+ */
39
+
40
+struct hijack {
41
+	int fd;
42
+};
43
+
44
+struct hijack_device {
45
+	char *name;
46
+};
47
+
48
+static int hijack_poll ( struct nic *nic, int retrieve ) {
49
+	struct hijack *hijack = nic->priv_data;
50
+	fd_set fdset;
51
+	struct timeval tv;
52
+	int ready;
53
+	ssize_t len;
54
+
55
+	/* Poll for data */
56
+	FD_ZERO ( &fdset );
57
+	FD_SET ( hijack->fd, &fdset );
58
+	tv.tv_sec = 0;
59
+	tv.tv_usec = 500; /* 500us to avoid hogging CPU */
60
+	ready = select ( ( hijack->fd + 1 ), &fdset, NULL, NULL, &tv );
61
+	if ( ready < 0 ) {
62
+		fprintf ( stderr, "select() failed: %s\n",
63
+			  strerror ( errno ) );
64
+		return 0;
65
+	}
66
+	if ( ready == 0 )
67
+		return 0;
68
+
69
+	/* Return if we're not retrieving data yet */
70
+	if ( ! retrieve )
71
+		return 1;
72
+
73
+	/* Fetch data */
74
+	len = read ( hijack->fd, nic->packet, ETH_FRAME_LEN );
75
+	if ( len < 0 ) {
76
+		fprintf ( stderr, "read() failed: %s\n",
77
+			  strerror ( errno ) );
78
+		return 0;
79
+	}
80
+	nic->packetlen = len;
81
+
82
+	return 1;
83
+}
84
+
85
+static void hijack_transmit ( struct nic *nic, const char *dest,
86
+			      unsigned int type, unsigned int size,
87
+			      const char *packet ) {
88
+	struct hijack *hijack = nic->priv_data;
89
+	unsigned int nstype = htons ( type );
90
+	unsigned int total_size = ETH_HLEN + size;
91
+	char txbuf[ total_size ];
92
+
93
+	/* Build packet header */
94
+	memcpy ( txbuf, dest, ETH_ALEN );
95
+	memcpy ( txbuf + ETH_ALEN, nic->node_addr, ETH_ALEN );
96
+	memcpy ( txbuf + 2 * ETH_ALEN, &nstype, 2 );
97
+	memcpy ( txbuf + ETH_HLEN, packet, size );
98
+
99
+	/* Transmit data */
100
+	if ( write ( hijack->fd, txbuf, total_size ) != total_size ) {
101
+		fprintf ( stderr, "write() failed: %s\n",
102
+			  strerror ( errno ) );
103
+	}
104
+}
105
+
106
+static int hijack_connect ( struct nic *nic ) {
107
+	return 1;
108
+}
109
+
110
+static void hijack_irq ( struct nic *nic, irq_action_t action ) {
111
+	/* Do nothing */
112
+}
113
+
114
+static struct nic_operations hijack_operations = {
115
+	.connect	= hijack_connect,
116
+	.transmit	= hijack_transmit,
117
+	.poll		= hijack_poll,
118
+	.irq		= hijack_irq,
119
+};
120
+
121
+static int hijack_probe ( struct nic *nic, struct hijack_device *hijack_dev ) {
122
+	static struct hijack hijack;
123
+	struct sockaddr_un sun;
124
+	int i;
125
+
126
+	memset ( &hijack, 0, sizeof ( hijack ) );
127
+
128
+	/* Create socket */
129
+	hijack.fd = socket ( PF_UNIX, SOCK_SEQPACKET, 0 );
130
+	if ( hijack.fd < 0 ) {
131
+		fprintf ( stderr, "socket() failed: %s\n",
132
+			  strerror ( errno ) );
133
+		goto err;
134
+	}
135
+
136
+	/* Connect to hijack daemon */
137
+	sun.sun_family = AF_UNIX;
138
+	snprintf ( sun.sun_path, sizeof ( sun.sun_path ), "/var/run/hijack-%s",
139
+		   hijack_dev->name );
140
+	if ( connect ( hijack.fd, ( struct sockaddr * ) &sun,
141
+		       sizeof ( sun ) ) < 0 ) {
142
+		fprintf ( stderr, "could not connect to %s: %s\n",
143
+			  sun.sun_path, strerror ( errno ) );
144
+		goto err;
145
+	}
146
+
147
+	/* Generate MAC address */
148
+	srand ( time ( NULL ) );
149
+	for ( i = 0 ; i < ETH_ALEN ; i++ ) {
150
+		nic->node_addr[i] = ( rand() & 0xff );
151
+	}
152
+	nic->node_addr[0] &= 0xfe; /* clear multicast bit */
153
+	nic->node_addr[0] |= 0x02; /* set "locally-assigned" bit */
154
+
155
+	nic->priv_data = &hijack;
156
+	nic->nic_op = &hijack_operations;
157
+	return 1;
158
+
159
+ err:
160
+	if ( hijack.fd >= 0 )
161
+		close ( hijack.fd );
162
+	return 0;
163
+}
164
+
165
+static void hijack_disable ( struct nic *nic,
166
+			     struct hijack_device *hijack_dev ) {
167
+	struct hijack *hijack = nic->priv_data;
168
+	
169
+	close ( hijack->fd );
170
+}
171
+
172
+/*****************************************************************************
173
+ *
174
+ * Parse command-line options
175
+ *
176
+ */
177
+
178
+struct tester_options {
179
+	char interface[IF_NAMESIZE];
180
+};
181
+
182
+static void usage ( char **argv ) {
183
+	fprintf ( stderr,
184
+		  "Usage: %s [options]\n"
185
+		  "\n"
186
+		  "Options:\n"
187
+		  "  -h|--help              Print this help message\n"
188
+		  "  -i|--interface intf    Use specified network interface\n",
189
+		  argv[0] );
190
+}
191
+
192
+static int parse_options ( int argc, char **argv,
193
+			   struct tester_options *options ) {
194
+	static struct option long_options[] = {
195
+		{ "interface", 1, NULL, 'i' },
196
+		{ "help", 0, NULL, 'h' },
197
+		{ },
198
+	};
199
+	int c;
200
+
201
+	/* Set default options */
202
+	memset ( options, 0, sizeof ( *options ) );
203
+	strncpy ( options->interface, "eth0", sizeof ( options->interface ) );
204
+
205
+	/* Parse command-line options */
206
+	while ( 1 ) {
207
+		int option_index = 0;
208
+		
209
+		c = getopt_long ( argc, argv, "i:h", long_options,
210
+				  &option_index );
211
+		if ( c < 0 )
212
+			break;
213
+
214
+		switch ( c ) {
215
+		case 'i':
216
+			strncpy ( options->interface, optarg,
217
+				  sizeof ( options->interface ) );
218
+			break;
219
+		case 'h':
220
+			usage( argv );
221
+			return -1;
222
+		case '?':
223
+			/* Unrecognised option */
224
+			return -1;
225
+		default:
226
+			fprintf ( stderr, "Unrecognised option '-%c'\n", c );
227
+			return -1;
228
+		}
229
+	}
230
+
231
+	/* Check there's nothing left over on the command line */
232
+	if ( optind != argc ) {
233
+		usage ( argv );
234
+		return -1;
235
+	}
236
+
237
+	return 0;
238
+}
239
+
240
+/*****************************************************************************
241
+ *
242
+ * uIP wrapper layer
243
+ *
244
+ */
245
+
246
+#include "../proto/uip/uip.h"
247
+#include "../proto/uip/uip_arp.h"
248
+
249
+static int done;
250
+
251
+void UIP_APPCALL ( void ) {
252
+	printf ( "appcall\n" );
253
+}
254
+
255
+void udp_appcall ( void ) {
256
+}
257
+
258
+static void uip_transmit ( struct nic *nic ) {
259
+	uip_arp_out();
260
+	nic->nic_op->transmit ( nic, ( char * ) uip_buf,
261
+				ntohs ( *( ( uint16_t * ) ( uip_buf + 12 ) ) ),
262
+				uip_len - ETH_HLEN,
263
+				( char * ) uip_buf + ETH_HLEN );
264
+	uip_len = 0;
265
+}
266
+
267
+static void run_stack ( struct nic *nic ) {
268
+	struct uip_eth_addr hwaddr;
269
+	u16_t ipaddr[2];
270
+	uint16_t type;
271
+	int i;
272
+
273
+	uip_init();
274
+	uip_arp_init();
275
+	memcpy ( &hwaddr, nic->node_addr, sizeof ( hwaddr ) );
276
+	uip_setethaddr ( hwaddr );
277
+
278
+	uip_ipaddr(ipaddr, 192,168,0,1);
279
+	uip_connect(ipaddr, HTONS(80));
280
+
281
+	done = 0;
282
+	while ( ! done ) {
283
+		if ( nic->nic_op->poll ( nic, 1 ) ) {
284
+			/* We have data */
285
+			memcpy ( uip_buf, nic->packet, nic->packetlen );
286
+			uip_len = nic->packetlen;
287
+			type = ntohs ( *( ( uint16_t * ) ( uip_buf + 12 ) ) );
288
+			if ( type == ETHERTYPE_ARP ) {
289
+				uip_arp_arpin();
290
+			} else {
291
+				uip_arp_ipin();
292
+				uip_input();
293
+			}
294
+			if ( uip_len > 0 )
295
+				uip_transmit ( nic );
296
+		} else {
297
+			for ( i = 0 ; i < UIP_CONNS ; i++ ) {
298
+				uip_periodic ( i );
299
+				if ( uip_len > 0 )
300
+					uip_transmit ( nic );
301
+			}
302
+		}
303
+	}
304
+}
305
+
306
+/*****************************************************************************
307
+ *
308
+ * Main program
309
+ *
310
+ */
311
+
312
+int main ( int argc, char **argv ) {
313
+	struct tester_options options;
314
+	struct hijack_device hijack_dev;
315
+	static unsigned char node_addr[ETH_ALEN];
316
+	static unsigned char packet[ETH_FRAME_LEN];
317
+	struct nic nic = {
318
+		.node_addr = node_addr,
319
+		.packet = packet,
320
+	};
321
+
322
+	/* Parse command-line options */
323
+	if ( parse_options ( argc, argv, &options ) < 0 )
324
+		exit ( 1 );
325
+
326
+	/* Open the hijack device */
327
+	hijack_dev.name = options.interface;
328
+	if ( ! hijack_probe ( &nic, &hijack_dev ) )
329
+		exit ( 1 );
330
+
331
+	/* Run the stack to completion */
332
+	run_stack ( &nic );
333
+
334
+	/* Close the hijack device */
335
+	hijack_disable ( &nic, &hijack_dev );
336
+
337
+	return 0;
338
+}

Loading…
Cancel
Save