/* ARGSNOTUSED */ void kev_dispatch_msg(int fd, short event, void *bula) { char buf[RT_BUF_SIZE]; char *next, *lim; ssize_t n; struct rt_msghdr *rtm; struct if_msghdr ifm; struct iface *iface; if ((n = read(kev_state.fd, &buf, sizeof(buf))) == -1) fatal("kev_dispatch_rtmsg: read error"); if (n == 0) fatalx("kernel event socket closed"); lim = buf + n; for (next = buf; next < lim; next += rtm->rtm_msglen) { memcpy(&ifm, next, sizeof(ifm)); rtm = (struct rt_msghdr *)next; if (rtm->rtm_version != RTM_VERSION) continue; iface = if_find_index(ifm.ifm_index); if (iface == NULL) /* this interface isn't configured */ continue; switch (rtm->rtm_type) { case RTM_IFINFO: log_debug("RTM_IFINFO"); if (LINK_STATE_IS_UP(ifm.ifm_data.ifi_link_state)) if_fsm(iface, IF_EVT_UP); else if_fsm(iface, IF_EVT_DOWN); break; case RTM_IFANNOUNCE: log_debug("RTM_IFANNOUNCE"); break; case RTM_NEWADDR: /* TODO */ log_debug("RTM_NEWADDR"); break; case RTM_DELADDR: /* TODO */ log_debug("RTM_DELADDR"); break; default: /* ignore for now */ break; } } }
int rde_check_route(struct rip_route *e) { struct timeval tv, now; struct rt_node *rn; struct iface *iface; u_int8_t metric; if ((e->nexthop.s_addr & htonl(IN_CLASSA_NET)) == htonl(INADDR_LOOPBACK & IN_CLASSA_NET) || e->nexthop.s_addr == INADDR_ANY) return (-1); if ((iface = if_find_index(e->ifindex)) == NULL) return (-1); metric = MIN(INFINITY, e->metric + iface->cost); if ((rn = rt_find(e->address.s_addr, e->mask.s_addr)) == NULL) { if (metric >= INFINITY) return (0); rn = rt_new_rr(e, metric); rt_insert(rn); rde_send_change_kroute(rn); route_start_timeout(rn); triggered_update(rn); } else { /* * XXX don't we have to track all incoming routes? * what happens if the kernel route is removed later. */ if (rn->flags & F_KERNEL) return (0); if (metric < rn->metric) { rn->metric = metric; rn->nexthop.s_addr = e->nexthop.s_addr; rn->ifindex = e->ifindex; rde_send_change_kroute(rn); triggered_update(rn); } else if (e->nexthop.s_addr == rn->nexthop.s_addr && metric > rn->metric) { rn->metric = metric; rde_send_change_kroute(rn); triggered_update(rn); if (rn->metric == INFINITY) route_start_garbage(rn); } else if (e->nexthop.s_addr != rn->nexthop.s_addr && metric == rn->metric) { /* If the new metric is the same as the old one, * examine the timeout for the existing route. If it * is at least halfway to the expiration point, switch * to the new route. */ timerclear(&tv); gettimeofday(&now, NULL); evtimer_pending(&rn->timeout_timer, &tv); if (tv.tv_sec - now.tv_sec < ROUTE_TIMEOUT / 2) { rn->nexthop.s_addr = e->nexthop.s_addr; rn->ifindex = e->ifindex; rde_send_change_kroute(rn); } } if (e->nexthop.s_addr == rn->nexthop.s_addr && rn->metric < INFINITY) route_reset_timers(rn); } return (0); }