📄 agent.c
字号:
/*---------------------------------------------------------------------------- Copyright (C) 1995-6, Vipul Gupta and Abhijit Dixit. Created 1995-6. All rights reserved. Linux-Mobile-IP An implementation of Mobile IP for the LINUX operating system developed at the State University of New York, Binghamton (with partial support from the Center for Computing Technologies). Except as noted in the accompanying documentation, this implementation complies with revision 16 of the Internet Engineering Task Force (IETF) Mobile-IP draft. More information can be obtained from: http://anchor.cs.binghamton.edu/~mobileip/ Version: 1.00 05/23/1996 Authors: Abhijit Dixit <abhijit@cs.binghamton.edu> Vipul Gupta <vgupta@cs.binghamton.edu> Benjamin Lancki <ben@anchor.cs.binghamton.edu> Permission is hereby granted to redistribute this code and/or modify it under the terms of the GNU Genral Public License as published by the Free Software Foundation; either version two or (at your option) any later version provided this ENTIRE notice is retained in any copies or any part of this software. A copy of the GNU General Public License can be obtained by contacting the Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA. -----------------------------------------------------------------------------*//* agent.c - Design of the Mobile Agent (either home agent or * foreign agent). * * Command line arguments: * -a : agent's IP address on the network on which it supports mobility * -m : network mask corresponding to the IP address above * -h : hardware address of the mobility interface (used for proxies * and used only if this agent is a home agent * -i : Network interface name (eg eth0) on which MHs are supported. * * * * * * History of Changes: * Jul 25, 1995 First version coded - V.G. * Jul 31, 1995 Removed calls to GETRT - V.G. * Aug 1, 1995 Removed bug in sendRefusal and reorganized * it to improve efficiency - V.G. * Aug 9, 1995 Added support for MD5 authentication in * processing the registration and registration * reply - B.L. * Aug 13, 1995 Agent now reads config file /etc/mip-mh.ok to * initialize mhinfo struct - B.L. * Aug 14, 1995 Agent keeps a log in event of system crash * or shutdown and recovers on startup - B.L. * * Sept 22, 1995 Foreign agent has become more active. * Registerme and Regreply are sent to * foreign agent and foreign agent forwards * it -A.D. * * Sept 30, 1995 Agent does not exit when select * fails on INTR -A.D. * * Oct 2, 1995 huphandler added to toggle between * sending URHere and not sending URhere * on SIGHUP signal-A.D. * * Oct 3, 1995 URhere mesgs are now sent to link level * broadcast address -A.D. * * * Oct 6, 1995 Command line arguments changed. * Wired address is no more required so * removed from command line. * network interface is now command line * parameter -A.D. * * Oct 8, 1995 Agent does not exit when sendto fails * because of network or host unreachable * condition. -A.D. * * Nov 10, 1995 Due to addition of a 'special sleep' * agent consumes very little cpu time. -A.D. * * Dec 5, 1995 Router discovery messages are changed to use * ICMP. -A.D. * * May 1996 Agent now sends gratuitous ARP when it * starts Proxy ARPing for the MH. -A.D. * * May 1996 Agent now sends rejection to Deregistration * also on local network. -A.D * */ #include <stdio.h>#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <signal.h>#include <unistd.h>#include <stdlib.h>#include <netinet/ip.h>#include "messages.h"#include "low.h"#include "agent.h"#define SLEEPINTERVAL 0.5 /* second */#define ALARMINTERVAL 1 char DEVICE[32];int debug = 2;unsigned int sendURhere_flag = 1; extern void testprint(char *,int);extern int in_cksum(u_short *addr,int len);void sendReply(unsigned short, int, int, unsigned long, unsigned long, unsigned long, struct id);voidsendConfirm(unsigned short, int, int, unsigned long, unsigned long, unsigned long, int);voidsendRefusal(unsigned short, int, int, unsigned long, unsigned long, unsigned long, int);voidsendRefusalVMH(unsigned short fromport,int code,int time, unsigned long homeaddr,unsigned long ha,int vmh);void delay();extern void appendauth(char *,int *,char *,int,unsigned long);extern int authextfound(char *,int,int);extern int authok(char *,int,int,char *,int,unsigned long);extern void printext(char *,int,int);extern void printtime();extern int errno;extern void readvmhdata(char *); extern void readlog(char *), writelog(char *);void usage(char *), cleanup();int URheresid, Regreplysid; /* for sending, these could be the same */int WhereAmIsid; int RegisterMesid; /* for listening to requests, these are * bound to different ports */ int RegMeVMHid, RegReplyHAid; /* for sending and receiving regme for visiting MH and reg reply from HA of visiting MH respectively */int ioctlsid; /* for all kinds of low level ioctl calls */unsigned long tunnelbitvec = 0; /* a bit vector to track tunnels in use */char supportedMHnum = 0; /* # MHs we are configured to serve in mip-mh.ok */ char supportedVMHnum = 0; /* # VMHs we are configured to serve in mip-vmh.ok */char proxyHwAddr[7]; /* hw address to use for proxy ARP */unsigned long haAddr; /* home agent address */unsigned long haNetmask; /* home agent's network mask */struct sockaddr_in URhereto = { (short) AF_INET, (unsigned short) 0, (unsigned long) 0, (unsigned long) 0, (unsigned long) 0 };mhdata mhinfo[MAXMHNUM+1]; /* zeroth mh is not really used */ vmhdata vmhinfo[MAXMHNUM+1];struct stats { unsigned long badwhereami; unsigned long badregisterme; unsigned long mhprohibited; unsigned long idmismatch; unsigned long authfailed; unsigned long noresources; unsigned long successfulreg;} agentstats = { (long) 0, (long) 0, (long) 0, (long) 0, (long) 0, (long) 0, (long) 0 };voidinitsockets() { struct sockaddr_in sa; int enable = 1; Regreplysid = socket(AF_INET, SOCK_DGRAM, 0); WhereAmIsid = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); RegisterMesid = socket(AF_INET, SOCK_DGRAM, 0); ioctlsid = socket(AF_INET, SOCK_DGRAM, 0); RegReplyHAid = RegMeVMHid = socket(AF_INET, SOCK_DGRAM, 0); URheresid = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); if (Regreplysid < 0 || URheresid < 0 || WhereAmIsid < 0 || RegisterMesid < 0 || RegReplyHAid <0 ||ioctlsid < 0) { fprintf(stderr, "initsockets(): could not create sockets.\n"); exit(-1); } sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = 0; if (bind(Regreplysid, (struct sockaddr *) &sa, sizeof(sa)) < 0) { perror("initsockets(): Bind Regreplysid failed.\n"); cleanup(); exit(-1); } if (setsockopt(URheresid, SOL_SOCKET, SO_BROADCAST, (char *)&enable, sizeof(int)) < 0) { perror("initsockets(): setsockopt SO_BROADCAST failed"); cleanup(); exit(-1); } sa.sin_port = htons(MIPREGPORT); if (bind(RegisterMesid, (struct sockaddr *) &sa, sizeof(sa)) < 0) { perror("initsockets(): Bind RegisterMesid failed.\n"); cleanup(); exit(-1); } sa.sin_port = 0; /* FA can send to HA on any port */ sa.sin_addr.s_addr = haAddr; if (bind(RegReplyHAid, (struct sockaddr *) &sa, sizeof(sa)) < 0) { perror("initsockets(): Bind RegisterMesid failed.\n"); cleanup(); exit(-1); } if (debug > 0) fprintf(stderr, "Initialized sockets ...\n");}voidcleanup() { /* down all tunnels that we could have created and remove * proxy arps for all MHs we support if the arp HWaddr in * those entries is our own */ int i; for (i = 0; i < MAXTUNNELS; i++) lowifacereq(DOWN, i, 0, 0); for (i = 0; i < MAXMHNUM; i++) lowARPreq(REM0, mhinfo[i].ipaddr, proxyHwAddr); if (debug > 1) fprintf(stderr, "Done cleaning up ...\n");}voidgraceful_exit() { cleanup(); writelog("/usr/adm/mip-ha.log"); exit(0);}voidnewId(struct id *id1, struct id *id2) { static int count = 0; struct timeval tv; if (count++ == 0) { gettimeofday(&tv, NULL); srandom((int) tv.tv_usec); }; id1->high = (unsigned long) random(); id1->low = id2->low;} void sendURhere(struct sockaddr_in *toaddr) { static struct urhmsg { struct icmp icp; struct youarehere URh; unsigned long addr1; } mesg; static u_short seqno = 0; if (debug > 2) fprintf(stderr, "Sending a URhere message to %s \n", inet_ntoa(toaddr->sin_addr)); else if (debug > 0) fprintf(stderr, "."); /* fill the buffer appropriately and send */ mesg.icp.type = ROUTERADVTYPE; /* router advertisement */ mesg.icp.code = 0; mesg.icp.cksum = 0; mesg.icp.addrnum = 0; mesg.icp.addr_entry_size =0; mesg.icp.lifetime = 6 ; /* 3*period of URhere mesg. */ mesg.URh.type = YOUAREHERETYPE; /* Mobile serv ext */ mesg.URh.length = 10; /* 6 + 4*N bytes where N is # of addresses(1) */ mesg.URh.seqno = seqno++; mesg.URh.lifetime = MAXLIFETIME; mesg.URh.flags = MSRFLAG|MSHFLAG|MSFFLAG; mesg.addr1 = haAddr; mesg.icp.cksum = in_cksum((u_short*)&mesg,sizeof(struct urhmsg)); if(!seqno)seqno = 256; if (sendto(URheresid, (char *) &mesg, sizeof(mesg), 0, (struct sockaddr *) toaddr, sizeof(struct sockaddr)) < 0) { perror("sendURhere(): sendto failed.\n"); fprintf(stderr,"Send Addr: %s at %d\n", inet_ntoa(toaddr->sin_addr), (unsigned int) toaddr->sin_port); if(errno == ECONNREFUSED || errno == ENETUNREACH || errno == EHOSTUNREACH); else { cleanup(); exit(-1); } } }voidupdate_lifetimes() { /* Walk through the list of MH for which TUNNELUP is set and * decrement lifetimes. * If lifetime becomes zero or less, stop supporting this * MH i.e. * (a) remove its routing table entry, (route del ipaddr) * (b) destroy its tunnel name (ifconfig tunnelname down) * (c) stop proxying for this MH by removing its arp entry * (arp -d ipaddr) * (d) reset the TUNNELUP flag, timeleft, coaddr and * are set to 0. Tunnel name becomes a null string */ int i; char devname[10]; for (i = 1; i <= supportedMHnum; i++) { if ((mhinfo[i].status & TUNNELUP) == 0) continue; if ((mhinfo[i].timeleft -= 2) <= 0) { mhinfo[i].status &= ~TUNNELUP; mhinfo[i].timeleft = 0; mhinfo[i].coaddr = 0; newId(&(mhinfo[i].RegistrationId), &(mhinfo[i].RegistrationId)); if (debug > 1) { fprintf(stderr, "\n--Registration expired for %lx\n", htonl(mhinfo[i].ipaddr)); }; lowrtreq(DELRT, mhinfo[i].ipaddr, &(mhinfo[i].tunnelnum)); lowifacereq(DOWN, mhinfo[i].tunnelnum, 0, 0); lowARPreq(REM1, mhinfo[i].ipaddr, "000000"); mhinfo[i].tunnelnum = 0; } } /* In this part we check for lifetime of visiting * mobile hosts. If lifetime becomes zero and * status = confirmed then delet existing route * for VMH */ strcpy(devname,DEVICE); for(i = 1; i<= supportedVMHnum; i++) { if(vmhinfo[i].status == 0||vmhinfo[i].status == PENDING) continue; if((vmhinfo[i].timeleft -=2) <=0){ vmhinfo[i].status &= 0x0; vmhinfo[i].timeleft = 0; lowroutset(vmhinfo[i].ipaddr,devname,DELRT); } }}void hup_handler(){sendURhere_flag = sendURhere_flag ? 0 : 1;signal(SIGHUP, hup_handler);}voidalarm_handler() { /* Check for expired regitrations and send out URhere broadcast */ update_lifetimes(); if (sendURhere_flag) sendURhere(&URhereto); /* set things up to come back to this procedure sometime soon */ signal(SIGALRM, alarm_handler); alarm(ALARMINTERVAL);}voidinit() { initsockets(); /* set up sockets for listening to requests and * sending messages */ cleanup(); /* cleanup relies on ioctlsid */ URhereto.sin_addr.s_addr = inet_addr(ADVERTISEON);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -