WINLAB
 

Zhibin´s web templates

Zhibin ´s research

Zhibin´s web templates

Zhibin´s resume

Zhibin´s real life

Zhibin

 

 

 

 

 

 

 

C/C++ Programming

Debug with gdb

The procedures to use gdb for debugging a C program

  1. Build with an option -g

  2. gdb <program_name>

  3. set breakpoints with b <filename>:<line_number>. Remember the filename and path is relative to the location where the <program_name> is located.

  4. run <para1> <para2>....

  5. interactive commands :
    n --- next
    s --- step
    p --- print
    c --- continue
    l --- list the content of source code context

Socket Programming Example 1: Synchronize I/O Operations with Select ()

Select function is somewhat strange, but it's very useful. Take the following situation: you are a server and you want to listen for incoming connections as well as keep reading from the connections you already have.
No problem, you say, just an accept() and a couple of recv()s. Not so fast, buster! What if you're blocking on an accept() call? How are you going to recv() data at the same time? "Use non-blocking sockets!" No way! You don't want to be a CPU hog. What, then?
select() gives you the power to monitor several sockets at the same time. It'll tell you which ones are ready for reading, which are ready for writing, and which sockets have raised exceptions, if you really want to know that.
For example, in a socket program, if you have to send and recv with two different sockets in a same thread process, then it is better to use select instead of non-blocking sockets or polling. Not only recv or listen can be handled by select with read_fds, the write_fds could inculde the sending socket (whenever a tx_buffer is ready, select will return with this fd).
Following example show how to do it a UDP_SEND() function, hearing a broadcast message as well.
 
Check the example code: select_example.c

Socket Programming Example 2: RAW Socket

Doing some raw sockets programming and having some fun...this stuff has some real potential!
but having a strange bug in my ping program.....

The code comes from http://cboard.cprogramming.com/archive/index.php/t-41635.html

/*
* pinger.c
* This is a ping imitation program
* It will send an ICMP ECHO packet to the server of
* your choice and listen for an ICMP REPLY packet
* Have fun!
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <string.h>
#include <unistd.h>


char dst_addr[20];
char src_addr[20];

unsigned short in_cksum(unsigned short *, int);
void parse_argvs(char**, char*, char* );
void usage();
char* getip();
char* toip(char*);

int main(int argc, char* argv[])
{
struct iphdr* ip;
struct iphdr* ip_reply;
struct icmphdr* icmp;
struct sockaddr_in connection;
char* packet;
char* buffer;
int sockfd;
int optval;
int addrlen;
int siz;


if (getuid() != 0)
{
fprintf(stderr, "%s: root privelidges needed\n", *(argv + 0));
exit(EXIT_FAILURE);
}

parse_argvs(argv, dst_addr, src_addr);
strncpy(dst_addr, toip(dst_addr), 20);
strncpy(src_addr, toip(src_addr), 20);
printf("Source address: %s\n", src_addr);
printf("Destination address: %s\n", dst_addr);

/*
* allocate all necessary memory
*/
packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
buffer = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
/****************************************************************/

ip = (struct iphdr*) packet;
icmp = (struct icmphdr*) (packet + sizeof(struct iphdr));

/*
* here the ip packet is set up
*/
ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr);
ip->id = htons(0);
ip->frag_off = 0;
ip->ttl = 64;
ip->protocol = IPPROTO_ICMP;
ip->saddr = inet_addr(src_addr);
ip->daddr = inet_addr(dst_addr);
ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));

if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
{
perror("socket");
exit(EXIT_FAILURE);
}

/*
* IP_HDRINCL must be set on the socket so that
* the kernel does not attempt to automatically add
* a default ip header to the packet
*/

setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int));

/*
* here the icmp packet is created
* also the ip checksum is generated
*/
icmp->type = ICMP_ECHO;
icmp->code = 0;
icmp->un.echo.id = random();
icmp->un.echo.sequence = 0;
icmp-> checksum = in_cksum((unsigned short *)icmp, sizeof(struct icmphdr));


connection.sin_family = AF_INET;
connection.sin_addr.s_addr = inet_addr(dst_addr);

/*
* now the packet is sent
*/

sendto(sockfd, packet, ip->tot_len, 0, (struct sockaddr *)&connection, sizeof(struct sockaddr));
printf("Sent %d byte packet to %s\n", ip->tot_len, dst_addr);

/*
* now we listen for responses
*/
addrlen = sizeof(connection);
if (( siz = recvfrom(sockfd, buffer, sizeof(struct iphdr) + sizeof(struct icmphdr), 0, (struct sockaddr *)&connection, &addrlen)) == -1)
{
perror("recv");
}
else
{
printf("Received %d byte reply from %s:\n", siz , dst_addr);
ip_reply = (struct iphdr*) buffer;
printf("ID: %d\n", ntohs(ip_reply->id));
printf("TTL: %d\n", ip_reply->ttl);
}

free(packet);
free(buffer);
close(sockfd);
return 0;
}
void parse_argvs(char** argv, char* dst, char* src)
{
int i;
if(!(*(argv + 1)))
{
/* there are no options on the command line */
usage();
exit(EXIT_FAILURE);
}
if (*(argv + 1) && (!(*(argv + 2))))
{
/*
* only one argument provided
* assume it is the destination server
* source address is local host
*/
strncpy(dst, *(argv + 1), 15);
strncpy(src, getip(), 15);
return;
}
else if ((*(argv + 1) && (*(argv + 2))))
{
/*
* both the destination and source address are defined
* for now only implemented is a source address and
* destination address
*/
strncpy(dst, *(argv + 1), 15);
i = 2;
while(*(argv + i + 1))
{
if (strncmp(*(argv + i), "-s", 2) == 0)
{
strncpy(src, *(argv + i + 1), 15);
break;
}
i++;
}
}

}

void usage()
{
fprintf(stderr, "\nUsage: pinger [destination] <-s [source]>\n");
fprintf(stderr, "Destination must be provided\n");
fprintf(stderr, "Source is optional\n\n");
}

char* getip()
{
char buffer[256];
struct hostent* h;

gethostname(buffer, 256);
h = gethostbyname(buffer);

return inet_ntoa(*(struct in_addr *)h->h_addr);

}

/*
* return the ip address if host provided by DNS name
*/
char* toip(char* address)
{
struct hostent* h;
h = gethostbyname(address);
return inet_ntoa(*(struct in_addr *)h->h_addr);
}

/*
* in_cksum --
* Checksum routine for Internet Protocol
* family headers (C Version)
*/
unsigned short in_cksum(unsigned short *addr, int len)
{
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
/*
* 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;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
/* add 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);
}
 

 



Home  l  Research   l  Toolbox  l  Resume  l  Life  l  Contact Me

Last Updated in April, 2007 Zhibin Wu. ©All rights reserved.