📄 agent.c
字号:
/* No port # for ICMP delete later URhereto.sin_port = htons(ADVERTISETO); */ readmhdata("/etc/mip-mh.ok"); readvmhdata("/etc/mip-vmh.ok"); /* read data for visiting MH */ /* read the ipaddr, authtype and * secret for first MAXMHNUM mobile * hosts */ readlog("/usr/adm/mip-ha.log"); /* restore any state from a previous * incarnation of this daemon */ signal(SIGTERM, graceful_exit); /* terminate gracefully */ signal(SIGINT, graceful_exit); /* terminate gracefully */ signal(SIGALRM, alarm_handler); /* alarm_handler is the function * that gets called when alarm * goes off */ signal(SIGHUP, hup_handler); /* Added to toggle URH messages */ alarm(ALARMINTERVAL);}slp(double sec){ struct timeval tv; tv.tv_sec = 0; tv.tv_usec = sec*1000000 ; if((select(FD_SETSIZE, NULL, NULL, NULL, &tv)) < 0) { if(errno == EINTR || errno == ERESTART); else perror("select() failed in main loop.\n"); } }voidprocessWhereAmI(char *msg, int len, struct sockaddr_in *from) { /* if message is not of type WhereAmI, record this in a * debug log and ignore msg. Otherwise call sendURhere() * with the address and port obtained from the from * structure */ struct icmp *where; struct iphdr *ip; int iphdrlen; ip = (struct iphdr*)msg; iphdrlen = ip->ihl << 2; /* Bytes */ where = (struct icmp*)(msg+iphdrlen); if (where->type != ROUTERSOLTYPE || len < (iphdrlen + sizeof(struct icmp))) agentstats.badwhereami++; else { if (debug > 1) fprintf(stderr, "\n-- WHEREAMI from %s\n", inet_ntoa(from->sin_addr)); sendURhere(from);}} intIsOurAddress(unsigned long addr) { return((haAddr == addr) ? 1 : 0);}charnewtunnel() { char i; for (i = 1; i < MAXTUNNELS; i++) { if ((tunnelbitvec & (1 << i)) == 0) return(i); } return(0);}int whichmh(unsigned long addr) { int i; mhinfo[0].ipaddr = addr; for (i = supportedMHnum; i >= 0; i--) if (mhinfo[i].ipaddr == addr) break; return(i);}intwhichvmh(unsigned long addr) { int i; vmhinfo[0].ipaddr = addr; for(i= supportedVMHnum; i>=0; i--) if(vmhinfo[i].ipaddr == addr) break; return(i);}inthavetunnel(int mh, unsigned long coaddr) { /* Return 0 (false) or 1 (true) depending on whether we can find * an existing tunnel as required set up for the mobile host whose * mhinfo index is given in mh. This tunnel should end at * coaddr and a route to homeaddr must use the tunnel */ if ((mhinfo[mh].status & TUNNELUP) && (mhinfo[mh].coaddr == coaddr)) return (1); else return(0);}int maIdcmp(struct id *id1, struct id *id2) { return((id1->high == id2->high) ? 0:1);}voidprocessRegisterMe(char *msg, int len, struct sockaddr_in *from) { struct registerme *reg; int code = 0; int mh, vmh; int authoffset; char temp = 0; unsigned short fromport; unsigned long fromaddr; /* for sending back reg reply */ struct sockaddr_in toaddr; /* for sending mesg to HA */ if (debug > 2) fprintf(stderr, "<<<<<< Entering processRegisterMe \n"); if (debug > 0) { if (len < sizeof(struct registerme)) fprintf(stderr,"msg length short of registerme size.\n"); } reg = (struct registerme *) msg; fromport = (unsigned short) from->sin_port; fromaddr = (unsigned long) from->sin_addr.s_addr; if (debug > 0) { fprintf(stderr, "\n==========================\n"); printtime(); if (reg->lifetime == 0) fprintf(stderr, "-- DEREGISTERME from %s Port %2d\n", inet_ntoa(from->sin_addr),fromport); else fprintf(stderr, "-- REGISTERME from %s Port %2d\n", inet_ntoa(from->sin_addr), fromport); if (debug > 1) { fprintf(stderr, "[%8lx:%8lx] Type %2d Flags %2x Lifetime %8d\n", reg->Id.high, reg->Id.low, reg->type, reg->flags, reg->lifetime); fprintf(stderr, "Homeaddr: %8lx, Homeagent: %8lx, Careof: %8lx", htonl(reg->homeaddr), htonl(reg->ha), htonl(reg->coaddr)); printext(msg, len, 0); if (debug > 2) { fprintf(stderr, "\n--------------------\n"); testprint(msg, len); fprintf(stderr, "--------------------"); } } fprintf(stderr, "\n==========================\n"); } if(IsOurAddress(reg->ha)) { if(debug > 1)fprintf(stderr,"Acting as home agent...\n"); mh = 0; if (len < sizeof(struct registerme) || (reg->flags & 0x03)|| reg->type != REGISTERMETYPE || !IsOurAddress(reg->ha) || !(authoffset=authextfound(msg, len, 0))) { code = 134; /* badly formed request */ agentstats.badregisterme++; } else if ((mh = whichmh(reg->homeaddr)) == 0) { code = 129; /* administratvely prohibited */ agentstats.mhprohibited++; } else if (reg->lifetime == 0 && (reg->coaddr != mhinfo[mh].coaddr && reg->coaddr != mhinfo[mh].ipaddr)){ code = 134; agentstats.badregisterme++; } else if (maIdcmp(&mhinfo[mh].RegistrationId, &(reg->Id)) != 0) { code = 133; /* id is not quite what we expected */ agentstats.idmismatch++; } else if (reg->flags & 0x5c) { code = 128; /* reason unspecified no broadcast support no GRE encap no Van Jacobson header compession */ } else if (!authok(msg, len, authoffset, mhinfo[mh].secret, mhinfo[mh].keylen,mhinfo[mh].SPIval)) { code = 131; /* failed authentication */ agentstats.authfailed++; } /* create a new id we can use for our reply */ newId(&(mhinfo[mh].RegistrationId), &(reg->Id)); if (code) { /* Refusal */ sendRefusal(fromport, code, 0, reg->homeaddr, reg->coaddr, haAddr, mh); if (debug > 2) fprintf(stderr, "Refusal sent.\n"); /* If it was deregistration request rejection due to ID mismatch when mobile host is away, send that rejection also on local net*/ if(code == 133 && reg->lifetime == 0 && (mhinfo[mh].status & TUNNELUP)) { lowARPreq(REM0, mhinfo[mh].ipaddr, proxyHwAddr); lowrtreq(DELRT, mhinfo[mh].ipaddr, &temp); sendRefusal(fromport, code, 0, reg->homeaddr, reg->coaddr, haAddr, mh); lowARPreq(PROXY, mhinfo[mh].ipaddr, proxyHwAddr); lowrtreq(ADDRT, mhinfo[mh].ipaddr, &(mhinfo[mh].tunnelnum)); if(debug >2) fprintf(stderr, "Refusal sent on home network.\n"); } return; } /* Now we know that we are looking at a good request */ if (reg->lifetime == 0) /* We got a deregistration request */ { /* if this is a degistration request, we can always oblige. * i. make lifetime field zero, if there is a name in the * tunnel field, down it clear name Change status. Clear * coaddr field also. We can leave the RegistrationId field * unchanged. Update any statistics we maintain. code = 1 * lifetime = 0 */ mhinfo[mh].timeleft = 0; code = 1; mhinfo[mh].status &= ~TUNNELUP; mhinfo[mh].coaddr = 0; lowrtreq(DELRT, mhinfo[mh].ipaddr, &temp); lowifacereq(DOWN, mhinfo[mh].tunnelnum, 0, 0); lowARPreq(REM0, mhinfo[mh].ipaddr, proxyHwAddr); mhinfo[mh].tunnelnum = 0; agentstats.successfulreg++; sendConfirm(fromport, code, 0, reg->homeaddr, reg->coaddr, haAddr, mh); } else if (mhinfo[mh].status & TUNNELUP) { mhinfo[mh].timeleft = (reg->lifetime > MAXLIFETIME) ? MAXLIFETIME : (int) reg->lifetime; /* If S bit is set we send code =1 since this agent does not support simultaneous bindings */ if(reg->flags & 0x80) code = 1; else code = 0; if (reg->coaddr == mhinfo[mh].coaddr) { /* we have a renewal */ agentstats.successfulreg++; sendConfirm(fromport, code, mhinfo[mh].timeleft, reg->homeaddr, reg->coaddr, haAddr, mh); } else { /* the tunnel needs to be redirected */ mhinfo[mh].coaddr = reg->coaddr; lowifacereq(REDIRECT, mhinfo[mh].tunnelnum, 0, reg->coaddr); agentstats.successfulreg++; sendConfirm(fromport, code, mhinfo[mh].timeleft, reg->homeaddr, reg->coaddr, haAddr, mh); } } else { /* A tunnel does not already exist */ mhinfo[mh].timeleft = (reg->lifetime > MAXLIFETIME) ? MAXLIFETIME : (int) reg->lifetime; /* If S bit is set we send code =1 since this agent does not support simultaneous bindings */ if(reg->flags & 0x80) code = 1; else code = 0; if (mhinfo[mh].tunnelnum = newtunnel()) { /* we were able to find an unused tunnel name */ mhinfo[mh].status |= TUNNELUP; mhinfo[mh].coaddr = reg->coaddr; lowifacereq(MKPT2PT, mhinfo[mh].tunnelnum, haAddr, reg->coaddr); lowrtreq(ADDRT, mhinfo[mh].ipaddr, &(mhinfo[mh].tunnelnum)); lowARPreq(PROXY, mhinfo[mh].ipaddr, proxyHwAddr); /* Send gratuitous ARP */ lowarpsend(DEVICE,mhinfo[mh].ipaddr,proxyHwAddr,mhinfo[mh].ipaddr); agentstats.successfulreg++; sendConfirm(fromport, code, mhinfo[mh].timeleft, reg->homeaddr, reg->coaddr, haAddr, mh); } else { code = 130; /* insufficient resources */ agentstats.noresources++; sendRefusal(fromport, code, 0, reg->homeaddr, reg->coaddr, haAddr, mh); if (debug > 2) fprintf(stderr, "Refusal sent due to insuff resources.\n"); } } }else /* Now agent has to act as FA */ { code =0; if(debug>1)fprintf(stderr,"Acting as a foreign agent...\n"); vmh = 0; if (len < sizeof(struct registerme) || reg->type != REGISTERMETYPE) { code = 70; /* badly formed request */ agentstats.badregisterme++; } else if ((vmh = whichvmh(reg->homeaddr)) == 0) { code = 65; /* administratvely prohibited */ agentstats.mhprohibited++; } else if (vmhinfo[vmh].ha != reg->ha) code = 65; /* check for home agent address if it is the same as present in FA database */ else if (reg->flags & 0x08) /* No GRE encap */ code = 72; else if (reg->flags & 0x04) /* No Van Jacobson header comp.*/ code = 73; else if (reg->flags & 0x10) /* No minimal encap */ code = 72;vmhinfo[vmh].RegId.high = reg->Id.high;vmhinfo[vmh].RegId.low = reg->Id.low;if(code) /* refusal */ { sendRefusalVMH(fromport,code,0,reg->homeaddr,reg->ha,vmh); if(debug>2) fprintf(stderr,"Refusal sent to VMH\n"); return; }/* Now we have valid registerme (as far as FA is concerned ) */ if(vmhinfo[vmh].status != CONFIRMED){ vmhinfo[vmh].status |= PENDING; vmhinfo[vmh].timeleft = 0;} vmhinfo[vmh].RegId.high = reg->Id.high; vmhinfo[vmh].RegId.low = reg->Id.low; vmhinfo[vmh].fromport = fromport; toaddr.sin_family = AF_INET; toaddr.sin_port = htons(MIPREGPORT); toaddr.sin_addr.s_addr = vmhinfo[vmh].ha; reg = (struct registerme *) msg; errno = 0; if(sendto(RegMeVMHid,(char *)msg,len,0, (struct sockaddr *) &toaddr, sizeof(struct sockaddr))<0) { perror("FA: sendRegisterme for HA failed in sendto"); if(errno == ECONNREFUSED || errno == ENETUNREACH || errno == EHOSTUNREACH); else{ cleanup(); exit(-1); } } if(debug > 0){ fprintf(stderr,"====================================\n"); if(!errno) fprintf(stderr,"REGISTERME FORWARDED TO %s PORT %d\n", inet_ntoa(toaddr.sin_addr),(unsigned int) toaddr.sin_port); } } /* End of else part */ } /* End of ProcessRegisterme *//* Handle ragister reply from HA */void processRegReply(char *inmsg, int len, struct sockaddr_in *from) { struct regreply *rreply; int code = 0; int vmh; int authoffset; char temp = 0; unsigned short fromport; struct sockaddr_in toaddr; char devname[10]; strcpy(devname,DEVICE); rreply = (struct regreply*) inmsg; fromport = (unsigned short)from->sin_port; if(debug>0) { fprintf(stderr,"================================\n"); fprintf(stderr,"REPLY from HA %8lx for VMH %8lx Code %2d\n", htonl(rreply->ha),htonl(rreply->homeaddr),rreply->code); if(len < sizeof(struct regreply)) fprintf(stderr,"msg length short for register reply...ignoring\n"); fprintf(stderr,"===============================\n"); } vmh = whichvmh(rreply->homeaddr); if(vmh == 0) { if(debug>0) fprintf(stderr,"Regreply for unsupported VMH..ignoring\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -