/* Tests whether a packet sent to IP is LIKELY to route
through the kernel localhost interface */
#ifndef WIN32 /* This next group of functions are already defined in
wintcpip.c for now */
int islocalhost(struct in_addr *addr) {
char dev[128];
/* If it is 0.0.0.0 or starts with 127.0.0.1 then it is
probably localhost */
if ((addr->s_addr & htonl(0xFF000000)) == htonl(0x7F000000))
return 1;
if (!addr->s_addr)
return 1;
/* If it is the same addy as a local interface, then it is
probably localhost */
if (ipaddr2devname(dev, addr) != -1)
return 1;
/* OK, so to a first approximation, this addy is probably not
localhost */
return 0;
}
/* Calls pcap_open_live and spits out an error (and quits) if the call faile.
So a valid pcap_t will always be returned. */
pcap_t *my_pcap_open_live(char *device, int snaplen, int promisc, int to_ms)
{
char err0r[PCAP_ERRBUF_SIZE];
pcap_t *pt;
if (!((pt = pcap_open_live(device, snaplen, promisc, to_ms, err0r)))) {
fatal("pcap_open_live: %s\nThere are several possible reasons for this, depending on your operating system:\n"
"LINUX: If you are getting Socket type not supported, try modprobe af_packet or recompile your kernel with SOCK_PACKET enabled.\n"
"*BSD: If you are getting device not configured, you need to recompile your kernel with Berkeley Packet Filter support. If you are getting No such file or directory, try creating the device (eg cd /dev; MAKEDEV <device>; or use mknod).\n"
"SOLARIS: If you are trying to scan localhost and getting '/dev/lo0: No such file or directory', complain to Sun. I don't think Solaris can support advanced localhost scans. You can probably use \"-P0 -sT localhost\" though.\n\n", err0r);
}
return pt;
}
/* Standard BSD internet checksum routine */
unsigned short in_cksum(u16 *ptr,int nbytes) {
register u32 sum;
u16 oddbyte;
register u16 answer;
/*
* 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.
*/
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
/* mop up an odd byte, if necessary */
if (nbytes == 1) {
oddbyte = 0; /* make sure top half is zero */
*((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */
sum += oddbyte;
}
/*
* Add back carry outs from top 16 bits to low 16 bits.
*/
sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* ones-complement, then truncate to 16 bits */
return(answer);
}
/* Tries to resolve given hostname and stores
result in ip . returns 0 if hostname cannot
be resolved */
int resolve(char *hostname, struct in_addr *ip) {
struct hostent *h;
if (!hostname || !*hostname)
fatal("NULL or zero-length hostname passed to resolve()");
fprintf(stderr, "Failed to secure socket broadcasting permission\n");
perror("setsockopt");
}
}
/* Do a receive (recv()) on a socket and stick the results (upt to
len) into buf . Give up after 'seconds'. Returns the number of
bytes read (or -1 in the case of an error. It only does one recv
(it will not keep going until len bytes are read */
int recvtime(int sd, char *buf, int len, int seconds) {
int res;
struct timeval timeout;
fd_set readfd;
timeout.tv_sec = seconds;
timeout.tv_usec = 0;
FD_ZERO(&readfd);
FD_SET(sd, &readfd);
res = select(sd + 1, &readfd, NULL, NULL, &timeout);
if (res > 0 ) {
res = recv(sd, buf, len, 0);
if (res >= 0) return res;
perror("recv in recvtime");
return 0;
}
else if (!res) return 0;
perror("select() in recvtime");
return -1;
}
/* This attempts to calculate the round trip time (rtt) to a host by timing a
connect() to a port which isn't listening. A better approach is to time a
ping (since it is more likely to get through firewalls (note, this isn't
always true nowadays --fyodor). This is now
implemented in isup() for users who are root. */
unsigned long calculate_sleep(struct in_addr target) {
struct timeval begin, end;
int sd;
struct sockaddr_in sock;
int res;
if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{perror("Socket troubles"); exit(1);}
sock.sin_family = AF_INET;
sock.sin_addr.s_addr = target.s_addr;
sock.sin_port = htons(o.magic_port);
gettimeofday(&begin, NULL);
if ((res = connect(sd, (struct sockaddr *) &sock,
sizeof(struct sockaddr_in))) != -1)
fprintf(stderr, "WARNING: You might want to use a different value of -g (or change o.magic_port in the include file), as it seems to be listening on the target host!\n");