@@ -0,0 +1,33 @@
/* cpu.h
CPS 472 Sample Code
*/

#pragma once
#include <Winternl.h>
#include <psapi.h>
#include <math.h>

#define MAX_CPU 16
#define MEGABYTE 1048576

class CPU{
public:
int cpus; // # of CPUs
HMODULE hDll; // handle to the NT dll
HANDLE hProcess; // handle to the current process
NTSTATUS (__stdcall *NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);

SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info[MAX_CPU];
ULONG len;
__int64 idle[MAX_CPU], kernel [MAX_CPU], user [MAX_CPU];

CPU (void);
~CPU();
double GetCpuUtilization (double*);
int GetProcessRAMUsage(void);
int GetSystemRAM (void);
int GetSystemRAMUsage (void);
};

Large diffs are not rendered by default.

@@ -0,0 +1,47 @@
/* dns.h
CPS 472 Sample Code
*/

#include "headers.h"
#include "dns.h"

// NOTE: link with Iphlpapi.lib; prints primary/second DNS server info

// dnsIP is assigned the first IP address of local DNS servers after called
void DNS::printDNSServer(string & dnsIP)
{
// MSDN sample code
FIXED_INFO *FixedInfo;
ULONG ulOutBufLen;
DWORD dwRetVal;
IP_ADDR_STRING * pIPAddr;

ulOutBufLen = sizeof(FIXED_INFO);
FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );
ulOutBufLen = sizeof( FIXED_INFO );

if(ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &ulOutBufLen)) {
GlobalFree( FixedInfo );
FixedInfo = (FIXED_INFO *)GlobalAlloc( GPTR, ulOutBufLen );
}

if ( dwRetVal = GetNetworkParams( FixedInfo, &ulOutBufLen ) ) {
printf( "Call to GetNetworkParams failed. Return Value: %08x\n", dwRetVal );
}
else {
printf( "Host Name: %s\n", FixedInfo->HostName );
printf( "Domain Name: %s\n", FixedInfo->DomainName );

printf( "DNS Servers:\n" );
printf( "\t%s\n", FixedInfo->DnsServerList.IpAddress.String);
dnsIP = FixedInfo->DnsServerList.IpAddress.String;

pIPAddr = FixedInfo->DnsServerList.Next;
while ( pIPAddr ) {
printf( "\t%s\n", pIPAddr ->IpAddress.String);
pIPAddr = pIPAddr ->Next;
}
}

GlobalFree (FixedInfo);
}
@@ -0,0 +1,11 @@
/* dns.h
CPS 472 Sample Code
*/
#pragma once
#include <Iphlpapi.h>


class DNS {
public:
void printDNSServer (string & dnsIP);
};
@@ -0,0 +1,11 @@
// some .h files every .cpp needs
#pragma once
#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
#include <queue>
#include <map>
#include <string>


using namespace std; // if you're planning to use STL
@@ -0,0 +1,68 @@
#include "headers.h"
#include "lookup.h"
#include <iostream>

Question::Question(void) // constructor
{

};

// Packet visual:
// [ DNS Header - Question Buffer - Query Header ]
bool Question::MakePacket(char* pkt, FixedDNSheader &dnsheader, QueryHeader &queryheader)
{
int size_pkt = strlen(pkt);
int dhdr_size = sizeof(dnsheader);
int qhdr_size = sizeof(queryheader);
int buf_size = sizeof(rawbuffer);

// add the dns header to pkt
memcpy(pkt, &dnsheader, dhdr_size);

// copy the mem from rawbuffer to pkt
memcpy(pkt + dhdr_size, rawbuffer, buf_size);

// add the query header to pkt
//memcpy(pkt + size_pkt - qhdr_size, &queryheader, qhdr_size);

return true;
}

bool Question::CreateQuestion(string host)
{
// only creating the question, so only use size of question
rawbuffer = new char[host.size() + 2];

int position = host.find(".");
string sub_str;

int i = 0, sub_size = 0, hdr_size = sizeof(FixedDNSheader);

// parse the host and place contents in packet
host += ".";
while (position != -1)
{
sub_size = position - i;
sub_str = host.substr(i, position);

rawbuffer[i] = sub_size; // specify the size of the chunk (subdomain)
i++;
memcpy(rawbuffer + i, sub_str.c_str(), sub_size); // specify the actual subdomain

i += sub_size;
position = host.find(".", i);
}
rawbuffer[hdr_size + i] = 0;

for (int i = 0; i < host.size() + 2; i++)
{
std::cout << "i= " << i << " " << rawbuffer[i] << endl;
}
getchar();

return true;
}

int Question::Size() {
return sizeof(rawbuffer);
}
@@ -0,0 +1,97 @@
/* lookup.h
CPS 472 Sample Code
*/

/* query classes */
#define DNS_INET 1 /* the Internet */

// Query types are integer numbers specified in RFC 1035. Several useful queries:

/* DNS query types */
#define DNS_A 1 /* name -> IP */
#define DNS_NS 2 /* name server */
#define DNS_CNAME 5 /* canonical name */
#define DNS_PTR 12 /* IP->name */
#define DNS_HINFO 13 /* host info */
#define DNS_MX 15 /* mail exchange */
#define DNS_AXFR 252 /* request for zone transfer */
#define DNS_ANY 255 /* all records */


/* flags for the DNS header*/
#define DNS_QUERY (0 << 15) /* 0 = query; 1 = response */
#define DNS_RESPONSE (1 << 15)

#define DNS_STDQUERY (0) /* opcode - 4 bits */
#define DNS_INVQUERY (1 << 11)
#define DNS_SRVSTATUS (1 << 12)

#define DNS_AA (1 << 10) /* authoritative answer */
#define DNS_TC (1 << 9) /* truncated */
#define DNS_RD (1 << 8) /* recursion desired */
#define DNS_RA (1 << 7) /* recursion available */


/* possible result codes */
#define DNS_OK 0 /* rcode = reply codes */
#define DNS_FORMAT 1 /* format error (unable to interpret) */
#define DNS_SERVERFAIL 2 /* server failure */
#define DNS_ERROR 3 /* no DNS entry */
#define DNS_NOTIMPL 4 /* not implemented */
#define DNS_REFUSED 5 /* server refused the query */

// class defines the fixed query header
/* remember the current packing state */
#pragma pack(push) // exact fit data into a structure with given size -- no padding
#pragma pack(1)
class QueryHeader{ // 4 bytes
public:
u_short type;
u_short qclass;
};
/* now restore the previous packing state */
#pragma pack(pop)

// Fixed DNS header size:
#pragma pack(push) // exact fit data into a structure with given size -- no padding
#pragma pack(1)
class FixedDNSheader{ // 12 bytes
public:
u_short ID; // identification number

// flags: 2 bytes
u_short flags;

u_short questions; // number of question entries
u_short answers; // number of answer entries
u_short authRRs; // number of authority entries
u_short addRRs; // number of resource entries
};
#pragma pack(pop)


#pragma pack(push) // exact fit data into a structure with given size -- no padding
#pragma pack(1) // because the struct is 10 bytes
class FixedRR { // fixed header for RR
public:
u_short type;
u_short RRclass; //
u_int ttl; // 4 bytes
u_short len; // the length of the RDATA field
// RDATA field: a variable length string that describes the resource
};
#pragma pack(pop)

class Question{
public:
char *rawbuffer;

Question(void); // constructor

bool MakePacket(char* pkt, FixedDNSheader &dnsheader, QueryHeader &queryheader);

bool CreateQuestion(string host);

int Size();

};
@@ -0,0 +1,226 @@
/* main.cpp
CPS 472 Sample Code
To compile, you need to add additional libraries:
1. Right Click on project name, select "Properties"
2. Go to Linker/Input/Additional Dependencies: ws2_32.lib;winmm.lib;Iphlpapi.lib;Psapi.lib;
use ; to separate them.
*/

#define _WINSOCK_DEPRECATED_NO_WARNINGS // needed for "inet_add()" function call

#include "winsock.h" // must include winsock2.h at the very top of the file before include others
#include "headers.h"
#include "cpu.h"
#include "dns.h"
#include "lookup.h"

#include <iostream>



// this class is passed to all threads, acts as shared memory
class Parameters {
public:
HANDLE mutex;
HANDLE finished;
HANDLE eventQuit;
};

// this function is where the thread starts
UINT thread(LPVOID pParam)
{
Parameters *p = ((Parameters*)pParam);

// wait for mutex, then print and sleep inside the critical section
WaitForSingleObject(p->mutex, INFINITE); // lock mutex
printf("Thread %d started\n", GetCurrentThreadId()); // always print inside critical section to avoid screen garbage
Sleep(1000);
ReleaseMutex(p->mutex); // release critical section

// signal that this thread has exitted
ReleaseSemaphore(p->finished, 1, NULL);

return 0;
}

int main(int argc, char* argv[])
{
if (argc != 2) {
std::printf("Invalid number of args.\n");
return -1;
}
int arg_type;
string host = argv[1];
if (isdigit(host[0])) {
std::printf("IP\n");
arg_type = 1;
if (inet_addr(argv[1]) == INADDR_NONE) {
std::printf("Invalid IP");
return -1;
}
host = host + ".in-addr.arpa";
}
else {
std::printf("HOSTNAME\n");
arg_type = 2;
}
cout << "argc: " << argc << ", argv: " << host << endl;

WSADATA wsaData;

// Initialize WinSock in your project only once!
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
printf("WSAStartup error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}


printf("-----------------\n");

// print our primary/secondary DNS IPs
DNS mydns;
string dnsIP = "";
mydns.printDNSServer(dnsIP);

printf("-----------------\n");

CPU cpu;
// average CPU utilization over 500 ms; must sleep *after* the constructor of class CPU and between calls to GetCpuUtilization
Sleep(500);
// now print
double util = cpu.GetCpuUtilization(NULL);
printf("current CPU utilization %f%%\n", util);

printf("-----------------\n");

// thread handles are stored here; they can be used to check status of threads, or kill them
HANDLE *ptrs = new HANDLE[2];
Parameters p;

// create a mutex for accessing critical sections (including printf)
p.mutex = CreateMutex(NULL, 0, NULL);

// create a semaphore that counts the number of active threads
p.finished = CreateSemaphore(NULL, 0, 2, NULL);
p.eventQuit = CreateEvent(NULL, true, false, NULL);

// get current time
DWORD t = timeGetTime();

// structure p is the shared space between the threads
ptrs[0] = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)thread, &p, 0, NULL);
ptrs[1] = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)thread, &p, 0, NULL);

// make sure this thread hangs here until the other two quit; otherwise, the program will terminate prematurely
WaitForSingleObject(p.finished, INFINITE);
WaitForSingleObject(p.finished, INFINITE);


// ------------------------------- testing the DNS query -----------

// string host = "www.yahoo.com" ;
// string host = "7.74.238.131.in-addr.arpa";
int pkt_size = sizeof(FixedDNSheader) + sizeof(QueryHeader) + host.size() + 2; //+1 byte for "size" for last substring, +1 for "0" meaning the end of question

//char* pkt = new char[pkt_size];

//FixedDNSheader * dHDR = (FixedDNSheader *)pkt;
//QueryHeader *qHDR = (QueryHeader*)(pkt + pkt_size - sizeof(QueryHeader));

FixedDNSheader * dHDR = new FixedDNSheader;
QueryHeader * qHDR = new QueryHeader;

dHDR->ID = htons(102);
dHDR->questions = htons(1);
dHDR->addRRs = 0;
dHDR->answers = 0;
dHDR->authRRs = 0;
dHDR->flags = htons(DNS_QUERY | DNS_RD | DNS_STDQUERY);
// dHDR->flags = htons( 0x0100 );

qHDR->qclass = htons(DNS_INET);
// qHDR->qclass = htons( 0x0001);

// if hostname
if (arg_type == 2) {
qHDR->type = htons(DNS_A);
}
// if IP
else if (arg_type == 1) {
qHDR->type = htons(DNS_PTR); // for reverse dns lookup
}

Question q;

q.CreateQuestion(host);

int size = sizeof(FixedDNSheader) + q.Size() + sizeof(QueryHeader);
char *pkt = new char[size];

q.MakePacket(pkt, *dHDR, *qHDR);

Winsock ws;

SOCKET sock = ws.OpenSocket(); // defined in winsock.h

// set up the address of where we're sending data
struct sockaddr_in send_addr;
send_addr.sin_family = AF_INET;
send_addr.sin_addr.S_un.S_addr = inet_addr(dnsIP.c_str()); // 208.67.222.222
send_addr.sin_port = htons(53);

int send_addrSize = sizeof(struct sockaddr_in);

int sentbytes = sendto(sock, pkt, pkt_size, 0, (struct sockaddr*) &send_addr, send_addrSize);
cout << "sentbytes=" << sentbytes << endl;

for (int i = 0; i < pkt_size; i++)
{
cout << "i= " << i << " " << pkt[i] << endl;
}
cout << endl;

char recv_buf[512];

int recvbytes = 0;
if (sentbytes > 0)
recvbytes = recvfrom(sock, recv_buf, 512, 0, (sockaddr *)&send_addr, &send_addrSize);

cout << "recv_bytes=" << recvbytes << endl;

FixedDNSheader * rDNS = (FixedDNSheader *)recv_buf;
cout << "ID=" << ntohs(dHDR->ID) << "??" << ntohs(rDNS->ID) << endl;
cout << "questions=" << ntohs(rDNS->questions) << endl;
cout << "Answers=" << ntohs(rDNS->answers) << endl;
cout << "authRRs=" << ntohs(rDNS->authRRs) << endl;
cout << "addRRs=" << ntohs(rDNS->addRRs) << endl;

printf("flag 0x=%x\n", ntohs(rDNS->flags));
unsigned short rcode = 0x0F;
rcode = rcode & ntohs(rDNS->flags);
rcode = rcode & ntohs(rDNS->flags);
cout << "Rcode= " << rcode << endl; ;

// for debugging:
// for ( int i = 0; i< recvbytes; i++)
// {
// printf("%x\t", i, recv_buf[i] );
// }
// cout<<endl;

closesocket(sock);

delete[] pkt;


printf("Terminating main(), completion time %d ms\n", timeGetTime() - t);

getchar();

WSACleanup();

return 0;
}
@@ -0,0 +1,236 @@
/* main.cpp
CPS 472 Sample Code
To compile, you need to add additional libraries:
1. Right Click on project name, select "Properties"
2. Go to Linker/Input/Additional Dependencies: ws2_32.lib;winmm.lib;Iphlpapi.lib;Psapi.lib;
use ; to separate them.
*/

#define _WINSOCK_DEPRECATED_NO_WARNINGS // needed for "inet_add()" function call

#include "winsock.h" // must include winsock2.h at the very top of the file before include others
#include "headers.h"
#include "cpu.h"
#include "dns.h"
#include "lookup.h"

#include <iostream>



// this class is passed to all threads, acts as shared memory
class Parameters{
public:
HANDLE mutex;
HANDLE finished;
HANDLE eventQuit;
};

// this function is where the thread starts
UINT make_thread(LPVOID pParam)
{
Parameters *p = ((Parameters*)pParam);

// wait for mutex, then print and sleep inside the critical section
WaitForSingleObject(p->mutex, INFINITE); // lock mutex
printf ("Thread %d started\n", GetCurrentThreadId ()); // always print inside critical section to avoid screen garbage
Sleep (1000);
ReleaseMutex(p->mutex); // release critical section

// signal that this thread has exitted
ReleaseSemaphore(p->finished, 1, NULL);

return 0;
}

int ref_main(int argc, char* argv[])
{
if (argc != 2) {
std::printf("Invalid number of args");
return -1;
}
int arg_type;
string host = argv[1];
if (isdigit(host[0])) {
std::printf("IP\n");
arg_type = 1;
if (inet_addr(argv[1]) == INADDR_NONE) {
std::printf("Invalid IP");
return -1;
}
host = host + ".in-addr.arpa";
}
else {
std::printf("HOSTNAME\n");
arg_type = 2;
}
cout << "argc: " << argc << ", argv: " << host << endl;
WSADATA wsaData;

getchar();

// Initialize WinSock in your project only once!
WORD wVersionRequested = MAKEWORD(2,2);
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
printf("WSAStartup error %d\n", WSAGetLastError ());
WSACleanup();
return -1;
}


printf ("-----------------\n");

// print our primary/secondary DNS IPs
DNS mydns;
string dnsIP = "";
mydns.printDNSServer (dnsIP);

printf ("-----------------\n");

CPU cpu;
// average CPU utilization over 500 ms; must sleep *after* the constructor of class CPU and between calls to GetCpuUtilization
Sleep (500);
// now print
double util = cpu.GetCpuUtilization (NULL);
printf ("current CPU utilization %f%%\n", util);

printf ("-----------------\n");

// thread handles are stored here; they can be used to check status of threads, or kill them
HANDLE *ptrs = new HANDLE [2];
Parameters p;

// create a mutex for accessing critical sections (including printf)
p.mutex = CreateMutex (NULL, 0, NULL);

// create a semaphore that counts the number of active threads
p.finished = CreateSemaphore(NULL, 0, 2, NULL);
p.eventQuit = CreateEvent (NULL, true, false, NULL);

// get current time
DWORD t = timeGetTime();

// structure p is the shared space between the threads
ptrs[0] = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)make_thread, &p, 0, NULL);
ptrs[1] = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)make_thread, &p, 0, NULL);

// make sure this thread hangs here until the other two quit; otherwise, the program will terminate prematurely
WaitForSingleObject(p.finished, INFINITE);
WaitForSingleObject(p.finished, INFINITE);

// ---------------------------- testing the DNS query --------

// string host = "www.yahoo.com" ;
// string host = "7.74.238.131.in-addr.arpa";
int pkt_size = sizeof(FixedDNSheader) + sizeof(QueryHeader) + host.size() + 2; //+1 byte for "size" for last substring, +1 for "0" meaning the end of question

char* pkt = new char [pkt_size];

FixedDNSheader * dHDR = (FixedDNSheader *) pkt;
QueryHeader *qHDR = (QueryHeader*) ( pkt+ pkt_size -sizeof (QueryHeader) );

dHDR->ID = htons(102);
dHDR->questions = htons(1);
dHDR->addRRs = 0;
dHDR->answers = 0;
dHDR->authRRs = 0;
dHDR->flags = htons( DNS_QUERY | DNS_RD | DNS_STDQUERY );
// dHDR->flags = htons( 0x0100 );

int position = host.find (".");
string sub_str;

int i = 0, sub_size = 0, hdr_size = sizeof(FixedDNSheader);

host +="." ;
while ( position != -1 )
{
sub_size = position - i;
sub_str = host.substr( i, position );

pkt[hdr_size + i] = sub_size; // specify the size of the chunk (subdomain)
i++;
memcpy ( pkt + hdr_size + i, sub_str.c_str(), sub_size ); // specify the actual subdomain

i += sub_size;
position = host.find (".", i );
}
pkt[hdr_size+i]= 0;

qHDR->qclass = htons(DNS_INET);
// qHDR->qclass = htons( 0x0001);

// if hostname
if (arg_type == 2) {
qHDR->type = htons(DNS_A);
}
// if IP
else if (arg_type == 1) {
qHDR->type = htons(DNS_PTR); // for reverse dns lookup
}

Winsock ws;

SOCKET sock = ws.OpenSocket(); // defined in winsock.h

// set up the address of where we're sending data
struct sockaddr_in send_addr ;
send_addr.sin_family = AF_INET;
send_addr.sin_addr.S_un.S_addr = inet_addr( dnsIP.c_str() ); // 208.67.222.222
send_addr.sin_port = htons ( 53 );

int send_addrSize= sizeof(struct sockaddr_in);

int sentbytes = sendto (sock, pkt, pkt_size, 0, (struct sockaddr*) &send_addr, send_addrSize );
cout<<"sentbytes=" << sentbytes <<endl;

for ( int i = 0; i< pkt_size; i++)
{
cout << "i= " << i << " " << pkt[i] << endl;
}
cout << endl;

char recv_buf [512];

int recvbytes = 0;
if (sentbytes > 0)
recvbytes = recvfrom (sock, recv_buf, 512, 0, (sockaddr *)&send_addr, &send_addrSize);

cout<< "recv_bytes=" << recvbytes <<endl;

FixedDNSheader * rDNS = (FixedDNSheader *) recv_buf;
cout << "ID=" << ntohs( dHDR->ID )<< "??" << ntohs( rDNS->ID )<<endl;
cout << "questions=" << ntohs( rDNS->questions ) <<endl;
cout << "Answers=" << ntohs( rDNS->answers )<<endl;
cout << "authRRs="<<ntohs( rDNS->authRRs) <<endl;
cout << "addRRs=" << ntohs( rDNS->addRRs )<<endl;

printf ( "flag 0x=%x\n", ntohs( rDNS->flags ) ) ;
unsigned short rcode = 0x0F;
rcode = rcode & ntohs( rDNS->flags );
rcode = rcode & ntohs( rDNS->flags );
cout<<"Rcode= " << rcode <<endl; ;

// for debugging:
// for ( int i = 0; i< recvbytes; i++)
// {
// printf("%x\t", i, recv_buf[i] );
// }
// cout<<endl;


closesocket(sock);

delete[] pkt;


printf ("Terminating main(), completion time %d ms\n", timeGetTime() - t);

getchar();

WSACleanup();

return 0;
}

@@ -0,0 +1,32 @@

#include "winsock.h"


SOCKET Winsock::OpenSocket (void)
{
// open a UDP socket
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); //SOCK_DGRAM for UDP sockets
if(sock == INVALID_SOCKET)
{
printf ("socket() generated error %d\n", WSAGetLastError ());
WSACleanup ();
exit (-1); // not graceful, but sufficient for our purposes
}

struct sockaddr_in bind_addr;

// bind to the local address and port 0
bind_addr.sin_family = AF_INET;
bind_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // INADDR_ANY: choose the local address of this computer
bind_addr.sin_port = htons (0); // 0: let OS select the next available port on which
// the UDP sock listens for incoming response

if (bind (sock, (struct sockaddr*) &bind_addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
{
printf ("Bind failed with %d\n", WSAGetLastError());
exit (-1);
}

// then sendto and recvfrom
return sock;
}
@@ -0,0 +1,18 @@
/* winsock.h
CPS 472 Sample Code
Define a class that handles socket APIs
*/


//#pragma once
#include <stdio.h>
#include <winsock2.h>
#include <time.h>

class Winsock {

public:
SOCKET OpenSocket (void);

};