void rtm_read (struct rt_msghdr *rtm) { int flags; u_char zebra_flags; union sockunion dest, mask, gate; char ifname[INTERFACE_NAMSIZ + 1]; short ifnlen = 0; zebra_flags = 0; /* Read destination and netmask and gateway from rtm message structure. */ flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen); if (!(flags & RTF_DONE)) return; if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type, lookup (rtm_type_str, rtm->rtm_type)); #ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ if (flags & RTF_CLONED) return; #endif #ifdef RTF_WASCLONED /*freebsd*/ if (flags & RTF_WASCLONED) return; #endif if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP)) return; /* This is connected route. */ if (! (flags & RTF_GATEWAY)) return; if (flags & RTF_PROTO1) SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE); /* This is persistent route. */ if (flags & RTF_STATIC) SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC); /* This is a reject or blackhole route */ if (flags & RTF_REJECT) SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT); if (flags & RTF_BLACKHOLE) SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE); if (dest.sa.sa_family == AF_INET) { struct prefix_ipv4 p; p.family = AF_INET; p.prefix = dest.sin.sin_addr; if (flags & RTF_HOST) p.prefixlen = IPV4_MAX_PREFIXLEN; else p.prefixlen = ip_masklen (mask.sin.sin_addr); /* Catch self originated messages and match them against our current RIB. * At the same time, ignore unconfirmed messages, they should be tracked * by rtm_write() and kernel_rtm_ipv4(). */ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) { char buf[INET_ADDRSTRLEN], gate_buf[INET_ADDRSTRLEN]; int ret; if (! IS_ZEBRA_DEBUG_RIB) return; ret = rib_lookup_ipv4_route (&p, &gate); inet_ntop (AF_INET, &p.prefix, buf, INET_ADDRSTRLEN); switch (rtm->rtm_type) { case RTM_ADD: case RTM_GET: case RTM_CHANGE: /* The kernel notifies us about a new route in FIB created by us. Do we have a correspondent entry in our RIB? */ switch (ret) { case ZEBRA_RIB_NOTFOUND: zlog_debug ("%s: %s %s/%d: desync: RR isn't yet in RIB, while already in FIB", __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); break; case ZEBRA_RIB_FOUND_CONNECTED: case ZEBRA_RIB_FOUND_NOGATE: inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN); zlog_debug ("%s: %s %s/%d: desync: RR is in RIB, but gate differs (ours is %s)", __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen, gate_buf); break; case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */ zlog_debug ("%s: %s %s/%d: done Ok", __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); rib_lookup_and_dump (&p); return; break; } break; case RTM_DELETE: /* The kernel notifies us about a route deleted by us. Do we still have it in the RIB? Do we have anything instead? */ switch (ret) { case ZEBRA_RIB_FOUND_EXACT: zlog_debug ("%s: %s %s/%d: desync: RR is still in RIB, while already not in FIB", __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); rib_lookup_and_dump (&p); break; case ZEBRA_RIB_FOUND_CONNECTED: case ZEBRA_RIB_FOUND_NOGATE: zlog_debug ("%s: %s %s/%d: desync: RR is still in RIB, plus gate differs", __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); rib_lookup_and_dump (&p); break; case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ zlog_debug ("%s: %s %s/%d: done Ok", __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); rib_lookup_and_dump (&p); return; break; } break; default: zlog_debug ("%s: %s/%d: warning: loopback RTM of type %s received", __func__, buf, p.prefixlen, lookup (rtm_type_str, rtm->rtm_type)); } return; } /* Change, delete the old prefix, we have no further information * to specify the route really */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, NULL, 0, 0); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0, rtm->rtm_protocol); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, 0, 0); } #ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) { /* One day we might have a debug section here like one in the * IPv4 case above. Just ignore own messages at the moment. */ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) return; struct prefix_ipv6 p; unsigned int ifindex = 0; p.family = AF_INET6; p.prefix = dest.sin6.sin6_addr; if (flags & RTF_HOST) p.prefixlen = IPV6_MAX_PREFIXLEN; else p.prefixlen = ip6_masklen (mask.sin6.sin6_addr); #ifdef KAME if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr)) { ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr); SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0); } #endif /* KAME */ /* CHANGE: delete the old prefix, we have no further information * to specify the route really */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, NULL, 0, 0); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0); } #endif /* HAVE_IPV6 */ }
void rtm_read (struct rt_msghdr *rtm) { int flags; u_char zebra_flags; union sockunion dest, mask, gate; zebra_flags = 0; /* Discard self send message. */ if (rtm->rtm_type != RTM_GET && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid)) return; /* Read destination and netmask and gateway from rtm message structure. */ flags = rtm_read_mesg (rtm, &dest, &mask, &gate); #ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ if (flags & RTF_CLONED) return; #endif #ifdef RTF_WASCLONED /*freebsd*/ if (flags & RTF_WASCLONED) return; #endif if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP)) return; /* Ignore route which has both HOST and GATEWAY attribute. */ if ((flags & RTF_GATEWAY) && (flags & RTF_HOST)) return; /* This is connected route. */ if (! (flags & RTF_GATEWAY)) return; if (flags & RTF_PROTO1) SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE); /* This is persistent route. */ if (flags & RTF_STATIC) SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC); if (dest.sa.sa_family == AF_INET) { struct prefix_ipv4 p; p.family = AF_INET; p.prefix = dest.sin.sin_addr; p.prefixlen = ip_masklen (mask.sin.sin_addr); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, 0, 0, 0, 0); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, 0, 0); } #ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) { struct prefix_ipv6 p; unsigned int ifindex = 0; p.family = AF_INET6; p.prefix = dest.sin6.sin6_addr; p.prefixlen = ip6_masklen (mask.sin6.sin6_addr); #ifdef KAME if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr)) { ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr); SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0); } #endif /* KAME */ if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0); } #endif /* HAVE_IPV6 */ }
void rtm_read (struct rt_msghdr *rtm) { int flags; u_char zebra_flags; union sockunion dest, mask, gate; char ifname[INTERFACE_NAMSIZ + 1]; short ifnlen = 0; zebra_flags = 0; /* Discard self send message. */ if (rtm->rtm_type != RTM_GET && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid)) return; /* Read destination and netmask and gateway from rtm message structure. */ flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen); #ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ if (flags & RTF_CLONED) return; #endif #ifdef RTF_WASCLONED /*freebsd*/ if (flags & RTF_WASCLONED) return; #endif if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP)) return; /* This is connected route. */ if (! (flags & RTF_GATEWAY)) return; if (flags & RTF_PROTO1) SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE); /* This is persistent route. */ if (flags & RTF_STATIC) SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC); /* This is a reject or blackhole route */ if (flags & RTF_REJECT) SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT); if (flags & RTF_BLACKHOLE) SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE); if (dest.sa.sa_family == AF_INET) { struct prefix_ipv4 p; p.family = AF_INET; p.prefix = dest.sin.sin_addr; if (flags & RTF_HOST) p.prefixlen = IPV4_MAX_PREFIXLEN; else p.prefixlen = ip_masklen (mask.sin.sin_addr); /* Change, delete the old prefix, we have no further information * to specify the route really */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, NULL, 0, 0); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, 0, 0, 0, 0); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, 0, 0); } #ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) { struct prefix_ipv6 p; unsigned int ifindex = 0; p.family = AF_INET6; p.prefix = dest.sin6.sin6_addr; if (flags & RTF_HOST) p.prefixlen = IPV6_MAX_PREFIXLEN; else p.prefixlen = ip6_masklen (mask.sin6.sin6_addr); #ifdef KAME if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr)) { ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr); SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0); } #endif /* KAME */ /* CHANGE: delete the old prefix, we have no further information * to specify the route really */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, NULL, 0, 0); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0); } #endif /* HAVE_IPV6 */ }