/* * Timer routine. Performs routing information supply * duties and manages timers on routing and SAP table entries. */ void timer() { register struct rthash *rh; register struct rt_entry *rt; register struct sap_hash *sh; register struct sap_entry *sap; struct sap_hash *sap_base = sap_head; int timetobroadcast, ripbroadcast, sapbroadcast; timeval += TIMER_RATE; if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0) ifinit(); timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0; ripbroadcast = supplier && timetobroadcast && (timeval % RIP_INTERVAL) == 0; sapbroadcast = timetobroadcast && dosap && !ripbroadcast; for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) { rt = rh->rt_forw; for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { if (rt->rt_clone) { struct rt_entry *trt, *prt; /* * If a clone expire free it and mark the * main route RTS_CHANGED. */ prt = rt; trt = rt->rt_clone; while (trt) { trt->rt_timer += TIMER_RATE; if (trt->rt_timer >= EXPIRE_TIME) { prt->rt_clone = trt->rt_clone; free((char *)trt); trt = prt->rt_clone; rt->rt_state |= RTS_CHANGED; } else { prt = trt; trt = prt->rt_clone; } } } /* * We don't advance time on a routing entry for * a passive gateway or that for our only interface. * The latter is excused because we don't act as * a routing information supplier and hence would * time it out. This is fair as if it's down * we're cut off from the world anyway and it's * not likely we'll grow any new hardware in * the mean time. */ if (!(rt->rt_state & RTS_PASSIVE) && !(rt->rt_state & RTS_INTERFACE)) rt->rt_timer += TIMER_RATE; if (rt->rt_timer >= EXPIRE_TIME) { rt->rt_metric = HOPCNT_INFINITY; rt->rt_state |= RTS_CHANGED; } if (rt->rt_timer >= GARBAGE_TIME) { rt = rt->rt_back; /* Perhaps we should send a REQUEST for this route? */ rtdelete(rt->rt_forw); continue; } if (rt->rt_state & RTS_CHANGED) { rt->rt_state &= ~RTS_CHANGED; /* don't send extraneous packets */ if (!supplier || ripbroadcast) continue; if ((rt->rt_metric + 1) == HOPCNT_INFINITY) continue; msg->rip_cmd = htons(RIPCMD_RESPONSE); msg->rip_nets[0].rip_dst = (satoipx_addr(rt->rt_dst)).x_net; msg->rip_nets[0].rip_metric = htons(min(rt->rt_metric+1, HOPCNT_INFINITY)); msg->rip_nets[0].rip_ticks = htons(rt->rt_ticks + 1); toall(sndmsg, rt, 0); } } } if (ripbroadcast) toall(supply, NULL, 0); /* * Now do the SAP stuff. */ for (sh = sap_base; sh < &sap_base[SAPHASHSIZ]; sh++) { sap = sh->forw; for (; sap != (struct sap_entry *)sh; sap = sap->forw) { if (sap->clone) { struct sap_entry *tsap, *psap; /* * If a clone expire free it and mark the * main sap entry RTS_CHANGED. */ psap = sap; tsap = sap->clone; while (tsap) { tsap->timer += TIMER_RATE; if (tsap->timer >= EXPIRE_TIME) { psap->clone = tsap->clone; free((char *)tsap); tsap = psap->clone; sap->state |= RTS_CHANGED; } else { psap = tsap; tsap = psap->clone; } } } sap->timer += TIMER_RATE; if (sap->timer >= EXPIRE_TIME) { sap->sap.hops = htons(HOPCNT_INFINITY); sap->state |= RTS_CHANGED; } if (sap->timer >= GARBAGE_TIME) { sap = sap->back; /* Perhaps we should send a REQUEST for this route? */ sap_delete(sap->forw); continue; } /* * XXX sap_sndmsg on RTS_CHANGED */ if (sap->state & RTS_CHANGED) { sap->state &= ~RTS_CHANGED; #ifdef notyet /* don't send extraneous packets */ if (!supplier || sapbroadcast) continue; if ((ntohs(sap->sap.hops) + 1) == HOPCNT_INFINITY) continue; sap_msg->sap_cmd = htons(SAP_RESP); sap_msg->sap[0] = sap->sap; sap_msg->sap[0].hops = htons(min(sap->sap.hops+1, HOPCNT_INFINITY)); toall(sapsndmsg, rt, 0); #endif } } } if (sapbroadcast) sap_supply_toall(0); if (ftrace && sapbroadcast) dumpsaptable(ftrace, sap_head); }
static const char * fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) { static char workbuf[128]; const char *cp; if (sa == NULL) return ("null"); switch(sa->sa_family) { case AF_INET: { struct sockaddr_in *sockin = (struct sockaddr_in *)sa; if ((sockin->sin_addr.s_addr == INADDR_ANY) && mask && ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) ==0L) cp = "default" ; else if (flags & RTF_HOST) cp = routename(sockin->sin_addr.s_addr); else if (mask) cp = netname(sockin->sin_addr.s_addr, ntohl(((struct sockaddr_in *)mask) ->sin_addr.s_addr)); else cp = netname(sockin->sin_addr.s_addr, 0L); break; } #ifdef INET6 case AF_INET6: { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; in6_fillscopeid(sa6); if (flags & RTF_HOST) cp = routename6(sa6); else if (mask) cp = netname6(sa6, &((struct sockaddr_in6 *)mask)->sin6_addr); else { cp = netname6(sa6, NULL); } break; } #endif /*INET6*/ case AF_IPX: { struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; if (ipx_nullnet(satoipx_addr(work))) cp = "default"; else cp = ipx_print(sa); break; } case AF_APPLETALK: { if (!(flags & RTF_HOST) && mask) cp = atalk_print2(sa,mask,9); else cp = atalk_print(sa,11); break; } case AF_NETGRAPH: { strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data, sizeof(workbuf)); cp = workbuf; break; } case AF_LINK: { struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { (void) sprintf(workbuf, "link#%d", sdl->sdl_index); cp = workbuf; } else switch (sdl->sdl_type) { case IFT_ETHER: case IFT_L2VLAN: case IFT_BRIDGE: if (sdl->sdl_alen == ETHER_ADDR_LEN) { cp = ether_ntoa((struct ether_addr *) (sdl->sdl_data + sdl->sdl_nlen)); break; } /* FALLTHROUGH */ default: cp = link_ntoa(sdl); break; } break; } default: { u_char *s = (u_char *)sa->sa_data, *slim; char *cq, *cqlim; cq = workbuf; slim = sa->sa_len + (u_char *) sa; cqlim = cq + sizeof(workbuf) - 6; cq += sprintf(cq, "(%d)", sa->sa_family); while (s < slim && cq < cqlim) { cq += sprintf(cq, " %02x", *s++); if (s < slim) cq += sprintf(cq, "%02x", *s++); } cp = workbuf; } } return (cp); }