📄 mh.c
字号:
mhstats.idmismatch++; if (debug > 0) { fprintf(stderr, "Id mismatch -- Reply ignored.\n"); } return; } /* Check whether a valid reply */ if (reply->type != REGREPLYTYPE || len < sizeof(struct regreply) || !IsOurAgent(reply->ha) || !IsOurAddress(reply->homeaddr) || ((reply->code<16 || reply->code>127) && !(authoffset=authextfound(msg, len, 1)))) { mhstats.badregreply++; if (debug > 0) { fprintf(stderr, "Bad structure -- Reply ignored.\n"); } return; } if ((reply->code<16 || reply->code>127) && !authok(msg, len, authoffset, Myinfo.secret, Myinfo.secretlen,Myinfo.SPIval)) { mhstats.authfailed++; if (debug > 0) { fprintf(stderr, "Authentication failed -- Reply ignored.\n"); } return; } Myinfo.status &= ~AWAITINGREPLY; if (reply->code == 0 || reply->code == 1) { /* Our service request was approved */ mhstats.regsuccessful++; if (reply->lifetime == 0) { /* deregistration approved */ /* Timer won't be running now */ Myinfo.timeleft = 0; Myinfo.status |= DEREGISTERED; } else { Myinfo.timeleft = reply->lifetime; Myinfo.status |= REGISTERED; if((Myinfo.status & 0x03) == ASPOPUP) { lowifaceset(Myinfo.infname,Myinfo.homeaddr,Myinfo.homenetmask); lowifaceset("dummy",Myinfo.coaddr,Myinfo.foreignnetmask); lowhwaddrreq(Myinfo.infname,hwaddr); lowARPreq(PROXY, Myinfo.coaddr, hwaddr); lowrtset(Myinfo.coaddr, "dummy", ADDRT); } } } else /* Rejection */ { /* If we are not yet registered then rejection might be due to ID mismatch, so without waiting for timer to go off,send registration */ if(!(Myinfo.status & REGISTERED)) { Myinfo.status |= AWAITINGREPLY; Myinfo.timeleft = RETRYINTERVAL; sendRegisterMe((int) 0, Myinfo.flags,Myinfo.lifetime,Myinfo.homeaddr, Myinfo.homeagent, Myinfo.coaddr); } mhstats.regfailed++; } }/*Check whether received router discovery message is valid and cannot be ignored */int cannotignore(char *msg, u_long *src, int len){ struct youarehere *urh; char *p; struct icmp *icp; unsigned long *addr; /* We first check weather message is not corrupt or invalid */ icp = (struct icmp*)msg; if(icp->type != ROUTERADVTYPE) { if(debug>1) fprintf(stderr,"Not a router discovery message\n"); return FALSE; } urh = (struct youarehere*)(msg + SIZE_ICMP_HDR + 4*(icp->addr_entry_size)*(icp->addrnum)); len -= SIZE_ICMP_HDR + 4*(icp->addr_entry_size)*(icp->addrnum); if(urh->type != YOUAREHERETYPE || len <(sizeof(struct youarehere) + (urh->length-6))) { fprintf(stderr,"Rt discovery message is too short or type mismatch\n"); return FALSE; } p = msg + SIZE_ICMP_HDR + 4*(icp->addr_entry_size)*(icp->addrnum) + sizeof(struct youarehere); addr = (unsigned long *) p; if (debug > 2) { int i; fprintf(stderr, "Rt. discovery addrnum = %d, flags = %x seqno = %d lifetime = %d\n", (urh->length-6)/4, urh->flags,urh->seqno,urh->lifetime); for (i = 0; i < (urh->length-6)/4; i++) fprintf(stderr, "Address %lx\n", htonl(*(addr + i))); } if((IsOurAgent(*addr) && (urh->flags & MSHFLAG)) ||(!IsOurAgent(*addr) && (urh->flags & MSFFLAG)&& (!(urh->flags & MSBFLAG))&& urh->lifetime !=0)) { *src = *addr; return TRUE; } else return FALSE;}/* This function decides which action should be taken: HOMEACTION, FOREIGNACTION or POPUPACTION. It uses PickupURheres() to get any received router die]scovery message */void dsn_maker(int sockid){ unsigned long ipaddr,src,gw; short i,heard_no_adv; char dev[10], *p; static char msg[256]; unsigned int msglen,fromlen; struct sockaddr_in from; struct youarehere *urh; fd_set fdvec; static struct timeval tv; static struct icmp *icp; static struct iphdr *ip; u_short iphdrlen; msglen = 0; bzero(msg,sizeof(msg)); bzero((void*)&from,sizeof(struct sockaddr_in)); if(!doit)Dminfo.action = 0; if(debug >2) fprintf(stderr,"Decision Maker with doit = %d\n",doit); if(lowdefifcreq(&ipaddr,&gw,dev)<0) { fprintf(stderr,"lowdefifcreq failed\n"); return; } if(debug >2) { fprintf(stderr,"Default interface address %lx Interface name %s Gateway : %lx\n", ipaddr, dev, gw); } heard_no_adv = TRUE; for(i=0;i<MAXOVERLAP;i++) { FD_ZERO(&fdvec); FD_SET(sockid,&fdvec); tv.tv_sec = 0; tv.tv_usec = 0; if(select(FD_SETSIZE,&fdvec,NULL,NULL,&tv)<0) { if(errno == EINTR); /* This is expected since alarm is ruuning so do nothing */ else perror("select() failed in dsn_maker()"); } if(FD_ISSET(sockid,&fdvec)){ msglen = sizeof(msg); fromlen = sizeof(struct sockaddr_in); if((msglen = recvfrom(sockid,msg,msglen,0,(struct sockaddr*)&from, &fromlen))<0) { if(errno == ECONNREFUSED||errno == ENETUNREACH || errno == EHOSTUNREACH); else perror("recvfrom() failed in dsn_maker"); } if(msglen < 0)continue; ip = (struct iphdr *)msg; iphdrlen = ip->ihl <<2; /*Bytes */ icp = (struct icmp*)(msg + iphdrlen); /* remove IP header */ msglen -= iphdrlen; if(debug >2) fprintf(stderr,"Recvd message on rtdisc socket from %s \n",inet_ntoa(from.sin_addr)); else fprintf(stderr,"."); if(cannotignore((char*)icp,&src,msglen) && (heard_no_adv || src == Myinfo.closeagentaddr)) { heard_no_adv = FALSE; p = (msg + iphdrlen + SIZE_ICMP_HDR + 4*(icp->addr_entry_size)*(icp->addrnum)); msglen -= SIZE_ICMP_HDR +4*(icp->addr_entry_size)*(icp->addrnum); /*Store only router discovery message */ memcpy(Dminfo.rtdismsg,p,msglen); memcpy((char*)&Dminfo.from,(char*)&from,sizeof(struct sockaddr_in)); } } } /* Indicate in log that no adv is heard*/ if(heard_no_adv) fprintf(stderr,"?"); if(doit)return; if(!IsOurAddress(ipaddr)&& ipaddr != 0) { /* This indicates that MH interface addr is changed. So go for POPUPACTION */ Dminfo.action = POPUPACTION; Dminfo.coaddr = ipaddr; Dminfo.gw = gw; Dminfo.closeagentaddr = 0; strcpy(Dminfo.infname,dev); Dminfo.seqno = 0; Dminfo.lifetime = MAXLIFETIME; Dminfo.flags = 0; /* bzero(Dminfo.rtdismsg,sizeof(Dminfo.rtdismsg)); bzero(&(Dminfo.from),sizeof(struct sockaddr_in)); */ } if(heard_no_adv && Dminfo.action == POPUPACTION) { /* This indicates that MH has acquired new IP address due to PPP or DHCP and no router discovery messages are heard. */ doit =1; } else if(heard_no_adv == FALSE) { urh = (struct youarehere*)Dminfo.rtdismsg; if(IsOurAgent(src)) { Dminfo.action = HOMEACTION; Dminfo.closeagentaddr = src; Dminfo.coaddr = Myinfo.homeaddr; Dminfo.gw = gw; strcpy(Dminfo.infname,dev); Dminfo.seqno = urh->seqno; Dminfo.lifetime = urh->lifetime; Dminfo.flags = urh->flags; doit = 1; } else /* Not at Home */ { Dminfo.action = FOREIGNACTION; Dminfo.closeagentaddr = src; Dminfo.coaddr = src; Dminfo.gw =gw; strcpy(Dminfo.infname,dev); Dminfo.seqno = urh->seqno; Dminfo.lifetime = urh->lifetime; Dminfo.flags = urh->flags; doit = 1; } }}void copy_new(){ Myinfo.coaddr = Dminfo.coaddr; Myinfo.closeagentaddr = Dminfo.closeagentaddr; Myinfo.gw = Dminfo.gw; strcpy(Myinfo.infname,Dminfo.infname); Myinfo.seqno = Dminfo.seqno; Myinfo.lifetime = Dminfo.lifetime; Myinfo.agentflags = Dminfo.flags;}doer(){ struct sockaddr_in from; char msg[1024]; int len, fromlen; fd_set fdvec; struct timeval tv; if(doit) switch(Dminfo.action){ case FOREIGNACTION : if(Dminfo.coaddr != Myinfo.coaddr || did_reboot(Dminfo.seqno,Myinfo.seqno)) { if(debug>1) fprintf(stderr,"Doer processing FOREIGNACTION with Coaddr %lx\n", Dminfo.coaddr); /* Flush all ARP entries */ lowflshARP(); /* Down dummy (if present) */ lowifacedown("dummy"); /* Delete earlier default route */ lowrtset(0x00000000,Myinfo.infname,DELRT); /* Delete route to home network if present */ lowrtnetset((Myinfo.homeagent & Myinfo.homenetmask),Myinfo.infname,0,DELRT); /* Delete network route if earlier state was ASPOPUP */ if((Myinfo.status & 0x03)==ASPOPUP) lowrtnetset((Myinfo.coaddr & Myinfo.foreignnetmask),Myinfo.infname,0,DELRT); /* Delete route to existing default gateway*/ lowrtset(Myinfo.gw,Myinfo.infname,DELRT); /* If it is INIT delete route to home agent anyway */ if((Myinfo.status & 0x03) == INIT) lowrtset(Myinfo.homeagent,Myinfo.infname,DELRT); /* Clear Myinfo*/ init(1); /* Copy new info */ copy_new(); /* Set new routes */ if(debug>2)fprintf(stderr,"Setting new routes...\n"); lowrtset(Myinfo.closeagentaddr,Myinfo.infname,ADDRT); lowrtdefault(Myinfo.closeagentaddr); Myinfo.timeleft = RETRYINTERVAL; Myinfo.flags = 0x00|APREF; /* No Broadcast , FA will decapsulate, etc */ Myinfo.status = ATFOREIGN | WAITINGTOREGISTER | AWAITINGREPLY; sendRegisterMe(Myinfo.retries, Myinfo.flags, Myinfo.lifetime, Myinfo.homeaddr, Myinfo.homeagent, Myinfo.coaddr); if(debug >1) fprintf(stderr,"Done with FOREIGNACTION\n"); } doit = 0; break; case HOMEACTION : if(Dminfo.coaddr != Myinfo.coaddr || did_reboot(Dminfo.seqno,Myinfo.seqno)) { char hwaddr[6]; if(debug>1){ fprintf(stderr,"Doer processing HOMEACTION\n"); } /* Flush all ARP entries */ lowflshARP(); /* Down dummy (if present) */ lowifacedown("dummy"); /* Delete earlier default route */ lowrtset(0x00000000,Myinfo.infname,DELRT); /* Delete network route if earlier state was ASPOPUP */ if((Myinfo.status & 0x03)==ASPOPUP) lowrtnetset((Myinfo.coaddr & Myinfo.foreignnetmask),Myinfo.infname,0,DELRT); /* Delete route to existing default gateway*/ lowrtset(Myinfo.gw,Myinfo.infname,DELRT); /* Clear Myinfo*/ init(1); /* Copy new info */ copy_new(); /* Set new routes */ if(debug>2)fprintf(stderr,"Setting new routes...\n"); lowrtnetset((Myinfo.homeagent & Myinfo.homenetmask),Myinfo.infname,Myinfo.homenetmask,ADDRT); lowrtdefault(Myinfo.closeagentaddr); /* Send gratuitous ARP*/ lowhwaddrreq(Myinfo.infname,hwaddr); /* get hwaddr */ lowarpsend(Myinfo.infname,Myinfo.homeaddr,hwaddr,Myinfo.homeaddr); Myinfo.timeleft = RETRYINTERVAL; Myinfo.lifetime = 0; /*Deregistration */ Myinfo.flags = 0x00|APREF; Myinfo.status = ATHOME | WAITINGTODEREGISTER| AWAITINGREPLY; sendRegisterMe(Myinfo.retries, Myinfo.flags, Myinfo.lifetime, Myinfo.homeaddr, Myinfo.homeagent, Myinfo.coaddr); if(debug >1) fprintf(stderr,"Done with HOMEACTION\n"); } doit =0; break; case POPUPACTION: if(Dminfo.coaddr != Myinfo.coaddr) { if(debug>1) fprintf(stderr,"Doer processing POPUPACTION\n"); lowflshARP(); /* Make dummy down */ lowifacedown("dummy"); if((Myinfo.status & 0x03)==ASPOPUP) lowrtnetset((Myinfo.coaddr & Myinfo.foreignnetmask),Myinfo.infname,0,DELRT); /* Delete route to home network if present */ lowrtnetset((Myinfo.homeagent & Myinfo.homenetmask),Myinfo.infname,0,DELRT); /* Delete route to existing default gateway*/ lowrtset(Myinfo.gw,Myinfo.infname,DELRT); init(1); /* Copy new info */ copy_new(); /* Set new routes */ Myinfo.timeleft = RETRYINTERVAL; Myinfo.flags = 0x20|APREF; /* MH will decapsulate */ lownetmaskreq(Myinfo.infname,&Myinfo.foreignnetmask); Myinfo.status = ASPOPUP | WAITINGTOREGISTER| AWAITINGREPLY; sendRegisterMe(Myinfo.retries, Myinfo.flags, Myinfo.lifetime, Myinfo.homeaddr, Myinfo.homeagent, Myinfo.coaddr); if(debug >1) fprintf(stderr,"Done with POPUPACTION\n"); } doit =0; break; default: break; } /* Check for any registration reply */ FD_ZERO(&fdvec); FD_SET(Regreplysid, &fdvec); tv.tv_sec = 0; tv.tv_usec = 0; while(( select(FD_SETSIZE, &fdvec, NULL, NULL, &tv)) < 0) { if(errno == EINTR); else perror("select() failed in Doer\n"); } len = 1024; fromlen = sizeof(struct sockaddr_in); if (FD_ISSET(Regreplysid, &fdvec)) { if ((len = recvfrom(Regreplysid, msg, len, 0, (struct sockaddr *) &from, &fromlen)) < 0) { perror("recvfrom() on RegisterMesid failed.\n"); if(errno == ECONNREFUSED || errno == ENETUNREACH || errno == EHOSTUNREACH); else { cleanup(); exit(-1); } }; processRegreply(msg, len, &from); }}/* End of Doer */main(int argc, char **argv) { char *cmd; int c; extern char *optarg; extern int optind; unsigned char argsfound = 0; cmd = argv[0]; while ((c = getopt(argc, argv, "a:m:g:")) != -1) { switch ((char) c) { case 'a': argsfound |= 0x01; if ((Myinfo.homeaddr = inet_addr(optarg)) == -1) { fprintf(stderr, "Bad address passed to -a.\n"); exit(-1); }; break; case 'm': argsfound |= 0x02; if ((Myinfo.homenetmask = inet_addr(optarg)) == -1) { fprintf(stderr, "Bad netmask passed to -m.\n"); exit(-1); }; break; case 'g': argsfound |= 0x04; if ((Myinfo.homeagent = inet_addr(optarg)) == -1) { fprintf(stderr, "Bad address passed to -g.\n"); exit(-1); }; break; case '?': usage(cmd); exit(1); break; } } if (argsfound != 0x07) { usage(cmd); exit(1); } if (debug > 1) { fprintf(stderr, "IPaddr: %lx, Mask: %lx, HomeAgent: %lx\n", htonl(Myinfo.homeaddr), htonl(Myinfo.homenetmask), htonl(Myinfo.homeagent)); } init(0); sendroutersol(&routersolto); while (1) { doer(); slp(0.5); }}voidusage(char *cmd) { fprintf(stderr, "Usage is: %s -a homeaddr -m homenetmask -g haaddr \n", cmd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -