📄 zserv.c
字号:
/* 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 GNU Zebra; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <zebra.h>#include "prefix.h"#include "command.h"#include "if.h"#include "thread.h"#include "stream.h"#include "memory.h"#include "table.h"#include "rib.h"#include "network.h"#include "sockunion.h"#include "log.h"#include "zclient.h"#include "zebra/zserv.h"#include "zebra/redistribute.h"#include "zebra/debug.h"#include "zebra/ipforward.h"/* Event list of zebra. */enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };/* Zebra client list. */list client_list;/* Default rtm_table for all clients */int rtm_table_default = 0;void zebra_event (enum event event, int sock, struct zserv *client);extern struct thread_master *master;/* For logging of zebra meesages. */char *zebra_command_str [] ={ "NULL", "ZEBRA_INTERFACE_ADD", "ZEBRA_INTERFACE_DELETE", "ZEBRA_INTERFACE_ADDRESS_ADD", "ZEBRA_INTERFACE_ADDRESS_DELETE", "ZEBRA_INTERFACE_UP", "ZEBRA_INTERFACE_DOWN", "ZEBRA_IPV4_ROUTE_ADD", "ZEBRA_IPV4_ROUTE_DELETE", "ZEBRA_IPV6_ROUTE_ADD", "ZEBRA_IPV6_ROUTE_DELETE", "ZEBRA_REDISTRIBUTE_ADD", "ZEBRA_REDISTRIBUTE_DELETE", "ZEBRA_REDISTRIBUTE_DEFAULT_ADD", "ZEBRA_REDISTRIBUTE_DEFAULT_DELETE", "ZEBRA_IPV4_NEXTHOP_LOOKUP", "ZEBRA_IPV6_NEXTHOP_LOOKUP", "ZEBRA_IPV4_IMPORT_LOOKUP", "ZEBRA_IPV6_IMPORT_LOOKUP"};struct zebra_message_queue{ struct nsm_message_queue *next; struct nsm_message_queue *prev; u_char *buf; u_int16_t length; u_int16_t written;};struct thread *t_write;struct fifo message_queue;intzebra_server_dequeue (struct thread *t){ int sock; int nbytes; struct zebra_message_queue *queue; sock = THREAD_FD (t); t_write = NULL; queue = (struct zebra_message_queue *) FIFO_HEAD (&message_queue); if (queue) { nbytes = write (sock, queue->buf + queue->written, queue->length - queue->written); if (nbytes <= 0) { if (errno != EAGAIN) return -1; } else if (nbytes != (queue->length - queue->written)) { queue->written += nbytes; } else { FIFO_DEL (queue); XFREE (MTYPE_TMP, queue->buf); XFREE (MTYPE_TMP, queue); } } if (FIFO_TOP (&message_queue)) THREAD_WRITE_ON (master, t_write, zebra_server_dequeue, NULL, sock); return 0;}/* Enqueu message. */voidzebra_server_enqueue (int sock, u_char *buf, unsigned long length, unsigned long written){ struct zebra_message_queue *queue; queue = XCALLOC (MTYPE_TMP, sizeof (struct zebra_message_queue)); queue->buf = XMALLOC (MTYPE_TMP, length); memcpy (queue->buf, buf, length); queue->length = length; queue->written = written; FIFO_ADD (&message_queue, queue); THREAD_WRITE_ON (master, t_write, zebra_server_dequeue, NULL, sock);}intzebra_server_send_message (int sock, u_char *buf, unsigned long length){ int nbytes; if (FIFO_TOP (&message_queue)) { zebra_server_enqueue (sock, buf, length, 0); return 0; } /* Send message. */ nbytes = write (sock, buf, length); if (nbytes <= 0) { if (errno == EAGAIN) zebra_server_enqueue (sock, buf, length, 0); else return -1; } else if (nbytes != length) zebra_server_enqueue (sock, buf, length, nbytes); return 0;}/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */intzsend_interface_add (struct zserv *client, struct interface *ifp){ struct stream *s; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Message type. */ stream_putc (s, ZEBRA_INTERFACE_ADD); /* Interface information. */ stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putl (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->bandwidth);#ifdef HAVE_SOCKADDR_DL stream_put (s, &ifp->sdl, sizeof (ifp->sdl));#else stream_putl (s, ifp->hw_addr_len); if (ifp->hw_addr_len) stream_put (s, ifp->hw_addr, ifp->hw_addr_len);#endif /* HAVE_SOCKADDR_DL */ /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}/* Interface deletion from zebra daemon. */intzsend_interface_delete (struct zserv *client, struct interface *ifp){ struct stream *s; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Packet length placeholder. */ stream_putw (s, 0); /* Interface information. */ stream_putc (s, ZEBRA_INTERFACE_DELETE); stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putl (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->bandwidth); /* Write packet length. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}/* Interface address is added. Send ZEBRA_INTERFACE_ADDRESS_ADD to the client. */intzsend_interface_address_add (struct zserv *client, struct interface *ifp, struct connected *ifc){ int blen; struct stream *s; struct prefix *p; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); stream_putc (s, ZEBRA_INTERFACE_ADDRESS_ADD); 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); 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)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}/* Interface address is deleted. Send ZEBRA_INTERFACE_ADDRESS_DELETE to the client. */intzsend_interface_address_delete (struct zserv *client, struct interface *ifp, struct connected *ifc){ int blen; struct stream *s; struct prefix *p; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); stream_putc (s, ZEBRA_INTERFACE_ADDRESS_DELETE); 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); 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)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}intzsend_interface_up (struct zserv *client, struct interface *ifp){ struct stream *s; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Zebra command. */ stream_putc (s, ZEBRA_INTERFACE_UP); /* Interface information. */ stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putl (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->bandwidth); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}intzsend_interface_down (struct zserv *client, struct interface *ifp){ struct stream *s; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Zebra command. */ stream_putc (s, ZEBRA_INTERFACE_DOWN); /* Interface information. */ stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putl (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->bandwidth); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}intzsend_ipv4_add_multipath (struct zserv *client, struct prefix *p, struct rib *rib){ int psize; struct stream *s; struct nexthop *nexthop; struct in_addr empty; empty.s_addr = 0; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Put command, type and nexthop. */ stream_putc (s, ZEBRA_IPV4_ROUTE_ADD); stream_putc (s, rib->type); stream_putc (s, rib->flags); stream_putc (s, ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_IFINDEX | ZAPI_MESSAGE_METRIC); /* Prefix. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *)&p->u.prefix, psize); /* Nexthop */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) { stream_putc (s, 1); if (nexthop->type == NEXTHOP_TYPE_IPV4 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) stream_put_in_addr (s, &nexthop->gate.ipv4); else stream_put_in_addr (s, &empty); /* Interface index. */ stream_putc (s, 1); stream_putl (s, nexthop->ifindex); break; } } /* Metric */ stream_putl (s, rib->metric); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}intzsend_ipv4_delete_multipath (struct zserv *client, struct prefix *p, struct rib *rib){ int psize; struct stream *s; struct nexthop *nexthop; struct in_addr empty; empty.s_addr = 0; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Put command, type and nexthop. */ stream_putc (s, ZEBRA_IPV4_ROUTE_DELETE); stream_putc (s, rib->type); stream_putc (s, rib->flags); stream_putc (s, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX); /* Prefix. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *)&p->u.prefix, psize); /* Nexthop */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) { stream_putc (s, 1); if (nexthop->type == NEXTHOP_TYPE_IPV4) stream_put_in_addr (s, &nexthop->gate.ipv4); else stream_put_in_addr (s, &empty); /* Interface index. */ stream_putc (s, 1); stream_putl (s, nexthop->ifindex); break; } } /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}intzsend_ipv4_add (struct zserv *client, int type, int flags, struct prefix_ipv4 *p, struct in_addr *nexthop, unsigned int ifindex){ int psize; struct stream *s; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Put command, type and nexthop. */ stream_putc (s, ZEBRA_IPV4_ROUTE_ADD); stream_putc (s, type); stream_putc (s, flags); stream_putc (s, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX); /* Prefix. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *)&p->prefix, psize); /* Nexthop */ stream_putc (s, 1); stream_put_in_addr (s, nexthop); /* Interface index. */ stream_putc (s, 1); stream_putl (s, ifindex); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}intzsend_ipv4_delete (struct zserv *client, int type, int flags, struct prefix_ipv4 *p, struct in_addr *nexthop, unsigned int ifindex){ int psize; struct stream *s; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Put command, type and nexthop. */ stream_putc (s, ZEBRA_IPV4_ROUTE_DELETE); stream_putc (s, type); stream_putc (s, flags); stream_putc (s, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX); /* Prefix. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *)&p->prefix, psize); /* Nexthop */ stream_putc (s, 1); stream_put_in_addr (s, nexthop); /* Interface index. */ stream_putc (s, 1); stream_putl (s, ifindex); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}#ifdef HAVE_IPV6intzsend_ipv6_add (struct zserv *client, int type, int flags, struct prefix_ipv6 *p, struct in6_addr *nexthop, unsigned int ifindex){ int psize; struct stream *s; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Put command, type and nexthop. */ stream_putc (s, ZEBRA_IPV6_ROUTE_ADD); stream_putc (s, type); stream_putc (s, flags); stream_putc (s, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX); /* Prefix. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *)&p->prefix, psize); /* Nexthop */ stream_putc (s, 1); stream_write (s, (u_char *)nexthop, 16); /* Interface index. */ stream_putc (s, 1); stream_putl (s, ifindex); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -