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:
[ Follow Ups ] [ Post Followup ] [ Intranet eXchange ] [ IDM Home ]