Intranet Journal   Earthweb  
Events Jobs Premium Services Media Kit Network Map E-mail Offers Vendor Solutions Webcasts

   Intranet Journal Subjects
Search Earthweb

Privacy Policy



internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

internet commerce
Be a Commerce Partner
















 

[ Home | Discussion Forum | How Do I... | Lotus Notes Intranets | Microsoft SharePoint | Products | Shopping  ]

free news!


porting of linux code to visual c++


[ Follow Ups ] [ Post Followup ] [ Intranet eXchange ] [ IDM Home ]


Posted by charles annan on October 14, 2003 at 13:59:4:

could you please help me port the following code from linux to visual c++


*
* This is the main program at the mobile side
* file name: cipmobile.c
* related files: cipmobile_pcap.c cipmobile.h Makefile
*
* The main functions are:
* Activate the packet filter
* Set the appropriate mobile's state (IDLE/ACTIVE)
* create a dummy packet (page-update, route-update)
* transmit dummy packets (page-updae, route-update)
* reset inter page-update, route-update timers
* process handoff; forced handoff and SNR based automatic handoff
* manage Base Station by beacon signal
***************************************************************************/

#include "cipmobile.h"

int STATE; //indicate whether mobile is idle or active

int main(int argc, char *argv[])
{
struct ip *ip, *ip_hdr;
struct ether_header *e_hdr;

//variables for time stamp
float cur_time; //current time
float last_AC; //time when mobile has received
//downlink packet from BS
float last_idle; //time when the latest uplink packet
//is sent from mobile in idle state
float last_SU; //time when the latest uplink packet
//is sent from mobile in active state

// variables for packet capture filter
pcap_t *pd; //packet capture descriptor
int pfd; //file descriptor for packet capture filter
char pcap_filter[200];

//buffer for packets received
char *PKTS;

//arguments for 'select'
fd_set idle_rset, active_rset;
struct timeval idle_tv, active_tv;

int i, n, len, result;


/* Initialization */

// read configuration from the file
if(argv[1] == NULL)
parseConfFile("cipmobile.conf", &cfg);
else
parseConfFile(argv[1], &cfg);

// create channel to communicate with tcl/tk process
// sockets are used for communication with tcl/tk
create_channel();

// initialize data structure for beacon signal strength measurement
bzero((char *)&baseInfo[0], sizeof(baseInfo));

// make sure that NumofBS has proper value
if (NumofBS > IW_MAX_SPY) {
printf("main in cipmobile.c: NumbofBS should be less than IW_SPY_MAX");
exit(1);
}

// initially, assume acitve basestation is 0;
currentBS = 0;
strongBS = 0;
second_strongBS = 0;

// create thread for beacon signal meanagement
pthread_create(&bs_thread, NULL, (void *)thread_handle_beacon, (void *)baseInfo);


// build a basic packet to transmit to BS (uplink packet)
build_packet();

// initial mobile's STATE is idle
STATE = 0;

// create pcap filter
build_filter(pcap_filter);

// open pcap for wireless interface
pd = cg_open_pcap(cfg.name,200, 0, pcap_filter);
if (pd == NULL) {
perror("main in cipmobile.c: cannot open PCAP");
exit(1);
}
pfd = pcap_fileno(pd);

/*
if (ioctl(pfd, BIOCIMMEDIATE, &immediate) < 0)
perror("ioctl failed");
*/
// Initialize time
local_time(&last_idle);


/* Packet Processing in mobile */

// Inside of "while" below is forever loop.
// It is the impelementation of state behabor of mobile host.
// For detail information about state refer to 'cip draft'.

while(1) {

/* mobile is idle */
// - check if there is downlink or uplink packet and classify it.
// if there is downlink packet, change mobile's state to active
// - send page-update periodically
// - check forced hand-off
{
idle_tv.tv_sec = 0;
idle_tv.tv_usec = 10;

while (STATE == 0) {

// waiting for the event that a packet is captured
FD_ZERO(&idle_rset);
FD_SET(pfd, &idle_rset);
if (select(pfd+1, &idle_rset, NULL, NULL, &idle_tv) <0) {
#ifdef DEBUG
perror("select: error while idle state");
#endif
continue;
}

// check if the captured packet is downlink or uplink
if (FD_ISSET(pfd, &idle_rset) && \
((PKTS = my_next_packet(pd, &len)) != NULL)) {
// this means we have a packet, let's use mobile state machine
e_hdr = (struct ether_header *)PKTS;
ip = (struct ip *)(PKTS + sizeof(struct ether_header));

// It is a downlink data packet (packets from BS to the mobile)
// and thus activate the mobile's state
if (ip->ip_dst.s_addr == cfg.ip) {
local_time(&cur_time);
#ifdef D_DEBUG
printf(" %f ", cur_time);
printf("DOWN DATA %s --->", inet_ntoa(ip->ip_src));
printf(" %s\n", inet_ntoa(ip->ip_dst));
#endif
#ifdef DEBUG
printf("\n************ IDLE >>>>> ACTIVE ************\n");
#endif
STATE = 1;
local_time(&last_AC);
}

// It is a uplink packet (packets from mobile to BS)
// There're three kinds of uplink packet:
// Page-update packet, Route-update packet, and data packet
else {

if (ip->ip_p == IPPROTO_CIPPU) { //packet is page-update
local_time(&cur_time);
#ifdef D_DEBUG
printf(" %f ", cur_time);
printf("UP PAGE UPDATE %s --->", inet_ntoa(ip->ip_src));
printf(" %s\n", inet_ntoa(ip->ip_dst));
#endif
local_time(&last_idle);
}

else if (ip->ip_p == IPPROTO_CIPRU) { //packet is route-update
local_time(&cur_time);
#ifdef DEBUG
printf(" %f ", cur_time);
printf("UP Route UPDATE %s --->", inet_ntoa(ip->ip_src));
printf(" %s\n", inet_ntoa(ip->ip_dst));
#endif
local_time(&last_idle);
}

else { // packet is data
local_time(&cur_time);
#ifdef D_DEBUG
printf(" %f ", cur_time);
printf("UP DATA %s --->", inet_ntoa(ip->ip_src));
printf(" %s\n", inet_ntoa(ip->ip_dst));
#endif
local_time(&last_idle);
} // page update or route update or data

} //else: uplink packet (page-update, route-update, or data)
} //if: downlink or uplink


//While mobile is idle, send Page-update periodically to BS
{
local_time(&cur_time);
if (cur_time > (last_idle + (float)cfg.paging_timeout/1000)) {
//we need to send a new page pkt
local_time(&last_idle);
e_hdr = (struct ether_header *) full_pkt;
ip_hdr = (struct ip*)(full_pkt + sizeof(struct ether_header));
ip_hdr->ip_p = IPPROTO_CIPPU;
len = (sizeof(struct ether_header) + sizeof(struct udp_pkt));
result = write(pfd, full_pkt, len); //transmit a page update
if (result <= 0)
perror("main in cipmobile.c: couldn't transmit page update packet");
#ifdef D_DEBUG
printf(" Page Update.......\n");
#endif
}
} //sending page-update

// Check whether user forced a handoff to another BS
check_forced_handoff(pfd);

} //while (STATE == 0)
}


/* mobile is active */
// - check if there is downlink or uplink packet and classify it.
// Downlink packet: beacon signal or data packet
// Uplink packet: data or route-update packet
// - check if mobile can keep active state
// - send route-update periodically
// - check forced hand-off
{
active_tv.tv_sec = 0;
active_tv.tv_usec = 10;

while (STATE == 1) {

// waiting for the event that a packet is captured
FD_ZERO(&active_rset);
FD_SET(pfd, &active_rset);
if (select(pfd+1, &active_rset, NULL, NULL, &active_tv) <0) {
#ifdef DEBUG
perror("select: error while active state");
#endif
continue;
}

//check if the packet is downlink or uplink
if (FD_ISSET(pfd, &active_rset) && \
((PKTS = my_next_packet(pd, &len)) != NULL)) {
// this means we have a packet
e_hdr = (struct ether_header *)PKTS;
ip = (struct ip *)(PKTS + sizeof(struct ether_header));

// check if it is beacon signal from BS (Downlink packet)
if (!memcmp(e_hdr->ether_dhost, &beacon_dst, 6*sizeof(u_char))) {
handle_beacon(PKTS);
}
else {
//Downlink data packet
if(ip->ip_dst.s_addr == cfg.ip) {
#ifdef D_DEBUG
printf(" %f ", last_AC);
printf("DOWN DATA %s --->", inet_ntoa(ip->ip_src));
printf(" %s\n", inet_ntoa(ip->ip_dst));
#endif
local_time(&last_AC);
}
//Uplink routing update packet
else if (ip->ip_p == IPPROTO_CIPRU) {
#ifdef D_DEBUG
printf(" %f ", last_AC);
printf("UP SHOW_UP %s --->",inet_ntoa(ip->ip_src));
printf(" %s\n", inet_ntoa(ip->ip_dst));
#endif
local_time(&last_SU);
}
//Uplink data packet
else {
#ifdef D_DEBUG
printf(" %f ", last_AC);
printf("UP DATA %s --->", inet_ntoa(ip->ip_src));
printf(" %s\n", inet_ntoa(ip->ip_dst));
#endif
local_time(&last_SU);
}
} //else: uplink packet (route-update or data)
} //if: downlink or uplink packet

{
//If no packets received (downlink packet) for a designated while,
//chane mobile's state to idle
local_time(&cur_time);
if (cur_time > (last_AC + (float)cfg.as_timeout/1000)) {
STATE = 0;
local_time(&last_idle);
#ifdef DEBUG
printf("\n********* ACTIVE >>>>> IDLE *********\n");
#endif
}

// While mobile is active, send Route-update periodically to BS
else if (cur_time > (last_SU + (float)cfg.route_timeout/1000)) {
local_time(&last_SU);
e_hdr = (struct ether_header *) full_pkt;
ip_hdr = (struct ip*)(full_pkt + sizeof(struct ether_header));
ip_hdr->ip_p = IPPROTO_CIPRU;
len = sizeof(struct ether_header) + sizeof(struct ip) \
+ sizeof(struct udphdr);
result = write(pfd, full_pkt, len); //check for errors
if (result <= 0)
perror("main in cipmobile.c: couldn't transmit route update packet");
#ifdef D_DEBUG
printf(" Route Update.\n");
#endif
}
}

// Check whether user forced a handoff to another BS
check_forced_handoff(pfd);

} //while (STATE == 1)
}
} // end of forever loop "while"

return 0;
}


/*------------------------------------------------------------------*/
/* Check whether user has force handoff or requested SNR based */
/* handoff in the tcl/tk window */
/*------------------------------------------------------------------*/
void check_forced_handoff(int pfd)
{
char recvline[10];
int n, len, result;
fd_set rset;
struct timeval tv;

if(memset(recvline, 0, 10) == NULL) {
perror("check_forced_handoff: fail to memset");
exit(1);
}

FD_ZERO(&rset);
FD_SET(sd_ho, &rset);
tv.tv_sec = 0;
tv.tv_usec = 10;

if (select(sd_ho+1, &rset, NULL, NULL, &tv) > 0) {
if(FD_ISSET(sd_ho, &rset) && ((n = read(sd_ho, recvline, 10)) > 0)) {
// User has forced handoff
if(!strncmp(recvline, "handoff", 7)) {
printf("\n* Forced handoff\n\n");

cfg.handoff = 0; //change it to regular automatic handoff mode
forced_handoff();

len = sizeof(struct ether_header) + sizeof(struct ip) + \
sizeof(struct udphdr);
result = write(pfd,full_pkt, len);
if (result <= 0)
perror("check_forced_handoff: \
couldn't transmit page or route update packet initiated by forced handoff");
}
// User has requested SNR based auto handoff
else if(!strncmp(recvline, "SNRbase", 7)) {
printf("\n* SNR based Handoff is initiated ***\n\n");
cfg.handoff = 1;
}
}
}
}


/*------------------------------------------------------------------*/
/* currently signal measurement of aironet card is not working */
/* properly. */
/* only explicit forced handoff is available in arionet card. */
/*------------------------------------------------------------------*/
void handle_beacon(char * beacon_pkt)
{
struct in_addr ia;
int targetBS_index;
u_char *targetBS_ip;
struct ip *ip_hdr;

#ifdef WICACHE
//beacon signal packet has been received.
//measure SNR per beacon and compute average
wi_readcache(cfg.name, beacon_pkt);

//SNR based auto handoff
if(cfg.handoff) {
// check if handoff is needed
targetBS_index = need_handoff(currentBS);

if((targetBS_index != -1) && (targetBS_index != currentBS)) {
printf("###### SNR based HANDOFF to BS(%d) ######\n", targetBS_index);

{ /* handoff process */
//update gateway ip address of control packet
if(baseInfo[currentBS].gwId != baseInfo[targetBS_index].gwId) {
modify_gw_ip(full_pkt, baseInfo[targetBS_index].gwId);
}

// change currently active BS
currentBS = targetBS_index;

ip_hdr = (struct ip*)(full_pkt + sizeof(struct ether_header));

// change the packet type
if(STATE == 1)
ip_hdr->ip_p = IPPROTO_CIPRU; //route-update
else
ip_hdr->ip_p = IPPROTO_CIPPU; //page-update

// change the destination ethernet address of outgoing packet
modify_dest_mac(full_pkt, baseInfo[currentBS].bs_ether);

// show ip address of active base station in tcl/tk
ia.s_addr = baseInfo[targetBS_index].bsId;
targetBS_ip = inet_ntoa(ia);
write(sd_bs, targetBS_ip, strlen(targetBS_ip));
} /* handoff process */
}
}
#else

# ifdef ANCACHE
an_readcache(cfg.name, beacon_pkt);
# endif

#endif

}


/*------------------------------------------------------------------*/
/* build basic packet used for route-update and page-update */
/*------------------------------------------------------------------*/
void build_packet()
{
int len, src_prt, dst_prt;
struct udp_pkt pkt;
struct ether_header *e_hdr;
struct ip *ip_hdr;
u_long src_addr,dst_addr;

src_addr = cfg.ip;
dst_addr = 0;

src_prt=12153;
dst_prt=6451;

/* FILL HEADERS */

/* IP header */
memset(&pkt, 0, psize);
pkt.ip.ip_v = IPVERSION;
pkt.ip.ip_hl = 5 ;
pkt.ip.ip_tos = 1;
pkt.ip.ip_len = htons(psize); //for Linux
pkt.ip.ip_id = 0;
pkt.ip.ip_ttl = 255;
pkt.ip.ip_src.s_addr = src_addr;
pkt.ip.ip_dst.s_addr = dst_addr;
pkt.ip.ip_p = IPPROTO_CIPPU; //default is page-update packet

/* udp header */
pkt.udp.source = htons(src_prt);
pkt.udp.dest = htons(dst_prt);
pkt.udp.len = htons(sizeof(struct udphdr) + PADDING);
pkt.udp.check = 0;

/* Building basic packet (full_pkt) */
len = sizeof(struct ether_header) + sizeof(struct ip) + \
sizeof(struct udphdr)+PADDING;
full_pkt = (u_char *)malloc(len);
if (full_pkt == NULL) {
perror("build_packet: fail to allocating memory");
exit(1);
}
//Initialize full_pkt
bzero((u_char *)full_pkt, len);

e_hdr = (struct ether_header *) full_pkt;
ip_hdr = (struct ip*)(full_pkt + sizeof(struct ether_header));

// get src mac address
get_MAC_addr(e_hdr->ether_shost, cfg.name);

// set dest mac address to initial value (ff:ff:ff:ff:ff:ff)
e_hdr->ether_dhost[0] = 0xff; e_hdr->ether_dhost[1] = 0xff;
e_hdr->ether_dhost[2] = 0xff; e_hdr->ether_dhost[3] = 0xff;
e_hdr->ether_dhost[4] = 0xff; e_hdr->ether_dhost[5] = 0xff;

e_hdr->ether_type = 0x08; //must be not ETHERTYPE_IP but 0x08
//for the compatibility with BSD
// e_hdr->ether_type = ETHERTYPE_IP;

// build ip, udp field
memcpy(full_pkt + sizeof(struct ether_header), &pkt, psize);

//build checksum
ip_hdr->ip_sum = 0;
ip_hdr->ip_sum = checksum((u_short*)ip_hdr, ((u_short)(ip_hdr->ip_hl))*4);

}


/*------------------------------------------------------------------*/
/* Build packet capture filter */
/*------------------------------------------------------------------*/
void build_filter(char *pcap_filter)
{
struct in_addr ia;
char temp_str[20];

ia.s_addr = cfg.ip;

strcpy(pcap_filter, "src host ");
sprintf(temp_str, "%s", inet_ntoa(ia));
strcat(pcap_filter, temp_str);
strcat(pcap_filter, " or dst host ");
sprintf(temp_str, "%s", inet_ntoa(ia));
strcat(pcap_filter, temp_str);

#ifdef DEBUG
printf("\n* pcap_filter = %s\n", pcap_filter);
#endif
}


/*------------------------------------------------------------------*/
/* Calculate checksum for outgoing packet */
/*------------------------------------------------------------------*/
unsigned short checksum(unsigned short *data, unsigned short length)
{
register long value = 0;
unsigned short i;

for(i = 0; i < (length >> 1); i++)
value += data[i];

if ((length & 1) == 1)
value += (data[i] << 8);

value = (value & 65535) + (value >> 16);

return(~value);
}


/*------------------------------------------------------------------*/
/* Time stamp function */
/*------------------------------------------------------------------*/
void local_time(float *t)
{
struct timeval tv;
float decimal,entero1, entero2;

if (gettimeofday(&tv, NULL) < 0)
perror("local_time: error in gettimeofday");

decimal = tv.tv_usec*0.000001;
entero1 = (tv.tv_sec / 1000000);
entero2 = tv.tv_sec - (1000000 * entero1);
*t = entero2 + decimal;
}


/*------------------------------------------------------------------*/
/* Parse the configuration file */
/* Read the configuration file and fill out the Configuration */
/* data structure defined in the header file */
/*------------------------------------------------------------------*/
void parseConfFile(char *filename, struct Configuration *conf)
{
FILE *confFile;
unsigned int max_char = 200;
char tempChar, tempStr[max_char];
char *item;
int i = 0;

confFile = fopen(filename, "r");
if(!confFile) {
printf("parseConfFile: No configuration file !\n");
exit(1);
}
while((tempChar = getc(confFile)) != EOF)
{
i = 0;
ungetc(tempChar, confFile); //Put it back
fgets(tempStr, max_char, confFile);
/* parse our fgets string */
if(tempStr[0] == '%' || tempStr[0] == '\n' ||
tempStr[0] == '\t' || tempStr[0] == ' ') {
/* Don't parse this line, just skip it */
continue;
}

item = (char*)getParaName(tempStr, &i);
i++; //skip colon

//wireless interface
if(!strcmp(item, "wireless interface")) {
item = (char*)getStringToken(tempStr, &i);
if(item != NULL)
conf->name = item;
else {
printf("parseConfFile: interface name is missing!\n");
exit(1);
}
#ifdef DEBUG
printf("* name = %s\n", item);
#endif
continue;
}
else if(!strcmp(item, "mobile's IP address")) {
item = (char*)getStringToken(tempStr, &i);
if(item != NULL)
conf->ip = inet_addr(item);
else {
printf("parseConfFile: mobile's IP is missing!\n");
exit(1);
}
#ifdef DEBUG
printf("* ip address = %s\n", item);
#endif
continue;
}
else if(!strcmp(item, "air interface name")) {
item = (char*)getStringToken(tempStr, &i);
if(item != NULL)
conf->ai_name = item;
else {
printf("parseConfFile: air interface name is missing!\n");
exit(1);
}
#ifdef DEBUG
printf("* air interface = %s\n", item);
#endif
continue;
}
else if(!strcmp(item, "route-update-time")) {
item = (char*)getStringToken(tempStr, &i);
if(item != NULL)
conf->route_timeout = atoi(item);
else {
printf("parseConfFile: route-update-time is missing!\n");
exit(1);
}
#ifdef DEBUG
printf("* route-update-time = %s\n", item);
#endif
continue;
}
else if(!strcmp(item, "paging-update-time")) {
item = (char*)getStringToken(tempStr, &i);
if(item != NULL)
conf->paging_timeout = atoi(item);
else {
printf("parseConfFile: paging-upate-time is missing!\n");
exit(1);
}
#ifdef DEBUG
printf("* paging-update-time = %s\n", item);
#endif
continue;

}
else if(!strcmp(item, "acitve-state-timeout")) {
item = (char*)getStringToken(tempStr, &i);
if(item != NULL)
conf->as_timeout = atoi(item);
else {
printf("parseConfFile: acitve-state-timeout is missing!\n");
exit(1);
}
#ifdef DEBUG
printf("* active-state-time = %s\n", item);
#endif
continue;
}
else if(!strcmp(item, "handoff")) {
item = (char*)getStringToken(tempStr, &i);
if(item != NULL)
conf->handoff = atoi(item);
else {
printf("parseConfFile: handoff is missing!\n");
exit(1);
}
#ifdef DEBUG
printf("* handoff = %s\n", item);
#endif
continue;
}
else
continue;
}
}

/*------------------------------------------------------------------*/
/* Read name of each item in configuration file */
/*------------------------------------------------------------------*/
char *getParaName(char *string, int *pos)
{
char *newString = (char*)malloc(sizeof(char) * 50);
int i = 0;

while(string[*pos] != '\n'&& string[*pos] != ':') {
newString[i++] = string[(*pos)++];
}
return(newString);
}
/*------------------------------------------------------------------*/
/* Get one token from a read line */
/*------------------------------------------------------------------*/
char *getStringToken(char *string, int *pos)
{
char *newString = (char*)malloc(sizeof(char) * 50);
int i = 0;

while(string[*pos] == ' ')(*pos)++; //remove blank
while(string[*pos] != '\n'&& string[*pos] != ':'
&& string[*pos] != ' ' && string[*pos] != '%'
&& string[*pos] != ',' && string[*pos] != ')') {
newString[i++] = string[(*pos)++];
}
if(!strcmp(newString, "")) {
return NULL;
}
else return(newString);
}

