/* 
 * $smu-mark$ 
 * $name: sendudp.c$ 
 * $author: Salvatore Sanfilippo <antirez@invece.org>$ 
 * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$ 
 * $license: This software is under GPL version 2 of license$ 
 * $date: Fri Nov  5 11:55:49 MET 1999$ 
 * $rev: 8$ 
 */ 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

#include "hping2.h"
#include "globals.h"

/* void hexdumper(unsigned char *packet, int size); */

void send_udphdr (int signal_id)
{
	int			packet_size;
	int			errno_save = errno;
	char			*packet, *data;
	struct myudphdr		*udp;
	struct pseudohdr *pseudoheader;

	packet_size = UDPHDR_SIZE + data_size;
	packet = malloc(PSEUDOHDR_SIZE + packet_size);
	if (packet == NULL) {
		perror("[send_udphdr] malloc()");
		errno = errno_save;
		return;
	}
	pseudoheader = (struct pseudohdr*) packet;
	udp =  (struct myudphdr*) (packet+PSEUDOHDR_SIZE);
	data = (char*) (packet+PSEUDOHDR_SIZE+UDPHDR_SIZE);
	
	memset(packet, 0, PSEUDOHDR_SIZE+packet_size);

	/* udp pseudo header */
	memcpy(&pseudoheader->saddr, &local.sin_addr.s_addr, 4);
	memcpy(&pseudoheader->daddr, &remote.sin_addr.s_addr, 4);
	pseudoheader->protocol		= 17; /* udp */
	pseudoheader->lenght		= htons(packet_size);

	/* udp header */
	udp->uh_dport	= htons(dst_port);
	udp->uh_sport	= htons(src_port);
	udp->uh_ulen	= htons(packet_size);

	/* data */
	data_handler(data, data_size);

	/* compute checksum */
#ifdef STUPID_SOLARIS_CHECKSUM_BUG
	udp->uh_sum = packet_size;
#else
	udp->uh_sum = cksum((__u16*) packet, PSEUDOHDR_SIZE +
		      packet_size);
#endif

/*	hexdumper(packet, PSEUDOHDR_SIZE+packet_size); */

	/* adds this pkt in delaytable */
	delaytable[delaytable_index % TABLESIZE].seq = sequence;
	delaytable[delaytable_index % TABLESIZE].src = src_port;
	delaytable[delaytable_index % TABLESIZE].sec = time(NULL);
	delaytable[delaytable_index % TABLESIZE].usec = get_usec();
	delaytable[delaytable_index % TABLESIZE].status = S_SENT;

	/* send packet */
	send_ip_handler(packet+PSEUDOHDR_SIZE, packet_size);
	free(packet);

	delaytable_index++;
	sent_pkt++;
	Signal(SIGALRM, send_udphdr);
	
	if (count != -1 && count == sent_pkt)	/* count reached */
	{
		Signal(SIGALRM, print_statistics);
		alarm(COUNTREACHED_TIMEOUT);
	}
	else if (!opt_listenmode)
	{
		if (opt_waitinusec == FALSE)
			alarm(sending_wait);
		else
			setitimer(ITIMER_REAL, &usec_delay, NULL);
	}

	sequence++;	/* next sequence number */

	if (!opt_keepstill)
		src_port = (sequence + initsport) % 65536;

	errno = errno_save;
}

/*
void hexdumper(unsigned char *packet, int size)
{
	unsigned char *byte;
	int count = 0;

	printf("\t\t");
	for (byte = (unsigned char*) packet;
		byte < (unsigned char*) (packet+size); byte++)
	{
		count++;
		printf("%02x", *byte);
		if (count % 2 == 0) printf(" ");
		if (count % 16 == 0) printf("\n\t\t");
	}
	printf("\n\n");
}
*/
