/* Zebra daemon server routine. * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; see the file COPYING; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include /* for basename */ #include #include "prefix.h" #include "command.h" #include "if.h" #include "thread.h" #include "stream.h" #include "memory.h" #include "zebra_memory.h" #include "table.h" #include "rib.h" #include "network.h" #include "sockunion.h" #include "log.h" #include "zclient.h" #include "privs.h" #include "network.h" #include "buffer.h" #include "nexthop.h" #include "vrf.h" #include "libfrr.h" #include "sockopt.h" #include "zebra/zserv.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" #include "zebra/router-id.h" #include "zebra/redistribute.h" #include "zebra/debug.h" #include "zebra/zebra_rnh.h" #include "zebra/rt_netlink.h" #include "zebra/interface.h" #include "zebra/zebra_ptm.h" #include "zebra/rtadv.h" #include "zebra/zebra_mpls.h" #include "zebra/zebra_mroute.h" #include "zebra/label_manager.h" #include "zebra/zebra_vxlan.h" #include "zebra/rt.h" #include "zebra/zebra_pbr.h" /* Event list of zebra. */ enum event { ZEBRA_READ, ZEBRA_WRITE }; /* privileges */ extern struct zebra_privs_t zserv_privs; /* post event into client */ static void zebra_event(struct zserv *client, enum event event); /* Public interface ======================================================== */ int zebra_server_send_message(struct zserv *client, struct stream *msg) { stream_fifo_push(client->obuf_fifo, msg); zebra_event(client, ZEBRA_WRITE); return 0; } /* Encoding helpers -------------------------------------------------------- */ 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; const char *netns_name = zvrf_ns_name(zvrf); data.l.table_id = zvrf->table_id; if (netns_name) strlcpy(data.l.netns_name, basename((char *)netns_name), NS_NAMSIZ); else memset(data.l.netns_name, 0, NS_NAMSIZ); /* Pass the tableid and the netns NAME */ 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 int zserv_encode_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; } /* Send handlers ----------------------------------------------------------- */ /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */ /* * This function is called in the following situations: * - in response to a 3-byte ZEBRA_INTERFACE_ADD request * from the client. * - at startup, when zebra figures out the available interfaces * - when an interface is added (where support for * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is * received) */ int zsend_interface_add(struct zserv *client, struct interface *ifp) { struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); zserv_encode_interface(s, ifp); client->ifadd_cnt++; return zebra_server_send_message(client, s); } /* Interface deletion from zebra daemon. */ int zsend_interface_delete(struct zserv *client, struct interface *ifp) { struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); zserv_encode_interface(s, ifp); client->ifdel_cnt++; return zebra_server_send_message(client, s); } int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf) { struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf)); zserv_encode_vrf(s, zvrf); client->vrfadd_cnt++; return zebra_server_send_message(client, s); } /* VRF deletion from zebra daemon. */ int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf) { struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf)); zserv_encode_vrf(s, zvrf); client->vrfdel_cnt++; return zebra_server_send_message(client, s); } int zsend_interface_link_params(struct zserv *client, struct interface *ifp) { struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); /* Check this client need interface information. */ if (!client->ifinfo) { stream_free(s); return 0; } if (!ifp->link_params) { stream_free(s); return 0; } zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); /* Add Interface Index */ stream_putl(s, ifp->ifindex); /* Then TE Link Parameters */ if (zebra_interface_link_params_write(s, ifp) == 0) { stream_free(s); return 0; } /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); return zebra_server_send_message(client, s); } /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or * 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 * from the client, after the ZEBRA_INTERFACE_ADD has been * sent from zebra to the client * - redistribute new address info to all clients in the following situations * - at startup, when zebra figures out the available interfaces * - when an interface is added (where support for * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is * received) * - for the vty commands "ip address A.B.C.D/M [|