blob: bee1a9470ecf2bf65228a0e563196b8c4c8fd6e1 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* zebra client
2 Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#include <zebra.h>
22
23#include "command.h"
24#include "stream.h"
25#include "network.h"
26#include "prefix.h"
27#include "log.h"
28#include "sockunion.h"
29#include "zclient.h"
30#include "routemap.h"
31#include "thread.h"
Donald Sharp04907292016-01-07 10:03:01 -050032#include "filter.h"
paul718e3742002-12-13 20:15:29 +000033
34#include "bgpd/bgpd.h"
35#include "bgpd/bgp_route.h"
36#include "bgpd/bgp_attr.h"
37#include "bgpd/bgp_nexthop.h"
38#include "bgpd/bgp_zebra.h"
39#include "bgpd/bgp_fsm.h"
Andrew J. Schorra39275d2006-11-30 16:36:57 +000040#include "bgpd/bgp_debug.h"
Josh Bailey8196f132011-07-20 20:47:07 -070041#include "bgpd/bgp_mpath.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020042
paul718e3742002-12-13 20:15:29 +000043/* All information about zebra. */
Chris Caputo228da422009-07-18 05:44:03 +000044struct zclient *zclient = NULL;
hasso18a6dce2004-10-03 18:18:34 +000045struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000046
Josh Bailey8196f132011-07-20 20:47:07 -070047/* Growable buffer for nexthops sent to zebra */
48struct stream *bgp_nexthop_buf = NULL;
49
hasso18a6dce2004-10-03 18:18:34 +000050/* Router-id update message from zebra. */
paul94f2b392005-06-28 12:44:16 +000051static int
Feng Luc99f3482014-10-16 09:52:36 +080052bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
53 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000054{
hasso18a6dce2004-10-03 18:18:34 +000055 struct prefix router_id;
paul1eb8ef22005-04-07 07:30:20 +000056 struct listnode *node, *nnode;
hasso18a6dce2004-10-03 18:18:34 +000057 struct bgp *bgp;
paul718e3742002-12-13 20:15:29 +000058
hasso18a6dce2004-10-03 18:18:34 +000059 zebra_router_id_update_read(zclient->ibuf,&router_id);
Andrew J. Schorra39275d2006-11-30 16:36:57 +000060
61 if (BGP_DEBUG(zebra, ZEBRA))
62 {
63 char buf[128];
64 prefix2str(&router_id, buf, sizeof(buf));
65 zlog_debug("Zebra rcvd: router id update %s", buf);
66 }
67
hasso18a6dce2004-10-03 18:18:34 +000068 router_id_zebra = router_id.u.prefix4;
69
paul1eb8ef22005-04-07 07:30:20 +000070 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +000071 {
hasso18a6dce2004-10-03 18:18:34 +000072 if (!bgp->router_id_static.s_addr)
paul1eb8ef22005-04-07 07:30:20 +000073 bgp_router_id_set (bgp, &router_id.u.prefix4);
paul718e3742002-12-13 20:15:29 +000074 }
paul718e3742002-12-13 20:15:29 +000075
paul718e3742002-12-13 20:15:29 +000076 return 0;
77}
78
79/* Inteface addition message from zebra. */
paul94f2b392005-06-28 12:44:16 +000080static int
Feng Luc99f3482014-10-16 09:52:36 +080081bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
82 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000083{
84 struct interface *ifp;
85
Feng Luc99f3482014-10-16 09:52:36 +080086 ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +000087
Andrew J. Schorra39275d2006-11-30 16:36:57 +000088 if (BGP_DEBUG(zebra, ZEBRA) && ifp)
89 zlog_debug("Zebra rcvd: interface add %s", ifp->name);
90
paul718e3742002-12-13 20:15:29 +000091 return 0;
92}
93
paul94f2b392005-06-28 12:44:16 +000094static int
paul718e3742002-12-13 20:15:29 +000095bgp_interface_delete (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +080096 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000097{
98 struct stream *s;
99 struct interface *ifp;
100
101 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800102 ifp = zebra_interface_state_read (s, vrf_id);
ajsd2fc8892005-04-02 18:38:43 +0000103 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000104
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000105 if (BGP_DEBUG(zebra, ZEBRA))
106 zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
107
paul718e3742002-12-13 20:15:29 +0000108 return 0;
109}
110
paul94f2b392005-06-28 12:44:16 +0000111static int
Feng Luc99f3482014-10-16 09:52:36 +0800112bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length,
113 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000114{
115 struct stream *s;
116 struct interface *ifp;
117 struct connected *c;
paul1eb8ef22005-04-07 07:30:20 +0000118 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000119
120 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800121 ifp = zebra_interface_state_read (s, vrf_id);
paul718e3742002-12-13 20:15:29 +0000122
123 if (! ifp)
124 return 0;
125
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000126 if (BGP_DEBUG(zebra, ZEBRA))
127 zlog_debug("Zebra rcvd: interface %s up", ifp->name);
128
paul1eb8ef22005-04-07 07:30:20 +0000129 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
130 bgp_connected_add (c);
paul718e3742002-12-13 20:15:29 +0000131
132 return 0;
133}
134
paul94f2b392005-06-28 12:44:16 +0000135static int
Feng Luc99f3482014-10-16 09:52:36 +0800136bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
137 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000138{
139 struct stream *s;
140 struct interface *ifp;
141 struct connected *c;
paul1eb8ef22005-04-07 07:30:20 +0000142 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000143
144 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800145 ifp = zebra_interface_state_read (s, vrf_id);
paul718e3742002-12-13 20:15:29 +0000146 if (! ifp)
147 return 0;
148
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000149 if (BGP_DEBUG(zebra, ZEBRA))
150 zlog_debug("Zebra rcvd: interface %s down", ifp->name);
151
paul1eb8ef22005-04-07 07:30:20 +0000152 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
153 bgp_connected_delete (c);
paul718e3742002-12-13 20:15:29 +0000154
Pradosh Mohapatra8da86892013-09-11 03:33:55 +0000155 /* Fast external-failover */
paul718e3742002-12-13 20:15:29 +0000156 {
paul1eb8ef22005-04-07 07:30:20 +0000157 struct listnode *mnode;
paul718e3742002-12-13 20:15:29 +0000158 struct bgp *bgp;
159 struct peer *peer;
paul718e3742002-12-13 20:15:29 +0000160
paul1eb8ef22005-04-07 07:30:20 +0000161 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
paul718e3742002-12-13 20:15:29 +0000162 {
163 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
164 continue;
165
paul1eb8ef22005-04-07 07:30:20 +0000166 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000167 {
Pradosh Mohapatra8da86892013-09-11 03:33:55 +0000168 if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
paul718e3742002-12-13 20:15:29 +0000169 continue;
170
Pradosh Mohapatra8da86892013-09-11 03:33:55 +0000171 if (ifp == peer->nexthop.ifp)
paul718e3742002-12-13 20:15:29 +0000172 BGP_EVENT_ADD (peer, BGP_Stop);
173 }
174 }
175 }
176
177 return 0;
178}
179
paul94f2b392005-06-28 12:44:16 +0000180static int
paul718e3742002-12-13 20:15:29 +0000181bgp_interface_address_add (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800182 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000183{
184 struct connected *ifc;
185
Feng Luc99f3482014-10-16 09:52:36 +0800186 ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000187
188 if (ifc == NULL)
189 return 0;
190
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000191 if (BGP_DEBUG(zebra, ZEBRA))
192 {
193 char buf[128];
194 prefix2str(ifc->address, buf, sizeof(buf));
195 zlog_debug("Zebra rcvd: interface %s address add %s",
196 ifc->ifp->name, buf);
197 }
198
paul2e3b2e42002-12-13 21:03:13 +0000199 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000200 bgp_connected_add (ifc);
201
202 return 0;
203}
204
paul94f2b392005-06-28 12:44:16 +0000205static int
paul718e3742002-12-13 20:15:29 +0000206bgp_interface_address_delete (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800207 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000208{
209 struct connected *ifc;
210
Feng Luc99f3482014-10-16 09:52:36 +0800211 ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000212
213 if (ifc == NULL)
214 return 0;
215
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000216 if (BGP_DEBUG(zebra, ZEBRA))
217 {
218 char buf[128];
219 prefix2str(ifc->address, buf, sizeof(buf));
220 zlog_debug("Zebra rcvd: interface %s address delete %s",
221 ifc->ifp->name, buf);
222 }
223
paul2e3b2e42002-12-13 21:03:13 +0000224 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000225 bgp_connected_delete (ifc);
226
227 connected_free (ifc);
228
229 return 0;
230}
231
232/* Zebra route add and delete treatment. */
paul94f2b392005-06-28 12:44:16 +0000233static int
Feng Luc99f3482014-10-16 09:52:36 +0800234zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
235 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000236{
237 struct stream *s;
238 struct zapi_ipv4 api;
paul718e3742002-12-13 20:15:29 +0000239 struct in_addr nexthop;
240 struct prefix_ipv4 p;
241
242 s = zclient->ibuf;
paul718e3742002-12-13 20:15:29 +0000243 nexthop.s_addr = 0;
244
245 /* Type, flags, message. */
246 api.type = stream_getc (s);
247 api.flags = stream_getc (s);
248 api.message = stream_getc (s);
249
250 /* IPv4 prefix. */
251 memset (&p, 0, sizeof (struct prefix_ipv4));
252 p.family = AF_INET;
Paul Jakmabf83fa22016-02-09 15:23:03 +0000253 p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (s));
paul718e3742002-12-13 20:15:29 +0000254 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
255
256 /* Nexthop, ifindex, distance, metric. */
257 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
258 {
259 api.nexthop_num = stream_getc (s);
260 nexthop.s_addr = stream_get_ipv4 (s);
261 }
262 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
263 {
264 api.ifindex_num = stream_getc (s);
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400265 stream_getl (s); /* ifindex, unused */
paul718e3742002-12-13 20:15:29 +0000266 }
267 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
268 api.distance = stream_getc (s);
269 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
270 api.metric = stream_getl (s);
271 else
272 api.metric = 0;
273
274 if (command == ZEBRA_IPV4_ROUTE_ADD)
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000275 {
276 if (BGP_DEBUG(zebra, ZEBRA))
277 {
278 char buf[2][INET_ADDRSTRLEN];
279 zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
280 zebra_route_string(api.type),
281 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
282 p.prefixlen,
283 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
284 api.metric);
285 }
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400286 bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL,
287 api.metric, api.type);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000288 }
paul718e3742002-12-13 20:15:29 +0000289 else
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000290 {
291 if (BGP_DEBUG(zebra, ZEBRA))
292 {
293 char buf[2][INET_ADDRSTRLEN];
294 zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d "
295 "nexthop %s metric %u",
296 zebra_route_string(api.type),
297 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
298 p.prefixlen,
299 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
300 api.metric);
301 }
302 bgp_redistribute_delete((struct prefix *)&p, api.type);
303 }
paul718e3742002-12-13 20:15:29 +0000304
305 return 0;
306}
307
paul718e3742002-12-13 20:15:29 +0000308/* Zebra route add and delete treatment. */
paul94f2b392005-06-28 12:44:16 +0000309static int
Feng Luc99f3482014-10-16 09:52:36 +0800310zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length,
311 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000312{
313 struct stream *s;
314 struct zapi_ipv6 api;
paul718e3742002-12-13 20:15:29 +0000315 struct in6_addr nexthop;
316 struct prefix_ipv6 p;
317
318 s = zclient->ibuf;
paul718e3742002-12-13 20:15:29 +0000319 memset (&nexthop, 0, sizeof (struct in6_addr));
320
321 /* Type, flags, message. */
322 api.type = stream_getc (s);
323 api.flags = stream_getc (s);
324 api.message = stream_getc (s);
325
326 /* IPv6 prefix. */
327 memset (&p, 0, sizeof (struct prefix_ipv6));
328 p.family = AF_INET6;
Paul Jakmabf83fa22016-02-09 15:23:03 +0000329 p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc (s));
paul718e3742002-12-13 20:15:29 +0000330 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
331
332 /* Nexthop, ifindex, distance, metric. */
333 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
334 {
335 api.nexthop_num = stream_getc (s);
336 stream_get (&nexthop, s, 16);
337 }
338 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
339 {
340 api.ifindex_num = stream_getc (s);
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400341 stream_getl (s); /* ifindex, unused */
paul718e3742002-12-13 20:15:29 +0000342 }
343 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
344 api.distance = stream_getc (s);
345 else
346 api.distance = 0;
347 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
348 api.metric = stream_getl (s);
349 else
350 api.metric = 0;
351
352 /* Simply ignore link-local address. */
353 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
354 return 0;
355
356 if (command == ZEBRA_IPV6_ROUTE_ADD)
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000357 {
358 if (BGP_DEBUG(zebra, ZEBRA))
359 {
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400360 char buf[2][INET6_ADDRSTRLEN];
361 zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000362 zebra_route_string(api.type),
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400363 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
364 p.prefixlen,
365 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
366 api.metric);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000367 }
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400368 bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
369 api.metric, api.type);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000370 }
paul718e3742002-12-13 20:15:29 +0000371 else
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000372 {
373 if (BGP_DEBUG(zebra, ZEBRA))
374 {
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400375 char buf[2][INET6_ADDRSTRLEN];
376 zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d "
377 "nexthop %s metric %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000378 zebra_route_string(api.type),
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400379 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
380 p.prefixlen,
381 inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])),
382 api.metric);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000383 }
384 bgp_redistribute_delete ((struct prefix *) &p, api.type);
385 }
paul718e3742002-12-13 20:15:29 +0000386
387 return 0;
388}
David Lamparter6b0655a2014-06-04 06:53:35 +0200389
paul718e3742002-12-13 20:15:29 +0000390struct interface *
391if_lookup_by_ipv4 (struct in_addr *addr)
392{
hasso52dc7ee2004-09-23 19:18:23 +0000393 struct listnode *ifnode;
394 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000395 struct interface *ifp;
396 struct connected *connected;
397 struct prefix_ipv4 p;
398 struct prefix *cp;
399
400 p.family = AF_INET;
401 p.prefix = *addr;
402 p.prefixlen = IPV4_MAX_BITLEN;
403
paul1eb8ef22005-04-07 07:30:20 +0000404 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000405 {
paul1eb8ef22005-04-07 07:30:20 +0000406 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000407 {
paul718e3742002-12-13 20:15:29 +0000408 cp = connected->address;
409
410 if (cp->family == AF_INET)
411 if (prefix_match (cp, (struct prefix *)&p))
412 return ifp;
413 }
414 }
415 return NULL;
416}
417
418struct interface *
419if_lookup_by_ipv4_exact (struct in_addr *addr)
420{
hasso52dc7ee2004-09-23 19:18:23 +0000421 struct listnode *ifnode;
422 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000423 struct interface *ifp;
424 struct connected *connected;
425 struct prefix *cp;
426
paul1eb8ef22005-04-07 07:30:20 +0000427 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000428 {
paul1eb8ef22005-04-07 07:30:20 +0000429 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000430 {
paul718e3742002-12-13 20:15:29 +0000431 cp = connected->address;
432
433 if (cp->family == AF_INET)
434 if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
435 return ifp;
436 }
437 }
438 return NULL;
439}
440
paul718e3742002-12-13 20:15:29 +0000441struct interface *
442if_lookup_by_ipv6 (struct in6_addr *addr)
443{
hasso52dc7ee2004-09-23 19:18:23 +0000444 struct listnode *ifnode;
445 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000446 struct interface *ifp;
447 struct connected *connected;
448 struct prefix_ipv6 p;
449 struct prefix *cp;
450
451 p.family = AF_INET6;
452 p.prefix = *addr;
453 p.prefixlen = IPV6_MAX_BITLEN;
454
paul1eb8ef22005-04-07 07:30:20 +0000455 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000456 {
paul1eb8ef22005-04-07 07:30:20 +0000457 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000458 {
paul718e3742002-12-13 20:15:29 +0000459 cp = connected->address;
460
461 if (cp->family == AF_INET6)
462 if (prefix_match (cp, (struct prefix *)&p))
463 return ifp;
464 }
465 }
466 return NULL;
467}
468
469struct interface *
470if_lookup_by_ipv6_exact (struct in6_addr *addr)
471{
hasso52dc7ee2004-09-23 19:18:23 +0000472 struct listnode *ifnode;
473 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000474 struct interface *ifp;
475 struct connected *connected;
476 struct prefix *cp;
477
paul1eb8ef22005-04-07 07:30:20 +0000478 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000479 {
paul1eb8ef22005-04-07 07:30:20 +0000480 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000481 {
paul718e3742002-12-13 20:15:29 +0000482 cp = connected->address;
483
484 if (cp->family == AF_INET6)
485 if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
486 return ifp;
487 }
488 }
489 return NULL;
490}
491
paul94f2b392005-06-28 12:44:16 +0000492static int
paul718e3742002-12-13 20:15:29 +0000493if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
494{
hasso52dc7ee2004-09-23 19:18:23 +0000495 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000496 struct connected *connected;
497 struct prefix *cp;
498
paul1eb8ef22005-04-07 07:30:20 +0000499 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000500 {
paul718e3742002-12-13 20:15:29 +0000501 cp = connected->address;
502
503 if (cp->family == AF_INET6)
504 if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
505 {
506 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
507 return 1;
508 }
509 }
510 return 0;
511}
512
paul94f2b392005-06-28 12:44:16 +0000513static int
paul718e3742002-12-13 20:15:29 +0000514if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
515{
hasso52dc7ee2004-09-23 19:18:23 +0000516 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000517 struct connected *connected;
518 struct prefix *cp;
519
paul1eb8ef22005-04-07 07:30:20 +0000520 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000521 {
paul718e3742002-12-13 20:15:29 +0000522 cp = connected->address;
523
524 if (cp->family == AF_INET6)
525 if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
526 {
527 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
528 return 1;
529 }
530 }
531 return 0;
532}
paul718e3742002-12-13 20:15:29 +0000533
Pradosh Mohapatra6ee06fa2014-01-12 18:30:13 +0000534static int
535if_get_ipv4_address (struct interface *ifp, struct in_addr *addr)
536{
537 struct listnode *cnode;
538 struct connected *connected;
539 struct prefix *cp;
540
541 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
542 {
543 cp = connected->address;
544 if ((cp->family == AF_INET) && !ipv4_martian(&(cp->u.prefix4)))
545 {
546 *addr = cp->u.prefix4;
547 return 1;
548 }
549 }
550 return 0;
551}
552
paul718e3742002-12-13 20:15:29 +0000553int
554bgp_nexthop_set (union sockunion *local, union sockunion *remote,
555 struct bgp_nexthop *nexthop, struct peer *peer)
556{
557 int ret = 0;
558 struct interface *ifp = NULL;
559
560 memset (nexthop, 0, sizeof (struct bgp_nexthop));
561
562 if (!local)
563 return -1;
564 if (!remote)
565 return -1;
566
567 if (local->sa.sa_family == AF_INET)
568 {
569 nexthop->v4 = local->sin.sin_addr;
570 ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
571 }
paul718e3742002-12-13 20:15:29 +0000572 if (local->sa.sa_family == AF_INET6)
573 {
574 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
575 {
576 if (peer->ifname)
Feng Lu395828e2015-05-22 11:39:55 +0200577 ifp = if_lookup_by_name (peer->ifname);
paul718e3742002-12-13 20:15:29 +0000578 }
579 else
580 ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
581 }
paul718e3742002-12-13 20:15:29 +0000582
583 if (!ifp)
584 return -1;
585
586 nexthop->ifp = ifp;
587
588 /* IPv4 connection. */
589 if (local->sa.sa_family == AF_INET)
590 {
paul718e3742002-12-13 20:15:29 +0000591 /* IPv6 nexthop*/
592 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
593
594 /* There is no global nexthop. */
595 if (!ret)
596 if_get_ipv6_local (ifp, &nexthop->v6_global);
597 else
598 if_get_ipv6_local (ifp, &nexthop->v6_local);
paul718e3742002-12-13 20:15:29 +0000599 }
600
paul718e3742002-12-13 20:15:29 +0000601 /* IPv6 connection. */
602 if (local->sa.sa_family == AF_INET6)
603 {
604 struct interface *direct = NULL;
605
Pradosh Mohapatra6ee06fa2014-01-12 18:30:13 +0000606 /* IPv4 nexthop. */
607 ret = if_get_ipv4_address(ifp, &nexthop->v4);
608 if (!ret && peer->local_id.s_addr)
paul718e3742002-12-13 20:15:29 +0000609 nexthop->v4 = peer->local_id;
610
611 /* Global address*/
612 if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
613 {
614 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
615 IPV6_MAX_BYTELEN);
616
617 /* If directory connected set link-local address. */
618 direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
619 if (direct)
620 if_get_ipv6_local (ifp, &nexthop->v6_local);
621 }
622 else
623 /* Link-local address. */
624 {
625 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
626
627 /* If there is no global address. Set link-local address as
628 global. I know this break RFC specification... */
629 if (!ret)
630 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
631 IPV6_MAX_BYTELEN);
632 else
633 memcpy (&nexthop->v6_local, &local->sin6.sin6_addr,
634 IPV6_MAX_BYTELEN);
635 }
636 }
637
638 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
639 if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
640 peer->shared_network = 1;
641 else
642 peer->shared_network = 0;
643
644 /* KAME stack specific treatment. */
645#ifdef KAME
646 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
647 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
648 {
649 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
650 }
651 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
652 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
653 {
654 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
655 }
656#endif /* KAME */
paul718e3742002-12-13 20:15:29 +0000657 return ret;
658}
659
paul718e3742002-12-13 20:15:29 +0000660void
G.Balaji5a616c02011-11-26 21:58:42 +0400661bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi)
paul718e3742002-12-13 20:15:29 +0000662{
663 int flags;
664 u_char distance;
665 struct peer *peer;
Josh Bailey8196f132011-07-20 20:47:07 -0700666 struct bgp_info *mpinfo;
667 size_t oldsize, newsize;
paul718e3742002-12-13 20:15:29 +0000668
669 if (zclient->sock < 0)
670 return;
671
Feng Luc99f3482014-10-16 09:52:36 +0800672 if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000673 return;
674
675 flags = 0;
676 peer = info->peer;
677
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000678 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +0000679 {
680 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
681 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
682 }
683
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000684 if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
hasso6ffd2072005-02-02 14:50:11 +0000685 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000686 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
687
Josh Bailey8196f132011-07-20 20:47:07 -0700688 /* resize nexthop buffer size if necessary */
689 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
690 (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1)))
691 {
692 newsize = (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1));
693 newsize = stream_resize (bgp_nexthop_buf, newsize);
694 if (newsize == oldsize)
695 {
696 zlog_err ("can't resize nexthop buffer");
697 return;
698 }
699 }
700
701 stream_reset (bgp_nexthop_buf);
702
paul718e3742002-12-13 20:15:29 +0000703 if (p->family == AF_INET)
704 {
705 struct zapi_ipv4 api;
706 struct in_addr *nexthop;
707
Feng Luc99f3482014-10-16 09:52:36 +0800708 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000709 api.flags = flags;
710 nexthop = &info->attr->nexthop;
Josh Bailey8196f132011-07-20 20:47:07 -0700711 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
712 for (mpinfo = bgp_info_mpath_first (info); mpinfo;
713 mpinfo = bgp_info_mpath_next (mpinfo))
714 {
715 nexthop = &mpinfo->attr->nexthop;
716 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
717 }
paul718e3742002-12-13 20:15:29 +0000718
719 api.type = ZEBRA_ROUTE_BGP;
720 api.message = 0;
G.Balaji5a616c02011-11-26 21:58:42 +0400721 api.safi = safi;
paul718e3742002-12-13 20:15:29 +0000722 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
Josh Bailey8196f132011-07-20 20:47:07 -0700723 api.nexthop_num = 1 + bgp_info_mpath_count (info);
724 api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
paul718e3742002-12-13 20:15:29 +0000725 api.ifindex_num = 0;
726 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
727 api.metric = info->attr->med;
728
729 distance = bgp_distance_apply (p, info, bgp);
730
731 if (distance)
732 {
733 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
734 api.distance = distance;
735 }
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000736
737 if (BGP_DEBUG(zebra, ZEBRA))
738 {
Josh Bailey8196f132011-07-20 20:47:07 -0700739 int i;
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000740 char buf[2][INET_ADDRSTRLEN];
Josh Bailey8196f132011-07-20 20:47:07 -0700741 zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u"
742 " count %d",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000743 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
744 p->prefixlen,
Josh Bailey8196f132011-07-20 20:47:07 -0700745 inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])),
746 api.metric, api.nexthop_num);
747 for (i = 1; i < api.nexthop_num; i++)
748 zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s",
749 i, inet_ntop(AF_INET, api.nexthop[i], buf[1],
750 sizeof(buf[1])));
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000751 }
752
paul0a589352004-05-08 11:48:26 +0000753 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
754 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000755 }
Lou Berger205e6742016-01-12 13:42:11 -0500756
paul718e3742002-12-13 20:15:29 +0000757 /* We have to think about a IPv6 link-local address curse. */
758 if (p->family == AF_INET6)
759 {
Paul Jakma9099f9b2016-01-18 10:12:10 +0000760 ifindex_t ifindex;
paul718e3742002-12-13 20:15:29 +0000761 struct in6_addr *nexthop;
762 struct zapi_ipv6 api;
763
764 ifindex = 0;
765 nexthop = NULL;
Paul Jakmafb982c22007-05-04 20:15:47 +0000766
767 assert (info->attr->extra);
768
paul718e3742002-12-13 20:15:29 +0000769 /* Only global address nexthop exists. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000770 if (info->attr->extra->mp_nexthop_len == 16)
771 nexthop = &info->attr->extra->mp_nexthop_global;
paul718e3742002-12-13 20:15:29 +0000772
773 /* If both global and link-local address present. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000774 if (info->attr->extra->mp_nexthop_len == 32)
paul718e3742002-12-13 20:15:29 +0000775 {
776 /* Workaround for Cisco's nexthop bug. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000777 if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
paul718e3742002-12-13 20:15:29 +0000778 && peer->su_remote->sa.sa_family == AF_INET6)
779 nexthop = &peer->su_remote->sin6.sin6_addr;
780 else
Paul Jakmafb982c22007-05-04 20:15:47 +0000781 nexthop = &info->attr->extra->mp_nexthop_local;
paul718e3742002-12-13 20:15:29 +0000782
783 if (info->peer->nexthop.ifp)
784 ifindex = info->peer->nexthop.ifp->ifindex;
785 }
786
787 if (nexthop == NULL)
788 return;
789
790 if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
791 {
792 if (info->peer->ifname)
Feng Lu395828e2015-05-22 11:39:55 +0200793 ifindex = ifname2ifindex (info->peer->ifname);
paul718e3742002-12-13 20:15:29 +0000794 else if (info->peer->nexthop.ifp)
795 ifindex = info->peer->nexthop.ifp->ifindex;
796 }
797
798 /* Make Zebra API structure. */
Feng Luc99f3482014-10-16 09:52:36 +0800799 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000800 api.flags = flags;
801 api.type = ZEBRA_ROUTE_BGP;
802 api.message = 0;
G.Balajic7ec1792011-11-26 22:04:05 +0400803 api.safi = safi;
paul718e3742002-12-13 20:15:29 +0000804 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
805 api.nexthop_num = 1;
806 api.nexthop = &nexthop;
807 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
808 api.ifindex_num = 1;
809 api.ifindex = &ifindex;
810 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
811 api.metric = info->attr->med;
812
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000813 if (BGP_DEBUG(zebra, ZEBRA))
814 {
815 char buf[2][INET6_ADDRSTRLEN];
816 zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u",
817 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
818 p->prefixlen,
819 inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
820 api.metric);
821 }
822
paul0a589352004-05-08 11:48:26 +0000823 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
824 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000825 }
paul718e3742002-12-13 20:15:29 +0000826}
827
828void
G.Balaji5a616c02011-11-26 21:58:42 +0400829bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
paul718e3742002-12-13 20:15:29 +0000830{
831 int flags;
832 struct peer *peer;
833
834 if (zclient->sock < 0)
835 return;
836
Feng Luc99f3482014-10-16 09:52:36 +0800837 if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000838 return;
839
840 peer = info->peer;
841 flags = 0;
842
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000843 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000844 {
845 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
846 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
847 }
848
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000849 if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
hasso6ffd2072005-02-02 14:50:11 +0000850 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000851 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
852
853 if (p->family == AF_INET)
854 {
855 struct zapi_ipv4 api;
paul718e3742002-12-13 20:15:29 +0000856
Feng Luc99f3482014-10-16 09:52:36 +0800857 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000858 api.flags = flags;
paul718e3742002-12-13 20:15:29 +0000859
860 api.type = ZEBRA_ROUTE_BGP;
861 api.message = 0;
G.Balaji5a616c02011-11-26 21:58:42 +0400862 api.safi = safi;
Paul Jakma64e0ac22015-11-18 16:00:54 +0000863 api.nexthop_num = 0;
paul718e3742002-12-13 20:15:29 +0000864 api.ifindex_num = 0;
865 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
866 api.metric = info->attr->med;
867
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000868 if (BGP_DEBUG(zebra, ZEBRA))
869 {
870 char buf[2][INET_ADDRSTRLEN];
Paul Jakma64e0ac22015-11-18 16:00:54 +0000871 zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000872 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
873 p->prefixlen,
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000874 api.metric);
875 }
876
paul0a589352004-05-08 11:48:26 +0000877 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
878 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000879 }
Lou Berger205e6742016-01-12 13:42:11 -0500880
paul718e3742002-12-13 20:15:29 +0000881 /* We have to think about a IPv6 link-local address curse. */
882 if (p->family == AF_INET6)
883 {
884 struct zapi_ipv6 api;
Paul Jakmafb982c22007-05-04 20:15:47 +0000885
Feng Luc99f3482014-10-16 09:52:36 +0800886 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000887 api.flags = flags;
888 api.type = ZEBRA_ROUTE_BGP;
889 api.message = 0;
G.Balajic7ec1792011-11-26 22:04:05 +0400890 api.safi = safi;
Paul Jakma64e0ac22015-11-18 16:00:54 +0000891 api.nexthop_num = 0;
892 api.ifindex_num = 0;
paul718e3742002-12-13 20:15:29 +0000893 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
894 api.metric = info->attr->med;
895
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000896 if (BGP_DEBUG(zebra, ZEBRA))
897 {
898 char buf[2][INET6_ADDRSTRLEN];
Paul Jakma64e0ac22015-11-18 16:00:54 +0000899 zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000900 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
901 p->prefixlen,
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000902 api.metric);
903 }
904
paul0a589352004-05-08 11:48:26 +0000905 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
906 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000907 }
paul718e3742002-12-13 20:15:29 +0000908}
David Lamparter6b0655a2014-06-04 06:53:35 +0200909
paul718e3742002-12-13 20:15:29 +0000910/* Other routes redistribution into BGP. */
911int
912bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
913{
914 /* Set flag to BGP instance. */
915 bgp->redist[afi][type] = 1;
916
917 /* Return if already redistribute flag is set. */
Feng Luc99f3482014-10-16 09:52:36 +0800918 if (vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000919 return CMD_WARNING;
920
Feng Luc99f3482014-10-16 09:52:36 +0800921 vrf_bitmap_set (zclient->redist[type], VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000922
923 /* Return if zebra connection is not established. */
924 if (zclient->sock < 0)
925 return CMD_WARNING;
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000926
927 if (BGP_DEBUG(zebra, ZEBRA))
928 zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
paul718e3742002-12-13 20:15:29 +0000929
930 /* Send distribute add message to zebra. */
Feng Luc99f3482014-10-16 09:52:36 +0800931 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000932
933 return CMD_SUCCESS;
934}
935
936/* Redistribute with route-map specification. */
937int
paulfd79ac92004-10-13 05:06:08 +0000938bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
939 const char *name)
paul718e3742002-12-13 20:15:29 +0000940{
941 if (bgp->rmap[afi][type].name
942 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
943 return 0;
944
945 if (bgp->rmap[afi][type].name)
946 free (bgp->rmap[afi][type].name);
947 bgp->rmap[afi][type].name = strdup (name);
948 bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
949
950 return 1;
951}
952
953/* Redistribute with metric specification. */
954int
955bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
956 u_int32_t metric)
957{
958 if (bgp->redist_metric_flag[afi][type]
959 && bgp->redist_metric[afi][type] == metric)
960 return 0;
961
962 bgp->redist_metric_flag[afi][type] = 1;
963 bgp->redist_metric[afi][type] = metric;
964
965 return 1;
966}
967
968/* Unset redistribution. */
969int
970bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
971{
972 /* Unset flag from BGP instance. */
973 bgp->redist[afi][type] = 0;
974
975 /* Unset route-map. */
976 if (bgp->rmap[afi][type].name)
977 free (bgp->rmap[afi][type].name);
978 bgp->rmap[afi][type].name = NULL;
979 bgp->rmap[afi][type].map = NULL;
980
981 /* Unset metric. */
982 bgp->redist_metric_flag[afi][type] = 0;
983 bgp->redist_metric[afi][type] = 0;
984
985 /* Return if zebra connection is disabled. */
Feng Luc99f3482014-10-16 09:52:36 +0800986 if (! vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000987 return CMD_WARNING;
Feng Luc99f3482014-10-16 09:52:36 +0800988 vrf_bitmap_unset (zclient->redist[type], VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000989
990 if (bgp->redist[AFI_IP][type] == 0
991 && bgp->redist[AFI_IP6][type] == 0
992 && zclient->sock >= 0)
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000993 {
994 /* Send distribute delete message to zebra. */
995 if (BGP_DEBUG(zebra, ZEBRA))
996 zlog_debug("Zebra send: redistribute delete %s",
997 zebra_route_string(type));
Feng Luc99f3482014-10-16 09:52:36 +0800998 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type,
999 VRF_DEFAULT);
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001000 }
paul718e3742002-12-13 20:15:29 +00001001
1002 /* Withdraw redistributed routes from current BGP's routing table. */
1003 bgp_redistribute_withdraw (bgp, afi, type);
1004
1005 return CMD_SUCCESS;
1006}
1007
1008/* Unset redistribution route-map configuration. */
1009int
1010bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
1011{
1012 if (! bgp->rmap[afi][type].name)
1013 return 0;
1014
1015 /* Unset route-map. */
1016 free (bgp->rmap[afi][type].name);
1017 bgp->rmap[afi][type].name = NULL;
1018 bgp->rmap[afi][type].map = NULL;
1019
1020 return 1;
1021}
1022
1023/* Unset redistribution metric configuration. */
1024int
1025bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
1026{
1027 if (! bgp->redist_metric_flag[afi][type])
1028 return 0;
1029
1030 /* Unset metric. */
1031 bgp->redist_metric_flag[afi][type] = 0;
1032 bgp->redist_metric[afi][type] = 0;
1033
1034 return 1;
1035}
David Lamparter6b0655a2014-06-04 06:53:35 +02001036
paul718e3742002-12-13 20:15:29 +00001037void
paul94f2b392005-06-28 12:44:16 +00001038bgp_zclient_reset (void)
paul718e3742002-12-13 20:15:29 +00001039{
1040 zclient_reset (zclient);
1041}
1042
Feng Luc99f3482014-10-16 09:52:36 +08001043static void
1044bgp_zebra_connected (struct zclient *zclient)
1045{
1046 zclient_send_requests (zclient, VRF_DEFAULT);
1047}
1048
paul718e3742002-12-13 20:15:29 +00001049void
Donald Sharp71252932015-09-24 09:25:19 -04001050bgp_zebra_init (struct thread_master *master)
paul718e3742002-12-13 20:15:29 +00001051{
1052 /* Set default values. */
Donald Sharp71252932015-09-24 09:25:19 -04001053 zclient = zclient_new (master);
paul718e3742002-12-13 20:15:29 +00001054 zclient_init (zclient, ZEBRA_ROUTE_BGP);
Feng Luc99f3482014-10-16 09:52:36 +08001055 zclient->zebra_connected = bgp_zebra_connected;
hasso18a6dce2004-10-03 18:18:34 +00001056 zclient->router_id_update = bgp_router_id_update;
paul718e3742002-12-13 20:15:29 +00001057 zclient->interface_add = bgp_interface_add;
1058 zclient->interface_delete = bgp_interface_delete;
1059 zclient->interface_address_add = bgp_interface_address_add;
1060 zclient->interface_address_delete = bgp_interface_address_delete;
1061 zclient->ipv4_route_add = zebra_read_ipv4;
1062 zclient->ipv4_route_delete = zebra_read_ipv4;
1063 zclient->interface_up = bgp_interface_up;
1064 zclient->interface_down = bgp_interface_down;
paul718e3742002-12-13 20:15:29 +00001065 zclient->ipv6_route_add = zebra_read_ipv6;
1066 zclient->ipv6_route_delete = zebra_read_ipv6;
paul718e3742002-12-13 20:15:29 +00001067
Josh Bailey8196f132011-07-20 20:47:07 -07001068 bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001069}
Lou Berger82dd7072016-01-12 13:41:57 -05001070
1071void
1072bgp_zebra_destroy(void)
1073{
1074 if (zclient == NULL)
1075 return;
1076 zclient_stop(zclient);
1077 zclient_free(zclient);
1078 zclient = NULL;
1079}