diff options
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 2779 | 
1 files changed, 1378 insertions, 1401 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index a544593dd6..80c7c09229 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -96,517 +96,507 @@  #endif  /* End of temporary definitions */ -struct gw_family_t -{ -  u_int16_t     filler; -  u_int16_t     family; -  union g_addr  gate; +struct gw_family_t { +	u_int16_t filler; +	u_int16_t family; +	union g_addr gate;  };  /*  Pending: create an efficient table_id (in a tree/hash) based lookup)   */ -static vrf_id_t -vrf_lookup_by_table (u_int32_t table_id) +static vrf_id_t vrf_lookup_by_table(u_int32_t table_id)  { -  struct vrf *vrf; -  struct zebra_vrf *zvrf; +	struct vrf *vrf; +	struct zebra_vrf *zvrf; -  RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) -    { -      if ((zvrf = vrf->info) == NULL || -          (zvrf->table_id != table_id)) -        continue; +	RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) +	{ +		if ((zvrf = vrf->info) == NULL || (zvrf->table_id != table_id)) +			continue; -      return zvrf_id (zvrf); -    } +		return zvrf_id(zvrf); +	} -  return VRF_DEFAULT; +	return VRF_DEFAULT;  }  /* Looking up routing table by netlink interface. */ -static int -netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, -                                   ns_id_t ns_id, int startup) +static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, +					     struct nlmsghdr *h, ns_id_t ns_id, +					     int startup)  { -  int len; -  struct rtmsg *rtm; -  struct rtattr *tb[RTA_MAX + 1]; -  u_char flags = 0; -  struct prefix p; -  struct prefix_ipv6 src_p; -  vrf_id_t vrf_id = VRF_DEFAULT; - -  char anyaddr[16] = { 0 }; - -  int index = 0; -  int table; -  int metric = 0; -  u_int32_t mtu = 0; - -  void *dest = NULL; -  void *gate = NULL; -  void *prefsrc = NULL;		/* IPv4 preferred source host address */ -  void *src = NULL;		/* IPv6 srcdest   source prefix */ - -  rtm = NLMSG_DATA (h); - -  if (startup && h->nlmsg_type != RTM_NEWROUTE) -    return 0; -  if (startup && rtm->rtm_type != RTN_UNICAST) -    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 (!startup && -      rtm->rtm_protocol == RTPROT_ZEBRA && -      h->nlmsg_type == RTM_NEWROUTE) -    return 0; - -  /* We don't care about change notifications for the MPLS table. */ -  /* TODO: Revisit this. */ -  if (rtm->rtm_family == AF_MPLS) -    return 0; - -  /* Table corresponding to route. */ -  if (tb[RTA_TABLE]) -    table = *(int *) RTA_DATA (tb[RTA_TABLE]); -  else -    table = rtm->rtm_table; - -  /* Map to VRF */ -  vrf_id = vrf_lookup_by_table(table); -  if (vrf_id == VRF_DEFAULT) -    { -      if (!is_zebra_valid_kernel_table(table) && -          !is_zebra_main_routing_table(table)) -        return 0; -    } - -  /* Route which inserted by Zebra. */ -  if (rtm->rtm_protocol == RTPROT_ZEBRA) -    flags |= ZEBRA_FLAG_SELFROUTE; - -  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_SRC]) -    src = RTA_DATA (tb[RTA_SRC]); -  else -    src = anyaddr; - -  if (tb[RTA_PREFSRC]) -    prefsrc = RTA_DATA (tb[RTA_PREFSRC]); - -  if (tb[RTA_GATEWAY]) -    gate = RTA_DATA (tb[RTA_GATEWAY]); - -  if (h->nlmsg_type == RTM_NEWROUTE) -    { -      if (tb[RTA_PRIORITY]) -        metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); - -      if (tb[RTA_METRICS]) -        { -          struct rtattr *mxrta[RTAX_MAX+1]; - -          memset (mxrta, 0, sizeof mxrta); -          netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), -                                RTA_PAYLOAD(tb[RTA_METRICS])); - -          if (mxrta[RTAX_MTU]) -            mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); -        } -    } - -  if (rtm->rtm_family == AF_INET) -    { -      p.family = AF_INET; -      memcpy (&p.u.prefix4, dest, 4); -      p.prefixlen = rtm->rtm_dst_len; -    } -  else if (rtm->rtm_family == AF_INET6) -    { -      p.family = AF_INET6; -      memcpy (&p.u.prefix6, dest, 16); -      p.prefixlen = rtm->rtm_dst_len; - -      src_p.family = AF_INET6; -      memcpy (&src_p.prefix, src, 16); -      src_p.prefixlen = rtm->rtm_src_len; -    } - -  if (rtm->rtm_src_len != 0) -    { -      char buf[PREFIX_STRLEN]; -      zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", -                 prefix2str (&p, buf, sizeof(buf)), vrf_id); -      return 0; -    } - -  if (IS_ZEBRA_DEBUG_KERNEL) -    { -      char buf[PREFIX_STRLEN]; -      char buf2[PREFIX_STRLEN]; -      zlog_debug ("%s %s%s%s vrf %u", -                  nl_msg_type_to_str (h->nlmsg_type), -                  prefix2str (&p, buf, sizeof(buf)), -                  src_p.prefixlen ? " from " : "", -                  src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "", -                  vrf_id); -    } - -  afi_t afi = AFI_IP; -  if (rtm->rtm_family == AF_INET6) -    afi = AFI_IP6; - -  if (h->nlmsg_type == RTM_NEWROUTE) -    { -      if (!tb[RTA_MULTIPATH]) -        rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, -                 0, flags, &p, NULL, gate, prefsrc, index, -                 table, metric, mtu, 0); -      else -        { -          /* This is a multipath route */ - -          struct rib *rib; -          struct rtnexthop *rtnh = -            (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - -          len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - -          rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); -          rib->type = ZEBRA_ROUTE_KERNEL; -          rib->distance = 0; -          rib->flags = flags; -          rib->metric = metric; -          rib->mtu = mtu; -          rib->vrf_id = vrf_id; -          rib->table = table; -          rib->nexthop_num = 0; -          rib->uptime = time (NULL); - -          for (;;) -            { -              if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) -                break; - -              index = rtnh->rtnh_ifindex; -              gate = 0; -              if (rtnh->rtnh_len > sizeof (*rtnh)) -                { -                  memset (tb, 0, sizeof (tb)); -                  netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), -                                        rtnh->rtnh_len - sizeof (*rtnh)); -                  if (tb[RTA_GATEWAY]) -                    gate = RTA_DATA (tb[RTA_GATEWAY]); -                } - -              if (gate) -                { -                  if (rtm->rtm_family == AF_INET) -                    { -                      if (index) -                        rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index); -                      else -                        rib_nexthop_ipv4_add (rib, gate, prefsrc); -                    } -                  else if (rtm->rtm_family == AF_INET6) -                    { -                      if (index) -                        rib_nexthop_ipv6_ifindex_add (rib, gate, index); -                      else -                        rib_nexthop_ipv6_add (rib,gate); -                    } -                } -              else -                rib_nexthop_ifindex_add (rib, index); - -              len -= NLMSG_ALIGN(rtnh->rtnh_len); -              rtnh = RTNH_NEXT(rtnh); -            } - -          zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, -                                 rib->nexthop_num); -          if (rib->nexthop_num == 0) -            XFREE (MTYPE_RIB, rib); -          else -            rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib); -        } -    } -  else -    { -      if (!tb[RTA_MULTIPATH]) -        rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, -                    &p, NULL, gate, index, table); -      else -        { -          struct rtnexthop *rtnh = -            (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - -          len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - -          for (;;) -            { -              if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) -                break; - -              gate = NULL; -              if (rtnh->rtnh_len > sizeof (*rtnh)) -                { -                  memset (tb, 0, sizeof (tb)); -                  netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), -                                        rtnh->rtnh_len - sizeof (*rtnh)); -                  if (tb[RTA_GATEWAY]) -                    gate = RTA_DATA (tb[RTA_GATEWAY]); -                } - -              if (gate) -                rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, -                            &p, NULL, gate, index, table); - -              len -= NLMSG_ALIGN(rtnh->rtnh_len); -              rtnh = RTNH_NEXT(rtnh); -            } -        } -    } - -  return 0; +	int len; +	struct rtmsg *rtm; +	struct rtattr *tb[RTA_MAX + 1]; +	u_char flags = 0; +	struct prefix p; +	struct prefix_ipv6 src_p; +	vrf_id_t vrf_id = VRF_DEFAULT; + +	char anyaddr[16] = {0}; + +	int index = 0; +	int table; +	int metric = 0; +	u_int32_t mtu = 0; + +	void *dest = NULL; +	void *gate = NULL; +	void *prefsrc = NULL; /* IPv4 preferred source host address */ +	void *src = NULL;     /* IPv6 srcdest   source prefix */ + +	rtm = NLMSG_DATA(h); + +	if (startup && h->nlmsg_type != RTM_NEWROUTE) +		return 0; +	if (startup && rtm->rtm_type != RTN_UNICAST) +		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 (!startup && rtm->rtm_protocol == RTPROT_ZEBRA +	    && h->nlmsg_type == RTM_NEWROUTE) +		return 0; + +	/* We don't care about change notifications for the MPLS table. */ +	/* TODO: Revisit this. */ +	if (rtm->rtm_family == AF_MPLS) +		return 0; + +	/* Table corresponding to route. */ +	if (tb[RTA_TABLE]) +		table = *(int *)RTA_DATA(tb[RTA_TABLE]); +	else +		table = rtm->rtm_table; + +	/* Map to VRF */ +	vrf_id = vrf_lookup_by_table(table); +	if (vrf_id == VRF_DEFAULT) { +		if (!is_zebra_valid_kernel_table(table) +		    && !is_zebra_main_routing_table(table)) +			return 0; +	} + +	/* Route which inserted by Zebra. */ +	if (rtm->rtm_protocol == RTPROT_ZEBRA) +		flags |= ZEBRA_FLAG_SELFROUTE; + +	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_SRC]) +		src = RTA_DATA(tb[RTA_SRC]); +	else +		src = anyaddr; + +	if (tb[RTA_PREFSRC]) +		prefsrc = RTA_DATA(tb[RTA_PREFSRC]); + +	if (tb[RTA_GATEWAY]) +		gate = RTA_DATA(tb[RTA_GATEWAY]); + +	if (h->nlmsg_type == RTM_NEWROUTE) { +		if (tb[RTA_PRIORITY]) +			metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]); + +		if (tb[RTA_METRICS]) { +			struct rtattr *mxrta[RTAX_MAX + 1]; + +			memset(mxrta, 0, sizeof mxrta); +			netlink_parse_rtattr(mxrta, RTAX_MAX, +					     RTA_DATA(tb[RTA_METRICS]), +					     RTA_PAYLOAD(tb[RTA_METRICS])); + +			if (mxrta[RTAX_MTU]) +				mtu = *(u_int32_t *)RTA_DATA(mxrta[RTAX_MTU]); +		} +	} + +	if (rtm->rtm_family == AF_INET) { +		p.family = AF_INET; +		memcpy(&p.u.prefix4, dest, 4); +		p.prefixlen = rtm->rtm_dst_len; +	} else if (rtm->rtm_family == AF_INET6) { +		p.family = AF_INET6; +		memcpy(&p.u.prefix6, dest, 16); +		p.prefixlen = rtm->rtm_dst_len; + +		src_p.family = AF_INET6; +		memcpy(&src_p.prefix, src, 16); +		src_p.prefixlen = rtm->rtm_src_len; +	} + +	if (rtm->rtm_src_len != 0) { +		char buf[PREFIX_STRLEN]; +		zlog_warn( +			"unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", +			prefix2str(&p, buf, sizeof(buf)), vrf_id); +		return 0; +	} + +	if (IS_ZEBRA_DEBUG_KERNEL) { +		char buf[PREFIX_STRLEN]; +		char buf2[PREFIX_STRLEN]; +		zlog_debug( +			"%s %s%s%s vrf %u", nl_msg_type_to_str(h->nlmsg_type), +			prefix2str(&p, buf, sizeof(buf)), +			src_p.prefixlen ? " from " : "", +			src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) +					: "", +			vrf_id); +	} + +	afi_t afi = AFI_IP; +	if (rtm->rtm_family == AF_INET6) +		afi = AFI_IP6; + +	if (h->nlmsg_type == RTM_NEWROUTE) { +		if (!tb[RTA_MULTIPATH]) +			rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, +				0, flags, &p, NULL, gate, prefsrc, index, table, +				metric, mtu, 0); +		else { +			/* This is a multipath route */ + +			struct rib *rib; +			struct rtnexthop *rtnh = +				(struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + +			len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + +			rib = XCALLOC(MTYPE_RIB, sizeof(struct rib)); +			rib->type = ZEBRA_ROUTE_KERNEL; +			rib->distance = 0; +			rib->flags = flags; +			rib->metric = metric; +			rib->mtu = mtu; +			rib->vrf_id = vrf_id; +			rib->table = table; +			rib->nexthop_num = 0; +			rib->uptime = time(NULL); + +			for (;;) { +				if (len < (int)sizeof(*rtnh) +				    || rtnh->rtnh_len > len) +					break; + +				index = rtnh->rtnh_ifindex; +				gate = 0; +				if (rtnh->rtnh_len > sizeof(*rtnh)) { +					memset(tb, 0, sizeof(tb)); +					netlink_parse_rtattr( +						tb, RTA_MAX, RTNH_DATA(rtnh), +						rtnh->rtnh_len - sizeof(*rtnh)); +					if (tb[RTA_GATEWAY]) +						gate = RTA_DATA( +							tb[RTA_GATEWAY]); +				} + +				if (gate) { +					if (rtm->rtm_family == AF_INET) { +						if (index) +							rib_nexthop_ipv4_ifindex_add( +								rib, gate, +								prefsrc, index); +						else +							rib_nexthop_ipv4_add( +								rib, gate, +								prefsrc); +					} else if (rtm->rtm_family +						   == AF_INET6) { +						if (index) +							rib_nexthop_ipv6_ifindex_add( +								rib, gate, +								index); +						else +							rib_nexthop_ipv6_add( +								rib, gate); +					} +				} else +					rib_nexthop_ifindex_add(rib, index); + +				len -= NLMSG_ALIGN(rtnh->rtnh_len); +				rtnh = RTNH_NEXT(rtnh); +			} + +			zserv_nexthop_num_warn(__func__, +					       (const struct prefix *)&p, +					       rib->nexthop_num); +			if (rib->nexthop_num == 0) +				XFREE(MTYPE_RIB, rib); +			else +				rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, +						  NULL, rib); +		} +	} else { +		if (!tb[RTA_MULTIPATH]) +			rib_delete(afi, SAFI_UNICAST, vrf_id, +				   ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, gate, +				   index, table); +		else { +			struct rtnexthop *rtnh = +				(struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + +			len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + +			for (;;) { +				if (len < (int)sizeof(*rtnh) +				    || rtnh->rtnh_len > len) +					break; + +				gate = NULL; +				if (rtnh->rtnh_len > sizeof(*rtnh)) { +					memset(tb, 0, sizeof(tb)); +					netlink_parse_rtattr( +						tb, RTA_MAX, RTNH_DATA(rtnh), +						rtnh->rtnh_len - sizeof(*rtnh)); +					if (tb[RTA_GATEWAY]) +						gate = RTA_DATA( +							tb[RTA_GATEWAY]); +				} + +				if (gate) +					rib_delete(afi, SAFI_UNICAST, vrf_id, +						   ZEBRA_ROUTE_KERNEL, 0, flags, +						   &p, NULL, gate, index, +						   table); + +				len -= NLMSG_ALIGN(rtnh->rtnh_len); +				rtnh = RTNH_NEXT(rtnh); +			} +		} +	} + +	return 0;  }  static struct mcast_route_data *mroute = NULL; -static int -netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h, -                                     ns_id_t ns_id, int startup) +static int netlink_route_change_read_multicast(struct sockaddr_nl *snl, +					       struct nlmsghdr *h, +					       ns_id_t ns_id, int startup)  { -  int len; -  struct rtmsg *rtm; -  struct rtattr *tb[RTA_MAX + 1]; -  struct mcast_route_data *m; -  struct mcast_route_data mr; -  int iif = 0; -  int count; -  int oif[256]; -  int oif_count = 0; -  char sbuf[40]; -  char gbuf[40]; -  char oif_list[256] = "\0"; -  vrf_id_t vrf = ns_id; - -  if (mroute) -    m = mroute; -  else -    { -      memset (&mr, 0, sizeof (mr)); -      m = &mr; -    } - -  rtm = NLMSG_DATA (h); - -  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - -  memset (tb, 0, sizeof tb); -  netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); - -  if (tb[RTA_IIF]) -    iif = *(int *)RTA_DATA (tb[RTA_IIF]); - -  if (tb[RTA_SRC]) -    m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]); - -  if (tb[RTA_DST]) -    m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); - -  if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES]) -    m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); - -  if (tb[RTA_MULTIPATH]) -    { -      struct rtnexthop *rtnh = -        (struct rtnexthop *)RTA_DATA (tb[RTA_MULTIPATH]); - -      len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); -      for (;;) -        { -          if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) -	    break; - -	  oif[oif_count] = rtnh->rtnh_ifindex; -          oif_count++; - -	  len -= NLMSG_ALIGN (rtnh->rtnh_len); -	  rtnh = RTNH_NEXT (rtnh); -        } -    } - -  if (IS_ZEBRA_DEBUG_KERNEL) -    { -      struct interface *ifp; -      strcpy (sbuf, inet_ntoa (m->sg.src)); -      strcpy (gbuf, inet_ntoa (m->sg.grp)); -      for (count = 0; count < oif_count; count++) -	{ -	  ifp = if_lookup_by_index (oif[count], vrf); -	  char temp[256]; +	int len; +	struct rtmsg *rtm; +	struct rtattr *tb[RTA_MAX + 1]; +	struct mcast_route_data *m; +	struct mcast_route_data mr; +	int iif = 0; +	int count; +	int oif[256]; +	int oif_count = 0; +	char sbuf[40]; +	char gbuf[40]; +	char oif_list[256] = "\0"; +	vrf_id_t vrf = ns_id; + +	if (mroute) +		m = mroute; +	else { +		memset(&mr, 0, sizeof(mr)); +		m = &mr; +	} + +	rtm = NLMSG_DATA(h); -	  sprintf (temp, "%s ", ifp->name); -	  strcat (oif_list, temp); +	len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); + +	memset(tb, 0, sizeof tb); +	netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); + +	if (tb[RTA_IIF]) +		iif = *(int *)RTA_DATA(tb[RTA_IIF]); + +	if (tb[RTA_SRC]) +		m->sg.src = *(struct in_addr *)RTA_DATA(tb[RTA_SRC]); + +	if (tb[RTA_DST]) +		m->sg.grp = *(struct in_addr *)RTA_DATA(tb[RTA_DST]); + +	if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES]) +		m->lastused = *(unsigned long long *)RTA_DATA(tb[RTA_EXPIRES]); + +	if (tb[RTA_MULTIPATH]) { +		struct rtnexthop *rtnh = +			(struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + +		len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); +		for (;;) { +			if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) +				break; + +			oif[oif_count] = rtnh->rtnh_ifindex; +			oif_count++; + +			len -= NLMSG_ALIGN(rtnh->rtnh_len); +			rtnh = RTNH_NEXT(rtnh); +		}  	} -      ifp = if_lookup_by_index (iif, vrf); -      zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", -		  nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused); -    } -  return 0; + +	if (IS_ZEBRA_DEBUG_KERNEL) { +		struct interface *ifp; +		strcpy(sbuf, inet_ntoa(m->sg.src)); +		strcpy(gbuf, inet_ntoa(m->sg.grp)); +		for (count = 0; count < oif_count; count++) { +			ifp = if_lookup_by_index(oif[count], vrf); +			char temp[256]; + +			sprintf(temp, "%s ", ifp->name); +			strcat(oif_list, temp); +		} +		ifp = if_lookup_by_index(iif, vrf); +		zlog_debug("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", +			   nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, +			   ifp->name, oif_list, m->lastused); +	} +	return 0;  } -int -netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, -		      ns_id_t ns_id, int startup) +int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h, +			 ns_id_t ns_id, int startup)  { -  int len; -  vrf_id_t vrf_id = ns_id; -  struct rtmsg *rtm; - -  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 vrf %u\n", h->nlmsg_type, vrf_id); -      return 0; -    } - -  /* Connected route. */ -  if (IS_ZEBRA_DEBUG_KERNEL) -    zlog_debug ("%s %s %s proto %s vrf %u", -		nl_msg_type_to_str (h->nlmsg_type), -		nl_family_to_str (rtm->rtm_family), -		nl_rttype_to_str (rtm->rtm_type), -		nl_rtproto_to_str (rtm->rtm_protocol), -		vrf_id); - -  /* We don't care about change notifications for the MPLS table. */ -  /* TODO: Revisit this. */ -  if (rtm->rtm_family == AF_MPLS) -    return 0; - -  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); -  if (len < 0) -    return -1; - -  switch (rtm->rtm_type) -    { -    case RTN_UNICAST: -      netlink_route_change_read_unicast (snl, h, ns_id, startup); -      break; -    case RTN_MULTICAST: -      netlink_route_change_read_multicast (snl, h, ns_id, startup); -      break; -    default: -      return 0; -      break; -    } - -  return 0; +	int len; +	vrf_id_t vrf_id = ns_id; +	struct rtmsg *rtm; + +	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 vrf %u\n", h->nlmsg_type, vrf_id); +		return 0; +	} + +	/* Connected route. */ +	if (IS_ZEBRA_DEBUG_KERNEL) +		zlog_debug("%s %s %s proto %s vrf %u", +			   nl_msg_type_to_str(h->nlmsg_type), +			   nl_family_to_str(rtm->rtm_family), +			   nl_rttype_to_str(rtm->rtm_type), +			   nl_rtproto_to_str(rtm->rtm_protocol), vrf_id); + +	/* We don't care about change notifications for the MPLS table. */ +	/* TODO: Revisit this. */ +	if (rtm->rtm_family == AF_MPLS) +		return 0; + +	len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); +	if (len < 0) +		return -1; + +	switch (rtm->rtm_type) { +	case RTN_UNICAST: +		netlink_route_change_read_unicast(snl, h, ns_id, startup); +		break; +	case RTN_MULTICAST: +		netlink_route_change_read_multicast(snl, h, ns_id, startup); +		break; +	default: +		return 0; +		break; +	} + +	return 0;  }  /* Routing table read function using netlink interface.  Only called     bootstrap time. */ -int -netlink_route_read (struct zebra_ns *zns) +int netlink_route_read(struct zebra_ns *zns)  { -  int ret; - -  /* Get IPv4 routing table. */ -  ret = netlink_request (AF_INET, RTM_GETROUTE, &zns->netlink_cmd); -  if (ret < 0) -    return ret; -  ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1); -  if (ret < 0) -    return ret; - -  /* Get IPv6 routing table. */ -  ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd); -  if (ret < 0) -    return ret; -  ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1); -  if (ret < 0) -    return ret; - -  return 0; +	int ret; + +	/* Get IPv4 routing table. */ +	ret = netlink_request(AF_INET, RTM_GETROUTE, &zns->netlink_cmd); +	if (ret < 0) +		return ret; +	ret = netlink_parse_info(netlink_route_change_read_unicast, +				 &zns->netlink_cmd, zns, 0, 1); +	if (ret < 0) +		return ret; + +	/* Get IPv6 routing table. */ +	ret = netlink_request(AF_INET6, RTM_GETROUTE, &zns->netlink_cmd); +	if (ret < 0) +		return ret; +	ret = netlink_parse_info(netlink_route_change_read_unicast, +				 &zns->netlink_cmd, zns, 0, 1); +	if (ret < 0) +		return ret; + +	return 0;  } -static void -_netlink_route_nl_add_gateway_info (u_char route_family, u_char gw_family, -                                    struct nlmsghdr *nlmsg, -                                    size_t req_size, int bytelen, -                                    struct nexthop *nexthop) +static void _netlink_route_nl_add_gateway_info(u_char route_family, +					       u_char gw_family, +					       struct nlmsghdr *nlmsg, +					       size_t req_size, int bytelen, +					       struct nexthop *nexthop)  { -  if (route_family == AF_MPLS) -    { -      struct gw_family_t gw_fam; - -      gw_fam.family = gw_family; -      if (gw_family == AF_INET) -        memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); -      else -        memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); -      addattr_l (nlmsg, req_size, RTA_VIA, &gw_fam.family, bytelen+2); -    } -  else -    { -      if (gw_family == AF_INET) -        addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); -      else -        addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen); -    } +	if (route_family == AF_MPLS) { +		struct gw_family_t gw_fam; + +		gw_fam.family = gw_family; +		if (gw_family == AF_INET) +			memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); +		else +			memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); +		addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family, +			  bytelen + 2); +	} else { +		if (gw_family == AF_INET) +			addattr_l(nlmsg, req_size, RTA_GATEWAY, +				  &nexthop->gate.ipv4, bytelen); +		else +			addattr_l(nlmsg, req_size, RTA_GATEWAY, +				  &nexthop->gate.ipv6, bytelen); +	}  } -static void -_netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family, -                                     struct rtattr *rta, struct rtnexthop *rtnh, -                                     size_t req_size, int bytelen, -                                     struct nexthop *nexthop) +static void _netlink_route_rta_add_gateway_info(u_char route_family, +						u_char gw_family, +						struct rtattr *rta, +						struct rtnexthop *rtnh, +						size_t req_size, int bytelen, +						struct nexthop *nexthop)  { -  if (route_family == AF_MPLS) -    { -      struct gw_family_t gw_fam; - -      gw_fam.family = gw_family; -      if (gw_family == AF_INET) -        memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); -      else -        memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); -      rta_addattr_l (rta, req_size, RTA_VIA, &gw_fam.family, bytelen+2); -      rtnh->rtnh_len += RTA_LENGTH (bytelen + 2); -    } -  else -    { -      if (gw_family == AF_INET) -        rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); -      else -        rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen); -      rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; -    } +	if (route_family == AF_MPLS) { +		struct gw_family_t gw_fam; + +		gw_fam.family = gw_family; +		if (gw_family == AF_INET) +			memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); +		else +			memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); +		rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family, +			      bytelen + 2); +		rtnh->rtnh_len += RTA_LENGTH(bytelen + 2); +	} else { +		if (gw_family == AF_INET) +			rta_addattr_l(rta, req_size, RTA_GATEWAY, +				      &nexthop->gate.ipv4, bytelen); +		else +			rta_addattr_l(rta, req_size, RTA_GATEWAY, +				      &nexthop->gate.ipv6, bytelen); +		rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; +	}  }  /* This function takes a nexthop as argument and adds @@ -620,188 +610,180 @@ _netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family,   * @param nlmsg: nlmsghdr structure to fill in.   * @param req_size: The size allocated for the message.   */ -static void -_netlink_route_build_singlepath( -        const char *routedesc, -        int bytelen, -        struct nexthop *nexthop, -        struct nlmsghdr *nlmsg, -        struct rtmsg *rtmsg, -        size_t req_size, -	int cmd) +static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, +					    struct nexthop *nexthop, +					    struct nlmsghdr *nlmsg, +					    struct rtmsg *rtmsg, +					    size_t req_size, int cmd)  { -  struct nexthop_label *nh_label; -  mpls_lse_t out_lse[MPLS_MAX_LABELS]; -  char label_buf[100]; - -  if (rtmsg->rtm_family == AF_INET && -      (nexthop->type == NEXTHOP_TYPE_IPV6 -      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) -    { -      char buf[16] = "169.254.0.1"; -      struct in_addr ipv4_ll; - -      inet_pton (AF_INET, buf, &ipv4_ll); -      rtmsg->rtm_flags |= RTNH_F_ONLINK; -      addattr_l (nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4); -      addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); - -      if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) -        addattr_l (nlmsg, req_size, RTA_PREFSRC, -                   &nexthop->rmap_src.ipv4, bytelen); -      else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) -        addattr_l (nlmsg, req_size, RTA_PREFSRC, -                   &nexthop->src.ipv4, bytelen); - -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): " -                   "nexthop via %s if %u", -                   routedesc, buf, nexthop->ifindex); -      return; -    } - -  label_buf[0] = '\0'; -  /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP -   * (in the case of LER) -   */ -  nh_label = nexthop->nh_label; -  if (rtmsg->rtm_family == AF_MPLS) -    { -      assert (nh_label); -      assert (nh_label->num_labels == 1); -    } - -  if (nh_label && nh_label->num_labels) -    { -      int i, num_labels = 0; -      u_int32_t bos; -      char label_buf1[20]; - -      for (i = 0; i < nh_label->num_labels; i++) -        { -          if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) -            { -              bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0); -              out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos); -              if (!num_labels) -                sprintf (label_buf, "label %d", nh_label->label[i]); -              else -                { -                  sprintf (label_buf1, "/%d", nh_label->label[i]); -                  strcat (label_buf, label_buf1); -                } -              num_labels++; -            } -        } -      if (num_labels) -        { -          if (rtmsg->rtm_family == AF_MPLS) -            addattr_l (nlmsg, req_size, RTA_NEWDST, -                       &out_lse, num_labels * sizeof(mpls_lse_t)); -          else -            { -              struct rtattr *nest; -              u_int16_t encap = LWTUNNEL_ENCAP_MPLS; - -              addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, -                        &encap, sizeof (u_int16_t)); -              nest = addattr_nest(nlmsg, req_size, RTA_ENCAP); -              addattr_l (nlmsg, req_size, MPLS_IPTUNNEL_DST, -                         &out_lse, num_labels * sizeof(mpls_lse_t)); -              addattr_nest_end(nlmsg, nest); -            } -        } -    } - -  if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) -    rtmsg->rtm_flags |= RTNH_F_ONLINK; - -  if (nexthop->type == NEXTHOP_TYPE_IPV4 -      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) -    { -      /* Send deletes to the kernel without specifying the next-hop */ -      if (cmd != RTM_DELROUTE) -        _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET, nlmsg, -                                            req_size, bytelen, nexthop); - -      if (cmd == RTM_NEWROUTE) -	{ -	  if (nexthop->rmap_src.ipv4.s_addr) -	    addattr_l (nlmsg, req_size, RTA_PREFSRC, -		       &nexthop->rmap_src.ipv4, bytelen); -	  else if (nexthop->src.ipv4.s_addr) -	    addattr_l (nlmsg, req_size, RTA_PREFSRC, -		       &nexthop->src.ipv4, bytelen); +	struct nexthop_label *nh_label; +	mpls_lse_t out_lse[MPLS_MAX_LABELS]; +	char label_buf[100]; + +	if (rtmsg->rtm_family == AF_INET +	    && (nexthop->type == NEXTHOP_TYPE_IPV6 +		|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) { +		char buf[16] = "169.254.0.1"; +		struct in_addr ipv4_ll; + +		inet_pton(AF_INET, buf, &ipv4_ll); +		rtmsg->rtm_flags |= RTNH_F_ONLINK; +		addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4); +		addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + +		if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) +			addattr_l(nlmsg, req_size, RTA_PREFSRC, +				  &nexthop->rmap_src.ipv4, bytelen); +		else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) +			addattr_l(nlmsg, req_size, RTA_PREFSRC, +				  &nexthop->src.ipv4, bytelen); + +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				" 5549: _netlink_route_build_singlepath() (%s): " +				"nexthop via %s if %u", +				routedesc, buf, nexthop->ifindex); +		return;  	} -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug("netlink_route_multipath() (%s): " -                   "nexthop via %s %s if %u", -                   routedesc, -                   inet_ntoa (nexthop->gate.ipv4), -                   label_buf, nexthop->ifindex); -    } -  if (nexthop->type == NEXTHOP_TYPE_IPV6 -      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) -    { -      _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET6, nlmsg, -                                          req_size, bytelen, nexthop); - -      if (cmd == RTM_NEWROUTE) -	{ -	  if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) -	    addattr_l (nlmsg, req_size, RTA_PREFSRC, -		       &nexthop->rmap_src.ipv6, bytelen); -	  else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) -	    addattr_l (nlmsg, req_size, RTA_PREFSRC, -		       &nexthop->src.ipv6, bytelen); +	label_buf[0] = '\0'; +	/* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP +	 * (in the case of LER) +	 */ +	nh_label = nexthop->nh_label; +	if (rtmsg->rtm_family == AF_MPLS) { +		assert(nh_label); +		assert(nh_label->num_labels == 1);  	} -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug("netlink_route_multipath() (%s): " -                   "nexthop via %s %s if %u", -                   routedesc, -                   inet6_ntoa (nexthop->gate.ipv6), -                   label_buf, nexthop->ifindex); -    } -  if (nexthop->type == NEXTHOP_TYPE_IFINDEX -      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) -    { -      addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); - -      if (cmd == RTM_NEWROUTE) -	{ -	  if (nexthop->rmap_src.ipv4.s_addr) -	    addattr_l (nlmsg, req_size, RTA_PREFSRC, -		       &nexthop->rmap_src.ipv4, bytelen); -	  else if (nexthop->src.ipv4.s_addr) -	    addattr_l (nlmsg, req_size, RTA_PREFSRC, -		       &nexthop->src.ipv4, bytelen); +	if (nh_label && nh_label->num_labels) { +		int i, num_labels = 0; +		u_int32_t bos; +		char label_buf1[20]; + +		for (i = 0; i < nh_label->num_labels; i++) { +			if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) { +				bos = ((i == (nh_label->num_labels - 1)) ? 1 +									 : 0); +				out_lse[i] = mpls_lse_encode(nh_label->label[i], +							     0, 0, bos); +				if (!num_labels) +					sprintf(label_buf, "label %d", +						nh_label->label[i]); +				else { +					sprintf(label_buf1, "/%d", +						nh_label->label[i]); +					strcat(label_buf, label_buf1); +				} +				num_labels++; +			} +		} +		if (num_labels) { +			if (rtmsg->rtm_family == AF_MPLS) +				addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse, +					  num_labels * sizeof(mpls_lse_t)); +			else { +				struct rtattr *nest; +				u_int16_t encap = LWTUNNEL_ENCAP_MPLS; + +				addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, +					  &encap, sizeof(u_int16_t)); +				nest = addattr_nest(nlmsg, req_size, RTA_ENCAP); +				addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST, +					  &out_lse, +					  num_labels * sizeof(mpls_lse_t)); +				addattr_nest_end(nlmsg, nest); +			} +		}  	} -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug("netlink_route_multipath() (%s): " -                   "nexthop via if %u", routedesc, nexthop->ifindex); -    } +	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) +		rtmsg->rtm_flags |= RTNH_F_ONLINK; + +	if (nexthop->type == NEXTHOP_TYPE_IPV4 +	    || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { +		/* Send deletes to the kernel without specifying the next-hop */ +		if (cmd != RTM_DELROUTE) +			_netlink_route_nl_add_gateway_info( +				rtmsg->rtm_family, AF_INET, nlmsg, req_size, +				bytelen, nexthop); + +		if (cmd == RTM_NEWROUTE) { +			if (nexthop->rmap_src.ipv4.s_addr) +				addattr_l(nlmsg, req_size, RTA_PREFSRC, +					  &nexthop->rmap_src.ipv4, bytelen); +			else if (nexthop->src.ipv4.s_addr) +				addattr_l(nlmsg, req_size, RTA_PREFSRC, +					  &nexthop->src.ipv4, bytelen); +		} + +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath() (%s): " +				"nexthop via %s %s if %u", +				routedesc, inet_ntoa(nexthop->gate.ipv4), +				label_buf, nexthop->ifindex); +	} +	if (nexthop->type == NEXTHOP_TYPE_IPV6 +	    || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { +		_netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6, +						   nlmsg, req_size, bytelen, +						   nexthop); + +		if (cmd == RTM_NEWROUTE) { +			if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) +				addattr_l(nlmsg, req_size, RTA_PREFSRC, +					  &nexthop->rmap_src.ipv6, bytelen); +			else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) +				addattr_l(nlmsg, req_size, RTA_PREFSRC, +					  &nexthop->src.ipv6, bytelen); +		} -  if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) -    { -      addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath() (%s): " +				"nexthop via %s %s if %u", +				routedesc, inet6_ntoa(nexthop->gate.ipv6), +				label_buf, nexthop->ifindex); +	} +	if (nexthop->type == NEXTHOP_TYPE_IFINDEX +	    || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { +		addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + +		if (cmd == RTM_NEWROUTE) { +			if (nexthop->rmap_src.ipv4.s_addr) +				addattr_l(nlmsg, req_size, RTA_PREFSRC, +					  &nexthop->rmap_src.ipv4, bytelen); +			else if (nexthop->src.ipv4.s_addr) +				addattr_l(nlmsg, req_size, RTA_PREFSRC, +					  &nexthop->src.ipv4, bytelen); +		} -      if (cmd == RTM_NEWROUTE) -	{ -	  if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) -	    addattr_l (nlmsg, req_size, RTA_PREFSRC, -		       &nexthop->rmap_src.ipv6, bytelen); -	  else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) -	    addattr_l (nlmsg, req_size, RTA_PREFSRC, -		       &nexthop->src.ipv6, bytelen); +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath() (%s): " +				"nexthop via if %u", +				routedesc, nexthop->ifindex);  	} -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug("netlink_route_multipath() (%s): " -                   "nexthop via if %u", routedesc, nexthop->ifindex); -    } +	if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { +		addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + +		if (cmd == RTM_NEWROUTE) { +			if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) +				addattr_l(nlmsg, req_size, RTA_PREFSRC, +					  &nexthop->rmap_src.ipv6, bytelen); +			else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) +				addattr_l(nlmsg, req_size, RTA_PREFSRC, +					  &nexthop->src.ipv6, bytelen); +		} + +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath() (%s): " +				"nexthop via if %u", +				routedesc, nexthop->ifindex); +	}  }  /* This function takes a nexthop as argument and @@ -820,212 +802,201 @@ _netlink_route_build_singlepath(   * @param src: pointer pointing to a location where   *             the prefsrc should be stored.   */ -static void -_netlink_route_build_multipath( -        const char *routedesc, -        int bytelen, -        struct nexthop *nexthop, -        struct rtattr *rta, -        struct rtnexthop *rtnh, -        struct rtmsg *rtmsg, -        union g_addr **src) +static void _netlink_route_build_multipath(const char *routedesc, int bytelen, +					   struct nexthop *nexthop, +					   struct rtattr *rta, +					   struct rtnexthop *rtnh, +					   struct rtmsg *rtmsg, +					   union g_addr **src)  { -  struct nexthop_label *nh_label; -  mpls_lse_t out_lse[MPLS_MAX_LABELS]; -  char label_buf[100]; - -  rtnh->rtnh_len = sizeof (*rtnh); -  rtnh->rtnh_flags = 0; -  rtnh->rtnh_hops = 0; -  rta->rta_len += rtnh->rtnh_len; - -  if (rtmsg->rtm_family == AF_INET && -      (nexthop->type == NEXTHOP_TYPE_IPV6 -      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) -    { -      char buf[16] = "169.254.0.1"; -      struct in_addr ipv4_ll; - -      inet_pton (AF_INET, buf, &ipv4_ll); -      bytelen = 4; -      rtnh->rtnh_flags |= RTNH_F_ONLINK; -      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, -                     &ipv4_ll, bytelen); -      rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; -      rtnh->rtnh_ifindex = nexthop->ifindex; - -      if (nexthop->rmap_src.ipv4.s_addr) -        *src = &nexthop->rmap_src; -      else if (nexthop->src.ipv4.s_addr) -         *src = &nexthop->src; - -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug(" 5549: netlink_route_build_multipath() (%s): " -                   "nexthop via %s if %u", -                   routedesc, buf, nexthop->ifindex); -      return; -    } - -  label_buf[0] = '\0'; -  /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP -   * (in the case of LER) -   */ -  nh_label = nexthop->nh_label; -  if (rtmsg->rtm_family == AF_MPLS) -    { -      assert (nh_label); -      assert (nh_label->num_labels == 1); -    } - -  if (nh_label && nh_label->num_labels) -    { -      int i, num_labels = 0; -      u_int32_t bos; -      char label_buf1[20]; - -      for (i = 0; i < nh_label->num_labels; i++) -        { -          if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) -            { -              bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0); -              out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos); -              if (!num_labels) -                sprintf (label_buf, "label %d", nh_label->label[i]); -              else -                { -                  sprintf (label_buf1, "/%d", nh_label->label[i]); -                  strcat (label_buf, label_buf1); -                } -              num_labels++; -            } -        } -      if (num_labels) -        { -          if (rtmsg->rtm_family == AF_MPLS) -            { -              rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_NEWDST, -                             &out_lse, num_labels * sizeof(mpls_lse_t)); -              rtnh->rtnh_len += RTA_LENGTH (num_labels * sizeof(mpls_lse_t)); -            } -          else -            { -              struct rtattr *nest; -              u_int16_t encap = LWTUNNEL_ENCAP_MPLS; -              int len = rta->rta_len; - -              rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE, -                            &encap, sizeof (u_int16_t)); -              nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP); -              rta_addattr_l (rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST, -                             &out_lse, num_labels * sizeof(mpls_lse_t)); -              rta_nest_end(rta, nest); -              rtnh->rtnh_len += rta->rta_len - len; -            } -        } -    } - -  if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) -    rtnh->rtnh_flags |= RTNH_F_ONLINK; - -  if (nexthop->type == NEXTHOP_TYPE_IPV4 -      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) -    { -      _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET, rta, -                                     rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop); -      if (nexthop->rmap_src.ipv4.s_addr) -        *src = &nexthop->rmap_src; -      else if (nexthop->src.ipv4.s_addr) -         *src = &nexthop->src; - -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug("netlink_route_multipath() (%s): " -                   "nexthop via %s %s if %u", -                   routedesc, -                   inet_ntoa (nexthop->gate.ipv4), -                   label_buf, nexthop->ifindex); -    } -  if (nexthop->type == NEXTHOP_TYPE_IPV6 -      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) -    { -      _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET6, rta, -                                       rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop); - -      if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) -        *src = &nexthop->rmap_src; -      else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) -	*src = &nexthop->src; - -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug("netlink_route_multipath() (%s): " -                   "nexthop via %s %s if %u", -                   routedesc, -                   inet6_ntoa (nexthop->gate.ipv6), -                   label_buf, nexthop->ifindex); -    } -  /* ifindex */ -  if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX -      || nexthop->type == NEXTHOP_TYPE_IFINDEX) -    { -      rtnh->rtnh_ifindex = nexthop->ifindex; - -      if (nexthop->rmap_src.ipv4.s_addr) -        *src = &nexthop->rmap_src; -      else if (nexthop->src.ipv4.s_addr) -        *src = &nexthop->src; - -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug("netlink_route_multipath() (%s): " -                   "nexthop via if %u", routedesc, nexthop->ifindex); -    } -  else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) -    { -      rtnh->rtnh_ifindex = nexthop->ifindex; - -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug("netlink_route_multipath() (%s): " -                   "nexthop via if %u", routedesc, nexthop->ifindex); -    } -  else -    { -      rtnh->rtnh_ifindex = 0; -    } +	struct nexthop_label *nh_label; +	mpls_lse_t out_lse[MPLS_MAX_LABELS]; +	char label_buf[100]; + +	rtnh->rtnh_len = sizeof(*rtnh); +	rtnh->rtnh_flags = 0; +	rtnh->rtnh_hops = 0; +	rta->rta_len += rtnh->rtnh_len; + +	if (rtmsg->rtm_family == AF_INET +	    && (nexthop->type == NEXTHOP_TYPE_IPV6 +		|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) { +		char buf[16] = "169.254.0.1"; +		struct in_addr ipv4_ll; + +		inet_pton(AF_INET, buf, &ipv4_ll); +		bytelen = 4; +		rtnh->rtnh_flags |= RTNH_F_ONLINK; +		rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll, +			      bytelen); +		rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; +		rtnh->rtnh_ifindex = nexthop->ifindex; + +		if (nexthop->rmap_src.ipv4.s_addr) +			*src = &nexthop->rmap_src; +		else if (nexthop->src.ipv4.s_addr) +			*src = &nexthop->src; + +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				" 5549: netlink_route_build_multipath() (%s): " +				"nexthop via %s if %u", +				routedesc, buf, nexthop->ifindex); +		return; +	} + +	label_buf[0] = '\0'; +	/* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP +	 * (in the case of LER) +	 */ +	nh_label = nexthop->nh_label; +	if (rtmsg->rtm_family == AF_MPLS) { +		assert(nh_label); +		assert(nh_label->num_labels == 1); +	} + +	if (nh_label && nh_label->num_labels) { +		int i, num_labels = 0; +		u_int32_t bos; +		char label_buf1[20]; + +		for (i = 0; i < nh_label->num_labels; i++) { +			if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) { +				bos = ((i == (nh_label->num_labels - 1)) ? 1 +									 : 0); +				out_lse[i] = mpls_lse_encode(nh_label->label[i], +							     0, 0, bos); +				if (!num_labels) +					sprintf(label_buf, "label %d", +						nh_label->label[i]); +				else { +					sprintf(label_buf1, "/%d", +						nh_label->label[i]); +					strcat(label_buf, label_buf1); +				} +				num_labels++; +			} +		} +		if (num_labels) { +			if (rtmsg->rtm_family == AF_MPLS) { +				rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST, +					      &out_lse, +					      num_labels * sizeof(mpls_lse_t)); +				rtnh->rtnh_len += RTA_LENGTH( +					num_labels * sizeof(mpls_lse_t)); +			} else { +				struct rtattr *nest; +				u_int16_t encap = LWTUNNEL_ENCAP_MPLS; +				int len = rta->rta_len; + +				rta_addattr_l(rta, NL_PKT_BUF_SIZE, +					      RTA_ENCAP_TYPE, &encap, +					      sizeof(u_int16_t)); +				nest = rta_nest(rta, NL_PKT_BUF_SIZE, +						RTA_ENCAP); +				rta_addattr_l(rta, NL_PKT_BUF_SIZE, +					      MPLS_IPTUNNEL_DST, &out_lse, +					      num_labels * sizeof(mpls_lse_t)); +				rta_nest_end(rta, nest); +				rtnh->rtnh_len += rta->rta_len - len; +			} +		} +	} + +	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) +		rtnh->rtnh_flags |= RTNH_F_ONLINK; + +	if (nexthop->type == NEXTHOP_TYPE_IPV4 +	    || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { +		_netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET, +						    rta, rtnh, NL_PKT_BUF_SIZE, +						    bytelen, nexthop); +		if (nexthop->rmap_src.ipv4.s_addr) +			*src = &nexthop->rmap_src; +		else if (nexthop->src.ipv4.s_addr) +			*src = &nexthop->src; + +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath() (%s): " +				"nexthop via %s %s if %u", +				routedesc, inet_ntoa(nexthop->gate.ipv4), +				label_buf, nexthop->ifindex); +	} +	if (nexthop->type == NEXTHOP_TYPE_IPV6 +	    || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { +		_netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6, +						    rta, rtnh, NL_PKT_BUF_SIZE, +						    bytelen, nexthop); + +		if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) +			*src = &nexthop->rmap_src; +		else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) +			*src = &nexthop->src; + +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath() (%s): " +				"nexthop via %s %s if %u", +				routedesc, inet6_ntoa(nexthop->gate.ipv6), +				label_buf, nexthop->ifindex); +	} +	/* ifindex */ +	if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX +	    || nexthop->type == NEXTHOP_TYPE_IFINDEX) { +		rtnh->rtnh_ifindex = nexthop->ifindex; + +		if (nexthop->rmap_src.ipv4.s_addr) +			*src = &nexthop->rmap_src; +		else if (nexthop->src.ipv4.s_addr) +			*src = &nexthop->src; + +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath() (%s): " +				"nexthop via if %u", +				routedesc, nexthop->ifindex); +	} else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { +		rtnh->rtnh_ifindex = nexthop->ifindex; + +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath() (%s): " +				"nexthop via if %u", +				routedesc, nexthop->ifindex); +	} else { +		rtnh->rtnh_ifindex = 0; +	}  } -static inline void -_netlink_mpls_build_singlepath( -        const char *routedesc, -        zebra_nhlfe_t *nhlfe, -        struct nlmsghdr *nlmsg, -        struct rtmsg *rtmsg, -        size_t req_size, -	int cmd) +static inline void _netlink_mpls_build_singlepath(const char *routedesc, +						  zebra_nhlfe_t *nhlfe, +						  struct nlmsghdr *nlmsg, +						  struct rtmsg *rtmsg, +						  size_t req_size, int cmd)  { -  int bytelen; -  u_char family; +	int bytelen; +	u_char family; -  family = NHLFE_FAMILY (nhlfe); -  bytelen = (family == AF_INET ? 4 : 16); -  _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop, -                                  nlmsg, rtmsg, req_size, cmd); +	family = NHLFE_FAMILY(nhlfe); +	bytelen = (family == AF_INET ? 4 : 16); +	_netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop, +					nlmsg, rtmsg, req_size, cmd);  }  static inline void -_netlink_mpls_build_multipath( -        const char *routedesc, -        zebra_nhlfe_t *nhlfe, -        struct rtattr *rta, -        struct rtnexthop *rtnh, -        struct rtmsg *rtmsg, -        union g_addr **src) +_netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe, +			      struct rtattr *rta, struct rtnexthop *rtnh, +			      struct rtmsg *rtmsg, union g_addr **src)  { -  int bytelen; -  u_char family; +	int bytelen; +	u_char family; -  family = NHLFE_FAMILY (nhlfe); -  bytelen = (family == AF_INET ? 4 : 16); -  _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, -                                 rta, rtnh, rtmsg, src); +	family = NHLFE_FAMILY(nhlfe); +	bytelen = (family == AF_INET ? 4 : 16); +	_netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta, +				       rtnh, rtmsg, src);  } @@ -1039,603 +1010,609 @@ _netlink_mpls_build_multipath(   *                     (recursive, multipath, etc.)   * @param family: Address family which the change concerns   */ -static void -_netlink_route_debug( -        int cmd, -        struct prefix *p, -        struct nexthop *nexthop, -        const char *routedesc, -        int family, -        struct zebra_vrf *zvrf) +static void _netlink_route_debug(int cmd, struct prefix *p, +				 struct nexthop *nexthop, const char *routedesc, +				 int family, struct zebra_vrf *zvrf)  { -  if (IS_ZEBRA_DEBUG_KERNEL) -    { -      char buf[PREFIX_STRLEN]; -      zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s", -		  routedesc, -		  nl_msg_type_to_str (cmd), -		  prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf), -		  (nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK"); -    } -    } - -static void -_netlink_mpls_debug( -        int cmd, -        u_int32_t label, -        const char *routedesc) -{ -  if (IS_ZEBRA_DEBUG_KERNEL) -    zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20", -                routedesc, nl_msg_type_to_str (cmd), label); +	if (IS_ZEBRA_DEBUG_KERNEL) { +		char buf[PREFIX_STRLEN]; +		zlog_debug( +			"netlink_route_multipath() (%s): %s %s vrf %u type %s", +			routedesc, nl_msg_type_to_str(cmd), +			prefix2str(p, buf, sizeof(buf)), zvrf_id(zvrf), +			(nexthop) ? nexthop_type_to_str(nexthop->type) : "UNK"); +	}  } -static int -netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen) +static void _netlink_mpls_debug(int cmd, u_int32_t label, const char *routedesc)  { -  struct { -      struct nlmsghdr         n; -      struct ndmsg            ndm; -      char                    buf[256]; -  } req; - -  struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - -  memset(&req.n, 0, sizeof(req.n)); -  memset(&req.ndm, 0, sizeof(req.ndm)); - -  req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); -  req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; -  req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH -  req.ndm.ndm_family = AF_INET; -  req.ndm.ndm_state = NUD_PERMANENT; -  req.ndm.ndm_ifindex = ifindex; -  req.ndm.ndm_type = RTN_UNICAST; - -  addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); -  addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); +	if (IS_ZEBRA_DEBUG_KERNEL) +		zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc, +			   nl_msg_type_to_str(cmd), label); +} -  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); +static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, +				int llalen) +{ +	struct { +		struct nlmsghdr n; +		struct ndmsg ndm; +		char buf[256]; +	} req; + +	struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + +	memset(&req.n, 0, sizeof(req.n)); +	memset(&req.ndm, 0, sizeof(req.ndm)); + +	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); +	req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; +	req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH +	req.ndm.ndm_family = AF_INET; +	req.ndm.ndm_state = NUD_PERMANENT; +	req.ndm.ndm_ifindex = ifindex; +	req.ndm.ndm_type = RTN_UNICAST; + +	addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); +	addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); + +	return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, +			    0);  }  /* Routing table change via netlink interface. */  /* Update flag indicates whether this is a "replace" or not. */ -static int -netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p, -                         struct rib *rib, int update) +static int netlink_route_multipath(int cmd, struct prefix *p, +				   struct prefix *src_p, struct rib *rib, +				   int update)  { -  int bytelen; -  struct sockaddr_nl snl; -  struct nexthop *nexthop = NULL, *tnexthop; -  int recursing; -  unsigned int nexthop_num; -  int discard; -  int family = PREFIX_FAMILY(p); -  const char *routedesc; -  int setsrc = 0; -  union g_addr src; - -  struct -  { -    struct nlmsghdr n; -    struct rtmsg r; -    char buf[NL_PKT_BUF_SIZE]; -  } req; - -  struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); -  struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id); - -  memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); - -  bytelen = (family == AF_INET ? 4 : 16); - -  req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); -  req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; -  if ((cmd == RTM_NEWROUTE) && update) -    req.n.nlmsg_flags |= NLM_F_REPLACE; -  req.n.nlmsg_type = cmd; -  req.r.rtm_family = family; -  req.r.rtm_dst_len = p->prefixlen; -  req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; -  req.r.rtm_protocol = RTPROT_ZEBRA; -  req.r.rtm_scope = RT_SCOPE_UNIVERSE; - -  if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT)) -    discard = 1; -  else -    discard = 0; - -  if (cmd == RTM_NEWROUTE) -    { -      if (discard) -        { -          if (rib->flags & ZEBRA_FLAG_BLACKHOLE) -            req.r.rtm_type = RTN_BLACKHOLE; -          else if (rib->flags & ZEBRA_FLAG_REJECT) -            req.r.rtm_type = RTN_UNREACHABLE; -          else -            assert (RTN_BLACKHOLE != RTN_UNREACHABLE);  /* false */ -        } -      else -        req.r.rtm_type = RTN_UNICAST; -    } - -  addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); -  if (src_p) -    addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen); - -  /* Metric. */ -  /* Hardcode the metric for all routes coming from zebra. Metric isn't used -   * either by the kernel or by zebra. Its purely for calculating best path(s) -   * by the routing protocol and for communicating with protocol peers. -   */ -  addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); - -  /* Table corresponding to this route. */ -  if (rib->table < 256) -    req.r.rtm_table = rib->table; -  else -    { -      req.r.rtm_table = RT_TABLE_UNSPEC; -      addattr32(&req.n, sizeof req, RTA_TABLE, rib->table); -    } - -  if (rib->mtu || rib->nexthop_mtu) -    { -      char buf[NL_PKT_BUF_SIZE]; -      struct rtattr *rta = (void *) buf; -      u_int32_t mtu = rib->mtu; -      if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu)) -        mtu = rib->nexthop_mtu; -      rta->rta_type = RTA_METRICS; -      rta->rta_len = RTA_LENGTH(0); -      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); -      addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta), -                 RTA_PAYLOAD (rta)); -    } - -  if (discard) -    { -      if (cmd == RTM_NEWROUTE) -        for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) -          { -            /* We shouldn't encounter recursive nexthops on discard routes, -             * but it is probably better to handle that case correctly anyway. -             */ -            if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) -              continue; -          } -      goto skip; -    } - -  /* Count overall nexthops so we can decide whether to use singlepath -   * or multipath case. */ -  nexthop_num = 0; -  for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) -    { -      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) -        continue; -      if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) -        continue; -      if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) -        continue; - -      nexthop_num++; -    } - -  /* Singlepath case. */ -  if (nexthop_num == 1 || multipath_num == 1) -    { -      nexthop_num = 0; -      for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) -        { -          if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) -            { -              if (!setsrc) -                 { -		   if (family == AF_INET) -		     { -		       if (nexthop->rmap_src.ipv4.s_addr != 0) -			 { -			   src.ipv4 = nexthop->rmap_src.ipv4; -			   setsrc = 1; -			 } -		       else if (nexthop->src.ipv4.s_addr != 0) -			 { -			   src.ipv4 = nexthop->src.ipv4; -			   setsrc = 1; -			 } -		     } -		   else if (family == AF_INET6) -		     { -		       if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) -			 { -			   src.ipv6 = nexthop->rmap_src.ipv6; -			   setsrc = 1; -			 } -		       else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) -			 { -			   src.ipv6 = nexthop->src.ipv6; -			   setsrc = 1; -			 } -		     } -                 } -              continue; -	    } - -          if ((cmd == RTM_NEWROUTE -               && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) -              || (cmd == RTM_DELROUTE -                  && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) -            { -              routedesc = recursing ? "recursive, 1 hop" : "single hop"; - -              _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); -              _netlink_route_build_singlepath(routedesc, bytelen, -                                              nexthop, &req.n, &req.r, -                                              sizeof req, cmd); -              nexthop_num++; -              break; -            } -        } -      if (setsrc && (cmd == RTM_NEWROUTE)) -	{ -	  if (family == AF_INET) -	    addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); -	  else if (family == AF_INET6) -	    addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen); +	int bytelen; +	struct sockaddr_nl snl; +	struct nexthop *nexthop = NULL, *tnexthop; +	int recursing; +	unsigned int nexthop_num; +	int discard; +	int family = PREFIX_FAMILY(p); +	const char *routedesc; +	int setsrc = 0; +	union g_addr src; + +	struct { +		struct nlmsghdr n; +		struct rtmsg r; +		char buf[NL_PKT_BUF_SIZE]; +	} req; + +	struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); +	struct zebra_vrf *zvrf = vrf_info_lookup(rib->vrf_id); + +	memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + +	bytelen = (family == AF_INET ? 4 : 16); + +	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); +	req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; +	if ((cmd == RTM_NEWROUTE) && update) +		req.n.nlmsg_flags |= NLM_F_REPLACE; +	req.n.nlmsg_type = cmd; +	req.r.rtm_family = family; +	req.r.rtm_dst_len = p->prefixlen; +	req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; +	req.r.rtm_protocol = RTPROT_ZEBRA; +	req.r.rtm_scope = RT_SCOPE_UNIVERSE; + +	if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) +	    || (rib->flags & ZEBRA_FLAG_REJECT)) +		discard = 1; +	else +		discard = 0; + +	if (cmd == RTM_NEWROUTE) { +		if (discard) { +			if (rib->flags & ZEBRA_FLAG_BLACKHOLE) +				req.r.rtm_type = RTN_BLACKHOLE; +			else if (rib->flags & ZEBRA_FLAG_REJECT) +				req.r.rtm_type = RTN_UNREACHABLE; +			else +				assert(RTN_BLACKHOLE +				       != RTN_UNREACHABLE); /* false */ +		} else +			req.r.rtm_type = RTN_UNICAST;  	} -    } -  else -    { -      char buf[NL_PKT_BUF_SIZE]; -      struct rtattr *rta = (void *) buf; -      struct rtnexthop *rtnh; -      union g_addr *src1 = NULL; - -      rta->rta_type = RTA_MULTIPATH; -      rta->rta_len = RTA_LENGTH (0); -      rtnh = RTA_DATA (rta); - -      nexthop_num = 0; -      for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) -        { -          if (nexthop_num >= multipath_num) -            break; - -          if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) -	    { -              /* This only works for IPv4 now */ -              if (!setsrc) -                 { -		   if (family == AF_INET) -		     { -		       if (nexthop->rmap_src.ipv4.s_addr != 0) -			 { -			   src.ipv4 = nexthop->rmap_src.ipv4; -			   setsrc = 1; -			 } -		       else if (nexthop->src.ipv4.s_addr != 0) -			 { -			   src.ipv4 = nexthop->src.ipv4; -			   setsrc = 1; -			 } -		     } -		   else if (family == AF_INET6) -		     { -		       if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) -			 { -			   src.ipv6 = nexthop->rmap_src.ipv6; -			   setsrc = 1; -			 } -		       else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) -			 { -			   src.ipv6 = nexthop->src.ipv6; -			   setsrc = 1; -			 } -		     } -                 } -	      continue; -	    } - -          if ((cmd == RTM_NEWROUTE -               && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) -              || (cmd == RTM_DELROUTE -                  && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) -            { -              routedesc = recursing ? "recursive, multihop" : "multihop"; -              nexthop_num++; - -              _netlink_route_debug(cmd, p, nexthop, -                                   routedesc, family, zvrf); -              _netlink_route_build_multipath(routedesc, bytelen, -                                             nexthop, rta, rtnh, &req.r, &src1); -              rtnh = RTNH_NEXT (rtnh); - -	      if (!setsrc && src1) -		{ -		  if (family == AF_INET) -		    src.ipv4 = src1->ipv4; -		  else if (family == AF_INET6) -		    src.ipv6 = src1->ipv6; -		  setsrc = 1; -		} -            } -        } -      if (setsrc && (cmd == RTM_NEWROUTE)) -	{ -	  if (family == AF_INET) -	    addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); -	  else if (family == AF_INET6) -	    addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen); -          if (IS_ZEBRA_DEBUG_KERNEL) -	    zlog_debug("Setting source"); +	addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); +	if (src_p) +		addattr_l(&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, +			  bytelen); + +	/* Metric. */ +	/* Hardcode the metric for all routes coming from zebra. Metric isn't +	 * used +	 * either by the kernel or by zebra. Its purely for calculating best +	 * path(s) +	 * by the routing protocol and for communicating with protocol peers. +	 */ +	addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); + +	/* Table corresponding to this route. */ +	if (rib->table < 256) +		req.r.rtm_table = rib->table; +	else { +		req.r.rtm_table = RT_TABLE_UNSPEC; +		addattr32(&req.n, sizeof req, RTA_TABLE, rib->table); +	} + +	if (rib->mtu || rib->nexthop_mtu) { +		char buf[NL_PKT_BUF_SIZE]; +		struct rtattr *rta = (void *)buf; +		u_int32_t mtu = rib->mtu; +		if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu)) +			mtu = rib->nexthop_mtu; +		rta->rta_type = RTA_METRICS; +		rta->rta_len = RTA_LENGTH(0); +		rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); +		addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA(rta), +			  RTA_PAYLOAD(rta));  	} -      if (rta->rta_len > RTA_LENGTH (0)) -        addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta), -                   RTA_PAYLOAD (rta)); -    } +	if (discard) { +		if (cmd == RTM_NEWROUTE) +			for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, +					     recursing)) { +				/* We shouldn't encounter recursive nexthops on +				 * discard routes, +				 * but it is probably better to handle that case +				 * correctly anyway. +				 */ +				if (CHECK_FLAG(nexthop->flags, +					       NEXTHOP_FLAG_RECURSIVE)) +					continue; +			} +		goto skip; +	} -  /* If there is no useful nexthop then return. */ -  if (nexthop_num == 0) -    { -      if (IS_ZEBRA_DEBUG_KERNEL) -        zlog_debug ("netlink_route_multipath(): No useful nexthop."); -      return 0; -    } +	/* Count overall nexthops so we can decide whether to use singlepath +	 * or multipath case. */ +	nexthop_num = 0; +	for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { +		if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) +			continue; +		if (cmd == RTM_NEWROUTE +		    && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) +			continue; +		if (cmd == RTM_DELROUTE +		    && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) +			continue; + +		nexthop_num++; +	} + +	/* Singlepath case. */ +	if (nexthop_num == 1 || multipath_num == 1) { +		nexthop_num = 0; +		for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, +				     recursing)) { +			if (CHECK_FLAG(nexthop->flags, +				       NEXTHOP_FLAG_RECURSIVE)) { +				if (!setsrc) { +					if (family == AF_INET) { +						if (nexthop->rmap_src.ipv4 +							    .s_addr +						    != 0) { +							src.ipv4 = +								nexthop->rmap_src +									.ipv4; +							setsrc = 1; +						} else if (nexthop->src.ipv4 +								   .s_addr +							   != 0) { +							src.ipv4 = +								nexthop->src +									.ipv4; +							setsrc = 1; +						} +					} else if (family == AF_INET6) { +						if (!IN6_IS_ADDR_UNSPECIFIED( +							    &nexthop->rmap_src +								     .ipv6)) { +							src.ipv6 = +								nexthop->rmap_src +									.ipv6; +							setsrc = 1; +						} else if ( +							!IN6_IS_ADDR_UNSPECIFIED( +								&nexthop->src +									 .ipv6)) { +							src.ipv6 = +								nexthop->src +									.ipv6; +							setsrc = 1; +						} +					} +				} +				continue; +			} + +			if ((cmd == RTM_NEWROUTE +			     && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) +			    || (cmd == RTM_DELROUTE +				&& CHECK_FLAG(nexthop->flags, +					      NEXTHOP_FLAG_FIB))) { +				routedesc = recursing ? "recursive, 1 hop" +						      : "single hop"; + +				_netlink_route_debug(cmd, p, nexthop, routedesc, +						     family, zvrf); +				_netlink_route_build_singlepath( +					routedesc, bytelen, nexthop, &req.n, +					&req.r, sizeof req, cmd); +				nexthop_num++; +				break; +			} +		} +		if (setsrc && (cmd == RTM_NEWROUTE)) { +			if (family == AF_INET) +				addattr_l(&req.n, sizeof req, RTA_PREFSRC, +					  &src.ipv4, bytelen); +			else if (family == AF_INET6) +				addattr_l(&req.n, sizeof req, RTA_PREFSRC, +					  &src.ipv6, bytelen); +		} +	} else { +		char buf[NL_PKT_BUF_SIZE]; +		struct rtattr *rta = (void *)buf; +		struct rtnexthop *rtnh; +		union g_addr *src1 = NULL; + +		rta->rta_type = RTA_MULTIPATH; +		rta->rta_len = RTA_LENGTH(0); +		rtnh = RTA_DATA(rta); + +		nexthop_num = 0; +		for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, +				     recursing)) { +			if (nexthop_num >= multipath_num) +				break; + +			if (CHECK_FLAG(nexthop->flags, +				       NEXTHOP_FLAG_RECURSIVE)) { +				/* This only works for IPv4 now */ +				if (!setsrc) { +					if (family == AF_INET) { +						if (nexthop->rmap_src.ipv4 +							    .s_addr +						    != 0) { +							src.ipv4 = +								nexthop->rmap_src +									.ipv4; +							setsrc = 1; +						} else if (nexthop->src.ipv4 +								   .s_addr +							   != 0) { +							src.ipv4 = +								nexthop->src +									.ipv4; +							setsrc = 1; +						} +					} else if (family == AF_INET6) { +						if (!IN6_IS_ADDR_UNSPECIFIED( +							    &nexthop->rmap_src +								     .ipv6)) { +							src.ipv6 = +								nexthop->rmap_src +									.ipv6; +							setsrc = 1; +						} else if ( +							!IN6_IS_ADDR_UNSPECIFIED( +								&nexthop->src +									 .ipv6)) { +							src.ipv6 = +								nexthop->src +									.ipv6; +							setsrc = 1; +						} +					} +				} +				continue; +			} + +			if ((cmd == RTM_NEWROUTE +			     && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) +			    || (cmd == RTM_DELROUTE +				&& CHECK_FLAG(nexthop->flags, +					      NEXTHOP_FLAG_FIB))) { +				routedesc = recursing ? "recursive, multihop" +						      : "multihop"; +				nexthop_num++; + +				_netlink_route_debug(cmd, p, nexthop, routedesc, +						     family, zvrf); +				_netlink_route_build_multipath( +					routedesc, bytelen, nexthop, rta, rtnh, +					&req.r, &src1); +				rtnh = RTNH_NEXT(rtnh); + +				if (!setsrc && src1) { +					if (family == AF_INET) +						src.ipv4 = src1->ipv4; +					else if (family == AF_INET6) +						src.ipv6 = src1->ipv6; + +					setsrc = 1; +				} +			} +		} +		if (setsrc && (cmd == RTM_NEWROUTE)) { +			if (family == AF_INET) +				addattr_l(&req.n, sizeof req, RTA_PREFSRC, +					  &src.ipv4, bytelen); +			else if (family == AF_INET6) +				addattr_l(&req.n, sizeof req, RTA_PREFSRC, +					  &src.ipv6, bytelen); +			if (IS_ZEBRA_DEBUG_KERNEL) +				zlog_debug("Setting source"); +		} + +		if (rta->rta_len > RTA_LENGTH(0)) +			addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, +				  RTA_DATA(rta), RTA_PAYLOAD(rta)); +	} + +	/* If there is no useful nexthop then return. */ +	if (nexthop_num == 0) { +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug( +				"netlink_route_multipath(): No useful nexthop."); +		return 0; +	}  skip: -  /* Destination netlink address. */ -  memset (&snl, 0, sizeof snl); -  snl.nl_family = AF_NETLINK; +	/* Destination netlink address. */ +	memset(&snl, 0, sizeof snl); +	snl.nl_family = AF_NETLINK; -  /* Talk to netlink socket. */ -  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); +	/* Talk to netlink socket. */ +	return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, +			    0);  } -int -kernel_get_ipmr_sg_stats (void *in) +int kernel_get_ipmr_sg_stats(void *in)  { -  int suc = 0; -  struct mcast_route_data *mr = (struct mcast_route_data *)in; -  struct { -      struct nlmsghdr         n; -      struct ndmsg            ndm; -      char                    buf[256]; -  } req; - -  mroute = mr; -  struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - -  memset(&req.n, 0, sizeof(req.n)); -  memset(&req.ndm, 0, sizeof(req.ndm)); - -  req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); -  req.n.nlmsg_flags = NLM_F_REQUEST; -  req.ndm.ndm_family = AF_INET; -  req.n.nlmsg_type = RTM_GETROUTE; - -  addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4); -  addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4); -  addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4); -  addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4); - -  suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns, 0); - -  mroute = NULL; -  return suc; +	int suc = 0; +	struct mcast_route_data *mr = (struct mcast_route_data *)in; +	struct { +		struct nlmsghdr n; +		struct ndmsg ndm; +		char buf[256]; +	} req; + +	mroute = mr; +	struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + +	memset(&req.n, 0, sizeof(req.n)); +	memset(&req.ndm, 0, sizeof(req.ndm)); + +	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); +	req.n.nlmsg_flags = NLM_F_REQUEST; +	req.ndm.ndm_family = AF_INET; +	req.n.nlmsg_type = RTM_GETROUTE; + +	addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4); +	addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4); +	addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4); +	addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4); + +	suc = netlink_talk(netlink_route_change_read_multicast, &req.n, +			   &zns->netlink_cmd, zns, 0); + +	mroute = NULL; +	return suc;  } -int -kernel_route_rib (struct prefix *p, struct prefix *src_p, -                  struct rib *old, struct rib *new) +int kernel_route_rib(struct prefix *p, struct prefix *src_p, struct rib *old, +		     struct rib *new)  { -  if (!old && new) -    return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 0); -  if (old && !new) -    return netlink_route_multipath (RTM_DELROUTE, p, src_p, old, 0); +	if (!old && new) +		return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0); +	if (old && !new) +		return netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0); -  return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 1); +	return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 1);  } -int -kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, +			int llalen)  { -  return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, addr, -			      lla, llalen); +	return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, +				    addr, lla, llalen);  }  /*   * MPLS label forwarding table change via netlink interface.   */ -int -netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) +int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)  { -  mpls_lse_t lse; -  zebra_nhlfe_t *nhlfe; -  struct nexthop *nexthop = NULL; -  unsigned int nexthop_num; -  const char *routedesc; -  struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - -  struct -  { -    struct nlmsghdr n; -    struct rtmsg r; -    char buf[NL_PKT_BUF_SIZE]; -  } req; - -  memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); - - -  /* -   * Count # nexthops so we can decide whether to use singlepath -   * or multipath case. -   */ -  nexthop_num = 0; -  for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) -    { -      nexthop = nhlfe->nexthop; -      if (!nexthop) -        continue; -      if (cmd == RTM_NEWROUTE) -        { -          /* Count all selected NHLFEs */ -          if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && -              CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) -            nexthop_num++; -        } -      else /* DEL */ -        { -          /* Count all installed NHLFEs */ -          if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && -              CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) -            nexthop_num++; -        } -    } - -  if (nexthop_num == 0) // unexpected -    return 0; - -  req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); -  req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; -  req.n.nlmsg_type = cmd; -  req.r.rtm_family = AF_MPLS; -  req.r.rtm_table = RT_TABLE_MAIN; -  req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS; -  req.r.rtm_protocol = RTPROT_ZEBRA; -  req.r.rtm_scope = RT_SCOPE_UNIVERSE; -  req.r.rtm_type = RTN_UNICAST; - -  if (cmd == RTM_NEWROUTE) -    /* We do a replace to handle update. */ -    req.n.nlmsg_flags |= NLM_F_REPLACE; - -  /* Fill destination */ -  lse = mpls_lse_encode (lsp->ile.in_label, 0, 0, 1); -  addattr_l (&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t)); - -  /* Fill nexthops (paths) based on single-path or multipath. The paths -   * chosen depend on the operation. -   */ -  if (nexthop_num == 1 || multipath_num == 1) -    { -      routedesc = "single hop"; -      _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); - -      nexthop_num = 0; -      for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) -        { -          nexthop = nhlfe->nexthop; -          if (!nexthop) -            continue; - -          if ((cmd == RTM_NEWROUTE && -               (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && -                CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || -              (cmd == RTM_DELROUTE && -               (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && -                CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))) -            { -              /* Add the gateway */ -              _netlink_mpls_build_singlepath(routedesc, nhlfe, -                                             &req.n, &req.r, sizeof req, cmd); -              if (cmd == RTM_NEWROUTE) -                { -                  SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); -                  SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); -                } -              else -                { -                  UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); -                  UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); -                } -              nexthop_num++; -              break; -            } -        } -    } -  else /* Multipath case */ -    { -      char buf[NL_PKT_BUF_SIZE]; -      struct rtattr *rta = (void *) buf; -      struct rtnexthop *rtnh; -      union g_addr *src1 = NULL; - -      rta->rta_type = RTA_MULTIPATH; -      rta->rta_len = RTA_LENGTH (0); -      rtnh = RTA_DATA (rta); - -      routedesc = "multihop"; -      _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); - -      nexthop_num = 0; -      for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) -        { -          nexthop = nhlfe->nexthop; -          if (!nexthop) -            continue; - -          if (nexthop_num >= multipath_num) -            break; - -          if ((cmd == RTM_NEWROUTE && -               (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && -                CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || -              (cmd == RTM_DELROUTE && -               (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && -                CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))) -            { -              nexthop_num++; - -              /* Build the multipath */ -              _netlink_mpls_build_multipath(routedesc, nhlfe, rta, -                                            rtnh, &req.r, &src1); -              rtnh = RTNH_NEXT (rtnh); - -              if (cmd == RTM_NEWROUTE) -                { -                  SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); -                  SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); -                } -              else -                { -                  UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); -                  UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); -                } - -            } -        } - -      /* Add the multipath */ -      if (rta->rta_len > RTA_LENGTH (0)) -        addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta), -                   RTA_PAYLOAD (rta)); -    } - -  /* Talk to netlink socket. */ -  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); +	mpls_lse_t lse; +	zebra_nhlfe_t *nhlfe; +	struct nexthop *nexthop = NULL; +	unsigned int nexthop_num; +	const char *routedesc; +	struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + +	struct { +		struct nlmsghdr n; +		struct rtmsg r; +		char buf[NL_PKT_BUF_SIZE]; +	} req; + +	memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + + +	/* +	 * Count # nexthops so we can decide whether to use singlepath +	 * or multipath case. +	 */ +	nexthop_num = 0; +	for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { +		nexthop = nhlfe->nexthop; +		if (!nexthop) +			continue; +		if (cmd == RTM_NEWROUTE) { +			/* Count all selected NHLFEs */ +			if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) +			    && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) +				nexthop_num++; +		} else /* DEL */ +		{ +			/* Count all installed NHLFEs */ +			if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) +			    && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) +				nexthop_num++; +		} +	} + +	if (nexthop_num == 0) // unexpected +		return 0; + +	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); +	req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; +	req.n.nlmsg_type = cmd; +	req.r.rtm_family = AF_MPLS; +	req.r.rtm_table = RT_TABLE_MAIN; +	req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS; +	req.r.rtm_protocol = RTPROT_ZEBRA; +	req.r.rtm_scope = RT_SCOPE_UNIVERSE; +	req.r.rtm_type = RTN_UNICAST; + +	if (cmd == RTM_NEWROUTE) +		/* We do a replace to handle update. */ +		req.n.nlmsg_flags |= NLM_F_REPLACE; + +	/* Fill destination */ +	lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1); +	addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t)); + +	/* Fill nexthops (paths) based on single-path or multipath. The paths +	 * chosen depend on the operation. +	 */ +	if (nexthop_num == 1 || multipath_num == 1) { +		routedesc = "single hop"; +		_netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + +		nexthop_num = 0; +		for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { +			nexthop = nhlfe->nexthop; +			if (!nexthop) +				continue; + +			if ((cmd == RTM_NEWROUTE +			     && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) +				 && CHECK_FLAG(nexthop->flags, +					       NEXTHOP_FLAG_ACTIVE))) +			    || (cmd == RTM_DELROUTE +				&& (CHECK_FLAG(nhlfe->flags, +					       NHLFE_FLAG_INSTALLED) +				    && CHECK_FLAG(nexthop->flags, +						  NEXTHOP_FLAG_FIB)))) { +				/* Add the gateway */ +				_netlink_mpls_build_singlepath(routedesc, nhlfe, +							       &req.n, &req.r, +							       sizeof req, cmd); +				if (cmd == RTM_NEWROUTE) { +					SET_FLAG(nhlfe->flags, +						 NHLFE_FLAG_INSTALLED); +					SET_FLAG(nexthop->flags, +						 NEXTHOP_FLAG_FIB); +				} else { +					UNSET_FLAG(nhlfe->flags, +						   NHLFE_FLAG_INSTALLED); +					UNSET_FLAG(nexthop->flags, +						   NEXTHOP_FLAG_FIB); +				} +				nexthop_num++; +				break; +			} +		} +	} else /* Multipath case */ +	{ +		char buf[NL_PKT_BUF_SIZE]; +		struct rtattr *rta = (void *)buf; +		struct rtnexthop *rtnh; +		union g_addr *src1 = NULL; + +		rta->rta_type = RTA_MULTIPATH; +		rta->rta_len = RTA_LENGTH(0); +		rtnh = RTA_DATA(rta); + +		routedesc = "multihop"; +		_netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + +		nexthop_num = 0; +		for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { +			nexthop = nhlfe->nexthop; +			if (!nexthop) +				continue; + +			if (nexthop_num >= multipath_num) +				break; + +			if ((cmd == RTM_NEWROUTE +			     && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) +				 && CHECK_FLAG(nexthop->flags, +					       NEXTHOP_FLAG_ACTIVE))) +			    || (cmd == RTM_DELROUTE +				&& (CHECK_FLAG(nhlfe->flags, +					       NHLFE_FLAG_INSTALLED) +				    && CHECK_FLAG(nexthop->flags, +						  NEXTHOP_FLAG_FIB)))) { +				nexthop_num++; + +				/* Build the multipath */ +				_netlink_mpls_build_multipath(routedesc, nhlfe, +							      rta, rtnh, &req.r, +							      &src1); +				rtnh = RTNH_NEXT(rtnh); + +				if (cmd == RTM_NEWROUTE) { +					SET_FLAG(nhlfe->flags, +						 NHLFE_FLAG_INSTALLED); +					SET_FLAG(nexthop->flags, +						 NEXTHOP_FLAG_FIB); +				} else { +					UNSET_FLAG(nhlfe->flags, +						   NHLFE_FLAG_INSTALLED); +					UNSET_FLAG(nexthop->flags, +						   NEXTHOP_FLAG_FIB); +				} +			} +		} + +		/* Add the multipath */ +		if (rta->rta_len > RTA_LENGTH(0)) +			addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, +				  RTA_DATA(rta), RTA_PAYLOAD(rta)); +	} + +	/* Talk to netlink socket. */ +	return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, +			    0);  }  /*   * Handle failure in LSP install, clear flags for NHLFE.   */ -void -clear_nhlfe_installed (zebra_lsp_t *lsp) +void clear_nhlfe_installed(zebra_lsp_t *lsp)  { -  zebra_nhlfe_t *nhlfe; -  struct nexthop *nexthop; - -  for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) -    { -      nexthop = nhlfe->nexthop; -      if (!nexthop) -        continue; - -      UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); -      UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); -    } +	zebra_nhlfe_t *nhlfe; +	struct nexthop *nexthop; + +	for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { +		nexthop = nhlfe->nexthop; +		if (!nexthop) +			continue; + +		UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); +		UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); +	}  }  | 
