blob: c424b097baf68bc50a2f0112fbaa1132fd8df41c [file] [log] [blame]
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFER_SIZE (1<<16)
static unsigned short port = 0;
static unsigned int number = 1;
static unsigned short errornous = 0;
static unsigned short drop = 0;
static unsigned short verbose = 0;
static unsigned short showUsage = 0;
static unsigned short offset = 0;
struct common_header {
unsigned short source_port;
unsigned short destination_port;
unsigned long verification_tag;
unsigned long checksum;
};
struct pktdrp_header {
unsigned char type;
unsigned char flags;
unsigned short length;
unsigned long bandwidth;
unsigned long size;
unsigned short truncated_length;
unsigned short reservered;
unsigned char packet[0];
};
void printUsage(void)
{
printf("Usage: emulator -p port [options]\n");
printf("options:\n");
printf("-d discard and send packet drop report (default no)\n");
printf("-e introduce CRC/checksum errors (default: no)\n");
printf("-h show this message\n");
printf("-n number send each packet number times (default: 1 )\n");
printf("-o offset modify the byte with the given offset (default 0)\n");
printf("-v verbose mode (default: no)\n");
}
void getArgs(int argc, const char * argv[])
{
int c;
extern char *optarg;
/* extern int optind;*/
while ((c = getopt(argc, (char * const *)argv, "ehn:o:p:v")) != -1)
{
switch (c) {
case 'd':
drop =1;
break;
case 'e':
errornous = 1;
break;
case 'h':
showUsage = 1;
break;
case 'p':
port = atoi(optarg);
break;
case 'n':
number = atoi(optarg);
break;
case 'o':
offset = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
default:
showUsage = 1;
break;
}
}
}
void checkArgs(void)
{
if (port == 0) {
fprintf(stderr, "Error: No port number specified.\n");
printUsage();
exit(-1);
}
if (showUsage) {
printUsage();
exit(1);
}
}
int main(int argc, const char * argv[])
{
int fd, n, i, addr_len;
struct sockaddr_in addr;
char buffer[BUFFER_SIZE];
struct ip *ip_header;
struct common_header *common_header;
struct pktdrp_header *pktdrp_header;
getArgs(argc, argv);
checkArgs();
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT)) < 0)
perror("socket call failed");
bzero(&addr, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
perror("bind call failed");
bzero(&addr, sizeof(addr));
addr_len = sizeof(addr);
ip_header = (struct ip *)buffer;
while ((n = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr *) &addr, &addr_len)) > 0){
if (verbose) {
printf("Received %u bytes from %s.\n", n, inet_ntoa(addr.sin_addr));
fflush(stdout);
}
if ((errornous) && ((offset + (ip_header->ip_hl << 2)) < n)) {
buffer[offset + (ip_header->ip_hl << 2)]++;
if (verbose) {
printf("Modified the packet\n");
fflush(stdout);
}
}
/*
if (drop) {
memmove(buffer + (ip_header->ip_hl << 2) +
sizeof(struct common_header) +
sizeof(struct pktdrp_header), buffer + (ip_header->ip_hl << 2), n - (ip_header->ip_hl << 2));
common_header = (struct common_header *) (buffer + (ip_header->ip_hl << 2));
pktdrp_header = (struct pktdrp_header *) (buffer + (ip_header->ip_hl << 2) + sizeof(struct common_header));
common_header->source_port = ;
}
*/
for(i = 0; i < number; i++) {
if (n != sendto(fd, buffer, n, 0, (struct sockaddr *) &addr, addr_len)) {
fprintf(stderr, "Writing %u bytes failed.\n", n);
fflush(stderr);
}
}
if ((verbose) && (number > 0)) {
printf("Sent %u bytes from %s %u times.\n", n, inet_ntoa(addr.sin_addr), number);
fflush(stdout);
}
}
if (close(fd) < 0)
perror("close call failed");
return 0;
}