int start_arp(struct TCB *tp, unsigned long addr) { struct TCB *sp; int i; if ((addr == IP_STUB(tp)->destination) && (tp->status & TCB_ARP_ED)) return(1); if (driver_type == SLIP_DRIVER) // We dont need ARP goto arp_ed; if ((tp->option & SO_BROADCAST) && (addr == INADDR_BROADCAST)) { // Copy Broadcast Address copy_hw_addr(ETH_STUB(tp)->destination, ARP_STUB.ether_pkt.destination); goto arp_ed; }; for (sp = tcb, i = 0; i < num_socket; i++, sp++) { if ((sp->status & TCB_ARP_ED) && (IP_STUB(sp)->destination == addr)) { copy_hw_addr(ETH_STUB(tp)->destination, ETH_STUB(sp)->destination); arp_ed: IP_STUB(tp)->destination = addr; set_status(tp, TCB_ARP_ED); return(1); } } IP_STUB(tp)->destination = addr; arp_target(tp) = samenet(addr) ? addr : tcpipcfg.c_defgw; // Failed to find Matched Address, Now do the ARP ARP_STUB.his_proto_addr = arp_target(tp); clr_status(tp, TCB_ARP_ED); set_status(tp, TCB_ARP_ING); statistics.arpOutRequests++; tp->arp_retrytimer = ONE_SECOND; tp->timeout_count = 1; //rprintf("[ARP_S]"); //print_packet(&ARP_STUB, 0); snd_packet(&ARP_STUB, ARP_PLEN); return(0); }
/* * lookup info about a client in the database. Find an address on the * same net as riip. */ int lookup(Bootp *bp, Info *iip, Info *riip) { Ndbtuple *t, *nt; Ndbs s; char *hwattr; char *hwval, hwbuf[33]; uchar ciaddr[IPaddrlen]; if(opendb() == nil){ warning(1, "can't open db"); return -1; } memset(iip, 0, sizeof(*iip)); /* client knows its address? */ v4tov6(ciaddr, bp->ciaddr); if(validip(ciaddr)){ if(lookupip(ciaddr, iip, 0) < 0) { if (debug) warning(0, "don't know %I", ciaddr); return -1; /* don't know anything about it */ } if(!samenet(riip->ipaddr, iip)){ warning(0, "%I not on %I", ciaddr, riip->ipnet); return -1; } /* * see if this is a masquerade, i.e., if the ether * address doesn't match what we expected it to be. */ if(memcmp(iip->etheraddr, zeroes, 6) != 0) if(memcmp(bp->chaddr, iip->etheraddr, 6) != 0) warning(0, "ciaddr %I rcvd from %E instead of %E", ciaddr, bp->chaddr, iip->etheraddr); return 0; } if(bp->hlen > Maxhwlen) return -1; switch(bp->htype){ case 1: hwattr = "ether"; hwval = hwbuf; snprint(hwbuf, sizeof(hwbuf), "%E", bp->chaddr); break; default: syslog(0, blog, "not ethernet %E, htype %d, hlen %d", bp->chaddr, bp->htype, bp->hlen); return -1; } /* * use hardware address to find an ip address on * same net as riip */ t = ndbsearch(db, &s, hwattr, hwval); while(t){ for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") != 0) continue; parseip(ciaddr, nt->val); if(lookupip(ciaddr, iip, 0) < 0) continue; if(samenet(riip->ipaddr, iip)){ ndbfree(t); return 0; } } ndbfree(t); t = ndbsnext(&s, hwattr, hwval); } return -1; }