Networking 209
This reveals that the webserver is Apache version 2.0.52 and even that
the host runs CentOS. This can be useful for profiling, so let’s write a pro-
gram that automates this manual process.
The next few programs will be sending and receiving a lot of data. Since
the standard socket functions aren’t very friendly, let’s write some functions
to send and receive data. These functions, called send_string() and recv_line(),
will be added to a new include file called hacking-network.h.
The normal send() function returns the number of bytes written, which
isn’t always equal to the number of bytes you tried to send. The send_string()
function accepts a socket and a string pointer as arguments and makes sure
the entire string is sent out over the socket. It uses strlen() to figure out the
total length of the string passed to it.
You may have noticed that every packet the simple server received ended
with the bytes 0x0D and 0x0A. This is how telnet terminates the lines—it sends
a carriage return and a newline character. The HTTP protocol also expects
lines to be terminated with these two bytes. A quick look at an ASCII table
shows that 0x0D is a carriage return ('\r') and 0x0A is the newline character
('\n').
reader@hacking:~/booksrc $ man ascii | egrep "Hex|0A|0D"
Reformatting ascii(7), please wait...
Oct Dec Hex Char Oct Dec Hex Char
012 10 0A LF '\n' (new line) 112 74 4A J
015 13 0D CR '\r' (carriage ret) 115 77 4D M
reader@hacking:~/booksrc $
The recv_line() function reads entire lines of data. It reads from the socket
passed as the first argument into the a buffer that the second argument points
to. It continues receiving from the socket until it encounters the last two line-
termination bytes in sequence. Then it terminates the string and exits the
function. These new functions ensure that all bytes are sent and receive data
as lines terminated by '\r\n'. They are listed below in a new include file called
hacking-network.h.
hacking-network.h
/* This function accepts a socket FD and a ptr to the null terminated
- string to send. The function will make sure all the bytes of the
- string are sent. Returns 1 on success and 0 on failure.
/
int send_string(int sockfd, unsigned char buffer) {
int sent_bytes, bytes_to_send;
bytes_to_send = strlen(buffer);
while(bytes_to_send > 0) {
sent_bytes = send(sockfd, buffer, bytes_to_send, 0);
if(sent_bytes == -1)
return 0; // Return 0 on send error.