diff options
| author | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:03:14 +0200 | 
|---|---|---|
| committer | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:04:07 +0200 | 
| commit | d62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch) | |
| tree | 3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /zebra/zserv.c | |
| parent | 888ac268a0077fc9ebd1218cec6ae472af0bfc40 (diff) | |
*: reindentreindent-master-after
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'`
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'zebra/zserv.c')
| -rw-r--r-- | zebra/zserv.c | 4917 | 
1 files changed, 2425 insertions, 2492 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c index 15feb78c08..3bc5f83f64 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -59,150 +59,145 @@  /* Event list of zebra. */  enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE }; -static void zebra_event (enum event event, int sock, struct zserv *client); +static void zebra_event(enum event event, int sock, struct zserv *client);  extern struct zebra_privs_t zserv_privs; -static void zebra_client_close (struct zserv *client); - -static int -zserv_delayed_close(struct thread *thread) -{ -  struct zserv *client = THREAD_ARG(thread); - -  client->t_suicide = NULL; -  zebra_client_close(client); -  return 0; -} - -static int -zserv_flush_data(struct thread *thread) -{ -  struct zserv *client = THREAD_ARG(thread); - -  client->t_write = NULL; -  if (client->t_suicide) -    { -      zebra_client_close(client); -      return -1; -    } -  switch (buffer_flush_available(client->wb, client->sock)) -    { -    case BUFFER_ERROR: -      zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, " -      		"closing", __func__, client->sock); -      zebra_client_close(client); -      client = NULL; -      break; -    case BUFFER_PENDING: -      client->t_write = NULL; -      thread_add_write(zebrad.master, zserv_flush_data, client, client->sock, -                       &client->t_write); -      break; -    case BUFFER_EMPTY: -      break; -    } - -  if (client) -    client->last_write_time = monotime(NULL); -  return 0; -} - -int -zebra_server_send_message(struct zserv *client) -{ -  if (client->t_suicide) -    return -1; - -  if (client->is_synchronous) -    return 0; - -  stream_set_getp(client->obuf, 0); -  client->last_write_cmd = stream_getw_from(client->obuf, 6); -  switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf), -		       stream_get_endp(client->obuf))) -    { -    case BUFFER_ERROR: -      zlog_warn("%s: buffer_write failed to zserv client fd %d, closing", -      		 __func__, client->sock); -      /* Schedule a delayed close since many of the functions that call this -         one do not check the return code.  They do not allow for the -	 possibility that an I/O error may have caused the client to be -	 deleted. */ -      client->t_suicide = NULL; -      thread_add_event(zebrad.master, zserv_delayed_close, client, 0, -                       &client->t_suicide); -      return -1; -    case BUFFER_EMPTY: -      THREAD_OFF(client->t_write); -      break; -    case BUFFER_PENDING: -      thread_add_write(zebrad.master, zserv_flush_data, client, client->sock, -                       &client->t_write); -      break; -    } - -  client->last_write_time = monotime(NULL); -  return 0; -} - -void -zserv_create_header (struct stream *s, uint16_t cmd, vrf_id_t vrf_id) -{ -  /* length placeholder, caller can update */ -  stream_putw (s, ZEBRA_HEADER_SIZE); -  stream_putc (s, ZEBRA_HEADER_MARKER); -  stream_putc (s, ZSERV_VERSION); -  stream_putw (s, vrf_id); -  stream_putw (s, cmd); -} - -static void -zserv_encode_interface (struct stream *s, struct interface *ifp) -{ -  /* Interface information. */ -  stream_put (s, ifp->name, INTERFACE_NAMSIZ); -  stream_putl (s, ifp->ifindex); -  stream_putc (s, ifp->status); -  stream_putq (s, ifp->flags); -  stream_putc (s, ifp->ptm_enable); -  stream_putc (s, ifp->ptm_status); -  stream_putl (s, ifp->metric); -  stream_putl (s, ifp->speed); -  stream_putl (s, ifp->mtu); -  stream_putl (s, ifp->mtu6); -  stream_putl (s, ifp->bandwidth); -  stream_putl (s, ifp->ll_type); -  stream_putl (s, ifp->hw_addr_len); -  if (ifp->hw_addr_len) -    stream_put (s, ifp->hw_addr, ifp->hw_addr_len); - -  /* Then, Traffic Engineering parameters if any */ -  if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) -    { -      stream_putc (s, 1); -      zebra_interface_link_params_write (s, ifp); -    } -  else -    stream_putc (s, 0); - -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); -} - -static void -zserv_encode_vrf (struct stream *s, struct zebra_vrf *zvrf) -{ -  struct vrf_data data; - -  data.l.table_id = zvrf->table_id; -  /* Pass the tableid */ -  stream_put (s, &data, sizeof (struct vrf_data)); -  /* Interface information. */ -  stream_put (s, zvrf_name (zvrf), VRF_NAMSIZ); - -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); +static void zebra_client_close(struct zserv *client); + +static int zserv_delayed_close(struct thread *thread) +{ +	struct zserv *client = THREAD_ARG(thread); + +	client->t_suicide = NULL; +	zebra_client_close(client); +	return 0; +} + +static int zserv_flush_data(struct thread *thread) +{ +	struct zserv *client = THREAD_ARG(thread); + +	client->t_write = NULL; +	if (client->t_suicide) { +		zebra_client_close(client); +		return -1; +	} +	switch (buffer_flush_available(client->wb, client->sock)) { +	case BUFFER_ERROR: +		zlog_warn( +			"%s: buffer_flush_available failed on zserv client fd %d, " +			"closing", +			__func__, client->sock); +		zebra_client_close(client); +		client = NULL; +		break; +	case BUFFER_PENDING: +		client->t_write = NULL; +		thread_add_write(zebrad.master, zserv_flush_data, client, +				 client->sock, &client->t_write); +		break; +	case BUFFER_EMPTY: +		break; +	} + +	if (client) +		client->last_write_time = monotime(NULL); +	return 0; +} + +int zebra_server_send_message(struct zserv *client) +{ +	if (client->t_suicide) +		return -1; + +	if (client->is_synchronous) +		return 0; + +	stream_set_getp(client->obuf, 0); +	client->last_write_cmd = stream_getw_from(client->obuf, 6); +	switch (buffer_write(client->wb, client->sock, +			     STREAM_DATA(client->obuf), +			     stream_get_endp(client->obuf))) { +	case BUFFER_ERROR: +		zlog_warn( +			"%s: buffer_write failed to zserv client fd %d, closing", +			__func__, client->sock); +		/* Schedule a delayed close since many of the functions that +		   call this +		   one do not check the return code.  They do not allow for the +		   possibility that an I/O error may have caused the client to +		   be +		   deleted. */ +		client->t_suicide = NULL; +		thread_add_event(zebrad.master, zserv_delayed_close, client, 0, +				 &client->t_suicide); +		return -1; +	case BUFFER_EMPTY: +		THREAD_OFF(client->t_write); +		break; +	case BUFFER_PENDING: +		thread_add_write(zebrad.master, zserv_flush_data, client, +				 client->sock, &client->t_write); +		break; +	} + +	client->last_write_time = monotime(NULL); +	return 0; +} + +void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id) +{ +	/* length placeholder, caller can update */ +	stream_putw(s, ZEBRA_HEADER_SIZE); +	stream_putc(s, ZEBRA_HEADER_MARKER); +	stream_putc(s, ZSERV_VERSION); +	stream_putw(s, vrf_id); +	stream_putw(s, cmd); +} + +static void zserv_encode_interface(struct stream *s, struct interface *ifp) +{ +	/* Interface information. */ +	stream_put(s, ifp->name, INTERFACE_NAMSIZ); +	stream_putl(s, ifp->ifindex); +	stream_putc(s, ifp->status); +	stream_putq(s, ifp->flags); +	stream_putc(s, ifp->ptm_enable); +	stream_putc(s, ifp->ptm_status); +	stream_putl(s, ifp->metric); +	stream_putl(s, ifp->speed); +	stream_putl(s, ifp->mtu); +	stream_putl(s, ifp->mtu6); +	stream_putl(s, ifp->bandwidth); +	stream_putl(s, ifp->ll_type); +	stream_putl(s, ifp->hw_addr_len); +	if (ifp->hw_addr_len) +		stream_put(s, ifp->hw_addr, ifp->hw_addr_len); + +	/* Then, Traffic Engineering parameters if any */ +	if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) { +		stream_putc(s, 1); +		zebra_interface_link_params_write(s, ifp); +	} else +		stream_putc(s, 0); + +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); +} + +static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf) +{ +	struct vrf_data data; + +	data.l.table_id = zvrf->table_id; +	/* Pass the tableid */ +	stream_put(s, &data, sizeof(struct vrf_data)); +	/* Interface information. */ +	stream_put(s, zvrf_name(zvrf), VRF_NAMSIZ); + +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s));  }  /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */ @@ -216,99 +211,94 @@ zserv_encode_vrf (struct stream *s, struct zebra_vrf *zvrf)   *   an interface is marked IFF_UP (i.e., an RTM_IFINFO message is   *   received)   */ -int -zsend_interface_add (struct zserv *client, struct interface *ifp) +int zsend_interface_add(struct zserv *client, struct interface *ifp)  { -  struct stream *s; +	struct stream *s; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); -  zserv_encode_interface (s, ifp); +	zserv_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); +	zserv_encode_interface(s, ifp); -  client->ifadd_cnt++; -  return zebra_server_send_message(client); +	client->ifadd_cnt++; +	return zebra_server_send_message(client);  }  /* Interface deletion from zebra daemon. */ -int -zsend_interface_delete (struct zserv *client, struct interface *ifp) +int zsend_interface_delete(struct zserv *client, struct interface *ifp)  { -  struct stream *s; +	struct stream *s; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); -  zserv_encode_interface (s, ifp); +	zserv_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); +	zserv_encode_interface(s, ifp); -  client->ifdel_cnt++; -  return zebra_server_send_message (client); +	client->ifdel_cnt++; +	return zebra_server_send_message(client);  } -int -zsend_vrf_add (struct zserv *client, struct zebra_vrf *zvrf) +int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf)  { -  struct stream *s; +	struct stream *s; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, ZEBRA_VRF_ADD, zvrf_id (zvrf)); -  zserv_encode_vrf (s, zvrf); +	zserv_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf)); +	zserv_encode_vrf(s, zvrf); -  client->vrfadd_cnt++; -  return zebra_server_send_message(client); +	client->vrfadd_cnt++; +	return zebra_server_send_message(client);  }  /* VRF deletion from zebra daemon. */ -int -zsend_vrf_delete (struct zserv *client, struct zebra_vrf *zvrf) +int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf)  { -  struct stream *s; +	struct stream *s; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, ZEBRA_VRF_DELETE, zvrf_id (zvrf)); -  zserv_encode_vrf (s, zvrf); +	zserv_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf)); +	zserv_encode_vrf(s, zvrf); -  client->vrfdel_cnt++; -  return zebra_server_send_message (client); +	client->vrfdel_cnt++; +	return zebra_server_send_message(client);  } -int -zsend_interface_link_params (struct zserv *client, struct interface *ifp) +int zsend_interface_link_params(struct zserv *client, struct interface *ifp)  { -  struct stream *s; +	struct stream *s; -  /* Check this client need interface information. */ -  if (! client->ifinfo) -    return 0; +	/* Check this client need interface information. */ +	if (!client->ifinfo) +		return 0; -  if (!ifp->link_params) -    return 0; -  s = client->obuf; -  stream_reset (s); +	if (!ifp->link_params) +		return 0; +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); +	zserv_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); -  /* Add Interface Index */ -  stream_putl (s, ifp->ifindex); +	/* Add Interface Index */ +	stream_putl(s, ifp->ifindex); -  /* Then TE Link Parameters */ -  if (zebra_interface_link_params_write (s, ifp) == 0) -    return 0; +	/* Then TE Link Parameters */ +	if (zebra_interface_link_params_write(s, ifp) == 0) +		return 0; -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); -  return zebra_server_send_message (client); +	return zebra_server_send_message(client);  }  /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or - * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.  + * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.   *   * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:   * - in response to a 3-byte ZEBRA_INTERFACE_ADD request @@ -323,13 +313,13 @@ zsend_interface_link_params (struct zserv *client, struct interface *ifp)   *    - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"   *      and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"   *    - when an RTM_NEWADDR message is received from the kernel, - *  - * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:  + * + * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:   *   *                   zsend_interface_address(DELETE) - *                           ^                          - *                           |                         - *          zebra_interface_address_delete_update     + *                           ^ + *                           | + *          zebra_interface_address_delete_update   *             ^                        ^      ^   *             |                        |      if_delete_update   *             |                        | @@ -345,232 +335,230 @@ zsend_interface_link_params (struct zserv *client, struct interface *ifp)   *     ["no ipv6 address X:X::X:X/M"]   *   */ -int -zsend_interface_address (int cmd, struct zserv *client,  -                         struct interface *ifp, struct connected *ifc) -{ -  int blen; -  struct stream *s; -  struct prefix *p; - -  s = client->obuf; -  stream_reset (s); -   -  zserv_create_header (s, cmd, ifp->vrf_id); -  stream_putl (s, ifp->ifindex); - -  /* Interface address flag. */ -  stream_putc (s, ifc->flags); - -  /* Prefix information. */ -  p = ifc->address; -  stream_putc (s, p->family); -  blen = prefix_blen (p); -  stream_put (s, &p->u.prefix, blen); - -  /*  -   * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE -   * but zebra_interface_address_delete_read() in the gnu version  -   * expects to find it -   */ -  stream_putc (s, p->prefixlen); - -  /* Destination. */ -  p = ifc->destination; -  if (p) -    stream_put (s, &p->u.prefix, blen); -  else -    stream_put (s, NULL, blen); +int zsend_interface_address(int cmd, struct zserv *client, +			    struct interface *ifp, struct connected *ifc) +{ +	int blen; +	struct stream *s; +	struct prefix *p; + +	s = client->obuf; +	stream_reset(s); + +	zserv_create_header(s, cmd, ifp->vrf_id); +	stream_putl(s, ifp->ifindex); + +	/* Interface address flag. */ +	stream_putc(s, ifc->flags); + +	/* Prefix information. */ +	p = ifc->address; +	stream_putc(s, p->family); +	blen = prefix_blen(p); +	stream_put(s, &p->u.prefix, blen); + +	/* +	 * XXX gnu version does not send prefixlen for +	 * ZEBRA_INTERFACE_ADDRESS_DELETE +	 * but zebra_interface_address_delete_read() in the gnu version +	 * expects to find it +	 */ +	stream_putc(s, p->prefixlen); + +	/* Destination. */ +	p = ifc->destination; +	if (p) +		stream_put(s, &p->u.prefix, blen); +	else +		stream_put(s, NULL, blen); -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); -  client->connected_rt_add_cnt++; -  return zebra_server_send_message(client); +	client->connected_rt_add_cnt++; +	return zebra_server_send_message(client);  } -static int -zsend_interface_nbr_address (int cmd, struct zserv *client, -                             struct interface *ifp, struct nbr_connected *ifc) +static int zsend_interface_nbr_address(int cmd, struct zserv *client, +				       struct interface *ifp, +				       struct nbr_connected *ifc)  { -  int blen; -  struct stream *s; -  struct prefix *p; +	int blen; +	struct stream *s; +	struct prefix *p; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, cmd, ifp->vrf_id); -  stream_putl (s, ifp->ifindex); +	zserv_create_header(s, cmd, ifp->vrf_id); +	stream_putl(s, ifp->ifindex); -  /* Prefix information. */ -  p = ifc->address; -  stream_putc (s, p->family); -  blen = prefix_blen (p); -  stream_put (s, &p->u.prefix, blen); +	/* Prefix information. */ +	p = ifc->address; +	stream_putc(s, p->family); +	blen = prefix_blen(p); +	stream_put(s, &p->u.prefix, blen); -  /* -   * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE -   * but zebra_interface_address_delete_read() in the gnu version -   * expects to find it -   */ -  stream_putc (s, p->prefixlen); +	/* +	 * XXX gnu version does not send prefixlen for +	 * ZEBRA_INTERFACE_ADDRESS_DELETE +	 * but zebra_interface_address_delete_read() in the gnu version +	 * expects to find it +	 */ +	stream_putc(s, p->prefixlen); -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); -  return zebra_server_send_message(client); +	return zebra_server_send_message(client);  }  /* Interface address addition. */ -static void -zebra_interface_nbr_address_add_update (struct interface *ifp, -                                        struct nbr_connected *ifc) -{ -  struct listnode *node, *nnode; -  struct zserv *client; -  struct prefix *p; - -  if (IS_ZEBRA_DEBUG_EVENT) -    { -      char buf[INET6_ADDRSTRLEN]; - -      p = ifc->address; -      zlog_debug ("MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_ADD %s/%d on %s", -      inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN), -      p->prefixlen, ifc->ifp->name); -    } +static void zebra_interface_nbr_address_add_update(struct interface *ifp, +						   struct nbr_connected *ifc) +{ +	struct listnode *node, *nnode; +	struct zserv *client; +	struct prefix *p; + +	if (IS_ZEBRA_DEBUG_EVENT) { +		char buf[INET6_ADDRSTRLEN]; + +		p = ifc->address; +		zlog_debug( +			"MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_ADD %s/%d on %s", +			inet_ntop(p->family, &p->u.prefix, buf, +				  INET6_ADDRSTRLEN), +			p->prefixlen, ifc->ifp->name); +	} -  for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) -    zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD, client, ifp, ifc); +	for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) +		zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD, +					    client, ifp, ifc);  }  /* Interface address deletion. */ -static void -zebra_interface_nbr_address_delete_update (struct interface *ifp, -                                           struct nbr_connected *ifc) -{ -  struct listnode *node, *nnode; -  struct zserv *client; -  struct prefix *p; - -  if (IS_ZEBRA_DEBUG_EVENT) -    { -      char buf[INET6_ADDRSTRLEN]; - -      p = ifc->address; -      zlog_debug ("MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_DELETE %s/%d on %s", -		  inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN), -		 p->prefixlen, ifc->ifp->name); -    } +static void zebra_interface_nbr_address_delete_update(struct interface *ifp, +						      struct nbr_connected *ifc) +{ +	struct listnode *node, *nnode; +	struct zserv *client; +	struct prefix *p; + +	if (IS_ZEBRA_DEBUG_EVENT) { +		char buf[INET6_ADDRSTRLEN]; + +		p = ifc->address; +		zlog_debug( +			"MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_DELETE %s/%d on %s", +			inet_ntop(p->family, &p->u.prefix, buf, +				  INET6_ADDRSTRLEN), +			p->prefixlen, ifc->ifp->name); +	} -  for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) -    zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, client, ifp, ifc); +	for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) +		zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, +					    client, ifp, ifc);  }  /* Send addresses on interface to client */ -int -zsend_interface_addresses (struct zserv *client, struct interface *ifp) +int zsend_interface_addresses(struct zserv *client, struct interface *ifp)  { -  struct listnode *cnode, *cnnode; -  struct connected *c; -  struct nbr_connected *nc; +	struct listnode *cnode, *cnnode; +	struct connected *c; +	struct nbr_connected *nc; -  /* Send interface addresses. */ -  for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c)) -    { -      if (!CHECK_FLAG (c->conf, ZEBRA_IFC_REAL)) -        continue; +	/* Send interface addresses. */ +	for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { +		if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL)) +			continue; -      if (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, -                                   ifp, c) < 0) -        return -1; -    } +		if (zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD, client, +					    ifp, c) +		    < 0) +			return -1; +	} -  /* Send interface neighbors. */ -  for (ALL_LIST_ELEMENTS (ifp->nbr_connected, cnode, cnnode, nc)) -    { -      if (zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD, -                                       client, ifp, nc) < 0) -        return -1; -    } +	/* Send interface neighbors. */ +	for (ALL_LIST_ELEMENTS(ifp->nbr_connected, cnode, cnnode, nc)) { +		if (zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD, +						client, ifp, nc) +		    < 0) +			return -1; +	} -  return 0; +	return 0;  }  /* Notify client about interface moving from one VRF to another.   * Whether client is interested in old and new VRF is checked by caller.   */ -int -zsend_interface_vrf_update (struct zserv *client, struct interface *ifp, -                            vrf_id_t vrf_id) +int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp, +			       vrf_id_t vrf_id)  { -  struct stream *s; +	struct stream *s; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id); +	zserv_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id); -  /* Fill in the ifIndex of the interface and its new VRF (id) */ -  stream_putl (s, ifp->ifindex); -  stream_putw (s, vrf_id); +	/* Fill in the ifIndex of the interface and its new VRF (id) */ +	stream_putl(s, ifp->ifindex); +	stream_putw(s, vrf_id); -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); -  client->if_vrfchg_cnt++; -  return zebra_server_send_message(client); +	client->if_vrfchg_cnt++; +	return zebra_server_send_message(client);  }  /* Add new nbr connected IPv6 address */ -void -nbr_connected_add_ipv6 (struct interface *ifp, struct in6_addr *address) +void nbr_connected_add_ipv6(struct interface *ifp, struct in6_addr *address)  { -  struct nbr_connected *ifc; -  struct prefix p; +	struct nbr_connected *ifc; +	struct prefix p; -  p.family = AF_INET6; -  IPV6_ADDR_COPY (&p.u.prefix, address); -  p.prefixlen = IPV6_MAX_PREFIXLEN; +	p.family = AF_INET6; +	IPV6_ADDR_COPY(&p.u.prefix, address); +	p.prefixlen = IPV6_MAX_PREFIXLEN; -  if (!(ifc = listnode_head(ifp->nbr_connected))) -    { -      /* new addition */ -      ifc = nbr_connected_new (); -      ifc->address = prefix_new(); -      ifc->ifp = ifp; -      listnode_add (ifp->nbr_connected, ifc); -    } +	if (!(ifc = listnode_head(ifp->nbr_connected))) { +		/* new addition */ +		ifc = nbr_connected_new(); +		ifc->address = prefix_new(); +		ifc->ifp = ifp; +		listnode_add(ifp->nbr_connected, ifc); +	} -  prefix_copy(ifc->address, &p); +	prefix_copy(ifc->address, &p); -  zebra_interface_nbr_address_add_update (ifp, ifc); +	zebra_interface_nbr_address_add_update(ifp, ifc); -  if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 1); +	if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 1);  } -void -nbr_connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address) +void nbr_connected_delete_ipv6(struct interface *ifp, struct in6_addr *address)  { -  struct nbr_connected *ifc; -  struct prefix p; +	struct nbr_connected *ifc; +	struct prefix p; -  p.family = AF_INET6; -  IPV6_ADDR_COPY (&p.u.prefix, address); -  p.prefixlen = IPV6_MAX_PREFIXLEN; +	p.family = AF_INET6; +	IPV6_ADDR_COPY(&p.u.prefix, address); +	p.prefixlen = IPV6_MAX_PREFIXLEN; -  ifc = nbr_connected_check(ifp, &p); -  if (!ifc) -    return; +	ifc = nbr_connected_check(ifp, &p); +	if (!ifc) +		return; -  listnode_delete (ifp->nbr_connected, ifc); +	listnode_delete(ifp->nbr_connected, ifc); -  zebra_interface_nbr_address_delete_update (ifp, ifc); +	zebra_interface_nbr_address_delete_update(ifp, ifc); -  if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 0); +	if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 0); -  nbr_connected_free (ifc); +	nbr_connected_free(ifc);  }  /* @@ -583,23 +571,22 @@ nbr_connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address)   *   - a vty command modifying the bandwidth of an interface is received.   * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.   */ -int -zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp) +int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)  { -  struct stream *s; +	struct stream *s; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, cmd, ifp->vrf_id); -  zserv_encode_interface (s, ifp); +	zserv_create_header(s, cmd, ifp->vrf_id); +	zserv_encode_interface(s, ifp); -  if (cmd == ZEBRA_INTERFACE_UP) -    client->ifup_cnt++; -  else -    client->ifdown_cnt++; +	if (cmd == ZEBRA_INTERFACE_UP) +		client->ifup_cnt++; +	else +		client->ifdown_cnt++; -  return zebra_server_send_message(client); +	return zebra_server_send_message(client);  }  /* @@ -609,441 +596,413 @@ zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)   * away or ignored by the receiver. This is the leaner function that is not a   * duplicate of the zapi_ipv4_route_add/del.   * - * The primary difference is that this function merely sends a single NH instead of + * The primary difference is that this function merely sends a single NH instead + * of   * all the nexthops.   */ -int -zsend_redistribute_route (int add, struct zserv *client, struct prefix *p, -                          struct prefix *src_p, struct route_entry *re) -{ -  afi_t afi; -  int cmd; -  int psize; -  struct stream *s; -  struct nexthop *nexthop; -  unsigned long nhnummark = 0, messmark = 0; -  int nhnum = 0; -  u_char zapi_flags = 0; -  struct nexthop dummy_nh; - -  afi = family2afi (p->family); -  if (add) -    { -      switch (afi) -	{ -	case AFI_IP: -	  cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD; -	  client->redist_v4_add_cnt++; -	  break; -	case AFI_IP6: -	  cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD; -	  client->redist_v6_add_cnt++; -	  break; -	default: -	  return -1; -	} -    } -  else -    { -      switch (afi) -	{ -	case AFI_IP: -	  cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL; -	  client->redist_v4_del_cnt++; -	  break; -	case AFI_IP6: -	  cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL; -	  client->redist_v6_del_cnt++; -	  break; -	default: -	  return -1; -	} -    } - -  s = client->obuf; -  stream_reset (s); -  memset(&dummy_nh, 0, sizeof(struct nexthop)); - -  zserv_create_header (s, cmd, re->vrf_id); -   -  /* Put type and nexthop. */ -  stream_putc (s, re->type); -  stream_putw (s, re->instance); -  stream_putl (s, re->flags); - -  /* marker for message flags field */ -  messmark = stream_get_endp (s); -  stream_putc (s, 0); - -  /* Prefix. */ -  psize = PSIZE (p->prefixlen); -  stream_putc (s, p->prefixlen); -  stream_write (s, (u_char *) & p->u.prefix, psize); - -  if (src_p) -    { -      SET_FLAG (zapi_flags, ZAPI_MESSAGE_SRCPFX); -      psize = PSIZE (src_p->prefixlen); -      stream_putc (s, src_p->prefixlen); -      stream_write (s, (u_char *) & src_p->u.prefix, psize); -    } - -  for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) -    { -      /* We don't send any nexthops when there's a multipath */ -      if (re->nexthop_active_num > 1 && client->proto != ZEBRA_ROUTE_LDP) -	{ -          SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP); -          SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX); - -	  stream_putc(s, 1); -	  if (p->family == AF_INET) -	    { -	      stream_put_in_addr (s, &dummy_nh.gate.ipv4); -	    } -	  else if (p->family == AF_INET6) -	    { -                stream_write (s, (u_char *) &dummy_nh.gate.ipv6, 16); -	    } -	  else -	    { -	      /* We don't handle anything else now, abort */ -	      zlog_err("%s: Unable to redistribute route of unknown family, %d\n", -		       __func__, p->family); -	      return -1; -	    } -          stream_putc (s, 1); -          stream_putl (s, 0);	/* dummy ifindex */ -	  break; +int zsend_redistribute_route(int add, struct zserv *client, struct prefix *p, +			     struct prefix *src_p, struct route_entry *re) +{ +	afi_t afi; +	int cmd; +	int psize; +	struct stream *s; +	struct nexthop *nexthop; +	unsigned long nhnummark = 0, messmark = 0; +	int nhnum = 0; +	u_char zapi_flags = 0; +	struct nexthop dummy_nh; + +	afi = family2afi(p->family); +	if (add) { +		switch (afi) { +		case AFI_IP: +			cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD; +			client->redist_v4_add_cnt++; +			break; +		case AFI_IP6: +			cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD; +			client->redist_v6_add_cnt++; +			break; +		default: +			return -1; +		} +	} else { +		switch (afi) { +		case AFI_IP: +			cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL; +			client->redist_v4_del_cnt++; +			break; +		case AFI_IP6: +			cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL; +			client->redist_v6_del_cnt++; +			break; +		default: +			return -1; +		}  	} -      if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) -        { -          SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP); -          SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX); -          if (nhnummark == 0) -            { -              nhnummark = stream_get_endp (s); -              stream_putc (s, 1); /* placeholder */ -            } -          nhnum++; - -          switch(nexthop->type)  -            { -              case NEXTHOP_TYPE_IPV4: -              case NEXTHOP_TYPE_IPV4_IFINDEX: -                stream_put_in_addr (s, &nexthop->gate.ipv4); -                break; -              case NEXTHOP_TYPE_IPV6: -              case NEXTHOP_TYPE_IPV6_IFINDEX: -		/* Only BGP supports IPv4 prefix with IPv6 NH, so kill this */ -		if (p->family == AF_INET) -		  stream_put_in_addr(s, &dummy_nh.gate.ipv4); -		else -		  stream_write (s, (u_char *) &nexthop->gate.ipv6, 16); -                break; -              default: -                if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD -                    || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) -                  { -                    struct in_addr empty; -                    memset (&empty, 0, sizeof (struct in_addr)); -                    stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN); -                  } -                else -                  { -                    struct in6_addr empty; -                    memset (&empty, 0, sizeof (struct in6_addr)); -                    stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN); -                  } -              } - -          /* Interface index. */ -          stream_putc (s, 1); -          stream_putl (s, nexthop->ifindex); - -	  /* ldpd needs all nexthops */ -	  if (client->proto != ZEBRA_ROUTE_LDP) -            break; -        } -    } - -  /* Distance */ -  SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE); -  stream_putc (s, re->distance); - -  /* Metric */ -  SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC); -  stream_putl (s, re->metric); - -  /* Tag */ -  if (re->tag) -    { -      SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); -      stream_putl(s, re->tag); -    } - -  /* MTU */ -  SET_FLAG (zapi_flags, ZAPI_MESSAGE_MTU); -  stream_putl (s, re->mtu); - -  /* write real message flags value */ -  stream_putc_at (s, messmark, zapi_flags); - -  /* Write next-hop number */ -  if (nhnummark) -    stream_putc_at (s, nhnummark, nhnum); - -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); - -  return zebra_server_send_message(client); -} - -static int -zsend_write_nexthop (struct stream *s, struct nexthop *nexthop) -{ -  stream_putc (s, nexthop->type); -  switch (nexthop->type) -    { -    case NEXTHOP_TYPE_IPV4: -    case NEXTHOP_TYPE_IPV4_IFINDEX: -      stream_put_in_addr (s, &nexthop->gate.ipv4); -      stream_putl (s, nexthop->ifindex); -      break; -    case NEXTHOP_TYPE_IPV6: -      stream_put (s, &nexthop->gate.ipv6, 16); -      break; -    case NEXTHOP_TYPE_IPV6_IFINDEX: -      stream_put (s, &nexthop->gate.ipv6, 16); -      stream_putl (s, nexthop->ifindex); -      break; -    case NEXTHOP_TYPE_IFINDEX: -      stream_putl (s, nexthop->ifindex); -      break; -    default: -      /* do nothing */ -      break; -    } -  return 1; -} +	s = client->obuf; +	stream_reset(s); +	memset(&dummy_nh, 0, sizeof(struct nexthop)); -/* Nexthop register */ -static int -zserv_rnh_register (struct zserv *client, int sock, u_short length, -		    rnh_type_t type, struct zebra_vrf *zvrf) -{ -  struct rnh *rnh; -  struct stream *s; -  struct prefix p; -  u_short l = 0; -  u_char flags = 0; - -  if (IS_ZEBRA_DEBUG_NHT) -    zlog_debug("rnh_register msg from client %s: length=%d, type=%s\n", -	       zebra_route_string(client->proto), length, -	       (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); - -  s = client->ibuf; - -  client->nh_reg_time = monotime(NULL); - -  while (l < length) -    { -      flags = stream_getc(s); -      p.family = stream_getw(s); -      p.prefixlen = stream_getc(s); -      l += 4; -      if (p.family == AF_INET) -	{ -	  p.u.prefix4.s_addr = stream_get_ipv4(s); -	  l += IPV4_MAX_BYTELEN; -	} -      else if (p.family == AF_INET6) -	{ -	  stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); -	  l += IPV6_MAX_BYTELEN; -	} -      else -	{ -	  zlog_err("rnh_register: Received unknown family type %d\n", -		   p.family); -	  return -1; +	zserv_create_header(s, cmd, re->vrf_id); + +	/* Put type and nexthop. */ +	stream_putc(s, re->type); +	stream_putw(s, re->instance); +	stream_putl(s, re->flags); + +	/* marker for message flags field */ +	messmark = stream_get_endp(s); +	stream_putc(s, 0); + +	/* Prefix. */ +	psize = PSIZE(p->prefixlen); +	stream_putc(s, p->prefixlen); +	stream_write(s, (u_char *)&p->u.prefix, psize); + +	if (src_p) { +		SET_FLAG(zapi_flags, ZAPI_MESSAGE_SRCPFX); +		psize = PSIZE(src_p->prefixlen); +		stream_putc(s, src_p->prefixlen); +		stream_write(s, (u_char *)&src_p->u.prefix, psize);  	} -      rnh = zebra_add_rnh(&p, zvrf_id (zvrf), type); -      if (type == RNH_NEXTHOP_TYPE) -	{ -	  if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) -	    SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); -	  else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) -	    UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + +	for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { +		/* We don't send any nexthops when there's a multipath */ +		if (re->nexthop_active_num > 1 +		    && client->proto != ZEBRA_ROUTE_LDP) { +			SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP); +			SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX); + +			stream_putc(s, 1); +			if (p->family == AF_INET) { +				stream_put_in_addr(s, &dummy_nh.gate.ipv4); +			} else if (p->family == AF_INET6) { +				stream_write(s, (u_char *)&dummy_nh.gate.ipv6, +					     16); +			} else { +				/* We don't handle anything else now, abort */ +				zlog_err( +					"%s: Unable to redistribute route of unknown family, %d\n", +					__func__, p->family); +				return -1; +			} +			stream_putc(s, 1); +			stream_putl(s, 0); /* dummy ifindex */ +			break; +		} + +		if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { +			SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP); +			SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX); +			if (nhnummark == 0) { +				nhnummark = stream_get_endp(s); +				stream_putc(s, 1); /* placeholder */ +			} +			nhnum++; + +			switch (nexthop->type) { +			case NEXTHOP_TYPE_IPV4: +			case NEXTHOP_TYPE_IPV4_IFINDEX: +				stream_put_in_addr(s, &nexthop->gate.ipv4); +				break; +			case NEXTHOP_TYPE_IPV6: +			case NEXTHOP_TYPE_IPV6_IFINDEX: +				/* Only BGP supports IPv4 prefix with IPv6 NH, +				 * so kill this */ +				if (p->family == AF_INET) +					stream_put_in_addr(s, +							   &dummy_nh.gate.ipv4); +				else +					stream_write( +						s, +						(u_char *)&nexthop->gate.ipv6, +						16); +				break; +			default: +				if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD +				    || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) { +					struct in_addr empty; +					memset(&empty, 0, +					       sizeof(struct in_addr)); +					stream_write(s, (u_char *)&empty, +						     IPV4_MAX_BYTELEN); +				} else { +					struct in6_addr empty; +					memset(&empty, 0, +					       sizeof(struct in6_addr)); +					stream_write(s, (u_char *)&empty, +						     IPV6_MAX_BYTELEN); +				} +			} + +			/* Interface index. */ +			stream_putc(s, 1); +			stream_putl(s, nexthop->ifindex); + +			/* ldpd needs all nexthops */ +			if (client->proto != ZEBRA_ROUTE_LDP) +				break; +		}  	} -      else if (type == RNH_IMPORT_CHECK_TYPE) -	{ -	  if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) -	    SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); -	  else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) -	    UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); + +	/* Distance */ +	SET_FLAG(zapi_flags, ZAPI_MESSAGE_DISTANCE); +	stream_putc(s, re->distance); + +	/* Metric */ +	SET_FLAG(zapi_flags, ZAPI_MESSAGE_METRIC); +	stream_putl(s, re->metric); + +	/* Tag */ +	if (re->tag) { +		SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); +		stream_putl(s, re->tag);  	} -      zebra_add_rnh_client(rnh, client, type, zvrf_id (zvrf)); -      /* Anything not AF_INET/INET6 has been filtered out above */ -      zebra_evaluate_rnh(zvrf_id (zvrf), p.family, 1, type, &p); -    } -  return 0; +	/* MTU */ +	SET_FLAG(zapi_flags, ZAPI_MESSAGE_MTU); +	stream_putl(s, re->mtu); + +	/* write real message flags value */ +	stream_putc_at(s, messmark, zapi_flags); + +	/* Write next-hop number */ +	if (nhnummark) +		stream_putc_at(s, nhnummark, nhnum); + +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); + +	return zebra_server_send_message(client); +} + +static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop) +{ +	stream_putc(s, nexthop->type); +	switch (nexthop->type) { +	case NEXTHOP_TYPE_IPV4: +	case NEXTHOP_TYPE_IPV4_IFINDEX: +		stream_put_in_addr(s, &nexthop->gate.ipv4); +		stream_putl(s, nexthop->ifindex); +		break; +	case NEXTHOP_TYPE_IPV6: +		stream_put(s, &nexthop->gate.ipv6, 16); +		break; +	case NEXTHOP_TYPE_IPV6_IFINDEX: +		stream_put(s, &nexthop->gate.ipv6, 16); +		stream_putl(s, nexthop->ifindex); +		break; +	case NEXTHOP_TYPE_IFINDEX: +		stream_putl(s, nexthop->ifindex); +		break; +	default: +		/* do nothing */ +		break; +	} +	return 1;  }  /* Nexthop register */ -static int -zserv_rnh_unregister (struct zserv *client, int sock, u_short length, -		      rnh_type_t type, struct zebra_vrf *zvrf) -{ -  struct rnh *rnh; -  struct stream *s; -  struct prefix p; -  u_short l = 0; - -  if (IS_ZEBRA_DEBUG_NHT) -    zlog_debug("rnh_unregister msg from client %s: length=%d\n", -	       zebra_route_string(client->proto), length); - -  s = client->ibuf; - -  while (l < length) -    { -      (void)stream_getc(s); //Connected or not.  Not used in this function -      p.family = stream_getw(s); -      p.prefixlen = stream_getc(s); -      l += 4; -      if (p.family == AF_INET) -	{ -	  p.u.prefix4.s_addr = stream_get_ipv4(s); -	  l += IPV4_MAX_BYTELEN; -	} -      else if (p.family == AF_INET6) -	{ -	  stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); -	  l += IPV6_MAX_BYTELEN; -	} -      else -	{ -	  zlog_err("rnh_register: Received unknown family type %d\n", -		   p.family); -	  return -1; +static int zserv_rnh_register(struct zserv *client, int sock, u_short length, +			      rnh_type_t type, struct zebra_vrf *zvrf) +{ +	struct rnh *rnh; +	struct stream *s; +	struct prefix p; +	u_short l = 0; +	u_char flags = 0; + +	if (IS_ZEBRA_DEBUG_NHT) +		zlog_debug( +			"rnh_register msg from client %s: length=%d, type=%s\n", +			zebra_route_string(client->proto), length, +			(type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); + +	s = client->ibuf; + +	client->nh_reg_time = monotime(NULL); + +	while (l < length) { +		flags = stream_getc(s); +		p.family = stream_getw(s); +		p.prefixlen = stream_getc(s); +		l += 4; +		if (p.family == AF_INET) { +			p.u.prefix4.s_addr = stream_get_ipv4(s); +			l += IPV4_MAX_BYTELEN; +		} else if (p.family == AF_INET6) { +			stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); +			l += IPV6_MAX_BYTELEN; +		} else { +			zlog_err( +				"rnh_register: Received unknown family type %d\n", +				p.family); +			return -1; +		} +		rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); +		if (type == RNH_NEXTHOP_TYPE) { +			if (flags +			    && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) +				SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); +			else if (!flags +				 && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) +				UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); +		} else if (type == RNH_IMPORT_CHECK_TYPE) { +			if (flags +			    && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) +				SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); +			else if (!flags && CHECK_FLAG(rnh->flags, +						      ZEBRA_NHT_EXACT_MATCH)) +				UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); +		} + +		zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); +		/* Anything not AF_INET/INET6 has been filtered out above */ +		zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p);  	} -      rnh = zebra_lookup_rnh(&p, zvrf_id (zvrf), type); -      if (rnh) -	{ -	  client->nh_dereg_time = monotime(NULL); -	  zebra_remove_rnh_client(rnh, client, type); +	return 0; +} + +/* Nexthop register */ +static int zserv_rnh_unregister(struct zserv *client, int sock, u_short length, +				rnh_type_t type, struct zebra_vrf *zvrf) +{ +	struct rnh *rnh; +	struct stream *s; +	struct prefix p; +	u_short l = 0; + +	if (IS_ZEBRA_DEBUG_NHT) +		zlog_debug("rnh_unregister msg from client %s: length=%d\n", +			   zebra_route_string(client->proto), length); + +	s = client->ibuf; + +	while (l < length) { +		(void)stream_getc( +			s); // Connected or not.  Not used in this function +		p.family = stream_getw(s); +		p.prefixlen = stream_getc(s); +		l += 4; +		if (p.family == AF_INET) { +			p.u.prefix4.s_addr = stream_get_ipv4(s); +			l += IPV4_MAX_BYTELEN; +		} else if (p.family == AF_INET6) { +			stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); +			l += IPV6_MAX_BYTELEN; +		} else { +			zlog_err( +				"rnh_register: Received unknown family type %d\n", +				p.family); +			return -1; +		} +		rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); +		if (rnh) { +			client->nh_dereg_time = monotime(NULL); +			zebra_remove_rnh_client(rnh, client, type); +		}  	} -    } -  return 0; +	return 0;  }  #define ZEBRA_MIN_FEC_LENGTH 5  /* FEC register */ -static int -zserv_fec_register (struct zserv *client, int sock, u_short length) -{ -  struct stream *s; -  struct zebra_vrf *zvrf; -  u_short l = 0; -  struct prefix p; -  u_int16_t flags; -  u_int32_t label_index = MPLS_INVALID_LABEL_INDEX; - -  s = client->ibuf; -  zvrf = vrf_info_lookup(VRF_DEFAULT); -  if (!zvrf) -    return 0; // unexpected - -  /* -   * The minimum amount of data that can be sent for one fec -   * registration -   */ -  if (length < ZEBRA_MIN_FEC_LENGTH) -    { -      zlog_err ("fec_register: Received a fec register of length %d, it is of insufficient size to properly decode", -                length); -      return -1; -    } - -  while (l < length) -    { -      flags = stream_getw(s); -      p.family = stream_getw(s); -      if (p.family != AF_INET && -          p.family != AF_INET6) -        { -          zlog_err ("fec_register: Received unknown family type %d\n", -                    p.family); -          return -1; -        } -      p.prefixlen = stream_getc(s); -      l += 5; -      stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); -      l += PSIZE(p.prefixlen); -      if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) -        { -          label_index = stream_getl(s); -          l += 4; -        } -      else -        label_index = MPLS_INVALID_LABEL_INDEX; -      zebra_mpls_fec_register (zvrf, &p, label_index, client); -    } - -  return 0; +static int zserv_fec_register(struct zserv *client, int sock, u_short length) +{ +	struct stream *s; +	struct zebra_vrf *zvrf; +	u_short l = 0; +	struct prefix p; +	u_int16_t flags; +	u_int32_t label_index = MPLS_INVALID_LABEL_INDEX; + +	s = client->ibuf; +	zvrf = vrf_info_lookup(VRF_DEFAULT); +	if (!zvrf) +		return 0; // unexpected + +	/* +	 * The minimum amount of data that can be sent for one fec +	 * registration +	 */ +	if (length < ZEBRA_MIN_FEC_LENGTH) { +		zlog_err( +			"fec_register: Received a fec register of length %d, it is of insufficient size to properly decode", +			length); +		return -1; +	} + +	while (l < length) { +		flags = stream_getw(s); +		p.family = stream_getw(s); +		if (p.family != AF_INET && p.family != AF_INET6) { +			zlog_err( +				"fec_register: Received unknown family type %d\n", +				p.family); +			return -1; +		} +		p.prefixlen = stream_getc(s); +		l += 5; +		stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); +		l += PSIZE(p.prefixlen); +		if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) { +			label_index = stream_getl(s); +			l += 4; +		} else +			label_index = MPLS_INVALID_LABEL_INDEX; +		zebra_mpls_fec_register(zvrf, &p, label_index, client); +	} + +	return 0;  }  /* FEC unregister */ -static int -zserv_fec_unregister (struct zserv *client, int sock, u_short length) -{ -  struct stream *s; -  struct zebra_vrf *zvrf; -  u_short l = 0; -  struct prefix p; -  //u_int16_t flags; - -  s = client->ibuf; -  zvrf = vrf_info_lookup(VRF_DEFAULT); -  if (!zvrf) -    return 0;  // unexpected - -  /* -   * The minimum amount of data that can be sent for one -   * fec unregistration -   */ -  if (length < ZEBRA_MIN_FEC_LENGTH) -    { -      zlog_err ("fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode", -                length); -      return -1; -    } - -  while (l < length) -    { -      //flags = stream_getw(s); -      (void)stream_getw(s); -      p.family = stream_getw(s); -      if (p.family != AF_INET && -          p.family != AF_INET6) -        { -          zlog_err ("fec_unregister: Received unknown family type %d\n", -                    p.family); -          return -1; -        } -      p.prefixlen = stream_getc(s); -      l += 5; -      stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); -      l += PSIZE(p.prefixlen); -      zebra_mpls_fec_unregister (zvrf, &p, client); -    } - -  return 0; +static int zserv_fec_unregister(struct zserv *client, int sock, u_short length) +{ +	struct stream *s; +	struct zebra_vrf *zvrf; +	u_short l = 0; +	struct prefix p; +	// u_int16_t flags; + +	s = client->ibuf; +	zvrf = vrf_info_lookup(VRF_DEFAULT); +	if (!zvrf) +		return 0; // unexpected + +	/* +	 * The minimum amount of data that can be sent for one +	 * fec unregistration +	 */ +	if (length < ZEBRA_MIN_FEC_LENGTH) { +		zlog_err( +			"fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode", +			length); +		return -1; +	} + +	while (l < length) { +		// flags = stream_getw(s); +		(void)stream_getw(s); +		p.family = stream_getw(s); +		if (p.family != AF_INET && p.family != AF_INET6) { +			zlog_err( +				"fec_unregister: Received unknown family type %d\n", +				p.family); +			return -1; +		} +		p.prefixlen = stream_getc(s); +		l += 5; +		stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); +		l += PSIZE(p.prefixlen); +		zebra_mpls_fec_unregister(zvrf, &p, client); +	} + +	return 0;  }  /* @@ -1051,1514 +1010,1510 @@ zserv_fec_unregister (struct zserv *client, int sock, u_short length)    Query unicast rib if nexthop is not found on mrib.    Returns both route metric and protocol distance.  */ -static int -zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr, struct route_entry *re, struct zebra_vrf *zvrf) -{ -  struct stream *s; -  unsigned long nump; -  u_char num; -  struct nexthop *nexthop; - -  /* Get output stream. */ -  s = client->obuf; -  stream_reset (s); - -  /* Fill in result. */ -  zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id (zvrf)); -  stream_put_in_addr (s, &addr); - -  if (re) -    { -      stream_putc (s, re->distance); -      stream_putl (s, re->metric); -      num = 0; -      nump = stream_get_endp(s); /* remember position for nexthop_num */ -      stream_putc (s, 0);        /* reserve room for nexthop_num */ -      /* Only non-recursive routes are elegible to resolve the nexthop we -       * are looking up. Therefore, we will just iterate over the top -       * chain of nexthops. */ -      for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) -	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) -	    num += zsend_write_nexthop (s, nexthop); -     -      stream_putc_at (s, nump, num); /* store nexthop_num */ -    } -  else -    { -      stream_putc (s, 0); /* distance */ -      stream_putl (s, 0); /* metric */ -      stream_putc (s, 0); /* nexthop_num */ -    } - -  stream_putw_at (s, 0, stream_get_endp (s)); -   -  return zebra_server_send_message(client); +static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, +					  struct in_addr addr, +					  struct route_entry *re, +					  struct zebra_vrf *zvrf) +{ +	struct stream *s; +	unsigned long nump; +	u_char num; +	struct nexthop *nexthop; + +	/* Get output stream. */ +	s = client->obuf; +	stream_reset(s); + +	/* Fill in result. */ +	zserv_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf)); +	stream_put_in_addr(s, &addr); + +	if (re) { +		stream_putc(s, re->distance); +		stream_putl(s, re->metric); +		num = 0; +		nump = stream_get_endp( +			s);	/* remember position for nexthop_num */ +		stream_putc(s, 0); /* reserve room for nexthop_num */ +		/* Only non-recursive routes are elegible to resolve the nexthop +		 * we +		 * are looking up. Therefore, we will just iterate over the top +		 * chain of nexthops. */ +		for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) +			if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) +				num += zsend_write_nexthop(s, nexthop); + +		stream_putc_at(s, nump, num); /* store nexthop_num */ +	} else { +		stream_putc(s, 0); /* distance */ +		stream_putl(s, 0); /* metric */ +		stream_putc(s, 0); /* nexthop_num */ +	} + +	stream_putw_at(s, 0, stream_get_endp(s)); + +	return zebra_server_send_message(client);  }  /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ -int -zsend_router_id_update (struct zserv *client, struct prefix *p, -    vrf_id_t vrf_id) +int zsend_router_id_update(struct zserv *client, struct prefix *p, +			   vrf_id_t vrf_id)  { -  struct stream *s; -  int blen; +	struct stream *s; +	int blen; -  /* Check this client need interface information. */ -  if (! vrf_bitmap_check (client->ridinfo, vrf_id)) -    return 0; +	/* Check this client need interface information. */ +	if (!vrf_bitmap_check(client->ridinfo, vrf_id)) +		return 0; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  /* Message type. */ -  zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); +	/* Message type. */ +	zserv_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); -  /* Prefix information. */ -  stream_putc (s, p->family); -  blen = prefix_blen (p); -  stream_put (s, &p->u.prefix, blen); -  stream_putc (s, p->prefixlen); +	/* Prefix information. */ +	stream_putc(s, p->family); +	blen = prefix_blen(p); +	stream_put(s, &p->u.prefix, blen); +	stream_putc(s, p->prefixlen); -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); -  return zebra_server_send_message(client); +	return zebra_server_send_message(client);  }  /* Register zebra server interface information.  Send current all     interface and address information. */ -static int -zread_interface_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_interface_add(struct zserv *client, u_short length, +			       struct zebra_vrf *zvrf)  { -  struct vrf *vrf; -  struct listnode *ifnode, *ifnnode; -  struct interface *ifp; +	struct vrf *vrf; +	struct listnode *ifnode, *ifnnode; +	struct interface *ifp; -  /* Interface information is needed. */ -  vrf_bitmap_set (client->ifinfo, zvrf_id (zvrf)); +	/* Interface information is needed. */ +	vrf_bitmap_set(client->ifinfo, zvrf_id(zvrf)); -  RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) -    { -      for (ALL_LIST_ELEMENTS (vrf->iflist, ifnode, ifnnode, ifp)) -        { -          /* Skip pseudo interface. */ -          if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) -	    continue; +	RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) +	{ +		for (ALL_LIST_ELEMENTS(vrf->iflist, ifnode, ifnnode, ifp)) { +			/* Skip pseudo interface. */ +			if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) +				continue; -          if (zsend_interface_add (client, ifp) < 0) -            return -1; +			if (zsend_interface_add(client, ifp) < 0) +				return -1; -          if (zsend_interface_addresses (client, ifp) < 0) -            return -1; -        } -    } -  return 0; +			if (zsend_interface_addresses(client, ifp) < 0) +				return -1; +		} +	} +	return 0;  }  /* Unregister zebra server interface information. */ -static int -zread_interface_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_interface_delete(struct zserv *client, u_short length, +				  struct zebra_vrf *zvrf)  { -  vrf_bitmap_unset (client->ifinfo, zvrf_id (zvrf)); -  return 0; +	vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf)); +	return 0;  } -void -zserv_nexthop_num_warn (const char *caller, const struct prefix *p, const unsigned int nexthop_num) +void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, +			    const unsigned int nexthop_num)  { -  if (nexthop_num > multipath_num) -    { -      char buff[PREFIX2STR_BUFFER]; -      prefix2str(p, buff, sizeof (buff)); -      zlog_warn("%s: Prefix %s has %d nexthops, but we can only use the first %d", -		caller, buff, nexthop_num, multipath_num); -    } +	if (nexthop_num > multipath_num) { +		char buff[PREFIX2STR_BUFFER]; +		prefix2str(p, buff, sizeof(buff)); +		zlog_warn( +			"%s: Prefix %s has %d nexthops, but we can only use the first %d", +			caller, buff, nexthop_num, multipath_num); +	}  }  /* This function support multiple nexthop. */ -/*  +/*   * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and - * add kernel route.  + * add kernel route.   */ -static int -zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ -  int i; -  struct route_entry *re; -  struct prefix p; -  u_char message; -  struct in_addr nhop_addr; -  u_char nexthop_num; -  u_char nexthop_type; -  struct stream *s; -  ifindex_t ifindex; -  safi_t safi; -  int ret; -  mpls_label_t label; -  struct nexthop *nexthop; - -  /* Get input stream.  */ -  s = client->ibuf; - -  /* Allocate new re. */ -  re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); -   -  /* Type, flags, message. */ -  re->type = stream_getc (s); -  re->instance = stream_getw (s); -  re->flags = stream_getl (s); -  message = stream_getc (s);  -  safi = stream_getw (s); -  re->uptime = time (NULL); - -  /* IPv4 prefix. */ -  memset (&p, 0, sizeof (struct prefix_ipv4)); -  p.family = AF_INET; -  p.prefixlen = stream_getc (s); -  stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); - -  /* VRF ID */ -  re->vrf_id = zvrf_id (zvrf); - -  /* Nexthop parse. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) -    { -      nexthop_num = stream_getc (s); -      zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); - -      for (i = 0; i < nexthop_num; i++) -	{ -	  nexthop_type = stream_getc (s); - -	  switch (nexthop_type) -	    { -	    case NEXTHOP_TYPE_IFINDEX: -	      ifindex = stream_getl (s); -	      route_entry_nexthop_ifindex_add (re, ifindex); -	      break; -	    case NEXTHOP_TYPE_IPV4: -              nhop_addr.s_addr = stream_get_ipv4 (s); -              nexthop = route_entry_nexthop_ipv4_add (re, &nhop_addr, NULL); -              /* For labeled-unicast, each nexthop is followed by label. */ -              if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) -                { -                  label = (mpls_label_t)stream_getl (s); -                  nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &label); -                } -	      break; -	    case NEXTHOP_TYPE_IPV4_IFINDEX: -	      nhop_addr.s_addr = stream_get_ipv4 (s); -	      ifindex = stream_getl (s); -	      route_entry_nexthop_ipv4_ifindex_add (re, &nhop_addr, NULL, ifindex); -	      break; -	    case NEXTHOP_TYPE_IPV6: -	      stream_forward_getp (s, IPV6_MAX_BYTELEN); -	      break; -            case NEXTHOP_TYPE_BLACKHOLE: -              route_entry_nexthop_blackhole_add (re); -              break; -            } +static int zread_ipv4_add(struct zserv *client, u_short length, +			  struct zebra_vrf *zvrf) +{ +	int i; +	struct route_entry *re; +	struct prefix p; +	u_char message; +	struct in_addr nhop_addr; +	u_char nexthop_num; +	u_char nexthop_type; +	struct stream *s; +	ifindex_t ifindex; +	safi_t safi; +	int ret; +	mpls_label_t label; +	struct nexthop *nexthop; + +	/* Get input stream.  */ +	s = client->ibuf; + +	/* Allocate new re. */ +	re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + +	/* Type, flags, message. */ +	re->type = stream_getc(s); +	re->instance = stream_getw(s); +	re->flags = stream_getl(s); +	message = stream_getc(s); +	safi = stream_getw(s); +	re->uptime = time(NULL); + +	/* IPv4 prefix. */ +	memset(&p, 0, sizeof(struct prefix_ipv4)); +	p.family = AF_INET; +	p.prefixlen = stream_getc(s); +	stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); + +	/* VRF ID */ +	re->vrf_id = zvrf_id(zvrf); + +	/* Nexthop parse. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { +		nexthop_num = stream_getc(s); +		zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, +				       nexthop_num); + +		for (i = 0; i < nexthop_num; i++) { +			nexthop_type = stream_getc(s); + +			switch (nexthop_type) { +			case NEXTHOP_TYPE_IFINDEX: +				ifindex = stream_getl(s); +				route_entry_nexthop_ifindex_add(re, ifindex); +				break; +			case NEXTHOP_TYPE_IPV4: +				nhop_addr.s_addr = stream_get_ipv4(s); +				nexthop = route_entry_nexthop_ipv4_add( +					re, &nhop_addr, NULL); +				/* For labeled-unicast, each nexthop is followed +				 * by label. */ +				if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { +					label = (mpls_label_t)stream_getl(s); +					nexthop_add_labels( +						nexthop, nexthop->nh_label_type, +						1, &label); +				} +				break; +			case NEXTHOP_TYPE_IPV4_IFINDEX: +				nhop_addr.s_addr = stream_get_ipv4(s); +				ifindex = stream_getl(s); +				route_entry_nexthop_ipv4_ifindex_add( +					re, &nhop_addr, NULL, ifindex); +				break; +			case NEXTHOP_TYPE_IPV6: +				stream_forward_getp(s, IPV6_MAX_BYTELEN); +				break; +			case NEXTHOP_TYPE_BLACKHOLE: +				route_entry_nexthop_blackhole_add(re); +				break; +			} +		}  	} -    } -  /* Distance. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) -    re->distance = stream_getc (s); +	/* Distance. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) +		re->distance = stream_getc(s); -  /* Metric. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) -    re->metric = stream_getl (s); -     -  /* Tag */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) -    re->tag = stream_getl (s); -  else -    re->tag = 0; +	/* Metric. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) +		re->metric = stream_getl(s); -  if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) -    re->mtu = stream_getl (s); -  else -    re->mtu = 0; +	/* Tag */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) +		re->tag = stream_getl(s); +	else +		re->tag = 0; -  /* Table */ -  re->table = zvrf->table_id; +	if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) +		re->mtu = stream_getl(s); +	else +		re->mtu = 0; + +	/* Table */ +	re->table = zvrf->table_id; -  ret = rib_add_multipath (AFI_IP, safi, &p, NULL, re); +	ret = rib_add_multipath(AFI_IP, safi, &p, NULL, re); -  /* Stats */ -  if (ret > 0) -    client->v4_route_add_cnt++; -  else if (ret < 0) -    client->v4_route_upd8_cnt++; -  return 0; +	/* Stats */ +	if (ret > 0) +		client->v4_route_add_cnt++; +	else if (ret < 0) +		client->v4_route_upd8_cnt++; +	return 0;  }  /* Zebra server IPv4 prefix delete function. */ -static int -zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ -  int i; -  struct stream *s; -  struct zapi_ipv4 api; -  struct in_addr nexthop; -  union g_addr *nexthop_p; -  unsigned long ifindex; -  struct prefix p; -  u_char nexthop_num; -  u_char nexthop_type; -  u_int32_t table_id; - -  s = client->ibuf; -  ifindex = 0; -  nexthop.s_addr = 0; -  nexthop_p = NULL; - -  /* Type, flags, message. */ -  api.type = stream_getc (s); -  api.instance = stream_getw (s); -  api.flags = stream_getl (s); -  api.message = stream_getc (s); -  api.safi = stream_getw (s); - -  /* IPv4 prefix. */ -  memset (&p, 0, sizeof (struct prefix)); -  p.family = AF_INET; -  p.prefixlen = stream_getc (s); -  stream_get (&p.u.prefix4, 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 NEXTHOP_TYPE_IFINDEX: -	      ifindex = stream_getl (s); -	      break; -	    case NEXTHOP_TYPE_IPV4: -	      nexthop.s_addr = stream_get_ipv4 (s); -              /* For labeled-unicast, each nexthop is followed by label, but -               * we don't care for delete. -               */ -              if (CHECK_FLAG (api.message, ZAPI_MESSAGE_LABEL)) -                stream_forward_getp (s, sizeof(u_int32_t)); -	      nexthop_p = (union g_addr *)&nexthop; -	      break; -	    case NEXTHOP_TYPE_IPV4_IFINDEX: -	      nexthop.s_addr = stream_get_ipv4 (s); -	      nexthop_p = (union g_addr *)&nexthop; -	      ifindex = stream_getl (s); -	      break; -	    case NEXTHOP_TYPE_IPV6: -	      stream_forward_getp (s, IPV6_MAX_BYTELEN); -	      break; -	    } +static int zread_ipv4_delete(struct zserv *client, u_short length, +			     struct zebra_vrf *zvrf) +{ +	int i; +	struct stream *s; +	struct zapi_ipv4 api; +	struct in_addr nexthop; +	union g_addr *nexthop_p; +	unsigned long ifindex; +	struct prefix p; +	u_char nexthop_num; +	u_char nexthop_type; +	u_int32_t table_id; + +	s = client->ibuf; +	ifindex = 0; +	nexthop.s_addr = 0; +	nexthop_p = NULL; + +	/* Type, flags, message. */ +	api.type = stream_getc(s); +	api.instance = stream_getw(s); +	api.flags = stream_getl(s); +	api.message = stream_getc(s); +	api.safi = stream_getw(s); + +	/* IPv4 prefix. */ +	memset(&p, 0, sizeof(struct prefix)); +	p.family = AF_INET; +	p.prefixlen = stream_getc(s); +	stream_get(&p.u.prefix4, 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 NEXTHOP_TYPE_IFINDEX: +				ifindex = stream_getl(s); +				break; +			case NEXTHOP_TYPE_IPV4: +				nexthop.s_addr = stream_get_ipv4(s); +				/* For labeled-unicast, each nexthop is followed +				 * by label, but +				 * we don't care for delete. +				 */ +				if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)) +					stream_forward_getp(s, +							    sizeof(u_int32_t)); +				nexthop_p = (union g_addr *)&nexthop; +				break; +			case NEXTHOP_TYPE_IPV4_IFINDEX: +				nexthop.s_addr = stream_get_ipv4(s); +				nexthop_p = (union g_addr *)&nexthop; +				ifindex = stream_getl(s); +				break; +			case NEXTHOP_TYPE_IPV6: +				stream_forward_getp(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; -     -  /* tag */ -  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) -    api.tag = stream_getl (s); -  else -    api.tag = 0; - -  table_id = zvrf->table_id; - -  rib_delete (AFI_IP, api.safi, zvrf_id (zvrf), api.type, api.instance, -	      api.flags, &p, NULL, nexthop_p, ifindex, table_id); -  client->v4_route_del_cnt++; -  return 0; + +	/* 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; + +	/* tag */ +	if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) +		api.tag = stream_getl(s); +	else +		api.tag = 0; + +	table_id = zvrf->table_id; + +	rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance, +		   api.flags, &p, NULL, nexthop_p, ifindex, table_id); +	client->v4_route_del_cnt++; +	return 0;  }  /* MRIB Nexthop lookup for IPv4. */ -static int -zread_ipv4_nexthop_lookup_mrib (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_ipv4_nexthop_lookup_mrib(struct zserv *client, u_short length, +					  struct zebra_vrf *zvrf)  { -  struct in_addr addr; -  struct route_entry *re; +	struct in_addr addr; +	struct route_entry *re; -  addr.s_addr = stream_get_ipv4 (client->ibuf); -  re = rib_match_ipv4_multicast (zvrf_id (zvrf), addr, NULL); -  return zsend_ipv4_nexthop_lookup_mrib (client, addr, re, zvrf); +	addr.s_addr = stream_get_ipv4(client->ibuf); +	re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL); +	return zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf);  }  /* Zebra server IPv6 prefix add function. */ -static int -zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ -  unsigned int i; -  struct stream *s; -  struct in6_addr nhop_addr; -  struct route_entry *re; -  u_char message; -  u_char nexthop_num; -  u_char nexthop_type; -  struct prefix p; -  safi_t safi; -  static struct in6_addr nexthops[MULTIPATH_NUM]; -  static unsigned int ifindices[MULTIPATH_NUM]; -  int ret; -  static mpls_label_t labels[MULTIPATH_NUM]; -  mpls_label_t label; -  struct nexthop *nexthop; - -  /* Get input stream.  */ -  s = client->ibuf; - -  memset (&nhop_addr, 0, sizeof (struct in6_addr)); - -  /* Allocate new re. */ -  re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - -  /* Type, flags, message. */ -  re->type = stream_getc (s); -  re->instance = stream_getw (s); -  re->flags = stream_getl (s); -  message = stream_getc (s); -  safi = stream_getw (s); -  re->uptime = time (NULL); - -  /* IPv4 prefix. */ -  memset (&p, 0, sizeof (struct prefix_ipv4)); -  p.family = AF_INET; -  p.prefixlen = stream_getc (s); -  stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); - -  /* VRF ID */ -  re->vrf_id = zvrf_id (zvrf); - -  /* We need to give nh-addr, nh-ifindex with the same next-hop object -   * to the re to ensure that IPv6 multipathing works; need to coalesce -   * these. Clients should send the same number of paired set of -   * next-hop-addr/next-hop-ifindices. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) -    { -      unsigned int nh_count = 0; -      unsigned int if_count = 0; -      unsigned int max_nh_if = 0; - -      nexthop_num = stream_getc (s); -      zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); -      for (i = 0; i < nexthop_num; i++) -	{ -	  nexthop_type = stream_getc (s); - -	  switch (nexthop_type) -	    { -	    case NEXTHOP_TYPE_IPV6: -              stream_get (&nhop_addr, s, 16); -              if (nh_count < MULTIPATH_NUM) -                { -                  /* For labeled-unicast, each nexthop is followed by label. */ -                  if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) -                    { -                      label = (mpls_label_t)stream_getl (s); -                      labels[nh_count] = label; -                    } -                  nexthops[nh_count] = nhop_addr; -                  nh_count++; -                } -              break; -	    case NEXTHOP_TYPE_IFINDEX: -              if (if_count < multipath_num) { -	        ifindices[if_count++] = stream_getl (s); -              } -	      break; -            case NEXTHOP_TYPE_BLACKHOLE: -              route_entry_nexthop_blackhole_add (re); -              break; -	    } +static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, +					     u_short length, +					     struct zebra_vrf *zvrf) +{ +	unsigned int i; +	struct stream *s; +	struct in6_addr nhop_addr; +	struct route_entry *re; +	u_char message; +	u_char nexthop_num; +	u_char nexthop_type; +	struct prefix p; +	safi_t safi; +	static struct in6_addr nexthops[MULTIPATH_NUM]; +	static unsigned int ifindices[MULTIPATH_NUM]; +	int ret; +	static mpls_label_t labels[MULTIPATH_NUM]; +	mpls_label_t label; +	struct nexthop *nexthop; + +	/* Get input stream.  */ +	s = client->ibuf; + +	memset(&nhop_addr, 0, sizeof(struct in6_addr)); + +	/* Allocate new re. */ +	re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + +	/* Type, flags, message. */ +	re->type = stream_getc(s); +	re->instance = stream_getw(s); +	re->flags = stream_getl(s); +	message = stream_getc(s); +	safi = stream_getw(s); +	re->uptime = time(NULL); + +	/* IPv4 prefix. */ +	memset(&p, 0, sizeof(struct prefix_ipv4)); +	p.family = AF_INET; +	p.prefixlen = stream_getc(s); +	stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); + +	/* VRF ID */ +	re->vrf_id = zvrf_id(zvrf); + +	/* We need to give nh-addr, nh-ifindex with the same next-hop object +	 * to the re to ensure that IPv6 multipathing works; need to coalesce +	 * these. Clients should send the same number of paired set of +	 * next-hop-addr/next-hop-ifindices. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { +		unsigned int nh_count = 0; +		unsigned int if_count = 0; +		unsigned int max_nh_if = 0; + +		nexthop_num = stream_getc(s); +		zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, +				       nexthop_num); +		for (i = 0; i < nexthop_num; i++) { +			nexthop_type = stream_getc(s); + +			switch (nexthop_type) { +			case NEXTHOP_TYPE_IPV6: +				stream_get(&nhop_addr, s, 16); +				if (nh_count < MULTIPATH_NUM) { +					/* For labeled-unicast, each nexthop is +					 * followed by label. */ +					if (CHECK_FLAG(message, +						       ZAPI_MESSAGE_LABEL)) { +						label = (mpls_label_t) +							stream_getl(s); +						labels[nh_count] = label; +					} +					nexthops[nh_count] = nhop_addr; +					nh_count++; +				} +				break; +			case NEXTHOP_TYPE_IFINDEX: +				if (if_count < multipath_num) { +					ifindices[if_count++] = stream_getl(s); +				} +				break; +			case NEXTHOP_TYPE_BLACKHOLE: +				route_entry_nexthop_blackhole_add(re); +				break; +			} +		} + +		max_nh_if = (nh_count > if_count) ? nh_count : if_count; +		for (i = 0; i < max_nh_if; i++) { +			if ((i < nh_count) +			    && !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) { +				if ((i < if_count) && ifindices[i]) +					nexthop = +						route_entry_nexthop_ipv6_ifindex_add( +							re, &nexthops[i], +							ifindices[i]); +				else +					nexthop = route_entry_nexthop_ipv6_add( +						re, &nexthops[i]); + +				if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) +					nexthop_add_labels( +						nexthop, nexthop->nh_label_type, +						1, &labels[i]); +			} else { +				if ((i < if_count) && ifindices[i]) +					route_entry_nexthop_ifindex_add( +						re, ifindices[i]); +			} +		}  	} -      max_nh_if = (nh_count > if_count) ? nh_count : if_count; -      for (i = 0; i < max_nh_if; i++) -        { -	  if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) { -            if ((i < if_count) && ifindices[i]) -              nexthop = route_entry_nexthop_ipv6_ifindex_add (re, &nexthops[i], ifindices[i]); -            else -	      nexthop = route_entry_nexthop_ipv6_add (re, &nexthops[i]); - -           if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) -              nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &labels[i]); -          } -          else { -            if ((i < if_count) && ifindices[i]) -	      route_entry_nexthop_ifindex_add (re, ifindices[i]); -            } -	} -    } - -  /* Distance. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) -    re->distance = stream_getc (s); - -  /* Metric. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) -    re->metric = stream_getl (s); - -  /* Tag */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) -    re->tag = stream_getl (s); -  else -    re->tag = 0; - -  if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) -    re->mtu = stream_getl (s); -  else -    re->mtu = 0; - -  /* Table */ -  re->table = zvrf->table_id; - -  ret = rib_add_multipath (AFI_IP6, safi, &p, NULL, re); -  /* Stats */ -  if (ret > 0) -    client->v4_route_add_cnt++; -  else if (ret < 0) -    client->v4_route_upd8_cnt++; - -  return 0; -} - -static int -zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ -  unsigned int i; -  struct stream *s; -  struct in6_addr nhop_addr; -  struct route_entry *re; -  u_char message; -  u_char nexthop_num; -  u_char nexthop_type; -  struct prefix p; -  struct prefix_ipv6 src_p, *src_pp; -  safi_t safi; -  static struct in6_addr nexthops[MULTIPATH_NUM]; -  static unsigned int ifindices[MULTIPATH_NUM]; -  int ret; -  static mpls_label_t labels[MULTIPATH_NUM]; -  mpls_label_t label; -  struct nexthop *nexthop; - -  /* Get input stream.  */ -  s = client->ibuf; - -  memset (&nhop_addr, 0, sizeof (struct in6_addr)); - -  /* Allocate new re. */ -  re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - -  /* Type, flags, message. */ -  re->type = stream_getc (s); -  re->instance = stream_getw (s); -  re->flags = stream_getl (s); -  message = stream_getc (s); -  safi = stream_getw (s); -  re->uptime = time (NULL); - -  /* IPv6 prefix. */ -  memset (&p, 0, sizeof (struct prefix_ipv6)); -  p.family = AF_INET6; -  p.prefixlen = stream_getc (s); -  stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); - -  if (CHECK_FLAG (message, ZAPI_MESSAGE_SRCPFX)) -    { -      memset (&src_p, 0, sizeof (struct prefix_ipv6)); -      src_p.family = AF_INET6; -      src_p.prefixlen = stream_getc (s); -      stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); -      src_pp = &src_p; -    } -  else -    src_pp = NULL; - -  /* We need to give nh-addr, nh-ifindex with the same next-hop object -   * to the re to ensure that IPv6 multipathing works; need to coalesce -   * these. Clients should send the same number of paired set of -   * next-hop-addr/next-hop-ifindices. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) -    { -      unsigned int nh_count = 0; -      unsigned int if_count = 0; -      unsigned int max_nh_if = 0; - -      nexthop_num = stream_getc (s); -      zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); -      for (i = 0; i < nexthop_num; i++)  -	{ -	  nexthop_type = stream_getc (s); - -	  switch (nexthop_type) -	    { -	    case NEXTHOP_TYPE_IPV6: -              stream_get (&nhop_addr, s, 16); -              if (nh_count < MULTIPATH_NUM) -                { -                  /* For labeled-unicast, each nexthop is followed by label. */ -                  if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) -                    { -                      label = (mpls_label_t)stream_getl (s); -                      labels[nh_count] = label; -                    } -                 nexthops[nh_count++] = nhop_addr; -                } -	      break; -	    case NEXTHOP_TYPE_IFINDEX: -              if (if_count < multipath_num) { -	        ifindices[if_count++] = stream_getl (s); -              } -	      break; -            case NEXTHOP_TYPE_BLACKHOLE: -              route_entry_nexthop_blackhole_add (re); -              break; -	    } -	} +	/* Distance. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) +		re->distance = stream_getc(s); -      max_nh_if = (nh_count > if_count) ? nh_count : if_count; -      for (i = 0; i < max_nh_if; i++) -        { -	  if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) { -            if ((i < if_count) && ifindices[i]) -              nexthop = route_entry_nexthop_ipv6_ifindex_add (re, &nexthops[i], ifindices[i]); -            else -	      nexthop = route_entry_nexthop_ipv6_add (re, &nexthops[i]); -            if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) -              nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &labels[i]); -          } -          else { -            if ((i < if_count) && ifindices[i]) -	      route_entry_nexthop_ifindex_add (re, ifindices[i]); -          } +	/* Metric. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) +		re->metric = stream_getl(s); + +	/* Tag */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) +		re->tag = stream_getl(s); +	else +		re->tag = 0; + +	if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) +		re->mtu = stream_getl(s); +	else +		re->mtu = 0; + +	/* Table */ +	re->table = zvrf->table_id; + +	ret = rib_add_multipath(AFI_IP6, safi, &p, NULL, re); +	/* Stats */ +	if (ret > 0) +		client->v4_route_add_cnt++; +	else if (ret < 0) +		client->v4_route_upd8_cnt++; + +	return 0; +} + +static int zread_ipv6_add(struct zserv *client, u_short length, +			  struct zebra_vrf *zvrf) +{ +	unsigned int i; +	struct stream *s; +	struct in6_addr nhop_addr; +	struct route_entry *re; +	u_char message; +	u_char nexthop_num; +	u_char nexthop_type; +	struct prefix p; +	struct prefix_ipv6 src_p, *src_pp; +	safi_t safi; +	static struct in6_addr nexthops[MULTIPATH_NUM]; +	static unsigned int ifindices[MULTIPATH_NUM]; +	int ret; +	static mpls_label_t labels[MULTIPATH_NUM]; +	mpls_label_t label; +	struct nexthop *nexthop; + +	/* Get input stream.  */ +	s = client->ibuf; + +	memset(&nhop_addr, 0, sizeof(struct in6_addr)); + +	/* Allocate new re. */ +	re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + +	/* Type, flags, message. */ +	re->type = stream_getc(s); +	re->instance = stream_getw(s); +	re->flags = stream_getl(s); +	message = stream_getc(s); +	safi = stream_getw(s); +	re->uptime = time(NULL); + +	/* IPv6 prefix. */ +	memset(&p, 0, sizeof(struct prefix_ipv6)); +	p.family = AF_INET6; +	p.prefixlen = stream_getc(s); +	stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); + +	if (CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) { +		memset(&src_p, 0, sizeof(struct prefix_ipv6)); +		src_p.family = AF_INET6; +		src_p.prefixlen = stream_getc(s); +		stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); +		src_pp = &src_p; +	} else +		src_pp = NULL; + +	/* We need to give nh-addr, nh-ifindex with the same next-hop object +	 * to the re to ensure that IPv6 multipathing works; need to coalesce +	 * these. Clients should send the same number of paired set of +	 * next-hop-addr/next-hop-ifindices. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { +		unsigned int nh_count = 0; +		unsigned int if_count = 0; +		unsigned int max_nh_if = 0; + +		nexthop_num = stream_getc(s); +		zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, +				       nexthop_num); +		for (i = 0; i < nexthop_num; i++) { +			nexthop_type = stream_getc(s); + +			switch (nexthop_type) { +			case NEXTHOP_TYPE_IPV6: +				stream_get(&nhop_addr, s, 16); +				if (nh_count < MULTIPATH_NUM) { +					/* For labeled-unicast, each nexthop is +					 * followed by label. */ +					if (CHECK_FLAG(message, +						       ZAPI_MESSAGE_LABEL)) { +						label = (mpls_label_t) +							stream_getl(s); +						labels[nh_count] = label; +					} +					nexthops[nh_count++] = nhop_addr; +				} +				break; +			case NEXTHOP_TYPE_IFINDEX: +				if (if_count < multipath_num) { +					ifindices[if_count++] = stream_getl(s); +				} +				break; +			case NEXTHOP_TYPE_BLACKHOLE: +				route_entry_nexthop_blackhole_add(re); +				break; +			} +		} + +		max_nh_if = (nh_count > if_count) ? nh_count : if_count; +		for (i = 0; i < max_nh_if; i++) { +			if ((i < nh_count) +			    && !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) { +				if ((i < if_count) && ifindices[i]) +					nexthop = +						route_entry_nexthop_ipv6_ifindex_add( +							re, &nexthops[i], +							ifindices[i]); +				else +					nexthop = route_entry_nexthop_ipv6_add( +						re, &nexthops[i]); +				if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) +					nexthop_add_labels( +						nexthop, nexthop->nh_label_type, +						1, &labels[i]); +			} else { +				if ((i < if_count) && ifindices[i]) +					route_entry_nexthop_ifindex_add( +						re, ifindices[i]); +			} +		}  	} -    } -  /* Distance. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) -    re->distance = stream_getc (s); +	/* Distance. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) +		re->distance = stream_getc(s); + +	/* Metric. */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) +		re->metric = stream_getl(s); -  /* Metric. */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) -    re->metric = stream_getl (s); -     -  /* Tag */ -  if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) -    re->tag = stream_getl (s); -  else -    re->tag = 0; +	/* Tag */ +	if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) +		re->tag = stream_getl(s); +	else +		re->tag = 0; -  if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) -    re->mtu = stream_getl (s); -  else -    re->mtu = 0; +	if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) +		re->mtu = stream_getl(s); +	else +		re->mtu = 0; -  /* VRF ID */ -  re->vrf_id = zvrf_id (zvrf); -  re->table = zvrf->table_id; +	/* VRF ID */ +	re->vrf_id = zvrf_id(zvrf); +	re->table = zvrf->table_id; -  ret = rib_add_multipath (AFI_IP6, safi, &p, src_pp, re); -  /* Stats */ -  if (ret > 0) -    client->v6_route_add_cnt++; -  else if (ret < 0) -    client->v6_route_upd8_cnt++; +	ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re); +	/* Stats */ +	if (ret > 0) +		client->v6_route_add_cnt++; +	else if (ret < 0) +		client->v6_route_upd8_cnt++; -  return 0; +	return 0;  }  /* Zebra server IPv6 prefix delete function. */ -static int -zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ -  int i; -  struct stream *s; -  struct zapi_ipv6 api; -  struct in6_addr nexthop; -  union g_addr *pnexthop = NULL; -  unsigned long ifindex; -  struct prefix p; -  struct prefix_ipv6 src_p, *src_pp; -   -  s = client->ibuf; -  ifindex = 0; -  memset (&nexthop, 0, sizeof (struct in6_addr)); - -  /* Type, flags, message. */ -  api.type = stream_getc (s); -  api.instance = stream_getw (s); -  api.flags = stream_getl (s); -  api.message = stream_getc (s); -  api.safi = stream_getw (s); - -  /* IPv4 prefix. */ -  memset (&p, 0, sizeof (struct prefix_ipv6)); -  p.family = AF_INET6; -  p.prefixlen = stream_getc (s); -  stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); - -  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX)) -    { -      memset (&src_p, 0, sizeof (struct prefix_ipv6)); -      src_p.family = AF_INET6; -      src_p.prefixlen = stream_getc (s); -      stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); -      src_pp = &src_p; -    } -  else -    src_pp = NULL; - -  /* Nexthop, ifindex, distance, metric. */ -  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) -    { -      u_char nexthop_type; - -      api.nexthop_num = stream_getc (s); -      for (i = 0; i < api.nexthop_num; i++) -	{ -	  nexthop_type = stream_getc (s); - -	  switch (nexthop_type) -	    { -	    case NEXTHOP_TYPE_IPV6: -	      stream_get (&nexthop, s, 16); -              /* For labeled-unicast, each nexthop is followed by label, but -               * we don't care for delete. -               */ -              if (CHECK_FLAG (api.message, ZAPI_MESSAGE_LABEL)) -                stream_forward_getp (s, sizeof(u_int32_t)); -	      pnexthop = (union g_addr *)&nexthop; -	      break; -	    case NEXTHOP_TYPE_IFINDEX: -	      ifindex = stream_getl (s); -	      break; -	    } +static int zread_ipv6_delete(struct zserv *client, u_short length, +			     struct zebra_vrf *zvrf) +{ +	int i; +	struct stream *s; +	struct zapi_ipv6 api; +	struct in6_addr nexthop; +	union g_addr *pnexthop = NULL; +	unsigned long ifindex; +	struct prefix p; +	struct prefix_ipv6 src_p, *src_pp; + +	s = client->ibuf; +	ifindex = 0; +	memset(&nexthop, 0, sizeof(struct in6_addr)); + +	/* Type, flags, message. */ +	api.type = stream_getc(s); +	api.instance = stream_getw(s); +	api.flags = stream_getl(s); +	api.message = stream_getc(s); +	api.safi = stream_getw(s); + +	/* IPv4 prefix. */ +	memset(&p, 0, sizeof(struct prefix_ipv6)); +	p.family = AF_INET6; +	p.prefixlen = stream_getc(s); +	stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); + +	if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { +		memset(&src_p, 0, sizeof(struct prefix_ipv6)); +		src_p.family = AF_INET6; +		src_p.prefixlen = stream_getc(s); +		stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); +		src_pp = &src_p; +	} else +		src_pp = NULL; + +	/* Nexthop, ifindex, distance, metric. */ +	if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { +		u_char nexthop_type; + +		api.nexthop_num = stream_getc(s); +		for (i = 0; i < api.nexthop_num; i++) { +			nexthop_type = stream_getc(s); + +			switch (nexthop_type) { +			case NEXTHOP_TYPE_IPV6: +				stream_get(&nexthop, s, 16); +				/* For labeled-unicast, each nexthop is followed +				 * by label, but +				 * we don't care for delete. +				 */ +				if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)) +					stream_forward_getp(s, +							    sizeof(u_int32_t)); +				pnexthop = (union g_addr *)&nexthop; +				break; +			case NEXTHOP_TYPE_IFINDEX: +				ifindex = stream_getl(s); +				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; -     -  /* tag */ -  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) -    api.tag = stream_getl (s); -  else -    api.tag = 0; - -  if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) -    rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance, -		api.flags, &p, src_pp, NULL, ifindex, client->rtm_table); -  else -    rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance, -		api.flags, &p, src_pp, pnexthop, ifindex, client->rtm_table); - -  client->v6_route_del_cnt++; -  return 0; + +	/* 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; + +	/* tag */ +	if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) +		api.tag = stream_getl(s); +	else +		api.tag = 0; + +	if (IN6_IS_ADDR_UNSPECIFIED(&nexthop)) +		rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, +			   api.instance, api.flags, &p, src_pp, NULL, ifindex, +			   client->rtm_table); +	else +		rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, +			   api.instance, api.flags, &p, src_pp, pnexthop, +			   ifindex, client->rtm_table); + +	client->v6_route_del_cnt++; +	return 0;  }  /* Register zebra server router-id information.  Send current router-id */ -static int -zread_router_id_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_router_id_add(struct zserv *client, u_short length, +			       struct zebra_vrf *zvrf)  { -  struct prefix p; +	struct prefix p; -  /* Router-id information is needed. */ -  vrf_bitmap_set (client->ridinfo, zvrf_id (zvrf)); +	/* Router-id information is needed. */ +	vrf_bitmap_set(client->ridinfo, zvrf_id(zvrf)); -  router_id_get (&p, zvrf_id (zvrf)); +	router_id_get(&p, zvrf_id(zvrf)); -  return zsend_router_id_update (client, &p, zvrf_id (zvrf)); +	return zsend_router_id_update(client, &p, zvrf_id(zvrf));  }  /* Unregister zebra server router-id information. */ -static int -zread_router_id_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_router_id_delete(struct zserv *client, u_short length, +				  struct zebra_vrf *zvrf)  { -  vrf_bitmap_unset (client->ridinfo, zvrf_id (zvrf)); -  return 0; +	vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); +	return 0;  }  /* Tie up route-type and client->sock */ -static void -zread_hello (struct zserv *client) +static void zread_hello(struct zserv *client)  { -  /* type of protocol (lib/zebra.h) */ -  u_char proto; -  u_short instance; +	/* type of protocol (lib/zebra.h) */ +	u_char proto; +	u_short instance; -  proto = stream_getc (client->ibuf); -  instance = stream_getw (client->ibuf); +	proto = stream_getc(client->ibuf); +	instance = stream_getw(client->ibuf); -  /* accept only dynamic routing protocols */ -  if ((proto < ZEBRA_ROUTE_MAX) -  &&  (proto > ZEBRA_ROUTE_STATIC)) -    { -      zlog_notice ("client %d says hello and bids fair to announce only %s routes", -                    client->sock, zebra_route_string(proto)); -      if (instance) -        zlog_notice ("client protocol instance %d", instance); +	/* accept only dynamic routing protocols */ +	if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_STATIC)) { +		zlog_notice( +			"client %d says hello and bids fair to announce only %s routes", +			client->sock, zebra_route_string(proto)); +		if (instance) +			zlog_notice("client protocol instance %d", instance); -      client->proto = proto; -      client->instance = instance; -    } +		client->proto = proto; +		client->instance = instance; +	}  }  /* Unregister all information in a VRF. */ -static int -zread_vrf_unregister (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ -  int i; -  afi_t afi; - -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (i = 0; i < ZEBRA_ROUTE_MAX; i++) -      vrf_bitmap_unset (client->redist[afi][i], zvrf_id (zvrf)); -  vrf_bitmap_unset (client->redist_default, zvrf_id (zvrf)); -  vrf_bitmap_unset (client->ifinfo, zvrf_id (zvrf)); -  vrf_bitmap_unset (client->ridinfo, zvrf_id (zvrf)); - -  return 0; -} - -static void -zread_mpls_labels (int command, struct zserv *client, u_short length, -		   vrf_id_t vrf_id) -{ -  struct stream *s; -  enum lsp_types_t type; -  struct prefix prefix; -  enum nexthop_types_t gtype; -  union g_addr gate; -  ifindex_t ifindex; -  mpls_label_t in_label, out_label; -  u_int8_t distance; -  struct zebra_vrf *zvrf; - -  zvrf = vrf_info_lookup (vrf_id); -  if (!zvrf) -    return; - -  /* Get input stream.  */ -  s = client->ibuf; - -  /* Get data. */ -  type = stream_getc (s); -  prefix.family = stream_getl (s); -  switch (prefix.family) -    { -    case AF_INET: -      prefix.u.prefix4.s_addr = stream_get_ipv4 (s); -      prefix.prefixlen = stream_getc (s); -      gate.ipv4.s_addr = stream_get_ipv4 (s); -      break; -    case AF_INET6: -      stream_get (&prefix.u.prefix6, s, 16); -      prefix.prefixlen = stream_getc (s); -      stream_get (&gate.ipv6, s, 16); -      break; -    default: -      return; -    } -  ifindex = stream_getl (s); -  distance = stream_getc (s); -  in_label = stream_getl (s); -  out_label = stream_getl (s); - -  switch (prefix.family) -    { -    case AF_INET: -      if (ifindex) -	gtype = NEXTHOP_TYPE_IPV4_IFINDEX; -      else -	gtype = NEXTHOP_TYPE_IPV4; -      break; -    case AF_INET6: -      if (ifindex) -	gtype = NEXTHOP_TYPE_IPV6_IFINDEX; -      else -	gtype = NEXTHOP_TYPE_IPV6; -      break; -    default: -      return; -    } - -  if (! mpls_enabled) -    return; - -  if (command == ZEBRA_MPLS_LABELS_ADD) -    { -      mpls_lsp_install (zvrf, type, in_label, out_label, gtype, &gate, -			ifindex); -      if (out_label != MPLS_IMP_NULL_LABEL) -	mpls_ftn_update (1, zvrf, type, &prefix, gtype, &gate, ifindex, -			 distance, out_label); -    } -  else if (command == ZEBRA_MPLS_LABELS_DELETE) -    { -      mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, ifindex); -      if (out_label != MPLS_IMP_NULL_LABEL) -	mpls_ftn_update (0, zvrf, type, &prefix, gtype, &gate, ifindex, -			 distance, out_label); -    } +static int zread_vrf_unregister(struct zserv *client, u_short length, +				struct zebra_vrf *zvrf) +{ +	int i; +	afi_t afi; + +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (i = 0; i < ZEBRA_ROUTE_MAX; i++) +			vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf)); +	vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); +	vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf)); +	vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); + +	return 0; +} + +static void zread_mpls_labels(int command, struct zserv *client, u_short length, +			      vrf_id_t vrf_id) +{ +	struct stream *s; +	enum lsp_types_t type; +	struct prefix prefix; +	enum nexthop_types_t gtype; +	union g_addr gate; +	ifindex_t ifindex; +	mpls_label_t in_label, out_label; +	u_int8_t distance; +	struct zebra_vrf *zvrf; + +	zvrf = vrf_info_lookup(vrf_id); +	if (!zvrf) +		return; + +	/* Get input stream.  */ +	s = client->ibuf; + +	/* Get data. */ +	type = stream_getc(s); +	prefix.family = stream_getl(s); +	switch (prefix.family) { +	case AF_INET: +		prefix.u.prefix4.s_addr = stream_get_ipv4(s); +		prefix.prefixlen = stream_getc(s); +		gate.ipv4.s_addr = stream_get_ipv4(s); +		break; +	case AF_INET6: +		stream_get(&prefix.u.prefix6, s, 16); +		prefix.prefixlen = stream_getc(s); +		stream_get(&gate.ipv6, s, 16); +		break; +	default: +		return; +	} +	ifindex = stream_getl(s); +	distance = stream_getc(s); +	in_label = stream_getl(s); +	out_label = stream_getl(s); + +	switch (prefix.family) { +	case AF_INET: +		if (ifindex) +			gtype = NEXTHOP_TYPE_IPV4_IFINDEX; +		else +			gtype = NEXTHOP_TYPE_IPV4; +		break; +	case AF_INET6: +		if (ifindex) +			gtype = NEXTHOP_TYPE_IPV6_IFINDEX; +		else +			gtype = NEXTHOP_TYPE_IPV6; +		break; +	default: +		return; +	} + +	if (!mpls_enabled) +		return; + +	if (command == ZEBRA_MPLS_LABELS_ADD) { +		mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate, +				 ifindex); +		if (out_label != MPLS_IMP_NULL_LABEL) +			mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, +					ifindex, distance, out_label); +	} else if (command == ZEBRA_MPLS_LABELS_DELETE) { +		mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex); +		if (out_label != MPLS_IMP_NULL_LABEL) +			mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, +					ifindex, distance, out_label); +	}  }  /* Send response to a label manager connect request to client */ -static int -zsend_label_manager_connect_response (struct zserv *client, vrf_id_t vrf_id, u_short result) +static int zsend_label_manager_connect_response(struct zserv *client, +						vrf_id_t vrf_id, u_short result)  { -  struct stream *s; +	struct stream *s; -  s = client->obuf; -  stream_reset (s); +	s = client->obuf; +	stream_reset(s); -  zserv_create_header (s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); +	zserv_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); -  /* result */ -  stream_putc (s, result); +	/* result */ +	stream_putc(s, result); -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); -  return writen (client->sock, s->data, stream_get_endp (s)); +	return writen(client->sock, s->data, stream_get_endp(s));  } -static void -zread_label_manager_connect (struct zserv *client, vrf_id_t vrf_id) +static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id)  { -  struct stream *s; -  /* type of protocol (lib/zebra.h) */ -  u_char proto; -  u_short instance; +	struct stream *s; +	/* type of protocol (lib/zebra.h) */ +	u_char proto; +	u_short instance; -  /* Get input stream.  */ -  s = client->ibuf; +	/* Get input stream.  */ +	s = client->ibuf; -  /* Get data. */ -  proto = stream_getc (s); -  instance = stream_getw (s); +	/* Get data. */ +	proto = stream_getc(s); +	instance = stream_getw(s); -  /* accept only dynamic routing protocols */ -  if ((proto >= ZEBRA_ROUTE_MAX) -      ||  (proto <= ZEBRA_ROUTE_STATIC)) -    { -      zlog_err ("client %d has wrong protocol %s", -                client->sock, zebra_route_string(proto)); -      zsend_label_manager_connect_response (client, vrf_id, 1); -      return; -    } -  zlog_notice ("client %d with instance %u connected as %s", -               client->sock, instance, zebra_route_string(proto)); -  client->proto = proto; -  client->instance = instance; - -  /* -    Release previous labels of same protocol and instance. -    This is done in case it restarted from an unexpected shutdown. -  */ -  release_daemon_chunks (proto, instance); - -  zlog_debug (" Label Manager client connected: sock %d, proto %s, instance %u", -              client->sock, zebra_route_string(proto), instance); -  /* send response back */ -  zsend_label_manager_connect_response (client, vrf_id, 0); +	/* accept only dynamic routing protocols */ +	if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) { +		zlog_err("client %d has wrong protocol %s", client->sock, +			 zebra_route_string(proto)); +		zsend_label_manager_connect_response(client, vrf_id, 1); +		return; +	} +	zlog_notice("client %d with instance %u connected as %s", client->sock, +		    instance, zebra_route_string(proto)); +	client->proto = proto; +	client->instance = instance; + +	/* +	  Release previous labels of same protocol and instance. +	  This is done in case it restarted from an unexpected shutdown. +	*/ +	release_daemon_chunks(proto, instance); + +	zlog_debug( +		" Label Manager client connected: sock %d, proto %s, instance %u", +		client->sock, zebra_route_string(proto), instance); +	/* send response back */ +	zsend_label_manager_connect_response(client, vrf_id, 0);  }  /* Send response to a get label chunk request to client */ -static int -zsend_assign_label_chunk_response (struct zserv *client, vrf_id_t vrf_id, -                                   struct label_manager_chunk *lmc) +static int zsend_assign_label_chunk_response(struct zserv *client, +					     vrf_id_t vrf_id, +					     struct label_manager_chunk *lmc)  { -  struct stream *s; - -  s = client->obuf; -  stream_reset (s); +	struct stream *s; -  zserv_create_header (s, ZEBRA_GET_LABEL_CHUNK, vrf_id); +	s = client->obuf; +	stream_reset(s); -  if (lmc) -    { -      /* keep */ -      stream_putc (s, lmc->keep); -      /* start and end labels */ -      stream_putl (s, lmc->start); -      stream_putl (s, lmc->end); +	zserv_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id); -    } +	if (lmc) { +		/* keep */ +		stream_putc(s, lmc->keep); +		/* start and end labels */ +		stream_putl(s, lmc->start); +		stream_putl(s, lmc->end); +	} -  /* Write packet size. */ -  stream_putw_at (s, 0, stream_get_endp (s)); +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); -  return writen (client->sock, s->data, stream_get_endp (s)); +	return writen(client->sock, s->data, stream_get_endp(s));  } -static void -zread_get_label_chunk (struct zserv *client, vrf_id_t vrf_id) +static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id)  { -  struct stream *s; -  u_char keep; -  uint32_t size; -  struct label_manager_chunk *lmc; +	struct stream *s; +	u_char keep; +	uint32_t size; +	struct label_manager_chunk *lmc; -  /* Get input stream.  */ -  s = client->ibuf; +	/* Get input stream.  */ +	s = client->ibuf; -  /* Get data. */ -  keep = stream_getc (s); -  size = stream_getl (s); +	/* Get data. */ +	keep = stream_getc(s); +	size = stream_getl(s); -  lmc = assign_label_chunk (client->proto, client->instance, keep, size); -  if (!lmc) -    zlog_err ("%s: Unable to assign Label Chunk of size %u", __func__, size); -  else -    zlog_debug ("Assigned Label Chunk %u - %u to %u", -                lmc->start, lmc->end, keep); -  /* send response back */ -  zsend_assign_label_chunk_response (client, vrf_id, lmc); +	lmc = assign_label_chunk(client->proto, client->instance, keep, size); +	if (!lmc) +		zlog_err("%s: Unable to assign Label Chunk of size %u", +			 __func__, size); +	else +		zlog_debug("Assigned Label Chunk %u - %u to %u", lmc->start, +			   lmc->end, keep); +	/* send response back */ +	zsend_assign_label_chunk_response(client, vrf_id, lmc); +} + +static void zread_release_label_chunk(struct zserv *client) +{ +	struct stream *s; +	uint32_t start, end; + +	/* Get input stream.  */ +	s = client->ibuf; + +	/* Get data. */ +	start = stream_getl(s); +	end = stream_getl(s); + +	release_label_chunk(client->proto, client->instance, start, end); +} +static void zread_label_manager_request(int cmd, struct zserv *client, +					vrf_id_t vrf_id) +{ +	/* to avoid sending other messages like ZERBA_INTERFACE_UP */ +	if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) +		client->is_synchronous = 1; + +	/* external label manager */ +	if (lm_is_external) +		zread_relay_label_manager_request(cmd, client, vrf_id); +	/* this is a label manager */ +	else { +		if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) +			zread_label_manager_connect(client, vrf_id); +		else { +			/* Sanity: don't allow 'unidentified' requests */ +			if (!client->proto) { +				zlog_err( +					"Got label request from an unidentified client"); +				return; +			} +			if (cmd == ZEBRA_GET_LABEL_CHUNK) +				zread_get_label_chunk(client, vrf_id); +			else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) +				zread_release_label_chunk(client); +		} +	}  } -static void -zread_release_label_chunk (struct zserv *client) +/* Cleanup registered nexthops (across VRFs) upon client disconnect. */ +static void zebra_client_close_cleanup_rnh(struct zserv *client)  { -  struct stream *s; -  uint32_t start, end; - -  /* Get input stream.  */ -  s = client->ibuf; +	struct vrf *vrf; +	struct zebra_vrf *zvrf; -  /* Get data. */ -  start = stream_getl (s); -  end = stream_getl (s); - -  release_label_chunk (client->proto, client->instance, start, end); +	RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) +	{ +		if ((zvrf = vrf->info) != NULL) { +			zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client, +						 RNH_NEXTHOP_TYPE); +			zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6, +						 client, RNH_NEXTHOP_TYPE); +			zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client, +						 RNH_IMPORT_CHECK_TYPE); +			zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6, +						 client, RNH_IMPORT_CHECK_TYPE); +			if (client->proto == ZEBRA_ROUTE_LDP) { +				hash_iterate(zvrf->lsp_table, +					     mpls_ldp_lsp_uninstall_all, +					     zvrf->lsp_table); +				mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP); +				mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP6); +			} +		} +	}  } -static void -zread_label_manager_request (int cmd, struct zserv *client, vrf_id_t vrf_id) + +/* Close zebra client. */ +static void zebra_client_close(struct zserv *client)  { -  /* to avoid sending other messages like ZERBA_INTERFACE_UP */ -  if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) -    client->is_synchronous = 1; +	/* Send client de-registration to BFD */ +	zebra_ptm_bfd_client_deregister(client->proto); -  /* external label manager */ -  if (lm_is_external) -    zread_relay_label_manager_request (cmd, client, vrf_id); -  /* this is a label manager */ -  else -    { -      if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) -        zread_label_manager_connect (client, vrf_id); -      else -        { -          /* Sanity: don't allow 'unidentified' requests */ -          if (!client->proto) -            { -              zlog_err ("Got label request from an unidentified client"); -              return; -            } -          if (cmd == ZEBRA_GET_LABEL_CHUNK) -            zread_get_label_chunk (client, vrf_id); -          else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) -            zread_release_label_chunk (client); -        } -    } -} +	/* Cleanup any registered nexthops - across all VRFs. */ +	zebra_client_close_cleanup_rnh(client); -/* Cleanup registered nexthops (across VRFs) upon client disconnect. */ -static void -zebra_client_close_cleanup_rnh (struct zserv *client) -{ -  struct vrf *vrf; -  struct zebra_vrf *zvrf; - -  RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) -    { -      if ((zvrf = vrf->info) != NULL) -        { -          zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET, client, RNH_NEXTHOP_TYPE); -          zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET6, client, RNH_NEXTHOP_TYPE); -          zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET, client, RNH_IMPORT_CHECK_TYPE); -          zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET6, client, RNH_IMPORT_CHECK_TYPE); -	  if (client->proto == ZEBRA_ROUTE_LDP) -	    { -	      hash_iterate(zvrf->lsp_table, mpls_ldp_lsp_uninstall_all, -			   zvrf->lsp_table); -	      mpls_ldp_ftn_uninstall_all (zvrf, AFI_IP); -	      mpls_ldp_ftn_uninstall_all (zvrf, AFI_IP6); -	    } -        } -    } -} +	/* Release Label Manager chunks */ +	release_daemon_chunks(client->proto, client->instance); -/* Close zebra client. */ -static void -zebra_client_close (struct zserv *client) -{ -  /* Send client de-registration to BFD */ -  zebra_ptm_bfd_client_deregister(client->proto); - -  /* Cleanup any registered nexthops - across all VRFs. */ -  zebra_client_close_cleanup_rnh (client); - -  /* Release Label Manager chunks */ -  release_daemon_chunks (client->proto, client->instance); - - /* Cleanup any FECs registered by this client. */ -  zebra_mpls_cleanup_fecs_for_client (vrf_info_lookup(VRF_DEFAULT), client); - -  /* Close file descriptor. */ -  if (client->sock) -    { -      unsigned long nroutes; - -      close (client->sock); -      nroutes = rib_score_proto (client->proto, client->instance); -      zlog_notice ("client %d disconnected. %lu %s routes removed from the rib", -                   client->sock, nroutes, zebra_route_string (client->proto)); -      client->sock = -1; -    } - -  /* Free stream buffers. */ -  if (client->ibuf) -    stream_free (client->ibuf); -  if (client->obuf) -    stream_free (client->obuf); -  if (client->wb) -    buffer_free(client->wb); - -  /* Release threads. */ -  if (client->t_read) -    thread_cancel (client->t_read); -  if (client->t_write) -    thread_cancel (client->t_write); -  if (client->t_suicide) -    thread_cancel (client->t_suicide); - -  /* Free bitmaps. */ -  for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) -    for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) -      vrf_bitmap_free (client->redist[afi][i]); - -  vrf_bitmap_free (client->redist_default); -  vrf_bitmap_free (client->ifinfo); -  vrf_bitmap_free (client->ridinfo); - -  /* Free client structure. */ -  listnode_delete (zebrad.client_list, client); -  XFREE (MTYPE_TMP, client); +	/* Cleanup any FECs registered by this client. */ +	zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT), +					   client); + +	/* Close file descriptor. */ +	if (client->sock) { +		unsigned long nroutes; + +		close(client->sock); +		nroutes = rib_score_proto(client->proto, client->instance); +		zlog_notice( +			"client %d disconnected. %lu %s routes removed from the rib", +			client->sock, nroutes, +			zebra_route_string(client->proto)); +		client->sock = -1; +	} + +	/* Free stream buffers. */ +	if (client->ibuf) +		stream_free(client->ibuf); +	if (client->obuf) +		stream_free(client->obuf); +	if (client->wb) +		buffer_free(client->wb); + +	/* Release threads. */ +	if (client->t_read) +		thread_cancel(client->t_read); +	if (client->t_write) +		thread_cancel(client->t_write); +	if (client->t_suicide) +		thread_cancel(client->t_suicide); + +	/* Free bitmaps. */ +	for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) +		for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) +			vrf_bitmap_free(client->redist[afi][i]); + +	vrf_bitmap_free(client->redist_default); +	vrf_bitmap_free(client->ifinfo); +	vrf_bitmap_free(client->ridinfo); + +	/* Free client structure. */ +	listnode_delete(zebrad.client_list, client); +	XFREE(MTYPE_TMP, client);  }  /* Make new client. */ -static void -zebra_client_create (int sock) +static void zebra_client_create(int sock)  { -  struct zserv *client; -  int i; -  afi_t afi; +	struct zserv *client; +	int i; +	afi_t afi; + +	client = XCALLOC(MTYPE_TMP, sizeof(struct zserv)); -  client = XCALLOC (MTYPE_TMP, sizeof (struct zserv)); +	/* Make client input/output buffer. */ +	client->sock = sock; +	client->ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ); +	client->obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); +	client->wb = buffer_new(0); -  /* Make client input/output buffer. */ -  client->sock = sock; -  client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ); -  client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ); -  client->wb = buffer_new(0); +	/* Set table number. */ +	client->rtm_table = zebrad.rtm_table_default; -  /* Set table number. */ -  client->rtm_table = zebrad.rtm_table_default; +	client->connect_time = monotime(NULL); +	/* Initialize flags */ +	for (afi = AFI_IP; afi < AFI_MAX; afi++) +		for (i = 0; i < ZEBRA_ROUTE_MAX; i++) +			client->redist[afi][i] = vrf_bitmap_init(); +	client->redist_default = vrf_bitmap_init(); +	client->ifinfo = vrf_bitmap_init(); +	client->ridinfo = vrf_bitmap_init(); -  client->connect_time = monotime(NULL); -  /* Initialize flags */ -  for (afi = AFI_IP; afi < AFI_MAX; afi++) -    for (i = 0; i < ZEBRA_ROUTE_MAX; i++) -      client->redist[afi][i] = vrf_bitmap_init (); -  client->redist_default = vrf_bitmap_init (); -  client->ifinfo = vrf_bitmap_init (); -  client->ridinfo = vrf_bitmap_init (); +	/* by default, it's not a synchronous client */ +	client->is_synchronous = 0; -  /* by default, it's not a synchronous client */ -  client->is_synchronous = 0; +	/* Add this client to linked list. */ +	listnode_add(zebrad.client_list, client); -  /* Add this client to linked list. */ -  listnode_add (zebrad.client_list, client); -   -  /* Make new read thread. */ -  zebra_event (ZEBRA_READ, sock, client); +	/* Make new read thread. */ +	zebra_event(ZEBRA_READ, sock, client); -  zebra_vrf_update_all (client); +	zebra_vrf_update_all(client);  }  /* Handler of zebra service request. */ -static int -zebra_client_read (struct thread *thread) -{ -  int sock; -  struct zserv *client; -  size_t already; -  uint16_t length, command; -  uint8_t marker, version; -  vrf_id_t vrf_id; -  struct zebra_vrf *zvrf; - -  /* Get thread data.  Reset reading thread because I'm running. */ -  sock = THREAD_FD (thread); -  client = THREAD_ARG (thread); -  client->t_read = NULL; - -  if (client->t_suicide) -    { -      zebra_client_close(client); -      return -1; -    } - -  /* Read length and command (if we don't have it already). */ -  if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) -    { -      ssize_t nbyte; -      if (((nbyte = stream_read_try (client->ibuf, sock, -				     ZEBRA_HEADER_SIZE-already)) == 0) || -	  (nbyte == -1)) -	{ -	  if (IS_ZEBRA_DEBUG_EVENT) -	    zlog_debug ("connection closed socket [%d]", sock); -	  zebra_client_close (client); -	  return -1; +static int zebra_client_read(struct thread *thread) +{ +	int sock; +	struct zserv *client; +	size_t already; +	uint16_t length, command; +	uint8_t marker, version; +	vrf_id_t vrf_id; +	struct zebra_vrf *zvrf; + +	/* Get thread data.  Reset reading thread because I'm running. */ +	sock = THREAD_FD(thread); +	client = THREAD_ARG(thread); +	client->t_read = NULL; + +	if (client->t_suicide) { +		zebra_client_close(client); +		return -1;  	} -      if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already)) -	{ -	  /* Try again later. */ -	  zebra_event (ZEBRA_READ, sock, client); -	  return 0; + +	/* Read length and command (if we don't have it already). */ +	if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) { +		ssize_t nbyte; +		if (((nbyte = stream_read_try(client->ibuf, sock, +					      ZEBRA_HEADER_SIZE - already)) +		     == 0) +		    || (nbyte == -1)) { +			if (IS_ZEBRA_DEBUG_EVENT) +				zlog_debug("connection closed socket [%d]", +					   sock); +			zebra_client_close(client); +			return -1; +		} +		if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) { +			/* Try again later. */ +			zebra_event(ZEBRA_READ, sock, client); +			return 0; +		} +		already = ZEBRA_HEADER_SIZE;  	} -      already = ZEBRA_HEADER_SIZE; -    } - -  /* Reset to read from the beginning of the incoming packet. */ -  stream_set_getp(client->ibuf, 0); - -  /* Fetch header values */ -  length = stream_getw (client->ibuf); -  marker = stream_getc (client->ibuf); -  version = stream_getc (client->ibuf); -  vrf_id = stream_getw (client->ibuf); -  command = stream_getw (client->ibuf); - -  if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) -    { -      zlog_err("%s: socket %d version mismatch, marker %d, version %d", -               __func__, sock, marker, version); -      zebra_client_close (client); -      return -1; -    } -  if (length < ZEBRA_HEADER_SIZE)  -    { -      zlog_warn("%s: socket %d message length %u is less than header size %d", -	        __func__, sock, length, ZEBRA_HEADER_SIZE); -      zebra_client_close (client); -      return -1; -    } -  if (length > STREAM_SIZE(client->ibuf)) -    { -      zlog_warn("%s: socket %d message length %u exceeds buffer size %lu", -	        __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf)); -      zebra_client_close (client); -      return -1; -    } - -  /* Read rest of data. */ -  if (already < length) -    { -      ssize_t nbyte; -      if (((nbyte = stream_read_try (client->ibuf, sock, -				     length-already)) == 0) || -	  (nbyte == -1)) -	{ -	  if (IS_ZEBRA_DEBUG_EVENT) -	    zlog_debug ("connection closed [%d] when reading zebra data", sock); -	  zebra_client_close (client); -	  return -1; + +	/* Reset to read from the beginning of the incoming packet. */ +	stream_set_getp(client->ibuf, 0); + +	/* Fetch header values */ +	length = stream_getw(client->ibuf); +	marker = stream_getc(client->ibuf); +	version = stream_getc(client->ibuf); +	vrf_id = stream_getw(client->ibuf); +	command = stream_getw(client->ibuf); + +	if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { +		zlog_err( +			"%s: socket %d version mismatch, marker %d, version %d", +			__func__, sock, marker, version); +		zebra_client_close(client); +		return -1; +	} +	if (length < ZEBRA_HEADER_SIZE) { +		zlog_warn( +			"%s: socket %d message length %u is less than header size %d", +			__func__, sock, length, ZEBRA_HEADER_SIZE); +		zebra_client_close(client); +		return -1; +	} +	if (length > STREAM_SIZE(client->ibuf)) { +		zlog_warn( +			"%s: socket %d message length %u exceeds buffer size %lu", +			__func__, sock, length, +			(u_long)STREAM_SIZE(client->ibuf)); +		zebra_client_close(client); +		return -1;  	} -      if (nbyte != (ssize_t)(length-already)) -        { -	  /* Try again later. */ -	  zebra_event (ZEBRA_READ, sock, client); -	  return 0; + +	/* Read rest of data. */ +	if (already < length) { +		ssize_t nbyte; +		if (((nbyte = stream_read_try(client->ibuf, sock, +					      length - already)) +		     == 0) +		    || (nbyte == -1)) { +			if (IS_ZEBRA_DEBUG_EVENT) +				zlog_debug( +					"connection closed [%d] when reading zebra data", +					sock); +			zebra_client_close(client); +			return -1; +		} +		if (nbyte != (ssize_t)(length - already)) { +			/* Try again later. */ +			zebra_event(ZEBRA_READ, sock, client); +			return 0; +		} +	} + +	length -= ZEBRA_HEADER_SIZE; + +	/* Debug packet information. */ +	if (IS_ZEBRA_DEBUG_EVENT) +		zlog_debug("zebra message comes from socket [%d]", sock); + +	if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) +		zlog_debug("zebra message received [%s] %d in VRF %u", +			   zserv_command_string(command), length, vrf_id); + +	client->last_read_time = monotime(NULL); +	client->last_read_cmd = command; + +	zvrf = zebra_vrf_lookup_by_id(vrf_id); +	if (!zvrf) { +		if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) +			zlog_debug("zebra received unknown VRF[%u]", vrf_id); +		goto zclient_read_out;  	} -    } - -  length -= ZEBRA_HEADER_SIZE; - -  /* Debug packet information. */ -  if (IS_ZEBRA_DEBUG_EVENT) -    zlog_debug ("zebra message comes from socket [%d]", sock); - -  if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) -    zlog_debug ("zebra message received [%s] %d in VRF %u", -	       zserv_command_string (command), length, vrf_id); - -  client->last_read_time = monotime(NULL); -  client->last_read_cmd = command; - -  zvrf = zebra_vrf_lookup_by_id (vrf_id); -  if (!zvrf) -    { -      if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) -        zlog_debug ("zebra received unknown VRF[%u]", vrf_id); -      goto zclient_read_out; -    } - -  switch (command)  -    { -    case ZEBRA_ROUTER_ID_ADD: -      zread_router_id_add (client, length, zvrf); -      break; -    case ZEBRA_ROUTER_ID_DELETE: -      zread_router_id_delete (client, length, zvrf); -      break; -    case ZEBRA_INTERFACE_ADD: -      zread_interface_add (client, length, zvrf); -      break; -    case ZEBRA_INTERFACE_DELETE: -      zread_interface_delete (client, length, zvrf); -      break; -    case ZEBRA_IPV4_ROUTE_ADD: -      zread_ipv4_add (client, length, zvrf); -      break; -    case ZEBRA_IPV4_ROUTE_DELETE: -      zread_ipv4_delete (client, length, zvrf); -      break; -    case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: -      zread_ipv4_route_ipv6_nexthop_add (client, length, zvrf); -      break; -    case ZEBRA_IPV4_NEXTHOP_ADD: -      zread_ipv4_add(client, length, zvrf); /* LB: r1.0 merge - id was 1 */ -      break; -    case ZEBRA_IPV4_NEXTHOP_DELETE: -      zread_ipv4_delete(client, length, zvrf); /* LB: r1.0 merge - id was 1 */ -      break; -    case ZEBRA_IPV6_ROUTE_ADD: -      zread_ipv6_add (client, length, zvrf); -      break; -    case ZEBRA_IPV6_ROUTE_DELETE: -      zread_ipv6_delete (client, length, zvrf); -      break; -    case ZEBRA_REDISTRIBUTE_ADD: -      zebra_redistribute_add (command, client, length, zvrf); -      break; -    case ZEBRA_REDISTRIBUTE_DELETE: -      zebra_redistribute_delete (command, client, length, zvrf); -      break; -    case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: -      zebra_redistribute_default_add (command, client, length, zvrf); -      break; -    case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: -      zebra_redistribute_default_delete (command, client, length, zvrf); -      break; -    case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB: -      zread_ipv4_nexthop_lookup_mrib (client, length, zvrf); -      break; -    case ZEBRA_HELLO: -      zread_hello (client); -      break; -    case ZEBRA_NEXTHOP_REGISTER: -      zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, zvrf); -      break; -    case ZEBRA_NEXTHOP_UNREGISTER: -      zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, zvrf); -      break; -    case ZEBRA_IMPORT_ROUTE_REGISTER: -      zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, zvrf); -      break; -    case ZEBRA_IMPORT_ROUTE_UNREGISTER: -      zserv_rnh_unregister(client, sock, length, RNH_IMPORT_CHECK_TYPE, zvrf); -      break; -    case ZEBRA_BFD_DEST_UPDATE: -    case ZEBRA_BFD_DEST_REGISTER: -      zebra_ptm_bfd_dst_register(client, sock, length, command, zvrf); -      break; -    case ZEBRA_BFD_DEST_DEREGISTER: -      zebra_ptm_bfd_dst_deregister(client, sock, length, zvrf); -      break; -    case ZEBRA_VRF_UNREGISTER: -      zread_vrf_unregister (client, length, zvrf); -      break; -    case ZEBRA_BFD_CLIENT_REGISTER: -      zebra_ptm_bfd_client_register(client, sock, length); -      break; -    case ZEBRA_INTERFACE_ENABLE_RADV: -#if defined (HAVE_RTADV) -      zebra_interface_radv_set (client, sock, length, zvrf, 1); + +	switch (command) { +	case ZEBRA_ROUTER_ID_ADD: +		zread_router_id_add(client, length, zvrf); +		break; +	case ZEBRA_ROUTER_ID_DELETE: +		zread_router_id_delete(client, length, zvrf); +		break; +	case ZEBRA_INTERFACE_ADD: +		zread_interface_add(client, length, zvrf); +		break; +	case ZEBRA_INTERFACE_DELETE: +		zread_interface_delete(client, length, zvrf); +		break; +	case ZEBRA_IPV4_ROUTE_ADD: +		zread_ipv4_add(client, length, zvrf); +		break; +	case ZEBRA_IPV4_ROUTE_DELETE: +		zread_ipv4_delete(client, length, zvrf); +		break; +	case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: +		zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf); +		break; +	case ZEBRA_IPV4_NEXTHOP_ADD: +		zread_ipv4_add(client, length, +			       zvrf); /* LB: r1.0 merge - id was 1 */ +		break; +	case ZEBRA_IPV4_NEXTHOP_DELETE: +		zread_ipv4_delete(client, length, +				  zvrf); /* LB: r1.0 merge - id was 1 */ +		break; +	case ZEBRA_IPV6_ROUTE_ADD: +		zread_ipv6_add(client, length, zvrf); +		break; +	case ZEBRA_IPV6_ROUTE_DELETE: +		zread_ipv6_delete(client, length, zvrf); +		break; +	case ZEBRA_REDISTRIBUTE_ADD: +		zebra_redistribute_add(command, client, length, zvrf); +		break; +	case ZEBRA_REDISTRIBUTE_DELETE: +		zebra_redistribute_delete(command, client, length, zvrf); +		break; +	case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: +		zebra_redistribute_default_add(command, client, length, zvrf); +		break; +	case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: +		zebra_redistribute_default_delete(command, client, length, +						  zvrf); +		break; +	case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB: +		zread_ipv4_nexthop_lookup_mrib(client, length, zvrf); +		break; +	case ZEBRA_HELLO: +		zread_hello(client); +		break; +	case ZEBRA_NEXTHOP_REGISTER: +		zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, +				   zvrf); +		break; +	case ZEBRA_NEXTHOP_UNREGISTER: +		zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, +				     zvrf); +		break; +	case ZEBRA_IMPORT_ROUTE_REGISTER: +		zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, +				   zvrf); +		break; +	case ZEBRA_IMPORT_ROUTE_UNREGISTER: +		zserv_rnh_unregister(client, sock, length, +				     RNH_IMPORT_CHECK_TYPE, zvrf); +		break; +	case ZEBRA_BFD_DEST_UPDATE: +	case ZEBRA_BFD_DEST_REGISTER: +		zebra_ptm_bfd_dst_register(client, sock, length, command, zvrf); +		break; +	case ZEBRA_BFD_DEST_DEREGISTER: +		zebra_ptm_bfd_dst_deregister(client, sock, length, zvrf); +		break; +	case ZEBRA_VRF_UNREGISTER: +		zread_vrf_unregister(client, length, zvrf); +		break; +	case ZEBRA_BFD_CLIENT_REGISTER: +		zebra_ptm_bfd_client_register(client, sock, length); +		break; +	case ZEBRA_INTERFACE_ENABLE_RADV: +#if defined(HAVE_RTADV) +		zebra_interface_radv_set(client, sock, length, zvrf, 1);  #endif -      break; -    case ZEBRA_INTERFACE_DISABLE_RADV: -#if defined (HAVE_RTADV) -      zebra_interface_radv_set (client, sock, length, zvrf, 0); +		break; +	case ZEBRA_INTERFACE_DISABLE_RADV: +#if defined(HAVE_RTADV) +		zebra_interface_radv_set(client, sock, length, zvrf, 0);  #endif -      break; -    case ZEBRA_MPLS_LABELS_ADD: -    case ZEBRA_MPLS_LABELS_DELETE: -      zread_mpls_labels (command, client, length, vrf_id); -      break; -    case ZEBRA_IPMR_ROUTE_STATS: -      zebra_ipmr_route_stats (client, sock, length, zvrf); -      break; -    case ZEBRA_LABEL_MANAGER_CONNECT: -    case ZEBRA_GET_LABEL_CHUNK: -    case ZEBRA_RELEASE_LABEL_CHUNK: -      zread_label_manager_request (command, client, vrf_id); -      break; -    case ZEBRA_FEC_REGISTER: -      zserv_fec_register (client, sock, length); -      break; -    case ZEBRA_FEC_UNREGISTER: -      zserv_fec_unregister (client, sock, length); -      break; -    case ZEBRA_ADVERTISE_ALL_VNI: -      zebra_vxlan_advertise_all_vni (client, sock, length, zvrf); -      break; -    case ZEBRA_REMOTE_VTEP_ADD: -      zebra_vxlan_remote_vtep_add (client, sock, length, zvrf); -      break; -    case ZEBRA_REMOTE_VTEP_DEL: -      zebra_vxlan_remote_vtep_del (client, sock, length, zvrf); -      break; -    case ZEBRA_REMOTE_MACIP_ADD: -      zebra_vxlan_remote_macip_add (client, sock, length, zvrf); -      break; -    case ZEBRA_REMOTE_MACIP_DEL: -      zebra_vxlan_remote_macip_del (client, sock, length, zvrf); -      break; -    default: -      zlog_info ("Zebra received unknown command %d", command); -      break; -    } - -  if (client->t_suicide) -    { -      /* No need to wait for thread callback, just kill immediately. */ -      zebra_client_close(client); -      return -1; -    } - - zclient_read_out: -  stream_reset (client->ibuf); -  zebra_event (ZEBRA_READ, sock, client); -  return 0; +		break; +	case ZEBRA_MPLS_LABELS_ADD: +	case ZEBRA_MPLS_LABELS_DELETE: +		zread_mpls_labels(command, client, length, vrf_id); +		break; +	case ZEBRA_IPMR_ROUTE_STATS: +		zebra_ipmr_route_stats(client, sock, length, zvrf); +		break; +	case ZEBRA_LABEL_MANAGER_CONNECT: +	case ZEBRA_GET_LABEL_CHUNK: +	case ZEBRA_RELEASE_LABEL_CHUNK: +		zread_label_manager_request(command, client, vrf_id); +		break; +	case ZEBRA_FEC_REGISTER: +		zserv_fec_register(client, sock, length); +		break; +	case ZEBRA_FEC_UNREGISTER: +		zserv_fec_unregister(client, sock, length); +		break; +	case ZEBRA_ADVERTISE_ALL_VNI: +		zebra_vxlan_advertise_all_vni(client, sock, length, zvrf); +		break; +	case ZEBRA_REMOTE_VTEP_ADD: +		zebra_vxlan_remote_vtep_add(client, sock, length, zvrf); +		break; +	case ZEBRA_REMOTE_VTEP_DEL: +		zebra_vxlan_remote_vtep_del(client, sock, length, zvrf); +		break; +	case ZEBRA_REMOTE_MACIP_ADD: +		zebra_vxlan_remote_macip_add(client, sock, length, zvrf); +		break; +	case ZEBRA_REMOTE_MACIP_DEL: +		zebra_vxlan_remote_macip_del(client, sock, length, zvrf); +		break; +	default: +		zlog_info("Zebra received unknown command %d", command); +		break; +	} + +	if (client->t_suicide) { +		/* No need to wait for thread callback, just kill immediately. +		 */ +		zebra_client_close(client); +		return -1; +	} + +zclient_read_out: +	stream_reset(client->ibuf); +	zebra_event(ZEBRA_READ, sock, client); +	return 0;  }  /* Accept code of zebra server socket. */ -static int -zebra_accept (struct thread *thread) +static int zebra_accept(struct thread *thread)  { -  int accept_sock; -  int client_sock; -  struct sockaddr_in client; -  socklen_t len; +	int accept_sock; +	int client_sock; +	struct sockaddr_in client; +	socklen_t len; + +	accept_sock = THREAD_FD(thread); -  accept_sock = THREAD_FD (thread); +	/* Reregister myself. */ +	zebra_event(ZEBRA_SERV, accept_sock, NULL); -  /* Reregister myself. */ -  zebra_event (ZEBRA_SERV, accept_sock, NULL); +	len = sizeof(struct sockaddr_in); +	client_sock = accept(accept_sock, (struct sockaddr *)&client, &len); -  len = sizeof (struct sockaddr_in); -  client_sock = accept (accept_sock, (struct sockaddr *) &client, &len); +	if (client_sock < 0) { +		zlog_warn("Can't accept zebra socket: %s", +			  safe_strerror(errno)); +		return -1; +	} -  if (client_sock < 0) -    { -      zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno)); -      return -1; -    } +	/* Make client socket non-blocking.  */ +	set_nonblocking(client_sock); -  /* Make client socket non-blocking.  */ -  set_nonblocking(client_sock); -   -  /* Create new zebra client. */ -  zebra_client_create (client_sock); +	/* Create new zebra client. */ +	zebra_client_create(client_sock); -  return 0; +	return 0;  }  #ifdef HAVE_TCP_ZEBRA  /* Make zebra's server socket. */ -static void -zebra_serv () -{ -  int ret; -  int accept_sock; -  struct sockaddr_in addr; - -  accept_sock = socket (AF_INET, SOCK_STREAM, 0); - -  if (accept_sock < 0)  -    { -      zlog_warn ("Can't create zserv stream socket: %s",  -                 safe_strerror (errno)); -      zlog_warn ("zebra can't provice full functionality due to above error"); -      return; -    } - -  memset (&addr, 0, sizeof (struct sockaddr_in)); -  addr.sin_family = AF_INET; -  addr.sin_port = htons (ZEBRA_PORT); +static void zebra_serv() +{ +	int ret; +	int accept_sock; +	struct sockaddr_in addr; + +	accept_sock = socket(AF_INET, SOCK_STREAM, 0); + +	if (accept_sock < 0) { +		zlog_warn("Can't create zserv stream socket: %s", +			  safe_strerror(errno)); +		zlog_warn( +			"zebra can't provice full functionality due to above error"); +		return; +	} + +	memset(&addr, 0, sizeof(struct sockaddr_in)); +	addr.sin_family = AF_INET; +	addr.sin_port = htons(ZEBRA_PORT);  #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN -  addr.sin_len = sizeof (struct sockaddr_in); +	addr.sin_len = sizeof(struct sockaddr_in);  #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ -  addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - -  sockopt_reuseaddr (accept_sock); -  sockopt_reuseport (accept_sock); - -  if ( zserv_privs.change(ZPRIVS_RAISE) ) -    zlog_err("Can't raise privileges"); -     -  ret  = bind (accept_sock, (struct sockaddr *)&addr,  -	       sizeof (struct sockaddr_in)); -  if (ret < 0) -    { -      zlog_warn ("Can't bind to stream socket: %s",  -                 safe_strerror (errno)); -      zlog_warn ("zebra can't provice full functionality due to above error"); -      close (accept_sock);      /* Avoid sd leak. */ -      return; -    } -     -  if ( zserv_privs.change(ZPRIVS_LOWER) ) -    zlog_err("Can't lower privileges"); - -  ret = listen (accept_sock, 1); -  if (ret < 0) -    { -      zlog_warn ("Can't listen to stream socket: %s",  -                 safe_strerror (errno)); -      zlog_warn ("zebra can't provice full functionality due to above error"); -      close (accept_sock);	/* Avoid sd leak. */ -      return; -    } - -  zebra_event (ZEBRA_SERV, accept_sock, NULL); +	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + +	sockopt_reuseaddr(accept_sock); +	sockopt_reuseport(accept_sock); + +	if (zserv_privs.change(ZPRIVS_RAISE)) +		zlog_err("Can't raise privileges"); + +	ret = bind(accept_sock, (struct sockaddr *)&addr, +		   sizeof(struct sockaddr_in)); +	if (ret < 0) { +		zlog_warn("Can't bind to stream socket: %s", +			  safe_strerror(errno)); +		zlog_warn( +			"zebra can't provice full functionality due to above error"); +		close(accept_sock); /* Avoid sd leak. */ +		return; +	} + +	if (zserv_privs.change(ZPRIVS_LOWER)) +		zlog_err("Can't lower privileges"); + +	ret = listen(accept_sock, 1); +	if (ret < 0) { +		zlog_warn("Can't listen to stream socket: %s", +			  safe_strerror(errno)); +		zlog_warn( +			"zebra can't provice full functionality due to above error"); +		close(accept_sock); /* Avoid sd leak. */ +		return; +	} + +	zebra_event(ZEBRA_SERV, accept_sock, NULL);  }  #else /* HAVE_TCP_ZEBRA */ @@ -2566,221 +2521,212 @@ zebra_serv ()  #include <sys/un.h>  /* zebra server UNIX domain socket. */ -static void -zebra_serv_un (const char *path) -{ -  int ret; -  int sock, len; -  struct sockaddr_un serv; -  mode_t old_mask; - -  /* First of all, unlink existing socket */ -  unlink (path); - -  /* Set umask */ -  old_mask = umask (0077); - -  /* Make UNIX domain socket. */ -  sock = socket (AF_UNIX, SOCK_STREAM, 0); -  if (sock < 0) -    { -      zlog_warn ("Can't create zserv unix socket: %s",  -                 safe_strerror (errno)); -      zlog_warn ("zebra can't provide full functionality due to above error"); -      return; -    } - -  /* Make server socket. */ -  memset (&serv, 0, sizeof (struct sockaddr_un)); -  serv.sun_family = AF_UNIX; -  strncpy (serv.sun_path, path, strlen (path)); +static void zebra_serv_un(const char *path) +{ +	int ret; +	int sock, len; +	struct sockaddr_un serv; +	mode_t old_mask; + +	/* First of all, unlink existing socket */ +	unlink(path); + +	/* Set umask */ +	old_mask = umask(0077); + +	/* Make UNIX domain socket. */ +	sock = socket(AF_UNIX, SOCK_STREAM, 0); +	if (sock < 0) { +		zlog_warn("Can't create zserv unix socket: %s", +			  safe_strerror(errno)); +		zlog_warn( +			"zebra can't provide full functionality due to above error"); +		return; +	} + +	/* Make server socket. */ +	memset(&serv, 0, sizeof(struct sockaddr_un)); +	serv.sun_family = AF_UNIX; +	strncpy(serv.sun_path, path, strlen(path));  #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN -  len = serv.sun_len = SUN_LEN(&serv); +	len = serv.sun_len = SUN_LEN(&serv);  #else -  len = sizeof (serv.sun_family) + strlen (serv.sun_path); +	len = sizeof(serv.sun_family) + strlen(serv.sun_path);  #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ -  ret = bind (sock, (struct sockaddr *) &serv, len); -  if (ret < 0) -    { -      zlog_warn ("Can't bind to unix socket %s: %s",  -                 path, safe_strerror (errno)); -      zlog_warn ("zebra can't provide full functionality due to above error"); -      close (sock); -      return; -    } - -  ret = listen (sock, 5); -  if (ret < 0) -    { -      zlog_warn ("Can't listen to unix socket %s: %s",  -                 path, safe_strerror (errno)); -      zlog_warn ("zebra can't provide full functionality due to above error"); -      close (sock); -      return; -    } - -  umask (old_mask); - -  zebra_event (ZEBRA_SERV, sock, NULL); +	ret = bind(sock, (struct sockaddr *)&serv, len); +	if (ret < 0) { +		zlog_warn("Can't bind to unix socket %s: %s", path, +			  safe_strerror(errno)); +		zlog_warn( +			"zebra can't provide full functionality due to above error"); +		close(sock); +		return; +	} + +	ret = listen(sock, 5); +	if (ret < 0) { +		zlog_warn("Can't listen to unix socket %s: %s", path, +			  safe_strerror(errno)); +		zlog_warn( +			"zebra can't provide full functionality due to above error"); +		close(sock); +		return; +	} + +	umask(old_mask); + +	zebra_event(ZEBRA_SERV, sock, NULL);  }  #endif /* HAVE_TCP_ZEBRA */ -static void -zebra_event (enum event event, int sock, struct zserv *client) -{ -  switch (event) -    { -    case ZEBRA_SERV: -      thread_add_read(zebrad.master, zebra_accept, client, sock, NULL); -      break; -    case ZEBRA_READ: -      client->t_read = NULL; -      thread_add_read(zebrad.master, zebra_client_read, client, sock, -                      &client->t_read); -      break; -    case ZEBRA_WRITE: -      /**/ -      break; -    } +static void zebra_event(enum event event, int sock, struct zserv *client) +{ +	switch (event) { +	case ZEBRA_SERV: +		thread_add_read(zebrad.master, zebra_accept, client, sock, +				NULL); +		break; +	case ZEBRA_READ: +		client->t_read = NULL; +		thread_add_read(zebrad.master, zebra_client_read, client, sock, +				&client->t_read); +		break; +	case ZEBRA_WRITE: +		/**/ +		break; +	}  }  #define ZEBRA_TIME_BUF 32 -static char * -zserv_time_buf(time_t *time1, char *buf, int buflen) +static char *zserv_time_buf(time_t *time1, char *buf, int buflen)  { -  struct tm *tm; -  time_t now; +	struct tm *tm; +	time_t now; -  assert (buf != NULL); -  assert (buflen >= ZEBRA_TIME_BUF); -  assert (time1 != NULL); +	assert(buf != NULL); +	assert(buflen >= ZEBRA_TIME_BUF); +	assert(time1 != NULL); -  if (!*time1) -    { -      snprintf(buf, buflen, "never   "); -      return (buf); -    } +	if (!*time1) { +		snprintf(buf, buflen, "never   "); +		return (buf); +	} -  now = monotime(NULL); -  now -= *time1; -  tm = gmtime(&now); +	now = monotime(NULL); +	now -= *time1; +	tm = gmtime(&now); -  /* Making formatted timer strings. */ +/* Making formatted timer strings. */  #define ONE_DAY_SECOND 60*60*24  #define ONE_WEEK_SECOND 60*60*24*7 -  if (now < ONE_DAY_SECOND) -    snprintf (buf, buflen, "%02d:%02d:%02d", -	      tm->tm_hour, tm->tm_min, tm->tm_sec); -  else if (now < ONE_WEEK_SECOND) -    snprintf (buf, buflen, "%dd%02dh%02dm", -	      tm->tm_yday, tm->tm_hour, tm->tm_min); -  else -    snprintf (buf, buflen, "%02dw%dd%02dh", -	      tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); -  return buf; -} - -static void -zebra_show_client_detail (struct vty *vty, struct zserv *client) -{ -  char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF]; -  char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF]; - -  vty_out (vty, "Client: %s", zebra_route_string(client->proto)); -  if (client->instance) -    vty_out (vty, " Instance: %d", client->instance); -  vty_out (vty, "\n"); - -  vty_out (vty, "------------------------ \n"); -  vty_out (vty, "FD: %d \n", client->sock); -  vty_out (vty, "Route Table ID: %d \n", client->rtm_table); - -  vty_out (vty, "Connect Time: %s \n", -	   zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF)); -  if (client->nh_reg_time) -    { -      vty_out (vty, "Nexthop Registry Time: %s \n", -	       zserv_time_buf(&client->nh_reg_time, nhbuf, ZEBRA_TIME_BUF)); -      if (client->nh_last_upd_time) -	vty_out (vty, "Nexthop Last Update Time: %s \n", -		 zserv_time_buf(&client->nh_last_upd_time, mbuf, ZEBRA_TIME_BUF)); +	if (now < ONE_DAY_SECOND) +		snprintf(buf, buflen, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, +			 tm->tm_sec); +	else if (now < ONE_WEEK_SECOND) +		snprintf(buf, buflen, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, +			 tm->tm_min);  	else -		vty_out (vty, "No Nexthop Update sent\n"); -    } -  else -    vty_out (vty, "Not registered for Nexthop Updates\n"); - -  vty_out (vty, "Last Msg Rx Time: %s \n", -	   zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF)); -  vty_out (vty, "Last Msg Tx Time: %s \n", -	   zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF)); -  if (client->last_read_time) -    vty_out (vty, "Last Rcvd Cmd: %s \n", -	     zserv_command_string(client->last_read_cmd)); -  if (client->last_write_time) -    vty_out (vty, "Last Sent Cmd: %s \n", -	     zserv_command_string(client->last_write_cmd)); -  vty_out (vty, "\n"); - -  vty_out (vty, "Type        Add        Update     Del \n"); -  vty_out (vty, "================================================== \n"); -  vty_out (vty, "IPv4        %-12d%-12d%-12d\n", client->v4_route_add_cnt, -	   client->v4_route_upd8_cnt, client->v4_route_del_cnt); -  vty_out (vty, "IPv6        %-12d%-12d%-12d\n", client->v6_route_add_cnt, -	   client->v6_route_upd8_cnt, client->v6_route_del_cnt); -  vty_out (vty, "Redist:v4   %-12d%-12d%-12d\n", client->redist_v4_add_cnt, 0, -	   client->redist_v4_del_cnt); -  vty_out (vty, "Redist:v6   %-12d%-12d%-12d\n", client->redist_v6_add_cnt, 0, -	   client->redist_v6_del_cnt); -  vty_out (vty, "Connected   %-12d%-12d%-12d\n", client->ifadd_cnt, 0, -	   client->ifdel_cnt); -  vty_out (vty, "BFD peer    %-12d%-12d%-12d\n", client->bfd_peer_add_cnt, -       client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt); -  vty_out (vty, "Interface Up Notifications: %d\n",client->ifup_cnt); -  vty_out (vty, "Interface Down Notifications: %d\n",client->ifdown_cnt); -  vty_out (vty, "VNI add notifications: %d\n", client->vniadd_cnt); -  vty_out (vty, "VNI delete notifications: %d\n", client->vnidel_cnt); -  vty_out (vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt); -  vty_out (vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt); - -  vty_out (vty, "\n"); -  return; -} - -static void -zebra_show_client_brief (struct vty *vty, struct zserv *client) -{ -  char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF]; -  char wbuf[ZEBRA_TIME_BUF]; - -  vty_out (vty, "%-8s%12s %12s%12s%8d/%-8d%8d/%-8d\n", -	   zebra_route_string(client->proto), -	   zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF), -	   zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF), -	   zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF), -	   client->v4_route_add_cnt+client->v4_route_upd8_cnt, -	   client->v4_route_del_cnt, -	   client->v6_route_add_cnt+client->v6_route_upd8_cnt, -	   client->v6_route_del_cnt); - -} - -struct zserv * -zebra_find_client (u_char proto) -{ -  struct listnode *node, *nnode; -  struct zserv *client; - -  for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) -    { -      if (client->proto == proto) -        return client; -    } - -  return NULL; +		snprintf(buf, buflen, "%02dw%dd%02dh", tm->tm_yday / 7, +			 tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); +	return buf; +} + +static void zebra_show_client_detail(struct vty *vty, struct zserv *client) +{ +	char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF]; +	char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF]; + +	vty_out(vty, "Client: %s", zebra_route_string(client->proto)); +	if (client->instance) +		vty_out(vty, " Instance: %d", client->instance); +	vty_out(vty, "\n"); + +	vty_out(vty, "------------------------ \n"); +	vty_out(vty, "FD: %d \n", client->sock); +	vty_out(vty, "Route Table ID: %d \n", client->rtm_table); + +	vty_out(vty, "Connect Time: %s \n", +		zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF)); +	if (client->nh_reg_time) { +		vty_out(vty, "Nexthop Registry Time: %s \n", +			zserv_time_buf(&client->nh_reg_time, nhbuf, +				       ZEBRA_TIME_BUF)); +		if (client->nh_last_upd_time) +			vty_out(vty, "Nexthop Last Update Time: %s \n", +				zserv_time_buf(&client->nh_last_upd_time, mbuf, +					       ZEBRA_TIME_BUF)); +		else +			vty_out(vty, "No Nexthop Update sent\n"); +	} else +		vty_out(vty, "Not registered for Nexthop Updates\n"); + +	vty_out(vty, "Last Msg Rx Time: %s \n", +		zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF)); +	vty_out(vty, "Last Msg Tx Time: %s \n", +		zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF)); +	if (client->last_read_time) +		vty_out(vty, "Last Rcvd Cmd: %s \n", +			zserv_command_string(client->last_read_cmd)); +	if (client->last_write_time) +		vty_out(vty, "Last Sent Cmd: %s \n", +			zserv_command_string(client->last_write_cmd)); +	vty_out(vty, "\n"); + +	vty_out(vty, "Type        Add        Update     Del \n"); +	vty_out(vty, "================================================== \n"); +	vty_out(vty, "IPv4        %-12d%-12d%-12d\n", client->v4_route_add_cnt, +		client->v4_route_upd8_cnt, client->v4_route_del_cnt); +	vty_out(vty, "IPv6        %-12d%-12d%-12d\n", client->v6_route_add_cnt, +		client->v6_route_upd8_cnt, client->v6_route_del_cnt); +	vty_out(vty, "Redist:v4   %-12d%-12d%-12d\n", client->redist_v4_add_cnt, +		0, client->redist_v4_del_cnt); +	vty_out(vty, "Redist:v6   %-12d%-12d%-12d\n", client->redist_v6_add_cnt, +		0, client->redist_v6_del_cnt); +	vty_out(vty, "Connected   %-12d%-12d%-12d\n", client->ifadd_cnt, 0, +		client->ifdel_cnt); +	vty_out(vty, "BFD peer    %-12d%-12d%-12d\n", client->bfd_peer_add_cnt, +		client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt); +	vty_out(vty, "Interface Up Notifications: %d\n", client->ifup_cnt); +	vty_out(vty, "Interface Down Notifications: %d\n", client->ifdown_cnt); +	vty_out(vty, "VNI add notifications: %d\n", client->vniadd_cnt); +	vty_out(vty, "VNI delete notifications: %d\n", client->vnidel_cnt); +	vty_out(vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt); +	vty_out(vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt); + +	vty_out(vty, "\n"); +	return; +} + +static void zebra_show_client_brief(struct vty *vty, struct zserv *client) +{ +	char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF]; +	char wbuf[ZEBRA_TIME_BUF]; + +	vty_out(vty, "%-8s%12s %12s%12s%8d/%-8d%8d/%-8d\n", +		zebra_route_string(client->proto), +		zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF), +		zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF), +		zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF), +		client->v4_route_add_cnt + client->v4_route_upd8_cnt, +		client->v4_route_del_cnt, +		client->v6_route_add_cnt + client->v6_route_upd8_cnt, +		client->v6_route_del_cnt); +} + +struct zserv *zebra_find_client(u_char proto) +{ +	struct listnode *node, *nnode; +	struct zserv *client; + +	for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { +		if (client->proto == proto) +			return client; +	} + +	return NULL;  }  #ifdef HAVE_NETLINK @@ -2791,8 +2737,8 @@ DEFUN (show_table,         SHOW_STR         "default routing table to use for all clients\n")  { -  vty_out (vty, "table %d\n",zebrad.rtm_table_default); -  return CMD_SUCCESS; +	vty_out(vty, "table %d\n", zebrad.rtm_table_default); +	return CMD_SUCCESS;  }  DEFUN (config_table, @@ -2801,8 +2747,8 @@ DEFUN (config_table,         "Configure target kernel routing table\n"         "TABLE integer\n")  { -  zebrad.rtm_table_default = strtol (argv[1]->arg, (char**)0, 10); -  return CMD_SUCCESS; +	zebrad.rtm_table_default = strtol(argv[1]->arg, (char **)0, 10); +	return CMD_SUCCESS;  }  DEFUN (no_config_table, @@ -2812,8 +2758,8 @@ DEFUN (no_config_table,         "Configure target kernel routing table\n"         "TABLE integer\n")  { -  zebrad.rtm_table_default = 0; -  return CMD_SUCCESS; +	zebrad.rtm_table_default = 0; +	return CMD_SUCCESS;  }  #endif @@ -2823,19 +2769,18 @@ DEFUN (ip_forwarding,         IP_STR         "Turn on IP forwarding")  { -  int ret; +	int ret; -  ret = ipforward (); -  if (ret == 0) -    ret = ipforward_on (); +	ret = ipforward(); +	if (ret == 0) +		ret = ipforward_on(); -  if (ret == 0) -    { -      vty_out (vty, "Can't turn on IP forwarding\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (ret == 0) { +		vty_out(vty, "Can't turn on IP forwarding\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (no_ip_forwarding, @@ -2845,19 +2790,18 @@ DEFUN (no_ip_forwarding,         IP_STR         "Turn off IP forwarding")  { -  int ret; +	int ret; -  ret = ipforward (); -  if (ret != 0) -    ret = ipforward_off (); +	ret = ipforward(); +	if (ret != 0) +		ret = ipforward_off(); -  if (ret != 0) -    { -      vty_out (vty, "Can't turn off IP forwarding\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (ret != 0) { +		vty_out(vty, "Can't turn off IP forwarding\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_zebra, @@ -2866,21 +2810,23 @@ DEFUN (show_zebra,         SHOW_STR         "Zebra information\n")  { -  struct vrf *vrf; +	struct vrf *vrf; -  vty_out (vty, -             "                            Route      Route      Neighbor   LSP        LSP\n"); -  vty_out (vty, -             "VRF                         Installs   Removals    Updates   Installs   Removals\n"); -  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) -    { -      struct zebra_vrf *zvrf = vrf->info; -      vty_out (vty,"%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n", -               vrf->name, zvrf->installs, zvrf->removals, -               zvrf->neigh_updates, zvrf->lsp_installs,zvrf->lsp_removals); -    } +	vty_out(vty, +		"                            Route      Route      Neighbor   LSP        LSP\n"); +	vty_out(vty, +		"VRF                         Installs   Removals    Updates   Installs   Removals\n"); +	RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) +	{ +		struct zebra_vrf *zvrf = vrf->info; +		vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 +			     " %10" PRIu64 " %10" PRIu64 "\n", +			vrf->name, zvrf->installs, zvrf->removals, +			zvrf->neigh_updates, zvrf->lsp_installs, +			zvrf->lsp_removals); +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  /* This command is for debugging purpose. */ @@ -2891,13 +2837,13 @@ DEFUN (show_zebra_client,         "Zebra information\n"         "Client information\n")  { -  struct listnode *node; -  struct zserv *client; +	struct listnode *node; +	struct zserv *client; -  for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) -    zebra_show_client_detail(vty, client); +	for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) +		zebra_show_client_detail(vty, client); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  /* This command is for debugging purpose. */ @@ -2909,37 +2855,33 @@ DEFUN (show_zebra_client_summary,         "Client information brief\n"         "Brief Summary\n")  { -  struct listnode *node; -  struct zserv *client; +	struct listnode *node; +	struct zserv *client; -  vty_out (vty, -             "Name    Connect Time    Last Read  Last Write  IPv4 Routes       IPv6 Routes    \n"); -  vty_out (vty, -             "--------------------------------------------------------------------------------\n"); +	vty_out(vty, +		"Name    Connect Time    Last Read  Last Write  IPv4 Routes       IPv6 Routes    \n"); +	vty_out(vty, +		"--------------------------------------------------------------------------------\n"); -  for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) -    zebra_show_client_brief(vty, client); +	for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) +		zebra_show_client_brief(vty, client); -  vty_out (vty, "Routes column shows (added+updated)/deleted\n"); -  return CMD_SUCCESS; +	vty_out(vty, "Routes column shows (added+updated)/deleted\n"); +	return CMD_SUCCESS;  }  /* Table configuration write function. */ -static int -config_write_table (struct vty *vty) +static int config_write_table(struct vty *vty)  { -  if (zebrad.rtm_table_default) -    vty_out (vty, "table %d\n",zebrad.rtm_table_default); -  return 0; +	if (zebrad.rtm_table_default) +		vty_out(vty, "table %d\n", zebrad.rtm_table_default); +	return 0;  }  /* table node for routing tables. */ -static struct cmd_node table_node = -{ -  TABLE_NODE, -  "",				/* This node has no interface. */ -  1 -}; +static struct cmd_node table_node = {TABLE_NODE, +				     "", /* This node has no interface. */ +				     1};  /* Only display ip forwarding is enabled or not. */  DEFUN (show_ip_forwarding, @@ -2949,15 +2891,15 @@ DEFUN (show_ip_forwarding,         IP_STR         "IP forwarding status\n")  { -  int ret; +	int ret; -  ret = ipforward (); +	ret = ipforward(); -  if (ret == 0) -    vty_out (vty, "IP forwarding is off\n"); -  else -    vty_out (vty, "IP forwarding is on\n"); -  return CMD_SUCCESS; +	if (ret == 0) +		vty_out(vty, "IP forwarding is off\n"); +	else +		vty_out(vty, "IP forwarding is on\n"); +	return CMD_SUCCESS;  }  /* Only display ipv6 forwarding is enabled or not. */ @@ -2968,26 +2910,25 @@ DEFUN (show_ipv6_forwarding,         "IPv6 information\n"         "Forwarding status\n")  { -  int ret; +	int ret; -  ret = ipforward_ipv6 (); +	ret = ipforward_ipv6(); -  switch (ret) -    { -    case -1: -      vty_out (vty, "ipv6 forwarding is unknown\n"); -      break; -    case 0: -      vty_out (vty, "ipv6 forwarding is %s\n", "off"); -      break; -    case 1: -      vty_out (vty, "ipv6 forwarding is %s\n", "on"); -      break; -    default: -      vty_out (vty, "ipv6 forwarding is %s\n", "off"); -      break; -    } -  return CMD_SUCCESS; +	switch (ret) { +	case -1: +		vty_out(vty, "ipv6 forwarding is unknown\n"); +		break; +	case 0: +		vty_out(vty, "ipv6 forwarding is %s\n", "off"); +		break; +	case 1: +		vty_out(vty, "ipv6 forwarding is %s\n", "on"); +		break; +	default: +		vty_out(vty, "ipv6 forwarding is %s\n", "off"); +		break; +	} +	return CMD_SUCCESS;  }  DEFUN (ipv6_forwarding, @@ -2996,19 +2937,18 @@ DEFUN (ipv6_forwarding,         IPV6_STR         "Turn on IPv6 forwarding")  { -  int ret; +	int ret; -  ret = ipforward_ipv6 (); -  if (ret == 0) -    ret = ipforward_ipv6_on (); +	ret = ipforward_ipv6(); +	if (ret == 0) +		ret = ipforward_ipv6_on(); -  if (ret == 0) -    { -      vty_out (vty, "Can't turn on IPv6 forwarding\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (ret == 0) { +		vty_out(vty, "Can't turn on IPv6 forwarding\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (no_ipv6_forwarding, @@ -3018,83 +2958,76 @@ DEFUN (no_ipv6_forwarding,         IPV6_STR         "Turn off IPv6 forwarding")  { -  int ret; +	int ret; -  ret = ipforward_ipv6 (); -  if (ret != 0) -    ret = ipforward_ipv6_off (); +	ret = ipforward_ipv6(); +	if (ret != 0) +		ret = ipforward_ipv6_off(); -  if (ret != 0) -    { -      vty_out (vty, "Can't turn off IPv6 forwarding\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (ret != 0) { +		vty_out(vty, "Can't turn off IPv6 forwarding\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  /* IPForwarding configuration write function. */ -static int -config_write_forwarding (struct vty *vty) +static int config_write_forwarding(struct vty *vty)  { -  /* FIXME: Find better place for that. */ -  router_id_write (vty); +	/* FIXME: Find better place for that. */ +	router_id_write(vty); -  if (!ipforward ()) -    vty_out (vty, "no ip forwarding\n"); -  if (!ipforward_ipv6 ()) -    vty_out (vty, "no ipv6 forwarding\n"); -  vty_out (vty, "!\n"); -  return 0; +	if (!ipforward()) +		vty_out(vty, "no ip forwarding\n"); +	if (!ipforward_ipv6()) +		vty_out(vty, "no ipv6 forwarding\n"); +	vty_out(vty, "!\n"); +	return 0;  }  /* table node for routing tables. */ -static struct cmd_node forwarding_node = -{ -  FORWARDING_NODE, -  "",				/* This node has no interface. */ -  1 -}; +static struct cmd_node forwarding_node = {FORWARDING_NODE, +					  "", /* This node has no interface. */ +					  1};  /* Initialisation of zebra and installation of commands. */ -void -zebra_init (void) +void zebra_init(void)  { -  /* Client list init. */ -  zebrad.client_list = list_new (); +	/* Client list init. */ +	zebrad.client_list = list_new(); -  /* Install configuration write function. */ -  install_node (&table_node, config_write_table); -  install_node (&forwarding_node, config_write_forwarding); +	/* Install configuration write function. */ +	install_node(&table_node, config_write_table); +	install_node(&forwarding_node, config_write_forwarding); -  install_element (VIEW_NODE, &show_ip_forwarding_cmd); -  install_element (CONFIG_NODE, &ip_forwarding_cmd); -  install_element (CONFIG_NODE, &no_ip_forwarding_cmd); -  install_element (ENABLE_NODE, &show_zebra_cmd); -  install_element (ENABLE_NODE, &show_zebra_client_cmd); -  install_element (ENABLE_NODE, &show_zebra_client_summary_cmd); +	install_element(VIEW_NODE, &show_ip_forwarding_cmd); +	install_element(CONFIG_NODE, &ip_forwarding_cmd); +	install_element(CONFIG_NODE, &no_ip_forwarding_cmd); +	install_element(ENABLE_NODE, &show_zebra_cmd); +	install_element(ENABLE_NODE, &show_zebra_client_cmd); +	install_element(ENABLE_NODE, &show_zebra_client_summary_cmd);  #ifdef HAVE_NETLINK -  install_element (VIEW_NODE, &show_table_cmd); -  install_element (CONFIG_NODE, &config_table_cmd); -  install_element (CONFIG_NODE, &no_config_table_cmd); +	install_element(VIEW_NODE, &show_table_cmd); +	install_element(CONFIG_NODE, &config_table_cmd); +	install_element(CONFIG_NODE, &no_config_table_cmd);  #endif /* HAVE_NETLINK */ -  install_element (VIEW_NODE, &show_ipv6_forwarding_cmd); -  install_element (CONFIG_NODE, &ipv6_forwarding_cmd); -  install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd); +	install_element(VIEW_NODE, &show_ipv6_forwarding_cmd); +	install_element(CONFIG_NODE, &ipv6_forwarding_cmd); +	install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd); -  /* Route-map */ -  zebra_route_map_init (); +	/* Route-map */ +	zebra_route_map_init();  }  /* Make zebra server socket, wiping any existing one (see bug #403). */ -void -zebra_zserv_socket_init (char *path) +void zebra_zserv_socket_init(char *path)  {  #ifdef HAVE_TCP_ZEBRA -  zebra_serv (); +	zebra_serv();  #else -  zebra_serv_un (path ? path : ZEBRA_SERV_PATH); +	zebra_serv_un(path ? path : ZEBRA_SERV_PATH);  #endif /* HAVE_TCP_ZEBRA */  }  | 
