/****************************************************************************
Program: $Id: net.c,v 1.5 2006/11/19 21:01:17 rbeverly Exp $
Author: Rob Beverly <rbeverly@mit.edu>
Date: $Date: 2006/11/19 21:01:17 $
Description: Spoofer utility routines
****************************************************************************/
#include "spoof.h"
#ifdef _WIN32
static int rawsock = 1;
#endif
/* Fill buffer with the spoofed packet */
int craftPacket(char *buf, char *payload, int payloadlen,
struct sockaddr_in *src, struct sockaddr_in *dst, u_char ttl) {
struct udpiphdr *ui;
struct ip *ip;
int packetlen;
memset(buf, 0, BUFSIZE);
ip = (struct ip *)buf;
ui = (struct udpiphdr *)buf;
packetlen = payloadlen + sizeof(struct udpiphdr);
/* Copy payload */
memcpy((buf + sizeof(struct udpiphdr)), payload, payloadlen);
/* Create Pseudo-Header First */
ui->ui_pr = IPPROTO_UDP;
ui->ui_len = htons(payloadlen + sizeof(struct udphdr));
ui->ui_src = src->sin_addr;
ui->ui_dst = dst->sin_addr;
ui->ui_sport = src->sin_port;
ui->ui_dport = dst->sin_port;
ui->ui_ulen = ui->ui_len;
if ((ui->ui_sum = in_cksum((u_short *) ui, packetlen)) == 0)
ui->ui_sum = 0xffff;
ip->ip_v = IPVERSION;
ip->ip_hl = sizeof(struct ip) >> 2;
ip->ip_tos = 0;
/* FreeBSD raw sockets expect host not network order */
#ifdef _FBSD
ip->ip_len = packetlen;
ip->ip_off = IP_DF;
#else
ip->ip_len = htons(packetlen);
ip->ip_off = htons(IP_DF);
#endif
ip->ip_id = rand() % 32768;
ip->ip_sum = 0;
ip->ip_ttl = ttl;
if (DEBUG) {
printf("Complete packet:\n");
dumpPacket((unsigned char *)ip, packetlen);
}
return (packetlen);
}
/* Build Spoofer Report */
void craftReport(spoof_t *report, unsigned short unused,
unsigned long addr, char *seqno) {
#ifdef SPOOFER_BIG_ENDIAN
report->ver = byte16Swap(VERSION);
report->unused = byte16Swap(unused);
#else
report->ver = VERSION;
report->unused = unused;
#endif
report->addr = addr;
strncpy((char *) report->seqno, seqno, SEQNOSIZE);
}
unsigned short
in_cksum(unsigned short *addr, int len)
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* 4mop up an odd byte, if necessary */
if (nleft == 1) {
*(unsigned char *)(&answer) = *(unsigned char *)w ;
sum += answer;
}
/* 4add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);
}
/* Debug routine for examining raw packets */
void dumpPacket(unsigned char *pkt, int len) {
int i;
for (i=1;i<=len;i++) {
printf("%02x ", *pkt);
pkt++;
if (i%4 == 0) printf("\n");
}
printf("\n");
}
/* Generate a random ASCII sequence */
void genSequence(unsigned char *buf, int len) {
int i;
int byte;
rand();
for (i=0;i<len;i++) {
byte = (int) ((double)rand() / ((double)RAND_MAX + 1) * 256);
if (byte >= 48 && byte <= 57) {
*buf = byte;
buf++;
} else if (byte >= 97 && byte <= 122) {
*buf = byte;
buf++;
} else {
i--;
}
}
*buf = '\0';
}
/* Ugly and inefficient, but at least it's readable and endian-safe */
int checkRFC1918(struct in_addr *in) {
in_addr_t a1, a2;
a1 = inet_addr("10.0.0.0");
a2 = inet_addr("10.255.255.255");
if ( (ntohl(in->s_addr) >= ntohl(a1)) && (ntohl(in->s_addr) <= ntohl(a2)) )
return 1;
a1 = inet_addr("172.16.0.0");
a2 = inet_addr("172.31.255.255");
if ( (ntohl(in->s_addr) >= ntohl(a1)) && (ntohl(in->s_addr) <= ntohl(a2)) )
return 1;
a1 = inet_addr("192.168.0.0");
a2 = inet_addr("192.168.255.255");
if ( (ntohl(in->s_addr) >= ntohl(a1)) && (ntohl(in->s_addr) <= ntohl(a2)) )
return 1;
return 0;
}
/*
Handy routines that follow taken directly from R. Stevens UNP
*/
ssize_t /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
else
return(-1);
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
/* end readn */
ssize_t
Readn(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ( (n = readn(fd, ptr, nbytes)) < 0)
perror("readn error");
return(n);
}
ssize_t /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
#if _WIN32
if ( (nwritten = send(fd, ptr, nleft, 0)) <= 0) {
#else
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
#endif
if (errno == EINTR)
nwritten = 0; /* and call write() again */
else
return(-1); /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
/* end writen */
void
Writen(int fd, void *ptr, size_t nbytes)
{
if (writen(fd, ptr, nbytes) != nbytes)
perror("writen error");
}
static ssize_t
my_read(int fd, char *ptr)
{
static int read_cnt = 0;
static char *read_ptr;
static char read_buf[MAXLINE];
if (read_cnt <= 0) {
again:
#if _WIN32
if ( (read_cnt = recv(fd, read_buf, sizeof(read_buf), 0)) < 0) {
#else
if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
#endif
if (errno == EINTR)
goto again;
return(-1);
} else if (read_cnt == 0)
return(0);
read_ptr = read_buf;
}
read_cnt--;
*ptr = *read_ptr++;
return(1);
}
ssize_t
readline(int fd, void *vptr, size_t maxlen)
{
int n, rc;
char c, *ptr;
ptr = vptr;
for (n = 1; n < maxlen; n++) {
if ( (rc = my_read(fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break; /* newline is stored, like fgets() */
} else if (rc == 0) {
if (n == 1)
return(0); /* EOF, no data read */
else
break; /* EOF, some data was read */
} else
return(-1); /* error, errno set by read() */
}
*ptr = 0; /* null terminate like fgets() */
return(n);
}
/* end readline */
ssize_t
Readline(int fd, void *ptr, size_t maxlen)
{
ssize_t n;
if ( (n = readline(fd, ptr, maxlen)) < 0)
perror("readline error");
if (n == 0)
printf("** server terminated prematurely");
return(n);
}
/* New socket wrapper */
int newSocket(int type, int proto) {
int sock = 0;
#ifdef _WIN32
sock = socket(AF_INET, type, proto);
if (sock == INVALID_SOCKET)
winfatal("** WSASocket() failed: %d\n", WSAGetLastError());
#else
if ((sock = socket(AF_INET, type, proto)) < 0)
pfatal("create socket");
#endif
return (sock);
}
int connectSock(int sock, struct sockaddr_in *dst, int len) {
#ifdef _WIN32
int ret;
ret = connect(sock, (SOCKADDR *) dst, len);
if (ret == SOCKET_ERROR)
winfatal("** connect failed: %d\n", WSAGetLastError());
#else
if ((connect(sock, (struct sockaddr *) dst, len)) < 0)
pfatal("connect");
#endif
return (1);
}
int optSocketTTL(int sock, int val) {
#ifdef _WIN32
BOOL on = TRUE;
int ret;
#else
int on = 1;
#endif
on = val;
#ifdef _WIN32
ret = setsockopt(sock, IPPROTO_IP, IP_TTL, (char *)&on, sizeof(on));
if (ret == SOCKET_ERROR)
winfatal("** setsockopt(IP_TTL) failed: %d\n", WSAGetLastError());
#else
if ((setsockopt(sock, IPPROTO_IP, IP_TTL, (char *)&on, sizeof(on))) < 0)
pfatal("setsockopt IP_TTL");
#endif
return (1);
}
int optSocketHDRINCL(int sock) {
#ifdef _WIN32
BOOL on = TRUE;
int ret;
#else
int on = 1;
#endif
#ifdef _WIN32
ret = setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on));
if (ret == SOCKET_ERROR)
winfatal("** setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
#else
if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on))) < 0)
pfatal("setsockopt IP_HDRINCL");
#endif
return (1);
}
int socketSend(int sock, void *msg, int len, struct sockaddr_in *dst, int tolen) {
#ifdef _WIN32
int ret;
ret = sendto(sock, (unsigned char *)msg, len, 0, (SOCKADDR *) dst, tolen);
if (ret == SOCKET_ERROR) {
printf("** sendto() failed: %d\n", WSAGetLastError());
return (SOCKET_ERROR);
}
#else
if ((sendto(sock, (unsigned char *)msg, len, 0, (struct sockaddr *) dst, tolen)) < 0) {
perror("sendto");
return (SENDTO_ERROR);
}
#endif
return (1);
}
int socketSendSpoof(int sock, void *msg, int len, struct sockaddr_in *dst, int tolen) {
#ifdef _WIN32
int ret;
if (rawsock) {
ret = sendto(sock, (unsigned char *)msg, len, 0, (SOCKADDR *) dst, tolen);
if (ret == SOCKET_ERROR) {
if (WSAGetLastError() == 10004) {
printf("%s", WIN_SEND_ERR);
rawsock = 0;
return (WINRAWSOCK_ERROR);
} else {
printf("** sendto() failed: %d\n", WSAGetLastError());
}
return (SOCKET_ERROR);
}
} else {
ret = etherSend(msg, len);
}
#else
if ((sendto(sock, (unsigned char *)msg, len, 0, (struct sockaddr *) dst, tolen)) < 0) {
perror("sendto");
return (SENDTO_ERROR);
}
#endif
return (1);
}
syntax highlighted by Code2HTML, v. 0.9.1