|  | @@ -1,751 +0,0 @@
 | 
		
	
		
			
			| 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 <getopt.h>
 | 
		
	
		
			
			| 12 |  | -#include <assert.h>
 | 
		
	
		
			
			| 13 |  | -
 | 
		
	
		
			
			| 14 |  | -#include <gpxe/ip.h>
 | 
		
	
		
			
			| 15 |  | -#include <gpxe/tcp.h>
 | 
		
	
		
			
			| 16 |  | -#include <gpxe/hello.h>
 | 
		
	
		
			
			| 17 |  | -#include <gpxe/iscsi.h>
 | 
		
	
		
			
			| 18 |  | -
 | 
		
	
		
			
			| 19 |  | -typedef int irq_action_t;
 | 
		
	
		
			
			| 20 |  | -
 | 
		
	
		
			
			| 21 |  | -struct nic {
 | 
		
	
		
			
			| 22 |  | -	struct nic_operations	*nic_op;
 | 
		
	
		
			
			| 23 |  | -	unsigned char		*node_addr;
 | 
		
	
		
			
			| 24 |  | -	unsigned char		*packet;
 | 
		
	
		
			
			| 25 |  | -	unsigned int		packetlen;
 | 
		
	
		
			
			| 26 |  | -	void			*priv_data;	/* driver private data */
 | 
		
	
		
			
			| 27 |  | -};
 | 
		
	
		
			
			| 28 |  | -
 | 
		
	
		
			
			| 29 |  | -struct nic_operations {
 | 
		
	
		
			
			| 30 |  | -	int ( *connect ) ( struct nic * );
 | 
		
	
		
			
			| 31 |  | -	int ( *poll ) ( struct nic *, int retrieve );
 | 
		
	
		
			
			| 32 |  | -	void ( *transmit ) ( struct nic *, const char *,
 | 
		
	
		
			
			| 33 |  | -			     unsigned int, unsigned int, const char * );
 | 
		
	
		
			
			| 34 |  | -	void ( *irq ) ( struct nic *, irq_action_t );
 | 
		
	
		
			
			| 35 |  | -};
 | 
		
	
		
			
			| 36 |  | -
 | 
		
	
		
			
			| 37 |  | -/*****************************************************************************
 | 
		
	
		
			
			| 38 |  | - *
 | 
		
	
		
			
			| 39 |  | - * Net device layer
 | 
		
	
		
			
			| 40 |  | - *
 | 
		
	
		
			
			| 41 |  | - */
 | 
		
	
		
			
			| 42 |  | -
 | 
		
	
		
			
			| 43 |  | -#include "../proto/uip/uip_arp.h"
 | 
		
	
		
			
			| 44 |  | -
 | 
		
	
		
			
			| 45 |  | -static unsigned char node_addr[ETH_ALEN];
 | 
		
	
		
			
			| 46 |  | -static unsigned char packet[ETH_FRAME_LEN];
 | 
		
	
		
			
			| 47 |  | -struct nic static_nic = {
 | 
		
	
		
			
			| 48 |  | -	.node_addr = node_addr,
 | 
		
	
		
			
			| 49 |  | -	.packet = packet,
 | 
		
	
		
			
			| 50 |  | -};
 | 
		
	
		
			
			| 51 |  | -
 | 
		
	
		
			
			| 52 |  | -/* Must be a macro because priv_data[] is of variable size */
 | 
		
	
		
			
			| 53 |  | -#define alloc_netdevice( priv_size ) ( {	\
 | 
		
	
		
			
			| 54 |  | -	static char priv_data[priv_size];	\
 | 
		
	
		
			
			| 55 |  | -	static_nic.priv_data = priv_data;	\
 | 
		
	
		
			
			| 56 |  | -	&static_nic; } )
 | 
		
	
		
			
			| 57 |  | -
 | 
		
	
		
			
			| 58 |  | -static int register_netdevice ( struct nic *nic ) {
 | 
		
	
		
			
			| 59 |  | -	struct uip_eth_addr hwaddr;
 | 
		
	
		
			
			| 60 |  | -
 | 
		
	
		
			
			| 61 |  | -	memcpy ( &hwaddr, nic->node_addr, sizeof ( hwaddr ) );
 | 
		
	
		
			
			| 62 |  | -	uip_setethaddr ( hwaddr );
 | 
		
	
		
			
			| 63 |  | -	return 0;
 | 
		
	
		
			
			| 64 |  | -}
 | 
		
	
		
			
			| 65 |  | -
 | 
		
	
		
			
			| 66 |  | -static inline void unregister_netdevice ( struct nic *nic ) {
 | 
		
	
		
			
			| 67 |  | -	/* Do nothing */
 | 
		
	
		
			
			| 68 |  | -}
 | 
		
	
		
			
			| 69 |  | -
 | 
		
	
		
			
			| 70 |  | -static inline void free_netdevice ( struct nic *nic ) {
 | 
		
	
		
			
			| 71 |  | -	/* Do nothing */
 | 
		
	
		
			
			| 72 |  | -}
 | 
		
	
		
			
			| 73 |  | -
 | 
		
	
		
			
			| 74 |  | -int netdev_poll ( int retrieve, void **data, size_t *len ) {
 | 
		
	
		
			
			| 75 |  | -	int rc = static_nic.nic_op->poll ( &static_nic, retrieve );
 | 
		
	
		
			
			| 76 |  | -	*data = static_nic.packet;
 | 
		
	
		
			
			| 77 |  | -	*len = static_nic.packetlen;
 | 
		
	
		
			
			| 78 |  | -	return rc;
 | 
		
	
		
			
			| 79 |  | -}
 | 
		
	
		
			
			| 80 |  | -
 | 
		
	
		
			
			| 81 |  | -void netdev_transmit ( const void *data, size_t len ) {
 | 
		
	
		
			
			| 82 |  | -	uint16_t type = ntohs ( *( ( uint16_t * ) ( data + 12 ) ) );
 | 
		
	
		
			
			| 83 |  | -	static_nic.nic_op->transmit ( &static_nic, data, type,
 | 
		
	
		
			
			| 84 |  | -				      len - ETH_HLEN,
 | 
		
	
		
			
			| 85 |  | -				      data + ETH_HLEN );
 | 
		
	
		
			
			| 86 |  | -}
 | 
		
	
		
			
			| 87 |  | -
 | 
		
	
		
			
			| 88 |  | -/*****************************************************************************
 | 
		
	
		
			
			| 89 |  | - *
 | 
		
	
		
			
			| 90 |  | - * Utility functions
 | 
		
	
		
			
			| 91 |  | - *
 | 
		
	
		
			
			| 92 |  | - */
 | 
		
	
		
			
			| 93 |  | -
 | 
		
	
		
			
			| 94 |  | -static void hex_dump ( const void *data, size_t len ) {
 | 
		
	
		
			
			| 95 |  | -	unsigned int index;
 | 
		
	
		
			
			| 96 |  | -	for ( index = 0; index < len; index++ ) {
 | 
		
	
		
			
			| 97 |  | -		if ( ( index % 16 ) == 0 ) {
 | 
		
	
		
			
			| 98 |  | -			printf ( "\n%08x :", index );
 | 
		
	
		
			
			| 99 |  | -		}
 | 
		
	
		
			
			| 100 |  | -		printf ( " %02x", * ( ( unsigned char * ) ( data + index ) ) );
 | 
		
	
		
			
			| 101 |  | -	}
 | 
		
	
		
			
			| 102 |  | -	printf ( "\n" );
 | 
		
	
		
			
			| 103 |  | -}
 | 
		
	
		
			
			| 104 |  | -
 | 
		
	
		
			
			| 105 |  | -/*****************************************************************************
 | 
		
	
		
			
			| 106 |  | - *
 | 
		
	
		
			
			| 107 |  | - * Hijack device interface
 | 
		
	
		
			
			| 108 |  | - *
 | 
		
	
		
			
			| 109 |  | - * This requires a hijack daemon to be running
 | 
		
	
		
			
			| 110 |  | - *
 | 
		
	
		
			
			| 111 |  | - */
 | 
		
	
		
			
			| 112 |  | -
 | 
		
	
		
			
			| 113 |  | -struct hijack {
 | 
		
	
		
			
			| 114 |  | -	int fd;
 | 
		
	
		
			
			| 115 |  | -};
 | 
		
	
		
			
			| 116 |  | -
 | 
		
	
		
			
			| 117 |  | -struct hijack_device {
 | 
		
	
		
			
			| 118 |  | -	char *name;
 | 
		
	
		
			
			| 119 |  | -	void *priv;
 | 
		
	
		
			
			| 120 |  | -};
 | 
		
	
		
			
			| 121 |  | -
 | 
		
	
		
			
			| 122 |  | -static inline void hijack_set_drvdata ( struct hijack_device *hijack_dev,
 | 
		
	
		
			
			| 123 |  | -					void *data ) {
 | 
		
	
		
			
			| 124 |  | -	hijack_dev->priv = data;
 | 
		
	
		
			
			| 125 |  | -}
 | 
		
	
		
			
			| 126 |  | -
 | 
		
	
		
			
			| 127 |  | -static inline void * hijack_get_drvdata ( struct hijack_device *hijack_dev ) {
 | 
		
	
		
			
			| 128 |  | -	return hijack_dev->priv;
 | 
		
	
		
			
			| 129 |  | -}
 | 
		
	
		
			
			| 130 |  | -
 | 
		
	
		
			
			| 131 |  | -static int hijack_poll ( struct nic *nic, int retrieve ) {
 | 
		
	
		
			
			| 132 |  | -	struct hijack *hijack = nic->priv_data;
 | 
		
	
		
			
			| 133 |  | -	fd_set fdset;
 | 
		
	
		
			
			| 134 |  | -	struct timeval tv;
 | 
		
	
		
			
			| 135 |  | -	int ready;
 | 
		
	
		
			
			| 136 |  | -	ssize_t len;
 | 
		
	
		
			
			| 137 |  | -
 | 
		
	
		
			
			| 138 |  | -	/* Poll for data */
 | 
		
	
		
			
			| 139 |  | -	FD_ZERO ( &fdset );
 | 
		
	
		
			
			| 140 |  | -	FD_SET ( hijack->fd, &fdset );
 | 
		
	
		
			
			| 141 |  | -	tv.tv_sec = 0;
 | 
		
	
		
			
			| 142 |  | -	tv.tv_usec = 500; /* 500us to avoid hogging CPU */
 | 
		
	
		
			
			| 143 |  | -	ready = select ( ( hijack->fd + 1 ), &fdset, NULL, NULL, &tv );
 | 
		
	
		
			
			| 144 |  | -	if ( ready < 0 ) {
 | 
		
	
		
			
			| 145 |  | -		fprintf ( stderr, "select() failed: %s\n",
 | 
		
	
		
			
			| 146 |  | -			  strerror ( errno ) );
 | 
		
	
		
			
			| 147 |  | -		return 0;
 | 
		
	
		
			
			| 148 |  | -	}
 | 
		
	
		
			
			| 149 |  | -	if ( ready == 0 )
 | 
		
	
		
			
			| 150 |  | -		return 0;
 | 
		
	
		
			
			| 151 |  | -
 | 
		
	
		
			
			| 152 |  | -	/* Return if we're not retrieving data yet */
 | 
		
	
		
			
			| 153 |  | -	if ( ! retrieve )
 | 
		
	
		
			
			| 154 |  | -		return 1;
 | 
		
	
		
			
			| 155 |  | -
 | 
		
	
		
			
			| 156 |  | -	/* Fetch data */
 | 
		
	
		
			
			| 157 |  | -	len = read ( hijack->fd, nic->packet, ETH_FRAME_LEN );
 | 
		
	
		
			
			| 158 |  | -	if ( len < 0 ) {
 | 
		
	
		
			
			| 159 |  | -		fprintf ( stderr, "read() failed: %s\n",
 | 
		
	
		
			
			| 160 |  | -			  strerror ( errno ) );
 | 
		
	
		
			
			| 161 |  | -		return 0;
 | 
		
	
		
			
			| 162 |  | -	}
 | 
		
	
		
			
			| 163 |  | -	nic->packetlen = len;
 | 
		
	
		
			
			| 164 |  | -
 | 
		
	
		
			
			| 165 |  | -	return 1;
 | 
		
	
		
			
			| 166 |  | -}
 | 
		
	
		
			
			| 167 |  | -
 | 
		
	
		
			
			| 168 |  | -static void hijack_transmit ( struct nic *nic, const char *dest,
 | 
		
	
		
			
			| 169 |  | -			      unsigned int type, unsigned int size,
 | 
		
	
		
			
			| 170 |  | -			      const char *packet ) {
 | 
		
	
		
			
			| 171 |  | -	struct hijack *hijack = nic->priv_data;
 | 
		
	
		
			
			| 172 |  | -	unsigned int nstype = htons ( type );
 | 
		
	
		
			
			| 173 |  | -	unsigned int total_size = ETH_HLEN + size;
 | 
		
	
		
			
			| 174 |  | -	char txbuf[ total_size ];
 | 
		
	
		
			
			| 175 |  | -
 | 
		
	
		
			
			| 176 |  | -	/* Build packet header */
 | 
		
	
		
			
			| 177 |  | -	memcpy ( txbuf, dest, ETH_ALEN );
 | 
		
	
		
			
			| 178 |  | -	memcpy ( txbuf + ETH_ALEN, nic->node_addr, ETH_ALEN );
 | 
		
	
		
			
			| 179 |  | -	memcpy ( txbuf + 2 * ETH_ALEN, &nstype, 2 );
 | 
		
	
		
			
			| 180 |  | -	memcpy ( txbuf + ETH_HLEN, packet, size );
 | 
		
	
		
			
			| 181 |  | -
 | 
		
	
		
			
			| 182 |  | -	/* Transmit data */
 | 
		
	
		
			
			| 183 |  | -	if ( write ( hijack->fd, txbuf, total_size ) != total_size ) {
 | 
		
	
		
			
			| 184 |  | -		fprintf ( stderr, "write() failed: %s\n",
 | 
		
	
		
			
			| 185 |  | -			  strerror ( errno ) );
 | 
		
	
		
			
			| 186 |  | -	}
 | 
		
	
		
			
			| 187 |  | -}
 | 
		
	
		
			
			| 188 |  | -
 | 
		
	
		
			
			| 189 |  | -static int hijack_connect ( struct nic *nic ) {
 | 
		
	
		
			
			| 190 |  | -	return 1;
 | 
		
	
		
			
			| 191 |  | -}
 | 
		
	
		
			
			| 192 |  | -
 | 
		
	
		
			
			| 193 |  | -static void hijack_irq ( struct nic *nic, irq_action_t action ) {
 | 
		
	
		
			
			| 194 |  | -	/* Do nothing */
 | 
		
	
		
			
			| 195 |  | -}
 | 
		
	
		
			
			| 196 |  | -
 | 
		
	
		
			
			| 197 |  | -static struct nic_operations hijack_operations = {
 | 
		
	
		
			
			| 198 |  | -	.connect	= hijack_connect,
 | 
		
	
		
			
			| 199 |  | -	.transmit	= hijack_transmit,
 | 
		
	
		
			
			| 200 |  | -	.poll		= hijack_poll,
 | 
		
	
		
			
			| 201 |  | -	.irq		= hijack_irq,
 | 
		
	
		
			
			| 202 |  | -};
 | 
		
	
		
			
			| 203 |  | -
 | 
		
	
		
			
			| 204 |  | -int hijack_probe ( struct hijack_device *hijack_dev ) {
 | 
		
	
		
			
			| 205 |  | -	struct nic *nic;
 | 
		
	
		
			
			| 206 |  | -	struct hijack *hijack;
 | 
		
	
		
			
			| 207 |  | -	struct sockaddr_un sun;
 | 
		
	
		
			
			| 208 |  | -	int i;
 | 
		
	
		
			
			| 209 |  | -
 | 
		
	
		
			
			| 210 |  | -	nic = alloc_netdevice ( sizeof ( *hijack ) );
 | 
		
	
		
			
			| 211 |  | -	if ( ! nic ) {
 | 
		
	
		
			
			| 212 |  | -		fprintf ( stderr, "alloc_netdevice() failed\n" );
 | 
		
	
		
			
			| 213 |  | -		goto err_alloc;
 | 
		
	
		
			
			| 214 |  | -	}
 | 
		
	
		
			
			| 215 |  | -	hijack = nic->priv_data;
 | 
		
	
		
			
			| 216 |  | -	memset ( hijack, 0, sizeof ( *hijack ) );
 | 
		
	
		
			
			| 217 |  | -
 | 
		
	
		
			
			| 218 |  | -	/* Create socket */
 | 
		
	
		
			
			| 219 |  | -	hijack->fd = socket ( PF_UNIX, SOCK_SEQPACKET, 0 );
 | 
		
	
		
			
			| 220 |  | -	if ( hijack->fd < 0 ) {
 | 
		
	
		
			
			| 221 |  | -		fprintf ( stderr, "socket() failed: %s\n",
 | 
		
	
		
			
			| 222 |  | -			  strerror ( errno ) );
 | 
		
	
		
			
			| 223 |  | -		goto err;
 | 
		
	
		
			
			| 224 |  | -	}
 | 
		
	
		
			
			| 225 |  | -
 | 
		
	
		
			
			| 226 |  | -	/* Connect to hijack daemon */
 | 
		
	
		
			
			| 227 |  | -	sun.sun_family = AF_UNIX;
 | 
		
	
		
			
			| 228 |  | -	snprintf ( sun.sun_path, sizeof ( sun.sun_path ), "/var/run/hijack-%s",
 | 
		
	
		
			
			| 229 |  | -		   hijack_dev->name );
 | 
		
	
		
			
			| 230 |  | -	if ( connect ( hijack->fd, ( struct sockaddr * ) &sun,
 | 
		
	
		
			
			| 231 |  | -		       sizeof ( sun ) ) < 0 ) {
 | 
		
	
		
			
			| 232 |  | -		fprintf ( stderr, "could not connect to %s: %s\n",
 | 
		
	
		
			
			| 233 |  | -			  sun.sun_path, strerror ( errno ) );
 | 
		
	
		
			
			| 234 |  | -		goto err;
 | 
		
	
		
			
			| 235 |  | -	}
 | 
		
	
		
			
			| 236 |  | -
 | 
		
	
		
			
			| 237 |  | -	/* Generate MAC address */
 | 
		
	
		
			
			| 238 |  | -	srand ( time ( NULL ) );
 | 
		
	
		
			
			| 239 |  | -	for ( i = 0 ; i < ETH_ALEN ; i++ ) {
 | 
		
	
		
			
			| 240 |  | -		nic->node_addr[i] = ( rand() & 0xff );
 | 
		
	
		
			
			| 241 |  | -	}
 | 
		
	
		
			
			| 242 |  | -	nic->node_addr[0] &= 0xfe; /* clear multicast bit */
 | 
		
	
		
			
			| 243 |  | -	nic->node_addr[0] |= 0x02; /* set "locally-assigned" bit */
 | 
		
	
		
			
			| 244 |  | -
 | 
		
	
		
			
			| 245 |  | -	nic->nic_op = &hijack_operations;
 | 
		
	
		
			
			| 246 |  | -	if ( register_netdevice ( nic ) < 0 )
 | 
		
	
		
			
			| 247 |  | -		goto err;
 | 
		
	
		
			
			| 248 |  | -
 | 
		
	
		
			
			| 249 |  | -	hijack_set_drvdata ( hijack_dev, nic );
 | 
		
	
		
			
			| 250 |  | -	return 1;
 | 
		
	
		
			
			| 251 |  | -
 | 
		
	
		
			
			| 252 |  | - err:
 | 
		
	
		
			
			| 253 |  | -	if ( hijack->fd >= 0 )
 | 
		
	
		
			
			| 254 |  | -		close ( hijack->fd );
 | 
		
	
		
			
			| 255 |  | -	free_netdevice ( nic );
 | 
		
	
		
			
			| 256 |  | - err_alloc:
 | 
		
	
		
			
			| 257 |  | -	return 0;
 | 
		
	
		
			
			| 258 |  | -}
 | 
		
	
		
			
			| 259 |  | -
 | 
		
	
		
			
			| 260 |  | -static void hijack_disable ( struct hijack_device *hijack_dev ) {
 | 
		
	
		
			
			| 261 |  | -	struct nic *nic = hijack_get_drvdata ( hijack_dev );
 | 
		
	
		
			
			| 262 |  | -	struct hijack *hijack = nic->priv_data;
 | 
		
	
		
			
			| 263 |  | -	
 | 
		
	
		
			
			| 264 |  | -	unregister_netdevice ( nic );
 | 
		
	
		
			
			| 265 |  | -	close ( hijack->fd );
 | 
		
	
		
			
			| 266 |  | -}
 | 
		
	
		
			
			| 267 |  | -
 | 
		
	
		
			
			| 268 |  | -/*****************************************************************************
 | 
		
	
		
			
			| 269 |  | - *
 | 
		
	
		
			
			| 270 |  | - * "Hello world" protocol tester
 | 
		
	
		
			
			| 271 |  | - *
 | 
		
	
		
			
			| 272 |  | - */
 | 
		
	
		
			
			| 273 |  | -
 | 
		
	
		
			
			| 274 |  | -struct hello_options {
 | 
		
	
		
			
			| 275 |  | -	struct sockaddr_in server;
 | 
		
	
		
			
			| 276 |  | -	const char *message;
 | 
		
	
		
			
			| 277 |  | -};
 | 
		
	
		
			
			| 278 |  | -
 | 
		
	
		
			
			| 279 |  | -static void hello_usage ( char **argv ) {
 | 
		
	
		
			
			| 280 |  | -	fprintf ( stderr,
 | 
		
	
		
			
			| 281 |  | -		  "Usage: %s [global options] hello [hello-specific options]\n"
 | 
		
	
		
			
			| 282 |  | -		  "\n"
 | 
		
	
		
			
			| 283 |  | -		  "hello-specific options:\n"
 | 
		
	
		
			
			| 284 |  | -		  "  -h|--help              Print this help message\n"
 | 
		
	
		
			
			| 285 |  | -		  "  -s|--server ip_addr    Server IP address\n"
 | 
		
	
		
			
			| 286 |  | -		  "  -p|--port port         Port number\n"
 | 
		
	
		
			
			| 287 |  | -		  "  -m|--message msg       Message to send\n",
 | 
		
	
		
			
			| 288 |  | -		  argv[0] );
 | 
		
	
		
			
			| 289 |  | -}
 | 
		
	
		
			
			| 290 |  | -
 | 
		
	
		
			
			| 291 |  | -static int hello_parse_options ( int argc, char **argv,
 | 
		
	
		
			
			| 292 |  | -				 struct hello_options *options ) {
 | 
		
	
		
			
			| 293 |  | -	static struct option long_options[] = {
 | 
		
	
		
			
			| 294 |  | -		{ "server", 1, NULL, 's' },
 | 
		
	
		
			
			| 295 |  | -		{ "port", 1, NULL, 'p' },
 | 
		
	
		
			
			| 296 |  | -		{ "message", 1, NULL, 'm' },
 | 
		
	
		
			
			| 297 |  | -		{ "help", 0, NULL, 'h' },
 | 
		
	
		
			
			| 298 |  | -		{ },
 | 
		
	
		
			
			| 299 |  | -	};
 | 
		
	
		
			
			| 300 |  | -	int c;
 | 
		
	
		
			
			| 301 |  | -	char *endptr;
 | 
		
	
		
			
			| 302 |  | -
 | 
		
	
		
			
			| 303 |  | -	/* Set default options */
 | 
		
	
		
			
			| 304 |  | -	memset ( options, 0, sizeof ( *options ) );
 | 
		
	
		
			
			| 305 |  | -	inet_aton ( "192.168.0.1", &options->server.sin_addr );
 | 
		
	
		
			
			| 306 |  | -	options->server.sin_port = htons ( 80 );
 | 
		
	
		
			
			| 307 |  | -	options->message = "Hello world!";
 | 
		
	
		
			
			| 308 |  | -
 | 
		
	
		
			
			| 309 |  | -	/* Parse command-line options */
 | 
		
	
		
			
			| 310 |  | -	while ( 1 ) {
 | 
		
	
		
			
			| 311 |  | -		int option_index = 0;
 | 
		
	
		
			
			| 312 |  | -		
 | 
		
	
		
			
			| 313 |  | -		c = getopt_long ( argc, argv, "s:p:m:h", long_options,
 | 
		
	
		
			
			| 314 |  | -				  &option_index );
 | 
		
	
		
			
			| 315 |  | -		if ( c < 0 )
 | 
		
	
		
			
			| 316 |  | -			break;
 | 
		
	
		
			
			| 317 |  | -
 | 
		
	
		
			
			| 318 |  | -		switch ( c ) {
 | 
		
	
		
			
			| 319 |  | -		case 's':
 | 
		
	
		
			
			| 320 |  | -			if ( inet_aton ( optarg,
 | 
		
	
		
			
			| 321 |  | -					 &options->server.sin_addr ) == 0 ) {
 | 
		
	
		
			
			| 322 |  | -				fprintf ( stderr, "Invalid IP address %s\n",
 | 
		
	
		
			
			| 323 |  | -					  optarg );
 | 
		
	
		
			
			| 324 |  | -				return -1;
 | 
		
	
		
			
			| 325 |  | -			}
 | 
		
	
		
			
			| 326 |  | -			break;
 | 
		
	
		
			
			| 327 |  | -		case 'p':
 | 
		
	
		
			
			| 328 |  | -			options->server.sin_port =
 | 
		
	
		
			
			| 329 |  | -				htons ( strtoul ( optarg, &endptr, 0 ) );
 | 
		
	
		
			
			| 330 |  | -			if ( *endptr != '\0' ) {
 | 
		
	
		
			
			| 331 |  | -				fprintf ( stderr, "Invalid port %s\n",
 | 
		
	
		
			
			| 332 |  | -					  optarg );
 | 
		
	
		
			
			| 333 |  | -				return -1;
 | 
		
	
		
			
			| 334 |  | -			}
 | 
		
	
		
			
			| 335 |  | -			break;
 | 
		
	
		
			
			| 336 |  | -		case 'm':
 | 
		
	
		
			
			| 337 |  | -			options->message = optarg;
 | 
		
	
		
			
			| 338 |  | -			break;
 | 
		
	
		
			
			| 339 |  | -		case 'h':
 | 
		
	
		
			
			| 340 |  | -			hello_usage ( argv );
 | 
		
	
		
			
			| 341 |  | -			return -1;
 | 
		
	
		
			
			| 342 |  | -		case '?':
 | 
		
	
		
			
			| 343 |  | -			/* Unrecognised option */
 | 
		
	
		
			
			| 344 |  | -			return -1;
 | 
		
	
		
			
			| 345 |  | -		default:
 | 
		
	
		
			
			| 346 |  | -			fprintf ( stderr, "Unrecognised option '-%c'\n", c );
 | 
		
	
		
			
			| 347 |  | -			return -1;
 | 
		
	
		
			
			| 348 |  | -		}
 | 
		
	
		
			
			| 349 |  | -	}
 | 
		
	
		
			
			| 350 |  | -
 | 
		
	
		
			
			| 351 |  | -	/* Check there are no remaining arguments */
 | 
		
	
		
			
			| 352 |  | -	if ( optind != argc ) {
 | 
		
	
		
			
			| 353 |  | -		hello_usage ( argv );
 | 
		
	
		
			
			| 354 |  | -		return -1;
 | 
		
	
		
			
			| 355 |  | -	}
 | 
		
	
		
			
			| 356 |  | -	
 | 
		
	
		
			
			| 357 |  | -	return optind;
 | 
		
	
		
			
			| 358 |  | -}
 | 
		
	
		
			
			| 359 |  | -
 | 
		
	
		
			
			| 360 |  | -static void test_hello_callback ( char *data, size_t len ) {
 | 
		
	
		
			
			| 361 |  | -	int i;
 | 
		
	
		
			
			| 362 |  | -	char c;
 | 
		
	
		
			
			| 363 |  | -
 | 
		
	
		
			
			| 364 |  | -	for ( i = 0 ; i < len ; i++ ) {
 | 
		
	
		
			
			| 365 |  | -		c = data[i];
 | 
		
	
		
			
			| 366 |  | -		if ( c == '\r' ) {
 | 
		
	
		
			
			| 367 |  | -			/* Print nothing */
 | 
		
	
		
			
			| 368 |  | -		} else if ( ( c == '\n' ) || ( c >= 32 ) || ( c <= 126 ) ) {
 | 
		
	
		
			
			| 369 |  | -			putchar ( c );
 | 
		
	
		
			
			| 370 |  | -		} else {
 | 
		
	
		
			
			| 371 |  | -			putchar ( '.' );
 | 
		
	
		
			
			| 372 |  | -		}
 | 
		
	
		
			
			| 373 |  | -	}	
 | 
		
	
		
			
			| 374 |  | -}
 | 
		
	
		
			
			| 375 |  | -
 | 
		
	
		
			
			| 376 |  | -static int test_hello ( int argc, char **argv ) {
 | 
		
	
		
			
			| 377 |  | -	struct hello_options options;
 | 
		
	
		
			
			| 378 |  | -	struct hello_request hello;
 | 
		
	
		
			
			| 379 |  | -
 | 
		
	
		
			
			| 380 |  | -	/* Parse hello-specific options */
 | 
		
	
		
			
			| 381 |  | -	if ( hello_parse_options ( argc, argv, &options ) < 0 )
 | 
		
	
		
			
			| 382 |  | -		return -1;
 | 
		
	
		
			
			| 383 |  | -
 | 
		
	
		
			
			| 384 |  | -	/* Construct hello request */
 | 
		
	
		
			
			| 385 |  | -	memset ( &hello, 0, sizeof ( hello ) );
 | 
		
	
		
			
			| 386 |  | -	hello.tcp.sin = options.server;
 | 
		
	
		
			
			| 387 |  | -	hello.message = options.message;
 | 
		
	
		
			
			| 388 |  | -	hello.callback = test_hello_callback;
 | 
		
	
		
			
			| 389 |  | -	fprintf ( stderr, "Saying \"%s\" to %s:%d\n", hello.message,
 | 
		
	
		
			
			| 390 |  | -		  inet_ntoa ( hello.tcp.sin.sin_addr ),
 | 
		
	
		
			
			| 391 |  | -		  ntohs ( hello.tcp.sin.sin_port ) );
 | 
		
	
		
			
			| 392 |  | -
 | 
		
	
		
			
			| 393 |  | -	/* Issue hello request and run to completion */
 | 
		
	
		
			
			| 394 |  | -	hello_connect ( &hello );
 | 
		
	
		
			
			| 395 |  | -	while ( ! hello.complete ) {
 | 
		
	
		
			
			| 396 |  | -		run_tcpip ();
 | 
		
	
		
			
			| 397 |  | -	}
 | 
		
	
		
			
			| 398 |  | -
 | 
		
	
		
			
			| 399 |  | -	return 0;
 | 
		
	
		
			
			| 400 |  | -}
 | 
		
	
		
			
			| 401 |  | -
 | 
		
	
		
			
			| 402 |  | -/*****************************************************************************
 | 
		
	
		
			
			| 403 |  | - *
 | 
		
	
		
			
			| 404 |  | - * iSCSI protocol tester
 | 
		
	
		
			
			| 405 |  | - *
 | 
		
	
		
			
			| 406 |  | - */
 | 
		
	
		
			
			| 407 |  | -
 | 
		
	
		
			
			| 408 |  | -struct iscsi_options {
 | 
		
	
		
			
			| 409 |  | -	struct sockaddr_in server;
 | 
		
	
		
			
			| 410 |  | -	const char *initiator;
 | 
		
	
		
			
			| 411 |  | -	const char *target;
 | 
		
	
		
			
			| 412 |  | -};
 | 
		
	
		
			
			| 413 |  | -
 | 
		
	
		
			
			| 414 |  | -static void iscsi_usage ( char **argv ) {
 | 
		
	
		
			
			| 415 |  | -	fprintf ( stderr,
 | 
		
	
		
			
			| 416 |  | -		  "Usage: %s [global options] iscsi [iscsi-specific options]\n"
 | 
		
	
		
			
			| 417 |  | -		  "\n"
 | 
		
	
		
			
			| 418 |  | -		  "iscsi-specific options:\n"
 | 
		
	
		
			
			| 419 |  | -		  "  -h|--help              Print this help message\n"
 | 
		
	
		
			
			| 420 |  | -		  "  -s|--server ip_addr    Server IP address\n"
 | 
		
	
		
			
			| 421 |  | -		  "  -p|--port port         Port number\n"
 | 
		
	
		
			
			| 422 |  | -		  "  -i|--initiator iqn     iSCSI initiator name\n"
 | 
		
	
		
			
			| 423 |  | -		  "  -t|--target iqn        iSCSI target name\n",
 | 
		
	
		
			
			| 424 |  | -		  argv[0] );
 | 
		
	
		
			
			| 425 |  | -}
 | 
		
	
		
			
			| 426 |  | -
 | 
		
	
		
			
			| 427 |  | -static int iscsi_parse_options ( int argc, char **argv,
 | 
		
	
		
			
			| 428 |  | -				 struct iscsi_options *options ) {
 | 
		
	
		
			
			| 429 |  | -	static struct option long_options[] = {
 | 
		
	
		
			
			| 430 |  | -		{ "server", 1, NULL, 's' },
 | 
		
	
		
			
			| 431 |  | -		{ "port", 1, NULL, 'p' },
 | 
		
	
		
			
			| 432 |  | -		{ "initiator", 1, NULL, 'i' },
 | 
		
	
		
			
			| 433 |  | -		{ "target", 1, NULL, 't' },
 | 
		
	
		
			
			| 434 |  | -		{ "help", 0, NULL, 'h' },
 | 
		
	
		
			
			| 435 |  | -		{ },
 | 
		
	
		
			
			| 436 |  | -	};
 | 
		
	
		
			
			| 437 |  | -	int c;
 | 
		
	
		
			
			| 438 |  | -	char *endptr;
 | 
		
	
		
			
			| 439 |  | -
 | 
		
	
		
			
			| 440 |  | -	/* Set default options */
 | 
		
	
		
			
			| 441 |  | -	memset ( options, 0, sizeof ( *options ) );
 | 
		
	
		
			
			| 442 |  | -	inet_aton ( "192.168.0.1", &options->server.sin_addr );
 | 
		
	
		
			
			| 443 |  | -	options->server.sin_port = htons ( 3260 );
 | 
		
	
		
			
			| 444 |  | -	options->initiator = "iqn.1900-01.localdomain.localhost:initiator";
 | 
		
	
		
			
			| 445 |  | -	options->target = "iqn.1900-01.localdomain.localhost:target";
 | 
		
	
		
			
			| 446 |  | -
 | 
		
	
		
			
			| 447 |  | -	/* Parse command-line options */
 | 
		
	
		
			
			| 448 |  | -	while ( 1 ) {
 | 
		
	
		
			
			| 449 |  | -		int option_index = 0;
 | 
		
	
		
			
			| 450 |  | -		
 | 
		
	
		
			
			| 451 |  | -		c = getopt_long ( argc, argv, "s:p:i:t:h", long_options,
 | 
		
	
		
			
			| 452 |  | -				  &option_index );
 | 
		
	
		
			
			| 453 |  | -		if ( c < 0 )
 | 
		
	
		
			
			| 454 |  | -			break;
 | 
		
	
		
			
			| 455 |  | -
 | 
		
	
		
			
			| 456 |  | -		switch ( c ) {
 | 
		
	
		
			
			| 457 |  | -		case 's':
 | 
		
	
		
			
			| 458 |  | -			if ( inet_aton ( optarg,
 | 
		
	
		
			
			| 459 |  | -					 &options->server.sin_addr ) == 0 ) {
 | 
		
	
		
			
			| 460 |  | -				fprintf ( stderr, "Invalid IP address %s\n",
 | 
		
	
		
			
			| 461 |  | -					  optarg );
 | 
		
	
		
			
			| 462 |  | -				return -1;
 | 
		
	
		
			
			| 463 |  | -			}
 | 
		
	
		
			
			| 464 |  | -			break;
 | 
		
	
		
			
			| 465 |  | -		case 'p':
 | 
		
	
		
			
			| 466 |  | -			options->server.sin_port =
 | 
		
	
		
			
			| 467 |  | -				htons ( strtoul ( optarg, &endptr, 0 ) );
 | 
		
	
		
			
			| 468 |  | -			if ( *endptr != '\0' ) {
 | 
		
	
		
			
			| 469 |  | -				fprintf ( stderr, "Invalid port %s\n",
 | 
		
	
		
			
			| 470 |  | -					  optarg );
 | 
		
	
		
			
			| 471 |  | -				return -1;
 | 
		
	
		
			
			| 472 |  | -			}
 | 
		
	
		
			
			| 473 |  | -			break;
 | 
		
	
		
			
			| 474 |  | -		case 'i':
 | 
		
	
		
			
			| 475 |  | -			options->initiator = optarg;
 | 
		
	
		
			
			| 476 |  | -			break;
 | 
		
	
		
			
			| 477 |  | -		case 't':
 | 
		
	
		
			
			| 478 |  | -			options->target = optarg;
 | 
		
	
		
			
			| 479 |  | -			break;
 | 
		
	
		
			
			| 480 |  | -		case 'h':
 | 
		
	
		
			
			| 481 |  | -			iscsi_usage ( argv );
 | 
		
	
		
			
			| 482 |  | -			return -1;
 | 
		
	
		
			
			| 483 |  | -		case '?':
 | 
		
	
		
			
			| 484 |  | -			/* Unrecognised option */
 | 
		
	
		
			
			| 485 |  | -			return -1;
 | 
		
	
		
			
			| 486 |  | -		default:
 | 
		
	
		
			
			| 487 |  | -			fprintf ( stderr, "Unrecognised option '-%c'\n", c );
 | 
		
	
		
			
			| 488 |  | -			return -1;
 | 
		
	
		
			
			| 489 |  | -		}
 | 
		
	
		
			
			| 490 |  | -	}
 | 
		
	
		
			
			| 491 |  | -
 | 
		
	
		
			
			| 492 |  | -	/* Check there are no remaining arguments */
 | 
		
	
		
			
			| 493 |  | -	if ( optind != argc ) {
 | 
		
	
		
			
			| 494 |  | -		iscsi_usage ( argv );
 | 
		
	
		
			
			| 495 |  | -		return -1;
 | 
		
	
		
			
			| 496 |  | -	}
 | 
		
	
		
			
			| 497 |  | -	
 | 
		
	
		
			
			| 498 |  | -	return optind;
 | 
		
	
		
			
			| 499 |  | -}
 | 
		
	
		
			
			| 500 |  | -
 | 
		
	
		
			
			| 501 |  | -struct test_iscsi_buffer {
 | 
		
	
		
			
			| 502 |  | -	unsigned char data[512];
 | 
		
	
		
			
			| 503 |  | -};
 | 
		
	
		
			
			| 504 |  | -
 | 
		
	
		
			
			| 505 |  | -static void test_iscsi_callback ( void *private, const void *data,
 | 
		
	
		
			
			| 506 |  | -				  unsigned long offset, size_t len ) {
 | 
		
	
		
			
			| 507 |  | -	struct test_iscsi_buffer *buffer = private;
 | 
		
	
		
			
			| 508 |  | -
 | 
		
	
		
			
			| 509 |  | -	assert ( ( offset + len ) <= sizeof ( buffer->data ) );
 | 
		
	
		
			
			| 510 |  | -	memcpy ( buffer->data + offset, data, len );
 | 
		
	
		
			
			| 511 |  | -}
 | 
		
	
		
			
			| 512 |  | -
 | 
		
	
		
			
			| 513 |  | -static int test_iscsi_block ( struct iscsi_session *iscsi,
 | 
		
	
		
			
			| 514 |  | -			      unsigned int block ) {
 | 
		
	
		
			
			| 515 |  | -	struct test_iscsi_buffer buffer;
 | 
		
	
		
			
			| 516 |  | -
 | 
		
	
		
			
			| 517 |  | -	iscsi->block_size = 512;
 | 
		
	
		
			
			| 518 |  | -	iscsi->block_start = block;
 | 
		
	
		
			
			| 519 |  | -	iscsi->block_count = 1;
 | 
		
	
		
			
			| 520 |  | -	iscsi->block_read_callback = test_iscsi_callback;
 | 
		
	
		
			
			| 521 |  | -	iscsi->block_read_private = &buffer;
 | 
		
	
		
			
			| 522 |  | -	memset ( buffer.data, 0x61, sizeof ( buffer.data ) );
 | 
		
	
		
			
			| 523 |  | -
 | 
		
	
		
			
			| 524 |  | -	/* Start up iscsi session */
 | 
		
	
		
			
			| 525 |  | -	iscsi_wakeup ( iscsi );
 | 
		
	
		
			
			| 526 |  | -	while ( iscsi_busy ( iscsi ) ) {
 | 
		
	
		
			
			| 527 |  | -		run_tcpip ();
 | 
		
	
		
			
			| 528 |  | -	}
 | 
		
	
		
			
			| 529 |  | -
 | 
		
	
		
			
			| 530 |  | -	/* Check for errors */
 | 
		
	
		
			
			| 531 |  | -	if ( iscsi_error ( iscsi ) ) {
 | 
		
	
		
			
			| 532 |  | -		fprintf ( stderr, "iSCSI error on block %d\n", block );
 | 
		
	
		
			
			| 533 |  | -		return -1;
 | 
		
	
		
			
			| 534 |  | -	}
 | 
		
	
		
			
			| 535 |  | -
 | 
		
	
		
			
			| 536 |  | -	/* Dump out data */
 | 
		
	
		
			
			| 537 |  | -	hex_dump ( buffer.data, sizeof ( buffer.data ) );
 | 
		
	
		
			
			| 538 |  | -
 | 
		
	
		
			
			| 539 |  | -	return 0;
 | 
		
	
		
			
			| 540 |  | -}
 | 
		
	
		
			
			| 541 |  | -
 | 
		
	
		
			
			| 542 |  | -static int test_iscsi ( int argc, char **argv ) {
 | 
		
	
		
			
			| 543 |  | -	struct iscsi_options options;
 | 
		
	
		
			
			| 544 |  | -	struct iscsi_session iscsi;
 | 
		
	
		
			
			| 545 |  | -	unsigned int block;
 | 
		
	
		
			
			| 546 |  | -
 | 
		
	
		
			
			| 547 |  | -	/* Parse iscsi-specific options */
 | 
		
	
		
			
			| 548 |  | -	if ( iscsi_parse_options ( argc, argv, &options ) < 0 )
 | 
		
	
		
			
			| 549 |  | -		return -1;
 | 
		
	
		
			
			| 550 |  | -
 | 
		
	
		
			
			| 551 |  | -	/* Construct iscsi session */
 | 
		
	
		
			
			| 552 |  | -	memset ( &iscsi, 0, sizeof ( iscsi ) );
 | 
		
	
		
			
			| 553 |  | -	iscsi.tcp.sin = options.server;
 | 
		
	
		
			
			| 554 |  | -	iscsi.initiator = options.initiator;
 | 
		
	
		
			
			| 555 |  | -	iscsi.target = options.target;
 | 
		
	
		
			
			| 556 |  | -
 | 
		
	
		
			
			| 557 |  | -	/* Read some blocks */
 | 
		
	
		
			
			| 558 |  | -	for ( block = 0 ; block < 4 ; block += 2 ) {
 | 
		
	
		
			
			| 559 |  | -		if ( test_iscsi_block ( &iscsi, block ) < 0 )
 | 
		
	
		
			
			| 560 |  | -			return -1;
 | 
		
	
		
			
			| 561 |  | -	}
 | 
		
	
		
			
			| 562 |  | -
 | 
		
	
		
			
			| 563 |  | -	return 0;
 | 
		
	
		
			
			| 564 |  | -}
 | 
		
	
		
			
			| 565 |  | -
 | 
		
	
		
			
			| 566 |  | -/*****************************************************************************
 | 
		
	
		
			
			| 567 |  | - *
 | 
		
	
		
			
			| 568 |  | - * Protocol tester
 | 
		
	
		
			
			| 569 |  | - *
 | 
		
	
		
			
			| 570 |  | - */
 | 
		
	
		
			
			| 571 |  | -
 | 
		
	
		
			
			| 572 |  | -struct protocol_test {
 | 
		
	
		
			
			| 573 |  | -	const char *name;
 | 
		
	
		
			
			| 574 |  | -	int ( *exec ) ( int argc, char **argv );
 | 
		
	
		
			
			| 575 |  | -};
 | 
		
	
		
			
			| 576 |  | -
 | 
		
	
		
			
			| 577 |  | -static struct protocol_test tests[] = {
 | 
		
	
		
			
			| 578 |  | -	{ "hello", test_hello },
 | 
		
	
		
			
			| 579 |  | -	{ "iscsi", test_iscsi },
 | 
		
	
		
			
			| 580 |  | -};
 | 
		
	
		
			
			| 581 |  | -
 | 
		
	
		
			
			| 582 |  | -#define NUM_TESTS ( sizeof ( tests ) / sizeof ( tests[0] ) )
 | 
		
	
		
			
			| 583 |  | -
 | 
		
	
		
			
			| 584 |  | -static void list_tests ( void ) {
 | 
		
	
		
			
			| 585 |  | -	int i;
 | 
		
	
		
			
			| 586 |  | -
 | 
		
	
		
			
			| 587 |  | -	for ( i = 0 ; i < NUM_TESTS ; i++ ) {
 | 
		
	
		
			
			| 588 |  | -		printf ( "%s\n", tests[i].name );
 | 
		
	
		
			
			| 589 |  | -	}
 | 
		
	
		
			
			| 590 |  | -}
 | 
		
	
		
			
			| 591 |  | -
 | 
		
	
		
			
			| 592 |  | -static struct protocol_test * get_test_from_name ( const char *name ) {
 | 
		
	
		
			
			| 593 |  | -	int i;
 | 
		
	
		
			
			| 594 |  | -
 | 
		
	
		
			
			| 595 |  | -	for ( i = 0 ; i < NUM_TESTS ; i++ ) {
 | 
		
	
		
			
			| 596 |  | -		if ( strcmp ( name, tests[i].name ) == 0 )
 | 
		
	
		
			
			| 597 |  | -			return &tests[i];
 | 
		
	
		
			
			| 598 |  | -	}
 | 
		
	
		
			
			| 599 |  | -
 | 
		
	
		
			
			| 600 |  | -	return NULL;
 | 
		
	
		
			
			| 601 |  | -}
 | 
		
	
		
			
			| 602 |  | -
 | 
		
	
		
			
			| 603 |  | -/*****************************************************************************
 | 
		
	
		
			
			| 604 |  | - *
 | 
		
	
		
			
			| 605 |  | - * Parse command-line options
 | 
		
	
		
			
			| 606 |  | - *
 | 
		
	
		
			
			| 607 |  | - */
 | 
		
	
		
			
			| 608 |  | -
 | 
		
	
		
			
			| 609 |  | -struct tester_options {
 | 
		
	
		
			
			| 610 |  | -	char interface[IF_NAMESIZE];
 | 
		
	
		
			
			| 611 |  | -	struct in_addr in_addr;
 | 
		
	
		
			
			| 612 |  | -	struct in_addr netmask;
 | 
		
	
		
			
			| 613 |  | -	struct in_addr gateway;
 | 
		
	
		
			
			| 614 |  | -};
 | 
		
	
		
			
			| 615 |  | -
 | 
		
	
		
			
			| 616 |  | -static void usage ( char **argv ) {
 | 
		
	
		
			
			| 617 |  | -	fprintf ( stderr,
 | 
		
	
		
			
			| 618 |  | -		  "Usage: %s [global options] <test> [test-specific options]\n"
 | 
		
	
		
			
			| 619 |  | -		  "\n"
 | 
		
	
		
			
			| 620 |  | -		  "Global options:\n"
 | 
		
	
		
			
			| 621 |  | -		  "  -h|--help              Print this help message\n"
 | 
		
	
		
			
			| 622 |  | -		  "  -i|--interface intf    Use specified network interface\n"
 | 
		
	
		
			
			| 623 |  | -		  "  -f|--from ip-addr      Use specified local IP address\n"
 | 
		
	
		
			
			| 624 |  | -		  "  -n|--netmask mask      Use specified netmask\n"
 | 
		
	
		
			
			| 625 |  | -		  "  -g|--gateway ip-addr   Use specified default gateway\n"
 | 
		
	
		
			
			| 626 |  | -		  "  -l|--list              List available tests\n"
 | 
		
	
		
			
			| 627 |  | -		  "\n"
 | 
		
	
		
			
			| 628 |  | -		  "Use \"%s <test> -h\" to view test-specific options\n",
 | 
		
	
		
			
			| 629 |  | -		  argv[0], argv[0] );
 | 
		
	
		
			
			| 630 |  | -}
 | 
		
	
		
			
			| 631 |  | -
 | 
		
	
		
			
			| 632 |  | -static int parse_options ( int argc, char **argv,
 | 
		
	
		
			
			| 633 |  | -			   struct tester_options *options ) {
 | 
		
	
		
			
			| 634 |  | -	static struct option long_options[] = {
 | 
		
	
		
			
			| 635 |  | -		{ "interface", 1, NULL, 'i' },
 | 
		
	
		
			
			| 636 |  | -		{ "from", 1, NULL, 'f' },
 | 
		
	
		
			
			| 637 |  | -		{ "netmask", 1, NULL, 'n' },
 | 
		
	
		
			
			| 638 |  | -		{ "gateway", 1, NULL, 'g' },
 | 
		
	
		
			
			| 639 |  | -		{ "list", 0, NULL, 'l' },
 | 
		
	
		
			
			| 640 |  | -		{ "help", 0, NULL, 'h' },
 | 
		
	
		
			
			| 641 |  | -		{ },
 | 
		
	
		
			
			| 642 |  | -	};
 | 
		
	
		
			
			| 643 |  | -	int c;
 | 
		
	
		
			
			| 644 |  | -
 | 
		
	
		
			
			| 645 |  | -	/* Set default options */
 | 
		
	
		
			
			| 646 |  | -	memset ( options, 0, sizeof ( *options ) );
 | 
		
	
		
			
			| 647 |  | -	strncpy ( options->interface, "eth0", sizeof ( options->interface ) );
 | 
		
	
		
			
			| 648 |  | -	inet_aton ( "192.168.0.2", &options->in_addr );
 | 
		
	
		
			
			| 649 |  | -
 | 
		
	
		
			
			| 650 |  | -	/* Parse command-line options */
 | 
		
	
		
			
			| 651 |  | -	while ( 1 ) {
 | 
		
	
		
			
			| 652 |  | -		int option_index = 0;
 | 
		
	
		
			
			| 653 |  | -		
 | 
		
	
		
			
			| 654 |  | -		c = getopt_long ( argc, argv, "+i:f:n:g:hl", long_options,
 | 
		
	
		
			
			| 655 |  | -				  &option_index );
 | 
		
	
		
			
			| 656 |  | -		if ( c < 0 )
 | 
		
	
		
			
			| 657 |  | -			break;
 | 
		
	
		
			
			| 658 |  | -
 | 
		
	
		
			
			| 659 |  | -		switch ( c ) {
 | 
		
	
		
			
			| 660 |  | -		case 'i':
 | 
		
	
		
			
			| 661 |  | -			strncpy ( options->interface, optarg,
 | 
		
	
		
			
			| 662 |  | -				  sizeof ( options->interface ) );
 | 
		
	
		
			
			| 663 |  | -			break;
 | 
		
	
		
			
			| 664 |  | -		case 'f':
 | 
		
	
		
			
			| 665 |  | -			if ( inet_aton ( optarg, &options->in_addr ) == 0 ) {
 | 
		
	
		
			
			| 666 |  | -				fprintf ( stderr, "Invalid IP address %s\n",
 | 
		
	
		
			
			| 667 |  | -					  optarg );
 | 
		
	
		
			
			| 668 |  | -				return -1;
 | 
		
	
		
			
			| 669 |  | -			}
 | 
		
	
		
			
			| 670 |  | -			break;
 | 
		
	
		
			
			| 671 |  | -		case 'n':
 | 
		
	
		
			
			| 672 |  | -			if ( inet_aton ( optarg, &options->netmask ) == 0 ) {
 | 
		
	
		
			
			| 673 |  | -				fprintf ( stderr, "Invalid IP address %s\n",
 | 
		
	
		
			
			| 674 |  | -					  optarg );
 | 
		
	
		
			
			| 675 |  | -				return -1;
 | 
		
	
		
			
			| 676 |  | -			}
 | 
		
	
		
			
			| 677 |  | -			break;
 | 
		
	
		
			
			| 678 |  | -		case 'g':
 | 
		
	
		
			
			| 679 |  | -			if ( inet_aton ( optarg, &options->gateway ) == 0 ) {
 | 
		
	
		
			
			| 680 |  | -				fprintf ( stderr, "Invalid IP address %s\n",
 | 
		
	
		
			
			| 681 |  | -					  optarg );
 | 
		
	
		
			
			| 682 |  | -				return -1;
 | 
		
	
		
			
			| 683 |  | -			}
 | 
		
	
		
			
			| 684 |  | -			break;
 | 
		
	
		
			
			| 685 |  | -		case 'l':
 | 
		
	
		
			
			| 686 |  | -			list_tests ();
 | 
		
	
		
			
			| 687 |  | -			return -1;
 | 
		
	
		
			
			| 688 |  | -		case 'h':
 | 
		
	
		
			
			| 689 |  | -			usage ( argv );
 | 
		
	
		
			
			| 690 |  | -			return -1;
 | 
		
	
		
			
			| 691 |  | -		case '?':
 | 
		
	
		
			
			| 692 |  | -			/* Unrecognised option */
 | 
		
	
		
			
			| 693 |  | -			return -1;
 | 
		
	
		
			
			| 694 |  | -		default:
 | 
		
	
		
			
			| 695 |  | -			fprintf ( stderr, "Unrecognised option '-%c'\n", c );
 | 
		
	
		
			
			| 696 |  | -			return -1;
 | 
		
	
		
			
			| 697 |  | -		}
 | 
		
	
		
			
			| 698 |  | -	}
 | 
		
	
		
			
			| 699 |  | -
 | 
		
	
		
			
			| 700 |  | -	/* Check there is a test specified */
 | 
		
	
		
			
			| 701 |  | -	if ( optind == argc ) {
 | 
		
	
		
			
			| 702 |  | -		usage ( argv );
 | 
		
	
		
			
			| 703 |  | -		return -1;
 | 
		
	
		
			
			| 704 |  | -	}
 | 
		
	
		
			
			| 705 |  | -	
 | 
		
	
		
			
			| 706 |  | -	return optind;
 | 
		
	
		
			
			| 707 |  | -}
 | 
		
	
		
			
			| 708 |  | -
 | 
		
	
		
			
			| 709 |  | -/*****************************************************************************
 | 
		
	
		
			
			| 710 |  | - *
 | 
		
	
		
			
			| 711 |  | - * Main program
 | 
		
	
		
			
			| 712 |  | - *
 | 
		
	
		
			
			| 713 |  | - */
 | 
		
	
		
			
			| 714 |  | -
 | 
		
	
		
			
			| 715 |  | -int main ( int argc, char **argv ) {
 | 
		
	
		
			
			| 716 |  | -	struct tester_options options;
 | 
		
	
		
			
			| 717 |  | -	struct protocol_test *test;
 | 
		
	
		
			
			| 718 |  | -	struct hijack_device hijack_dev;
 | 
		
	
		
			
			| 719 |  | -
 | 
		
	
		
			
			| 720 |  | -	/* Parse command-line options */
 | 
		
	
		
			
			| 721 |  | -	if ( parse_options ( argc, argv, &options ) < 0 )
 | 
		
	
		
			
			| 722 |  | -		exit ( 1 );
 | 
		
	
		
			
			| 723 |  | -
 | 
		
	
		
			
			| 724 |  | -	/* Identify test */
 | 
		
	
		
			
			| 725 |  | -	test = get_test_from_name ( argv[optind] );
 | 
		
	
		
			
			| 726 |  | -	if ( ! test ) {
 | 
		
	
		
			
			| 727 |  | -		fprintf ( stderr, "Unrecognised test \"%s\"\n", argv[optind] );
 | 
		
	
		
			
			| 728 |  | -		exit ( 1 );
 | 
		
	
		
			
			| 729 |  | -	}
 | 
		
	
		
			
			| 730 |  | -	optind++;
 | 
		
	
		
			
			| 731 |  | -
 | 
		
	
		
			
			| 732 |  | -	/* Initialise the protocol stack */
 | 
		
	
		
			
			| 733 |  | -	init_tcpip();
 | 
		
	
		
			
			| 734 |  | -	set_ipaddr ( options.in_addr );
 | 
		
	
		
			
			| 735 |  | -	set_netmask ( options.netmask );
 | 
		
	
		
			
			| 736 |  | -	set_gateway ( options.gateway );
 | 
		
	
		
			
			| 737 |  | -
 | 
		
	
		
			
			| 738 |  | -	/* Open the hijack device */
 | 
		
	
		
			
			| 739 |  | -	hijack_dev.name = options.interface;
 | 
		
	
		
			
			| 740 |  | -	if ( ! hijack_probe ( &hijack_dev ) )
 | 
		
	
		
			
			| 741 |  | -		exit ( 1 );
 | 
		
	
		
			
			| 742 |  | -
 | 
		
	
		
			
			| 743 |  | -	/* Run the test */
 | 
		
	
		
			
			| 744 |  | -	if ( test->exec ( argc, argv ) < 0 )
 | 
		
	
		
			
			| 745 |  | -		exit ( 1 );
 | 
		
	
		
			
			| 746 |  | -
 | 
		
	
		
			
			| 747 |  | -	/* Close the hijack device */
 | 
		
	
		
			
			| 748 |  | -	hijack_disable ( &hijack_dev );
 | 
		
	
		
			
			| 749 |  | -
 | 
		
	
		
			
			| 750 |  | -	return 0;
 | 
		
	
		
			
			| 751 |  | -}
 |