/*------------------------------------------------------------------*/
/* Get ethernet address of interface */
/* input: interface name output: ethernet address */
/*------------------------------------------------------------------*/
void get_MAC_addr(u_char *mac, char *if_name)
{
int fd;
struct sockaddr *hw_addr;
struct ifreq ifr;

if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("get_MAC_addr: fail to open socket");
exit(1);
}

memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));

if (ioctl(fd, SIOCGIFHWADDR, (char *)&ifr) < 0) {
perror("get_MAC_addr: fail SIOCGIFHWADDR ioctl");
close(fd);
exit(1);
}

hw_addr = (struct sockaddr *) &ifr.ifr_hwaddr;

memcpy(mac, (u_char *)hw_addr->sa_data, sizeof(u_char)*6);
}


/*------------------------------------------------------------------*/
/* Print out ethernet address */
/*------------------------------------------------------------------*/
void
ether_print(u_char *ea)
{
printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
}

/*------------------------------------------------------------------*/
/* Create socket to communicate with tcl/tk program. */
/* Base station data, handoff data are exchanged between */
/* cipmobile(c program) and cip(tcl/tk) program over channel. */
/*------------------------------------------------------------------*/
void
create_channel()
{
int listenfd, clilen;
struct sockaddr_in cliaddr, servaddr;

listenfd = socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(9877);

bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listenfd, 1024);

clilen = sizeof(cliaddr);
sd_bs = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
printf("\nconnection established %d\n", sd_bs);

sd_ho = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
printf("connection established %d\n", sd_ho);

sd_ss = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
printf("connection established %d\n", sd_ss);
}

/*------------------------------------------------------------------*/
/* Aironet card: */
/* This function should read cache for signal measurement */
/* and get the average based on beacon signal. */
/* But signal measurement is not working properly for aironet card */
/* so only base station information is taken from beacon. */
/*------------------------------------------------------------------*/
#ifdef ANCACHE
static void an_readcache(char *iface, char *beacon_pkt)
{
int i;
int found=0, inserted=0;
int BS_index;
int empty_index = -1;
int max_age;
struct ether_header *e_hdr;
struct in_addr ia;

if (iface == NULL) {
printf("an_readcache: must specify interface name");
exit(1);
}

e_hdr = (struct ether_header *)beacon_pkt;

for (i=(NumofBS-1); i >= 0; i--) {

//skip empty items
//fill_cache flag indicate if the cache is filled(=1) or empty(=0)
if (baseInfo[i].fill_cache == 0) {
empty_index = i;
continue;
}

//aging
baseInfo[i].age++;

//Remove and free the cache item that exceeds the MAX_AGE_LIMIT
if (baseInfo[i].age > MAX_AGE_LIMIT) {
#ifdef DEBUG
ia.s_addr = baseInfo[i].bsId;
printf("\n--- deleting BS[%d] : ", i);
printf("* IP address %s\n\n", inet_ntoa(ia));
#endif
//bzero((char *)&baseInfo[i], sizeof(struct baseInfo));
baseInfo[i].fill_cache = 0;
}

//find the BS cache for the beacon signal with aging items
if (memcmp(baseInfo[i].bs_ether, e_hdr->ether_shost,\
sizeof(char)*6) == 0) {
baseInfo[i].age = 0; //reset age
BS_index = i; //the found cached BS item
found++;
}
} //for

//Only one cache item is supposed to exist for one BS
if (found > 1) {
printf("an_readcache: more than one cache for one BS");
exit(1);
}

//the BS cache for the beacon signal is found
//Since Aironet card does not support SPY function for signal measurement,
//there's nothing to do
else if (found == 1)
return;

//It is a new BS. Just insert it.
else { //found == 0

if (empty_index >= 0) { //BS cache is not full
inserted = insert_BS (empty_index, beacon_pkt);
}

else { //BS cache is full. Then, replace one with the oldest age

BS_index = 0; //initial cadidate for replacement
max_age = 0;
for (i=0; i < NumofBS; i++) {
if (baseInfo[i].age > max_age) {
max_age = baseInfo[i].age;
BS_index = i;
}
}
//Insert the new BS info
inserted = insert_BS (BS_index, beacon_pkt);
}

if (!inserted) {
printf("wi_readcache: cannot insert the new BS information");
exit(1);
}

} //else: found == 0

}
#endif


/*------------------------------------------------------------------*/
/* Function to insert a new BS information in the cache */
/*------------------------------------------------------------------*/
int insert_BS (int BS_index, char *beacon_pkt)
{
struct ether_header *e_hdr;
struct in_addr ia;
int i;

e_hdr = (struct ether_header *)beacon_pkt;

//the cache item is filled
baseInfo[BS_index].fill_cache = 1;

//initialize age
baseInfo[BS_index].age = 0;

//the new BS's ethernet address
memcpy(baseInfo[BS_index].bs_ether, e_hdr->ether_shost, ETH_ALEN);

//the new BS's IP address
memcpy(&ia, beacon_pkt+37, sizeof(ia));
baseInfo[BS_index].bsId = ia.s_addr;

//Gateway IP address of the new BS's beacon signal
memcpy(&ia, beacon_pkt+57, sizeof(ia));
baseInfo[BS_index].gwId = ia.s_addr;

#ifdef WICACHE
//the BS is active
baseInfo[BS_index].active = 1;
//Initializing
baseInfo[BS_index].index = 0;
baseInfo[BS_index].sum = 0;
baseInfo[BS_index].average = 0;
for (i=0; i < NumofBeacon; i++) {
baseInfo[BS_index].bcInfo[i].signal = 0;
baseInfo[BS_index].bcInfo[i].noise = 0;
baseInfo[BS_index].bcInfo[i].quality = 0;
}
#endif

#ifdef DEBUG
ia.s_addr = baseInfo[BS_index].bsId;
printf("\n+++ inserting BS[%d] : ", BS_index);
printf("* IP address %s\n\n", inet_ntoa(ia));
#endif
return 1;
}


/*------------------------------------------------------------------*/
/* WaveLAN card: */
/* Set and read SPY cache for signal measurement and get the average*/
/* based on the series of beacon signal from BS so as to enable SNR */
/* based auto handoff. This is only for WaveLAN card. */
/* If there is beacon signal from new BS, insert the BS information */
/* in the cache and set SPY for the new BS. */
/* The BS from which there has not been beacon signal is removed */
/* from the cache. */
/*------------------------------------------------------------------*/
#ifdef WICACHE
static void wi_readcache(char *iface, char *beacon_pkt)
{
int i;
int found=0, updated=0, inserted=0;
int BS_index, weak_BS;
int empty_index = -1;
int spyed;
int max_age;
struct ether_header *e_hdr;
struct in_addr ia;
struct sockaddr *hw;
struct iw_quality *qual;

if (iface == NULL) {
printf("wi_readcache: must specify interface name");
exit(1);
}

//get the currently spyed information
spyed = wi_spy_get(iface);

hw = (struct sockaddr *)spy_get_buffer;
qual = (struct iw_quality *) \
(spy_get_buffer + (sizeof(struct sockaddr) * spyed));
e_hdr = (struct ether_header *)beacon_pkt;

for (i=(NumofBS-1); i >= 0; i--) {
//skip empty items in cache
//fill_cache flag indicate if the cache is filled(=1) or empty(=0)
if (baseInfo[i].fill_cache == 0) {
empty_index = i;
continue;
}

//aging
baseInfo[i].age++;

//Check BS is active
if ((baseInfo[i].age > MAX_AGE_FOR_ACTIVE_BS) && \
(baseInfo[i].active == 1)) {
baseInfo[i].active = 0;
#ifdef DEBUG
ia.s_addr = baseInfo[i].bsId;
printf("\n* Is the BS down? Deactivating BS[%d] : ", i);
printf(" IP address %s\n\n", inet_ntoa(ia));
#endif
}

//Remove and free the cache item that exceeds the MAX_AGE_LIMIT
if (baseInfo[i].age > MAX_AGE_LIMIT) {
#ifdef DEBUG
ia.s_addr = baseInfo[i].bsId;
printf("\n--- deleting BS[%d] : ", i);
printf(" IP address %s\n\n", inet_ntoa(ia));
#endif
//bzero((char *)&baseInfo[i], sizeof(struct baseInfo));
baseInfo[i].fill_cache = 0;
}

//find the BS cache for the beacon signal
if (memcmp(baseInfo[i].bs_ether, e_hdr->ether_shost,\
6*sizeof(char)) == 0) {
baseInfo[i].age = 0; //reset age for the active BS
//so, active BS keep young
BS_index = i; //the found cached BS item
found++;
}
} //for

//Only one cache item is supposed to exist for one BS
if (found > 1) {
printf("wi_readcache: more than one cache for one BS");
exit(1);
}

else if (found == 1) { //the BS cache for the beacon signal is found
if (baseInfo[BS_index].active == 1) { //this is active BS
for (i=0; i < spyed; i++) {
if (memcmp(baseInfo[BS_index].bs_ether, hw[i].sa_data, \
ETH_ALEN) == 0) {
updated = update_BS (BS_index, &qual[i]);
break;
}
}

if (!updated) {
printf("wi_readcache: cannot find spy_cache entry for the BS");
exit(1);
}
}
else { //baseInfo[BS_index].active == 0: this is a reactivated BS
//reactivate and just add this BS again to the SPYed items
baseInfo[BS_index].active = 1; //reactivate the BS
wi_spy_set(iface); //Setting SPY
#ifdef DEBUG
ia.s_addr = baseInfo[BS_index].bsId;
printf("\n* Reactivating BS[%d] : ", BS_index);
printf("* IP address %s\n\n", inet_ntoa(ia));
#endif
}
} //found == 1

else { //found == 0
//It is a new BS.
//Insert it to the cache and Add the new BS to the spyed items.

if (empty_index >= 0) { //BS cache is not full.
inserted = insert_BS (empty_index, beacon_pkt);
wi_spy_set(iface); //Setting
}

else {
//BS cache is full -_-...we should find a whipping goat.
//Replace one with the oldest age
//If the oldest age is too young to be replaced (which means
//all BS in the cache is currently active,)
//Find the BS with the weakest signal strength

BS_index = 0; //Oldest BS
weak_BS = 0; //Weakest BS
max_age = 0;
for (i=0; i < NumofBS; i++) {
if (baseInfo[i].age > max_age) {
max_age = baseInfo[i].age;
BS_index = i;
}
if (baseInfo[i].average < baseInfo[weak_BS].average) {
weak_BS = i;
}
}

if (max_age > MIN_AGE_FOR_REPLACED) {
//Replace the new BS info with the old-aged BS
inserted = insert_BS (BS_index, beacon_pkt);
//Set SPYed BSs
wi_spy_set (iface); //Setting
}
else {
//Replace the new BS info with the weakest BS
inserted = insert_BS (weak_BS, beacon_pkt);
//Set SPYed BSs
wi_spy_set (iface); //Setting
}
}//else

if (!inserted) {
printf("wi_readcache: cannot insert the new BS information");
exit(1);
}

} //found == 0
}
#endif


/*------------------------------------------------------------------*/
/* Function to update BS information in the cache */
/* This is only for WaveLAN card. */
/*------------------------------------------------------------------*/
#ifdef WICACHE
int update_BS (int BS_index, struct iw_quality *quality)
{
int i, max_avg;

//the BS is active
baseInfo[BS_index].active = 1;

if (baseInfo[BS_index].index == NumofBeacon)
baseInfo[BS_index].index = 0;

//update 'sum' & 'average' based on the new beacon signal
if (baseInfo[BS_index].bcInfo[baseInfo[BS_index].index].quality != 0) {
//cache for beacon signal was full
baseInfo[BS_index].sum -= baseInfo[BS_index].\
bcInfo[baseInfo[BS_index].index].quality;
baseInfo[BS_index].sum += quality->qual;
baseInfo[BS_index].average = baseInfo[BS_index].sum / NumofBeacon;
}

else { //there a empty item for cache for beacon signal
baseInfo[BS_index].sum += quality->qual;
baseInfo[BS_index].average = baseInfo[BS_index].sum /
(baseInfo[BS_index].index+1);
}
#ifdef DEBUG
//printf("\nBS[%d]: sum = %d; average = %d\n", BS_index, \
baseInfo[BS_index].sum, baseInfo[BS_index].average);
#endif

//update 'quality', 'level', and 'noise'
baseInfo[BS_index].bcInfo[baseInfo[BS_index].index].quality = quality->qual;
baseInfo[BS_index].bcInfo[baseInfo[BS_index].index].signal = quality->level;
baseInfo[BS_index].bcInfo[baseInfo[BS_index].index].noise = quality->noise;
baseInfo[BS_index].index += 1;

//update strongBS and second_strongBS
//First, check whether strongBS and second strongBS is active
//The strongBS and second_strongBS should be active
{
if ((baseInfo[strongBS].active != 0) && \
(baseInfo[second_strongBS].active != 0)) {
if (baseInfo[BS_index].average > baseInfo[strongBS].average) {
second_strongBS = strongBS;
strongBS = BS_index;
}
}
else if ((baseInfo[strongBS].active == 0) && \
(baseInfo[second_strongBS].active != 0)) {
if (baseInfo[BS_index].average > baseInfo[second_strongBS].average) {
strongBS = BS_index;
//second_strongBS is same one.
}
else {
strongBS = second_strongBS;
second_strongBS = BS_index;
//Actually, BS_index could not be second strongBS.
//But, it doesn't matter because it'll be updated soon!
}
}
else if ((baseInfo[strongBS].active != 0) && \
(baseInfo[second_strongBS].active == 0)) {
if (baseInfo[BS_index].average > baseInfo[strongBS].average) {
second_strongBS = strongBS;
strongBS = BS_index;
}
else {
second_strongBS = BS_index;
//Actually, BS_index could not be second strongBS.
//But, it doesn't matter because it'll be updated soon!
}
}
else { //worst case: both strongBS and second_strongBS is inactive -_-
//some processing load seems inevitable
//find the active strongBS and second_strongBS
max_avg = 0;
strongBS = BS_index;
second_strongBS = BS_index;
for (i=0; i < NumofBS; i++) {
if (baseInfo[i].active == 0)
continue;
if (baseInfo[i].average > max_avg) {
max_avg = baseInfo[i].average;
second_strongBS = strongBS;
strongBS = i;
}
}
}
}

return 1;
}
#endif


