void connected_down_ipv4(struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ apply_mask_ipv4(&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any(&p)) return; /* Same logic as for connected_up_ipv4(): push the changes into the head. */ rib_delete_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST); rib_delete_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST); rib_update(); }
void connected_down_ipv4 (struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; struct prefix_ipv4 *addr; struct prefix_ipv4 *dest; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; addr = (struct prefix_ipv4 *)ifc->address; dest = (struct prefix_ipv4 *)ifc->destination; memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = addr->prefixlen; /* Point-to-point check. */ if (CONNECTED_POINTOPOINT_HOST(ifc)) p.prefix = dest->prefix; else p.prefix = addr->prefix; /* Apply mask to the network. */ apply_mask_ipv4 (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any (&p)) return; rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); rib_update (); }
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; /* 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 */ }
/* Zebra server IPv4 prefix delete function. */ static void zread_ipv4_delete (struct zserv *client, u_short length) { int i; struct stream *s; struct zapi_ipv4 api; struct in_addr nexthop; unsigned long ifindex; struct prefix_ipv4 p; u_char nexthop_num; u_char nexthop_type; u_char ifname_len; s = client->ibuf; ifindex = 0; nexthop.s_addr = 0; /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv4 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { nexthop_num = stream_getc (s); for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc (s); switch (nexthop_type) { case ZEBRA_NEXTHOP_IFINDEX: ifindex = stream_getl (s); break; case ZEBRA_NEXTHOP_IFNAME: ifname_len = stream_getc (s); stream_forward (s, ifname_len); break; case ZEBRA_NEXTHOP_IPV4: nexthop.s_addr = stream_get_ipv4 (s); break; case ZEBRA_NEXTHOP_IPV6: stream_forward (s, IPV6_MAX_BYTELEN); break; } } } /* Distance. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; /* Metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table); }
/* Routing information change from the kernel. */ int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; struct rtmsg *rtm; struct rtattr *tb [RTA_MAX + 1]; char anyaddr[16] = {0}; int index; int table; void *dest; void *gate; rtm = NLMSG_DATA (h); if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) { /* If this is not route add/delete message print warning. */ zlog_warn ("Kernel message: %d\n", h->nlmsg_type); return 0; } /* Connected route. */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_info ("%s %s %s proto %s", h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", rtm->rtm_family == AF_INET ? "ipv4" : "ipv6", rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", lookup (rtproto_str, rtm->rtm_protocol)); if (rtm->rtm_type != RTN_UNICAST) { return 0; } table = rtm->rtm_table; if (table != RT_TABLE_MAIN && table != rtm_table_default) { return 0; } len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg)); if (len < 0) return -1; memset (tb, 0, sizeof tb); netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); if (rtm->rtm_flags & RTM_F_CLONED) return 0; if (rtm->rtm_protocol == RTPROT_REDIRECT) return 0; if (rtm->rtm_protocol == RTPROT_KERNEL) return 0; if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE) return 0; if (rtm->rtm_src_len != 0) { zlog_warn ("netlink_route_change(): no src len"); return 0; } index = 0; dest = NULL; gate = NULL; if (tb[RTA_OIF]) index = *(int *) RTA_DATA (tb[RTA_OIF]); if (tb[RTA_DST]) dest = RTA_DATA (tb[RTA_DST]); else dest = anyaddr; if (tb[RTA_GATEWAY]) gate = RTA_DATA (tb[RTA_GATEWAY]); if (rtm->rtm_family == AF_INET) { struct prefix_ipv4 p; p.family = AF_INET; memcpy (&p.prefix, dest, 4); p.prefixlen = rtm->rtm_dst_len; if (IS_ZEBRA_DEBUG_KERNEL) { if (h->nlmsg_type == RTM_NEWROUTE) zlog_info ("RTM_NEWROUTE %s/%d", inet_ntoa (p.prefix), p.prefixlen); else zlog_info ("RTM_DELROUTE %s/%d", inet_ntoa (p.prefix), p.prefixlen); } if (h->nlmsg_type == RTM_NEWROUTE) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); } #ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) { struct prefix_ipv6 p; char buf[BUFSIZ]; p.family = AF_INET6; memcpy (&p.prefix, dest, 16); p.prefixlen = rtm->rtm_dst_len; if (IS_ZEBRA_DEBUG_KERNEL) { if (h->nlmsg_type == RTM_NEWROUTE) zlog_info ("RTM_NEWROUTE %s/%d", inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), p.prefixlen); else zlog_info ("RTM_DELROUTE %s/%d", inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), p.prefixlen); } if (h->nlmsg_type == RTM_NEWROUTE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0); } #endif /* HAVE_IPV6 */ return 0; }
void connected_down_ipv4 (struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; struct prefix_ipv4 *addr; struct prefix_ipv4 *dest; if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: start ", __func__); /*gujd: 2012-10-19, pm 3:49. When vrrp use virtual IP address , destination is NULL, so can't return.*/ #if 0 if(!ifc || !ifc->address || !ifc->destination|| !ifc->ifp) { zlog_err("ifc(%p), ifc->address(%p), ifc->destination(%p).\n", ifc,ifc->address,ifc->destination); return; } #else if(!ifc || !ifc->address || !ifc->ifp) { /*CID 11026 (#1 of 1): Dereference after null check (FORWARD_NULL) 4. var_deref_op: Dereferencing null pointer "ifc". Make sure , here is bug. So changed.*/ /*zlog_err("ifc(%p), ifc->address(%p), ifc->ifp(%p).\n", ifc,ifc->address,ifc->ifp); return ;*/ if(!ifc) { zlog_err("%s: line %d, ifc is null.\n",__func__,__LINE__); return ; } else { zlog_err("%s: line %d, ifc->address(%p), ifc->ifp(%p).\n", __func__,__LINE__,ifc->address,ifc->ifp); return ; } } #endif /* if(product != NULL)*/ if(product != NULL && product->board_type != BOARD_IS_ACTIVE_MASTER)/*gjd : change for active master 在删除ip时,直连路由没删除,因为重复添加,导致refcnt不为0释放不掉*/ goto skip; if(product != NULL && product->board_type == BOARD_IS_ACTIVE_MASTER &&CHECK_FLAG(ifp->if_scope, INTERFACE_LOCAL)) goto skip;/*local interface , skip the check the ifc->conf, because the ip address not install in the kernel .*/ if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; skip: addr = (struct prefix_ipv4 *)ifc->address; dest = (struct prefix_ipv4 *)ifc->destination; memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = addr->prefixlen; /* Point-to-point check. */ if (CONNECTED_POINTOPOINT_HOST(ifc)) p.prefix = dest->prefix; else p.prefix = addr->prefix; /* Apply mask to the network. */ apply_mask_ipv4 (&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any (&p)) return; rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: goto rib_update ", __func__); rib_update (); }
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 */ }