/*------------------------------------------------------------------*/
/* Function to set the items that will be SPYed in the driver. */
/* This is only for WaveLAN card. */
/*------------------------------------------------------------------*/
#ifdef WICACHE
static void wi_spy_set(char *iface)
{
struct sockaddr *hw;
struct iwreq wrq;
int spyed;
int i, r;

spyed = 0;
bzero(spy_set_buffer, sizeof(spy_set_buffer));
hw = (struct sockaddr *)spy_set_buffer;

//Set active BSs as the SPYed items
{
for (i=0; i < NumofBS; i++) {
if (baseInfo[i].active == 1) {
memcpy((char *)hw[spyed].sa_data, \
(char *)baseInfo[i].bs_ether, 6*sizeof(char));
spyed++;
}
}

//Set SIOCSIWSPY ioctl
memcpy(wrq.ifr_name, iface, IFNAMSIZ);
wrq.u.data.pointer = (caddr_t) spy_set_buffer;
wrq.u.data.length = spyed;
wrq.u.data.flags = 0;

r = ioctl(cfg.sock, SIOCSIWSPY, &wrq);
if (r < 0) {
perror("wi_spy_set: fail SIOCSIWSPY ioctl");
close(cfg.sock);
exit(1);
}
}
}
#endif


/*------------------------------------------------------------------*/
/* Function to get the SPYed information. */
/* This is only for WaveLAN card. */
/*------------------------------------------------------------------*/
#ifdef WICACHE
static int wi_spy_get(char *iface)
{
struct iwreq wrq;
int r;

memcpy(wrq.ifr_name, iface, IFNAMSIZ);
bzero(spy_get_buffer, sizeof(spy_get_buffer));
wrq.u.data.pointer = (caddr_t) spy_get_buffer;
wrq.u.data.length = 0;
wrq.u.data.flags = 0;

r = ioctl(cfg.sock, SIOCGIWSPY, &wrq);

if (r < 0) {
perror("wi_spy_get: fail SIOCGIWSPY ioctl");
close(cfg.sock);
exit(1);
}
return (wrq.u.data.length);
}
#endif


/*------------------------------------------------------------------*/
/* Decide whether mobile station needs to handoff */
/* If quality is above DESPERATE_HANDOFF_LEVEL it hands off only if */
/* difference of acitve and strong signal is larger than */
/* HANDOFF_WINDOW */
/* This function is currently only for WaveLAN card */
/*------------------------------------------------------------------*/
#ifdef WICACHE
int need_handoff(int activebs)
{
int i;

//There are two urgent situations that should be dealt immediately:
// 1. current BS's age is over MAX_AGE_FOR_ACTIVE_BS and thus it's state
// is inactive (which may mean the BS currently do not work.)
// 2. the signal from current BS is too weak

if ((baseInfo[activebs].active == 0) || \
(baseInfo[activebs].average < DESPERATE_HANDOFF_LEVEL)) {
//go to the any base station which has better quality than current one
if (activebs != strongBS) {
return strongBS;
}
else if (activebs != second_strongBS) {
return second_strongBS;
}
//need new base station to handoff but no candidate BS
else
return -1; //handoff is needed but cannot!
}

else if((baseInfo[strongBS].average - baseInfo[activebs].average) > HANDOFF_WINDOW){
#ifdef DEBUG
printf("\nAverage: strongBS[%d] - currentBS[%d] = %d\n", strongBS, activebs, \
baseInfo[strongBS].average - baseInfo[activebs].average);
printf("Handoff_window = %d\n", HANDOFF_WINDOW);
#endif
return strongBS;
}
else
return -1; // no handoff
}
#endif


/*------------------------------------------------------------------*/
/* Replace the destination mac addr. of the packet */
/* with provided address */
/*------------------------------------------------------------------*/
void modify_dest_mac(char *pkt, char *mac)
{
struct ether_header *e_hdr;
e_hdr = (struct ether_header*)pkt;
memcpy(e_hdr->ether_dhost, mac, 6 * sizeof(u_char));
printf(" New destination MAC addr: ");
ether_print(e_hdr->ether_dhost);
}


/*------------------------------------------------------------------*/
/* update gateway ip address in control packet */
/*------------------------------------------------------------------*/
void modify_gw_ip(char *pkt, u_long ip_addr)
{
struct ip *ip_hdr;
ip_hdr = (struct ip*)(pkt + sizeof(struct ether_header));
ip_hdr->ip_dst.s_addr = ip_addr;
ip_hdr->ip_sum = 0;
ip_hdr->ip_sum = checksum((u_short*)ip_hdr, 20);

printf("\n* New GW IP: %s\n", inet_ntoa(ip_hdr->ip_dst));
}


/*------------------------------------------------------------------*/
/* Set default base station that has the strongest beacon signal */
/* as default route */
/*------------------------------------------------------------------*/
void set_default_router()
{
pid_t childpid;
int status;
struct in_addr ia;

// char str[50];

#ifdef DEBUG
printf("\n* Setting default route with the current Base Station.\n");
#endif

if((childpid = fork()) == 0) {
ia.s_addr = baseInfo[strongBS].bsId;
//This command is to remove default route
system("route del default\n");
// sprintf(str, "route add default gw %s\n", inet_ntoa(ia));
// system(str);
// execlp("route", "route", "del", "default", NULL);
//Add default route
execlp("route", "route", "add", "default", "gw", inet_ntoa(ia), "netmask","0x00000000", NULL);

perror("set_default_router: fail to set default route");
exit(1);
}

else {
pid_t pid;

if (childpid < 0) {
perror("set_defauly_router: fork error");
exit(1);
}

pid = wait(&status);

#ifdef DEBUG
printf("Child %d completed with status %d\n", (int)pid, status);
#endif

}
}


/*------------------------------------------------------------------*/
/* this function is call when you press "Handoff now" in tcl/tk */
/*------------------------------------------------------------------*/
void forced_handoff()
{
int targetBS = -1;
int i;
char *targetBS_ip;
struct in_addr ia;
struct ip *ip_hdr;

//Find the next BS that is active.
//Handoff will be performed to the found BS
#ifdef WICACHE
for (i=1; i < NumofBS; i++) {
if (baseInfo[(currentBS+i)%NumofBS].active == 1) {
targetBS = (currentBS+i)%NumofBS;
break;
}
}
#else
# ifdef ANCACHE
for (i=1; i < NumofBS; i++) {
if (baseInfo[(currentBS+i)%NumofBS].fill_cache == 1) {
targetBS = (currentBS+i)%NumofBS;
break;
}
}
# endif
#endif


if (targetBS < 0) {
#ifdef DEBUG
printf("\n* forced_handoff: Only one BS; No handoff can be forced.\n");
#endif
return;
}

ia.s_addr = baseInfo[targetBS].bsId;
targetBS_ip = inet_ntoa(ia);
printf("****** Forced HANDOFF to %s ******\n", targetBS_ip);

/* handoff process */
{
//update gateway ip address of control packet
if(baseInfo[currentBS].gwId != baseInfo[targetBS].gwId) {
modify_gw_ip(full_pkt, baseInfo[targetBS].gwId);
}

//change the current BS to the targeted BS for handoff
currentBS = targetBS;

ip_hdr = (struct ip*)(full_pkt + sizeof(struct ether_header));

// change the packet type
if(STATE == 1)
ip_hdr->ip_p = IPPROTO_CIPRU;
else
ip_hdr->ip_p = IPPROTO_CIPPU;

// change the destination ethernet address of outgoing packet
modify_dest_mac(full_pkt, baseInfo[currentBS].bs_ether);

// show ip address of active base station in tcl/tk
write(sd_bs, targetBS_ip, strlen(targetBS_ip));

} /* handoff process */
}

/*------------------------------------------------------------------*/
/* create one thread that handles beacon signal */
/*------------------------------------------------------------------*/
void thread_handle_beacon()
{
pcap_t *thread_pd;
char *thread_pkts, *arg, temp[20];
int thread_pfd, thread_len, default_rt;
u_char *targetBS_ip;
struct ether_header *e_hdr;
struct in_addr ia;

char beacon_id = 0xef;
//the value to identify beacon signal.
//beacon signal's 26th char should have this value

//create pcap filter for beacon signals
// strcpy(arg, "ether dst ");
strcpy(arg, "ether host ");
sprintf(temp, "%02X:%02X:%02X:%02X:%02X:%02X", \
beacon_dst[0], beacon_dst[1], beacon_dst[2], \
beacon_dst[3], beacon_dst[4], beacon_dst[5]);
strcat(arg, temp);

#ifdef DEBUG
printf("\n* Argument for pcap open: %s\n", arg);
#endif

//open pcap for wireless interface
//In fact, the promiscuous mode for this pcap open should be inactive(i.e., 0)
//but, it doesn't work with 0. So, I used 1 instead of 0.
//possible bug of tcpdump??
thread_pd = cg_open_pcap(cfg.name, 200, 1, arg);
if (thread_pd == NULL) {
perror("thread_handle_beacon: cannot open PCAP");
exit(1);
}
thread_pfd = pcap_fileno(thread_pd);

//These are only for WaveLAN
#ifdef WICACHE
//open socket for SPY function
cfg.sock = socket(AF_INET, SOCK_DGRAM, 0);
if (cfg.sock == -1) {
perror("thread_handle_beacon: cannot open socket");
exit(1);
}
//initialize the SPYed items.
bzero(spy_set_buffer, sizeof(spy_set_buffer));
wi_spy_set(cfg.name);
#endif

/* Handle beacon signals */
{
default_rt = 1;

while (1) {
if ((thread_pkts= my_next_packet(thread_pd ,&thread_len)) != NULL)
{

//Firstly, examine if this is the CIP beacon
if (memcmp(thread_pkts+26, &beacon_id, sizeof(char)) != 0)
continue;

#ifdef D_DEBUG
printf("Received Beacon's ether_dst\n");
e_hdr = (struct ether_header *)thread_pkts;
ether_print(e_hdr->ether_dhost);
#endif
handle_beacon(thread_pkts);

// These are done only once at the initial time.
if (default_rt) {
#ifdef DEBUG
printf("* Updating route.\n");
#endif
//set default router
set_default_router();

// update gateway ip address of control packet
modify_gw_ip(full_pkt, baseInfo[strongBS].gwId);

// update dest ethernet address of control packet
modify_dest_mac(full_pkt, baseInfo[strongBS].bs_ether);

//show ip address of active base station in tcl/tk
ia.s_addr = baseInfo[strongBS].bsId;
targetBS_ip = inet_ntoa(ia);
write(sd_bs, targetBS_ip, strlen(targetBS_ip));

default_rt = 0;
}
}
}
} /* Handle beacon signals */
}

/*
cipmobile_pcap.c
*
*/

#include <sys/types.h>
#include <sys/socket.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pcap/pcap.h>

#include "cgmpd_extern.h"

#ifndef lint
static char rcsid[] =
"$Id: cgmpd_pcap.c,v 1.2 1998/03/22 17:31:26 wpaul Exp wpaul $";
#endif

#define PCAP_CMD "dst host 128.59.69.22 or src host 128.59.69.22"
#define MAXLINE 1024
#ifdef INET_ADDRSTRLEN
# undef INET_ADDRSTRLEN
# define INET_ADDRSTRLEN 1024
#endif
#define USE_PROMISC

pcap_t *cg_open_pcap(interface, snaplen, pro_mode, pcap_filter)
char *interface;
int snaplen;
int pro_mode;
char *pcap_filter;
{
bpf_u_int32 localnet, netmask;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fcode;
pcap_t *pd;
int datalink;


#ifdef USE_PROMISC
pd = pcap_open_live(interface, snaplen, pro_mode, 10, errbuf);
// printf("Finish\n");
#else
pd = pcap_open_live(interface, snaplen, pro_mode, 10, errbuf);
// printf("Finish\n");
#endif

if (pd == NULL) {
printf("%s\n", errbuf);
return(NULL);
}

if (pcap_lookupnet(interface, &localnet, &netmask, errbuf) == -1) {
printf("%s\n", errbuf);
pcap_close(pd);
return(NULL);
}
if (pcap_compile(pd, &fcode, pcap_filter, 0, netmask) == -1) {
printf("%s\n", errbuf);
pcap_close(pd);
return(NULL);
}
if (pcap_setfilter(pd, &fcode) == -1) {
printf("%s\n", pcap_geterr(pd));
pcap_close(pd);
return(NULL);
}

if ((datalink = pcap_datalink(pd)) == -1) {
printf("%s\n", pcap_geterr(pd));
pcap_close(pd);
return(NULL);
}

//printf("datalink: %d\n", datalink);
if (datalink != DLT_EN10MB) {
printf("only 10Mb/sec ethernet supported\n");
pcap_close(pd);
return(NULL);
}

return(pd);
}

void cg_close_pcap(pd)
pcap_t *pd;
{
pcap_close(pd);
return;
}


char *cg_next_pkt(pd, len)
pcap_t *pd;
int *len;
{
char *ptr;
struct pcap_pkthdr hdr;

/* while((ptr = (char *)pcap_next(pd, &hdr)) == NULL) ; */

ptr = (char *)pcap_next(pd, &hdr);
*len = hdr.caplen;
return(ptr);
}


struct singleton {
struct pcap_pkthdr *hdr;
const u_char *pkt;
};

static void
my_pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
{
struct singleton *sp = (struct singleton *)userData;
*sp->hdr = *h;
sp->pkt = pkt;
}


int my_pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int cc;

//if (p->sf.rfile != NULL)
// return (pcap_offline_read(p, cnt, callback, user));
/* XXX keep reading until we get something (or an error occurs) */
//do {
// cc = pcap_read(p, cnt, callback, user);
//} while (cc == 0);
//cnt = 1;
cc = pcap_read(p, cnt, callback, user);
//printf("yeah!!! i am in user space\n");
return (cc);
}


const u_char * my_pcap_next(pcap_t *p, struct pcap_pkthdr *h)
{
struct singleton s;

s.hdr = h;
if (my_pcap_dispatch(p, 1, my_pcap_oneshot, (u_char*)&s) <= 0)
return (0);
return (s.pkt);
}


char *my_next_packet(pd, len)
pcap_t *pd;
int *len;
{
char *ptr;
struct pcap_pkthdr hdr;

ptr = (char *)my_pcap_next(pd, &hdr);

*len = hdr.caplen;
return(ptr);
}


/*
cipmobile.h
*
* Header file for cipmobile.c
*/

#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <err.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <pcap/pcap.h>
#include <linux/wireless.h>

#include "cgmpd_extern.h"


/* Defines */

#define PADDING 0 /* Size of data in struct udp_pkt */

#define IPPROTO_CIPPU 200 /* CellularIP page-update type */
#define IPPROTO_CIPRU 201 /* CellularIP route-update type */

#define NumofBeacon 5 /* Number of Beacon signal cached */
/* for a Base Station */

#define NumofBS 5 /* Number of Base Station */
/* NumofBS should be less than IW_MAX_SPY*/
/* Currently, IW_MAX_SPY = 8 */

#ifdef WICACHE
# define HANDOFF_WINDOW 15 /* Handoff decision window */
# define DESPERATE_HANDOFF_LEVEL 10 /* The level that need desperate handoff */

# define MAX_AGE_FOR_ACTIVE_BS (2*NumofBS) /* Max age for a active BS */
# define MIN_AGE_FOR_REPLACED (600*NumofBS)
/* Min age for replacing a BS cache with */
/* a new BS */
#endif

#define MAX_AGE_LIMIT 30 /* Max age for a BS's information to */
/* keep cached. */

/* Structures */

struct Configuration {
char *name; /* interface name */
u_long ip; /* mobile's IP address */
char *ai_name; /* air interface name */
int freq; /* frequency */
int nwid; /* nwid */
unsigned int route_timeout; /* route cache timeout */
unsigned int paging_timeout; /* page cache timeout */
unsigned int as_timeout; /* active state time out */
int handoff; /* automatic or based on SNR */
#ifdef WICACHE
int sock; /* socket descriptor for SPY ioctl */
/* of this interface */
#endif
};

struct udp_pkt {
struct ip ip;
struct udphdr udp;
char data[PADDING]; /*currently, not used */
};

struct beaconInfo{ /* structure for a beacon signal */
int signal; /* signal strength of beacon signal */
int noise; /* noise level of beacon signal */
int quality; /* quality level of beacon signal */
} beaconInfo;

struct baseInfo { /* structure for a Base Station */
u_long bsId; /* BS's IP address */
u_long gwId; /* BS's Gateway IP address */
char bs_ether[6]; /* BS's MAC address of wireless interface */
int fill_cache; /* indicate BS info is currently stored at cache */
int age; /* age incease while the BS is inactive */
#ifdef WICACHE
int active; /* indicate whether the BS is currently active */
int index; /* index for the BS's beacon signal info (bcInfo) */
int sum; /* sum of quality level of the cached beacon signal*/
int average; /* average quality level of beacon signals */
struct beaconInfo bcInfo[NumofBeacon];
/* cached info of beacon signals from the BS */
#endif
};


/* Global variables */

struct Configuration cfg; /* configuration read from "cipmobile.conf" */
struct baseInfo baseInfo[NumofBS]; /* cache for BSs */
struct udp_pkt pkt;

int udplen=sizeof(struct udphdr);
int iplen=sizeof(struct ip);
int psize=sizeof(struct udphdr)+sizeof(struct ip)+PADDING;
int currentBS; /* index for baseInfo structures of the currently used BS */
int strongBS; /* index for baseInfo structures of the BS whose average */
/* quality level is currently highest and the strongest */
/* candidates for handoffs */
int second_strongBS; /* index for BS with the second strongest signal level */
/* this is needed for urgent handoff */
int sd_bs, sd_ho, sd_ss; /* socket descriptor to communicate with */
/* cip(Tcl/Tk) program */
u_char *full_pkt; /* buffer for packets sent by this mobile*/
/* : data, page-update, route-update */
u_char beacon_dst[6] = {0x09, 0x00, 0x0e, 0x20, 0x03, 0x00};
//u_char beacon_dst[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
/* Beacon signal's destination MAC addr: Broadcasting MAC addr */

pthread_t bs_thread; /* thread identifier for the thread for */
/* beacon signal management */
#ifdef WICACHE
char spy_set_buffer[(sizeof(struct sockaddr)) * IW_MAX_SPY];
/* buffer for SIOCSIWSPY ioctl */
char spy_get_buffer[(sizeof(struct sockaddr) + sizeof(struct iw_quality)) \
* IW_MAX_SPY]; /* buffer for SIOCGIWSPY ioctl */
#endif


/* Functions */

void check_forced_handoff(int);
void handle_beacon(char *);
void build_packet();
void build_filter(char *);
unsigned short checksum(u_short *, u_short );
void local_time(float *);
void parseConfFile(char *, struct Configuration *);
char *getParaName(char *, int *);
char *getStringToken(char *, int *);
void get_MAC_addr(u_char *, char *);
void ether_print(u_char *);
void create_channel();
#ifdef ANCACHE
static void an_readcache(char *, char *);
#endif
int insert_BS (int, char *);
#ifdef WICACHE
static void wi_readcache(char *, char *);
int update_BS (int, struct iw_quality *);
static void wi_spy_set(char *);
static int wi_spy_get(char *);
int need_handoff(int);
#endif
void modify_dest_mac(char *, char *);
void modify_gw_ip(char *, u_long ip_addr);
void set_default_router();
void forced_handoff();
void thread_handle_beacon();

CC = gcc
CFLAG = -g -I/usr/include/pcap
LIBS =
PACKAGE = cipnode cipmobile RegCenter


all: start ${PACKAGE}
@echo "---------------------------------------------------------------------"
@echo "Compilation is completed! Enjoy it"

start:
@clear
@echo "Compiling, please wait..."
@echo "---------------------------------------------------------------------"

cipnode: cipnode.o cip_pcap.o Advertisement.o CheckandDecap.o
${CC} ${CFLAG} -o cipnode cipnode.o cip_pcap.o Advertisement.o CheckandDecap.o -lpcap -lpthread

cipnode.o: cipnode.c cipnode.h
${CC} ${CFLAG} -c cipnode.c -DDEBUG_ -DMOBILE_IP_

cip_pcap.o: cip_pcap.c cip_pcap.h cipnode.h
${CC} ${CFLAG} -c cip_pcap.c

Advertisement.o: Advertisement.c
${CC} ${CFLAG} -c Advertisement.c

CheckandDecap.o: CheckandDecap.c
${CC} ${CFLAG} -c CheckandDecap.c -DDEBUG_

RegCenter: RegisterCenter.c
${CC} ${CFLAG} -o RegCenter RegisterCenter.c -DDEBUG_

cipmobile: cipmobile.o cipmobile_pcap.o
${CC} ${CFLAG} -o cipmobile cipmobile.o cipmobile_pcap.o -lpcap -lpthread

cipmobile.o: cipmobile.c cipmobile.h cgmpd_extern.h
${CC} ${CFLAG} -c cipmobile.c -DWICACHE -DANCACHE_ -DDEBUG_ -DD_DEBUG_

cipmobile_pcap.o: cipmobile_pcap.c cgmpd_extern.h
${CC} ${CFLAG} -c cipmobile_pcap.c

clean:
rm -f cipnode cipmobile RegCenter core *.o





Follow Ups:



Post a Followup

Name:     
E-Mail:   
Subject:  
Message:

Optional Link URL: 
Link Title:        

      




[ Follow Ups ] [ Post Followup ] [ Intranet eXchange ] [ IDM Home ]


email this page

Tutorials
and more at:
Intranet Journal's Tutorials
Intranet Journal Favorites

Creating a PHP-Based Content Management System

The Spyware Guide

Introduction to Microsoft SharePoint Portal

Intranet Journal
Part of the EarthWeb Network

Managing Editor
Intranet Journal

Tom Dunlap

EarthWeb Home Page
Jupitermedia Home Page

Media Kit



internet.commediabistro.comJusttechjobs.comGraphics.com

Search:

WebMediaBrands Corporate Info

Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
Advertise | Newsletters | Shopping | E-mail Offers | Freelance Jobs