blob: ba87ad1c87ea84f40d296f5023b9d5676c6172e5 [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"
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -050042#include "bgpd/bgp_nexthop.h"
43#include "bgpd/bgp_nht.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020044
paul718e3742002-12-13 20:15:29 +000045/* All information about zebra. */
Chris Caputo228da422009-07-18 05:44:03 +000046struct zclient *zclient = NULL;
hasso18a6dce2004-10-03 18:18:34 +000047struct in_addr router_id_zebra;
paul718e3742002-12-13 20:15:29 +000048
Josh Bailey8196f132011-07-20 20:47:07 -070049/* Growable buffer for nexthops sent to zebra */
50struct stream *bgp_nexthop_buf = NULL;
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -050051struct stream *bgp_ifindices_buf = NULL;
Josh Bailey8196f132011-07-20 20:47:07 -070052
Lou Berger68bfb612016-10-06 09:59:32 -040053int zclient_num_connects;
54
hasso18a6dce2004-10-03 18:18:34 +000055/* Router-id update message from zebra. */
paul94f2b392005-06-28 12:44:16 +000056static int
Feng Luc99f3482014-10-16 09:52:36 +080057bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
58 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000059{
hasso18a6dce2004-10-03 18:18:34 +000060 struct prefix router_id;
paul718e3742002-12-13 20:15:29 +000061
hasso18a6dce2004-10-03 18:18:34 +000062 zebra_router_id_update_read(zclient->ibuf,&router_id);
Andrew J. Schorra39275d2006-11-30 16:36:57 +000063
64 if (BGP_DEBUG(zebra, ZEBRA))
65 {
66 char buf[128];
67 prefix2str(&router_id, buf, sizeof(buf));
68 zlog_debug("Zebra rcvd: router id update %s", buf);
69 }
70
hasso18a6dce2004-10-03 18:18:34 +000071 router_id_zebra = router_id.u.prefix4;
72
David Lamparter584083d2016-05-24 18:58:08 +020073 bgp_router_id_zebra_bump ();
paul718e3742002-12-13 20:15:29 +000074 return 0;
75}
76
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -050077/* Nexthop update message from zebra. */
78static int
79bgp_read_nexthop_update (int command, struct zclient *zclient,
80 zebra_size_t length, vrf_id_t vrf_id)
81{
82 bgp_parse_nexthop_update();
83 return 0;
84}
85
paul718e3742002-12-13 20:15:29 +000086/* Inteface addition message from zebra. */
paul94f2b392005-06-28 12:44:16 +000087static int
Feng Luc99f3482014-10-16 09:52:36 +080088bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
89 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000090{
91 struct interface *ifp;
92
Feng Luc99f3482014-10-16 09:52:36 +080093 ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +000094
Andrew J. Schorra39275d2006-11-30 16:36:57 +000095 if (BGP_DEBUG(zebra, ZEBRA) && ifp)
96 zlog_debug("Zebra rcvd: interface add %s", ifp->name);
97
paul718e3742002-12-13 20:15:29 +000098 return 0;
99}
100
paul94f2b392005-06-28 12:44:16 +0000101static int
paul718e3742002-12-13 20:15:29 +0000102bgp_interface_delete (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800103 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000104{
105 struct stream *s;
106 struct interface *ifp;
107
108 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800109 ifp = zebra_interface_state_read (s, vrf_id);
ajsd2fc8892005-04-02 18:38:43 +0000110 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000111
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000112 if (BGP_DEBUG(zebra, ZEBRA))
113 zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
114
paul718e3742002-12-13 20:15:29 +0000115 return 0;
116}
117
paul94f2b392005-06-28 12:44:16 +0000118static int
Feng Luc99f3482014-10-16 09:52:36 +0800119bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length,
120 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000121{
122 struct stream *s;
123 struct interface *ifp;
124 struct connected *c;
paul1eb8ef22005-04-07 07:30:20 +0000125 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000126
127 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800128 ifp = zebra_interface_state_read (s, vrf_id);
paul718e3742002-12-13 20:15:29 +0000129
130 if (! ifp)
131 return 0;
132
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000133 if (BGP_DEBUG(zebra, ZEBRA))
134 zlog_debug("Zebra rcvd: interface %s up", ifp->name);
135
paul1eb8ef22005-04-07 07:30:20 +0000136 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
137 bgp_connected_add (c);
paul718e3742002-12-13 20:15:29 +0000138
139 return 0;
140}
141
paul94f2b392005-06-28 12:44:16 +0000142static int
Feng Luc99f3482014-10-16 09:52:36 +0800143bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
144 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000145{
146 struct stream *s;
147 struct interface *ifp;
148 struct connected *c;
paul1eb8ef22005-04-07 07:30:20 +0000149 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000150
151 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800152 ifp = zebra_interface_state_read (s, vrf_id);
paul718e3742002-12-13 20:15:29 +0000153 if (! ifp)
154 return 0;
155
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000156 if (BGP_DEBUG(zebra, ZEBRA))
157 zlog_debug("Zebra rcvd: interface %s down", ifp->name);
158
paul1eb8ef22005-04-07 07:30:20 +0000159 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
160 bgp_connected_delete (c);
paul718e3742002-12-13 20:15:29 +0000161
Pradosh Mohapatra8da86892013-09-11 03:33:55 +0000162 /* Fast external-failover */
paul718e3742002-12-13 20:15:29 +0000163 {
paul1eb8ef22005-04-07 07:30:20 +0000164 struct listnode *mnode;
paul718e3742002-12-13 20:15:29 +0000165 struct bgp *bgp;
166 struct peer *peer;
paul718e3742002-12-13 20:15:29 +0000167
paul1eb8ef22005-04-07 07:30:20 +0000168 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
paul718e3742002-12-13 20:15:29 +0000169 {
170 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
171 continue;
172
paul1eb8ef22005-04-07 07:30:20 +0000173 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000174 {
Timo Teräse3443a22016-10-19 16:02:34 +0300175 if (peer->gtsm_hops != 1 && peer_ttl (peer) != 1)
176 continue;
177 if (ifp == peer->nexthop.ifp)
178 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000179 }
180 }
181 }
182
183 return 0;
184}
185
paul94f2b392005-06-28 12:44:16 +0000186static int
paul718e3742002-12-13 20:15:29 +0000187bgp_interface_address_add (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800188 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000189{
190 struct connected *ifc;
191
Feng Luc99f3482014-10-16 09:52:36 +0800192 ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000193
194 if (ifc == NULL)
195 return 0;
196
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000197 if (BGP_DEBUG(zebra, ZEBRA))
198 {
199 char buf[128];
200 prefix2str(ifc->address, buf, sizeof(buf));
201 zlog_debug("Zebra rcvd: interface %s address add %s",
202 ifc->ifp->name, buf);
203 }
204
paul2e3b2e42002-12-13 21:03:13 +0000205 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000206 bgp_connected_add (ifc);
207
208 return 0;
209}
210
paul94f2b392005-06-28 12:44:16 +0000211static int
paul718e3742002-12-13 20:15:29 +0000212bgp_interface_address_delete (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800213 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000214{
215 struct connected *ifc;
216
Feng Luc99f3482014-10-16 09:52:36 +0800217 ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000218
219 if (ifc == NULL)
220 return 0;
221
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000222 if (BGP_DEBUG(zebra, ZEBRA))
223 {
224 char buf[128];
225 prefix2str(ifc->address, buf, sizeof(buf));
226 zlog_debug("Zebra rcvd: interface %s address delete %s",
227 ifc->ifp->name, buf);
228 }
229
paul2e3b2e42002-12-13 21:03:13 +0000230 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000231 bgp_connected_delete (ifc);
232
233 connected_free (ifc);
234
235 return 0;
236}
237
238/* Zebra route add and delete treatment. */
paul94f2b392005-06-28 12:44:16 +0000239static int
Feng Luc99f3482014-10-16 09:52:36 +0800240zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
241 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000242{
243 struct stream *s;
244 struct zapi_ipv4 api;
paul718e3742002-12-13 20:15:29 +0000245 struct in_addr nexthop;
246 struct prefix_ipv4 p;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500247 unsigned char plength = 0;
paul718e3742002-12-13 20:15:29 +0000248
249 s = zclient->ibuf;
paul718e3742002-12-13 20:15:29 +0000250 nexthop.s_addr = 0;
251
252 /* Type, flags, message. */
253 api.type = stream_getc (s);
254 api.flags = stream_getc (s);
255 api.message = stream_getc (s);
256
257 /* IPv4 prefix. */
258 memset (&p, 0, sizeof (struct prefix_ipv4));
259 p.family = AF_INET;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500260 plength = stream_getc (s);
261 p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, plength);
paul718e3742002-12-13 20:15:29 +0000262 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
263
264 /* Nexthop, ifindex, distance, metric. */
265 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
266 {
267 api.nexthop_num = stream_getc (s);
268 nexthop.s_addr = stream_get_ipv4 (s);
269 }
270 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
271 {
272 api.ifindex_num = stream_getc (s);
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400273 stream_getl (s); /* ifindex, unused */
paul718e3742002-12-13 20:15:29 +0000274 }
275 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
276 api.distance = stream_getc (s);
277 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
278 api.metric = stream_getl (s);
279 else
280 api.metric = 0;
281
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500282 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
Paul Jakma96d10602016-07-01 14:23:45 +0100283 api.tag = stream_getl (s);
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500284 else
285 api.tag = 0;
286
paul718e3742002-12-13 20:15:29 +0000287 if (command == ZEBRA_IPV4_ROUTE_ADD)
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000288 {
289 if (BGP_DEBUG(zebra, ZEBRA))
290 {
291 char buf[2][INET_ADDRSTRLEN];
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500292 zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u tag %d",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000293 zebra_route_string(api.type),
294 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
295 p.prefixlen,
296 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500297 api.metric,
298 api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000299 }
Piotr Chytła605aa332015-12-01 10:03:54 -0500300 bgp_redistribute_add ((struct prefix *)&p, &nexthop, NULL,
301 api.metric, api.type, api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000302 }
paul718e3742002-12-13 20:15:29 +0000303 else
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000304 {
305 if (BGP_DEBUG(zebra, ZEBRA))
306 {
307 char buf[2][INET_ADDRSTRLEN];
308 zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d "
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500309 "nexthop %s metric %u tag %d",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000310 zebra_route_string(api.type),
311 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
312 p.prefixlen,
313 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500314 api.metric,
315 api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000316 }
317 bgp_redistribute_delete((struct prefix *)&p, api.type);
318 }
paul718e3742002-12-13 20:15:29 +0000319
320 return 0;
321}
322
paul718e3742002-12-13 20:15:29 +0000323/* Zebra route add and delete treatment. */
paul94f2b392005-06-28 12:44:16 +0000324static int
Feng Luc99f3482014-10-16 09:52:36 +0800325zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length,
326 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000327{
328 struct stream *s;
329 struct zapi_ipv6 api;
paul718e3742002-12-13 20:15:29 +0000330 struct in6_addr nexthop;
331 struct prefix_ipv6 p;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500332 unsigned char plength = 0;
paul718e3742002-12-13 20:15:29 +0000333
334 s = zclient->ibuf;
paul718e3742002-12-13 20:15:29 +0000335 memset (&nexthop, 0, sizeof (struct in6_addr));
336
337 /* Type, flags, message. */
338 api.type = stream_getc (s);
339 api.flags = stream_getc (s);
340 api.message = stream_getc (s);
341
342 /* IPv6 prefix. */
343 memset (&p, 0, sizeof (struct prefix_ipv6));
344 p.family = AF_INET6;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500345 plength = stream_getc (s);
346 p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, plength);
paul718e3742002-12-13 20:15:29 +0000347 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
348
349 /* Nexthop, ifindex, distance, metric. */
350 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
351 {
352 api.nexthop_num = stream_getc (s);
353 stream_get (&nexthop, s, 16);
354 }
355 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
356 {
357 api.ifindex_num = stream_getc (s);
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400358 stream_getl (s); /* ifindex, unused */
paul718e3742002-12-13 20:15:29 +0000359 }
360 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
361 api.distance = stream_getc (s);
362 else
363 api.distance = 0;
364 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
365 api.metric = stream_getl (s);
366 else
367 api.metric = 0;
368
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500369 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
Paul Jakma96d10602016-07-01 14:23:45 +0100370 api.tag = stream_getl (s);
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500371 else
372 api.tag = 0;
373
paul718e3742002-12-13 20:15:29 +0000374 /* Simply ignore link-local address. */
375 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
376 return 0;
377
378 if (command == ZEBRA_IPV6_ROUTE_ADD)
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000379 {
380 if (BGP_DEBUG(zebra, ZEBRA))
381 {
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400382 char buf[2][INET6_ADDRSTRLEN];
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500383 zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u tag %d",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000384 zebra_route_string(api.type),
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400385 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
386 p.prefixlen,
387 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500388 api.metric,
389 api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000390 }
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400391 bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
Piotr Chytła605aa332015-12-01 10:03:54 -0500392 api.metric, api.type, api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000393 }
paul718e3742002-12-13 20:15:29 +0000394 else
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000395 {
396 if (BGP_DEBUG(zebra, ZEBRA))
397 {
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400398 char buf[2][INET6_ADDRSTRLEN];
399 zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d "
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500400 "nexthop %s metric %u tag %d",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000401 zebra_route_string(api.type),
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400402 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
403 p.prefixlen,
404 inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])),
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500405 api.metric,
406 api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000407 }
408 bgp_redistribute_delete ((struct prefix *) &p, api.type);
409 }
paul718e3742002-12-13 20:15:29 +0000410
411 return 0;
412}
David Lamparter6b0655a2014-06-04 06:53:35 +0200413
paul718e3742002-12-13 20:15:29 +0000414struct interface *
415if_lookup_by_ipv4 (struct in_addr *addr)
416{
hasso52dc7ee2004-09-23 19:18:23 +0000417 struct listnode *ifnode;
418 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000419 struct interface *ifp;
420 struct connected *connected;
421 struct prefix_ipv4 p;
422 struct prefix *cp;
423
424 p.family = AF_INET;
425 p.prefix = *addr;
426 p.prefixlen = IPV4_MAX_BITLEN;
427
paul1eb8ef22005-04-07 07:30:20 +0000428 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000429 {
paul1eb8ef22005-04-07 07:30:20 +0000430 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000431 {
paul718e3742002-12-13 20:15:29 +0000432 cp = connected->address;
433
434 if (cp->family == AF_INET)
435 if (prefix_match (cp, (struct prefix *)&p))
436 return ifp;
437 }
438 }
439 return NULL;
440}
441
442struct interface *
443if_lookup_by_ipv4_exact (struct in_addr *addr)
444{
hasso52dc7ee2004-09-23 19:18:23 +0000445 struct listnode *ifnode;
446 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000447 struct interface *ifp;
448 struct connected *connected;
449 struct prefix *cp;
450
paul1eb8ef22005-04-07 07:30:20 +0000451 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000452 {
paul1eb8ef22005-04-07 07:30:20 +0000453 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000454 {
paul718e3742002-12-13 20:15:29 +0000455 cp = connected->address;
456
457 if (cp->family == AF_INET)
458 if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
459 return ifp;
460 }
461 }
462 return NULL;
463}
464
paul718e3742002-12-13 20:15:29 +0000465struct interface *
466if_lookup_by_ipv6 (struct in6_addr *addr)
467{
hasso52dc7ee2004-09-23 19:18:23 +0000468 struct listnode *ifnode;
469 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000470 struct interface *ifp;
471 struct connected *connected;
472 struct prefix_ipv6 p;
473 struct prefix *cp;
474
475 p.family = AF_INET6;
476 p.prefix = *addr;
477 p.prefixlen = IPV6_MAX_BITLEN;
478
paul1eb8ef22005-04-07 07:30:20 +0000479 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000480 {
paul1eb8ef22005-04-07 07:30:20 +0000481 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000482 {
paul718e3742002-12-13 20:15:29 +0000483 cp = connected->address;
484
485 if (cp->family == AF_INET6)
486 if (prefix_match (cp, (struct prefix *)&p))
487 return ifp;
488 }
489 }
490 return NULL;
491}
492
493struct interface *
494if_lookup_by_ipv6_exact (struct in6_addr *addr)
495{
hasso52dc7ee2004-09-23 19:18:23 +0000496 struct listnode *ifnode;
497 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000498 struct interface *ifp;
499 struct connected *connected;
500 struct prefix *cp;
501
paul1eb8ef22005-04-07 07:30:20 +0000502 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000503 {
paul1eb8ef22005-04-07 07:30:20 +0000504 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000505 {
paul718e3742002-12-13 20:15:29 +0000506 cp = connected->address;
507
508 if (cp->family == AF_INET6)
509 if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
510 return ifp;
511 }
512 }
513 return NULL;
514}
515
paul94f2b392005-06-28 12:44:16 +0000516static int
paul718e3742002-12-13 20:15:29 +0000517if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
518{
hasso52dc7ee2004-09-23 19:18:23 +0000519 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000520 struct connected *connected;
521 struct prefix *cp;
522
paul1eb8ef22005-04-07 07:30:20 +0000523 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000524 {
paul718e3742002-12-13 20:15:29 +0000525 cp = connected->address;
526
527 if (cp->family == AF_INET6)
528 if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
529 {
530 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
531 return 1;
532 }
533 }
534 return 0;
535}
536
paul94f2b392005-06-28 12:44:16 +0000537static int
paul718e3742002-12-13 20:15:29 +0000538if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
539{
hasso52dc7ee2004-09-23 19:18:23 +0000540 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000541 struct connected *connected;
542 struct prefix *cp;
543
paul1eb8ef22005-04-07 07:30:20 +0000544 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000545 {
paul718e3742002-12-13 20:15:29 +0000546 cp = connected->address;
547
548 if (cp->family == AF_INET6)
549 if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
550 {
551 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
552 return 1;
553 }
554 }
555 return 0;
556}
paul718e3742002-12-13 20:15:29 +0000557
Pradosh Mohapatra6ee06fa2014-01-12 18:30:13 +0000558static int
559if_get_ipv4_address (struct interface *ifp, struct in_addr *addr)
560{
561 struct listnode *cnode;
562 struct connected *connected;
563 struct prefix *cp;
564
565 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
566 {
567 cp = connected->address;
568 if ((cp->family == AF_INET) && !ipv4_martian(&(cp->u.prefix4)))
569 {
570 *addr = cp->u.prefix4;
571 return 1;
572 }
573 }
574 return 0;
575}
576
paul718e3742002-12-13 20:15:29 +0000577int
578bgp_nexthop_set (union sockunion *local, union sockunion *remote,
579 struct bgp_nexthop *nexthop, struct peer *peer)
580{
581 int ret = 0;
582 struct interface *ifp = NULL;
583
584 memset (nexthop, 0, sizeof (struct bgp_nexthop));
585
586 if (!local)
587 return -1;
588 if (!remote)
589 return -1;
590
591 if (local->sa.sa_family == AF_INET)
592 {
593 nexthop->v4 = local->sin.sin_addr;
Vivek Venkatramanfa2e7862015-05-19 18:03:54 -0700594 if (peer->update_if)
595 ifp = if_lookup_by_name (peer->update_if);
596 else
597 ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr);
paul718e3742002-12-13 20:15:29 +0000598 }
paul718e3742002-12-13 20:15:29 +0000599 if (local->sa.sa_family == AF_INET6)
600 {
601 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
602 {
603 if (peer->ifname)
Feng Lu395828e2015-05-22 11:39:55 +0200604 ifp = if_lookup_by_name (peer->ifname);
paul718e3742002-12-13 20:15:29 +0000605 }
Vivek Venkatramanfa2e7862015-05-19 18:03:54 -0700606 else if (peer->update_if)
607 ifp = if_lookup_by_name (peer->update_if);
paul718e3742002-12-13 20:15:29 +0000608 else
Vivek Venkatramanfa2e7862015-05-19 18:03:54 -0700609 ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr);
paul718e3742002-12-13 20:15:29 +0000610 }
paul718e3742002-12-13 20:15:29 +0000611
612 if (!ifp)
613 return -1;
614
615 nexthop->ifp = ifp;
616
617 /* IPv4 connection. */
618 if (local->sa.sa_family == AF_INET)
619 {
paul718e3742002-12-13 20:15:29 +0000620 /* IPv6 nexthop*/
621 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
622
623 /* There is no global nexthop. */
624 if (!ret)
625 if_get_ipv6_local (ifp, &nexthop->v6_global);
626 else
627 if_get_ipv6_local (ifp, &nexthop->v6_local);
paul718e3742002-12-13 20:15:29 +0000628 }
629
paul718e3742002-12-13 20:15:29 +0000630 /* IPv6 connection. */
631 if (local->sa.sa_family == AF_INET6)
632 {
633 struct interface *direct = NULL;
634
Pradosh Mohapatra6ee06fa2014-01-12 18:30:13 +0000635 /* IPv4 nexthop. */
636 ret = if_get_ipv4_address(ifp, &nexthop->v4);
637 if (!ret && peer->local_id.s_addr)
paul718e3742002-12-13 20:15:29 +0000638 nexthop->v4 = peer->local_id;
639
640 /* Global address*/
641 if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
642 {
643 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
644 IPV6_MAX_BYTELEN);
645
646 /* If directory connected set link-local address. */
647 direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
648 if (direct)
649 if_get_ipv6_local (ifp, &nexthop->v6_local);
650 }
651 else
652 /* Link-local address. */
653 {
654 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
655
656 /* If there is no global address. Set link-local address as
657 global. I know this break RFC specification... */
658 if (!ret)
659 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
660 IPV6_MAX_BYTELEN);
661 else
662 memcpy (&nexthop->v6_local, &local->sin6.sin6_addr,
663 IPV6_MAX_BYTELEN);
664 }
665 }
666
667 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
668 if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
669 peer->shared_network = 1;
670 else
671 peer->shared_network = 0;
672
673 /* KAME stack specific treatment. */
674#ifdef KAME
675 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
676 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
677 {
678 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
679 }
680 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
681 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
682 {
683 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
684 }
685#endif /* KAME */
paul718e3742002-12-13 20:15:29 +0000686 return ret;
687}
688
paul718e3742002-12-13 20:15:29 +0000689void
G.Balaji5a616c02011-11-26 21:58:42 +0400690bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi)
paul718e3742002-12-13 20:15:29 +0000691{
692 int flags;
693 u_char distance;
694 struct peer *peer;
Josh Bailey8196f132011-07-20 20:47:07 -0700695 struct bgp_info *mpinfo;
696 size_t oldsize, newsize;
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500697 u_int32_t nhcount;
Paul Jakma96d10602016-07-01 14:23:45 +0100698 route_tag_t tag = 0;
paul718e3742002-12-13 20:15:29 +0000699
700 if (zclient->sock < 0)
701 return;
702
Feng Luc99f3482014-10-16 09:52:36 +0800703 if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000704 return;
705
706 flags = 0;
707 peer = info->peer;
708
Piotr Chytła605aa332015-12-01 10:03:54 -0500709 if ((info->attr->extra) && (info->attr->extra->tag != 0))
710 tag = info->attr->extra->tag;
711
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000712 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +0000713 {
714 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
715 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
716 }
717
Timo Teräse3443a22016-10-19 16:02:34 +0300718 if ((peer->sort == BGP_PEER_EBGP && peer_ttl (peer) != 1)
hasso6ffd2072005-02-02 14:50:11 +0000719 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000720 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
721
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500722 nhcount = 1 + bgp_info_mpath_count (info);
Josh Bailey8196f132011-07-20 20:47:07 -0700723
paul718e3742002-12-13 20:15:29 +0000724 if (p->family == AF_INET)
725 {
726 struct zapi_ipv4 api;
727 struct in_addr *nexthop;
728
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500729 /* resize nexthop buffer size if necessary */
730 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
731 (sizeof (struct in_addr *) * nhcount))
732 {
733 newsize = (sizeof (struct in_addr *) * nhcount);
734 newsize = stream_resize (bgp_nexthop_buf, newsize);
735 if (newsize == oldsize)
736 {
737 zlog_err ("can't resize nexthop buffer");
738 return;
739 }
740 }
741 stream_reset (bgp_nexthop_buf);
742
Feng Luc99f3482014-10-16 09:52:36 +0800743 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000744 api.flags = flags;
745 nexthop = &info->attr->nexthop;
Josh Bailey8196f132011-07-20 20:47:07 -0700746 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
747 for (mpinfo = bgp_info_mpath_first (info); mpinfo;
748 mpinfo = bgp_info_mpath_next (mpinfo))
749 {
750 nexthop = &mpinfo->attr->nexthop;
751 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
752 }
paul718e3742002-12-13 20:15:29 +0000753
754 api.type = ZEBRA_ROUTE_BGP;
755 api.message = 0;
G.Balaji5a616c02011-11-26 21:58:42 +0400756 api.safi = safi;
paul718e3742002-12-13 20:15:29 +0000757 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500758 api.nexthop_num = nhcount;
Josh Bailey8196f132011-07-20 20:47:07 -0700759 api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
paul718e3742002-12-13 20:15:29 +0000760 api.ifindex_num = 0;
761 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
762 api.metric = info->attr->med;
763
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500764 if (tag)
Piotr Chytła605aa332015-12-01 10:03:54 -0500765 {
766 SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
767 api.tag = tag;
768 }
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500769
paul718e3742002-12-13 20:15:29 +0000770 distance = bgp_distance_apply (p, info, bgp);
771
772 if (distance)
773 {
774 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
775 api.distance = distance;
776 }
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000777
778 if (BGP_DEBUG(zebra, ZEBRA))
779 {
Josh Bailey8196f132011-07-20 20:47:07 -0700780 int i;
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000781 char buf[2][INET_ADDRSTRLEN];
Josh Bailey8196f132011-07-20 20:47:07 -0700782 zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u"
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500783 " tag %u count %d",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000784 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
785 p->prefixlen,
Josh Bailey8196f132011-07-20 20:47:07 -0700786 inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])),
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500787 api.metric, api.tag, api.nexthop_num);
Josh Bailey8196f132011-07-20 20:47:07 -0700788 for (i = 1; i < api.nexthop_num; i++)
789 zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s",
790 i, inet_ntop(AF_INET, api.nexthop[i], buf[1],
791 sizeof(buf[1])));
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000792 }
793
paul0a589352004-05-08 11:48:26 +0000794 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
795 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000796 }
Lou Berger205e6742016-01-12 13:42:11 -0500797
paul718e3742002-12-13 20:15:29 +0000798 /* We have to think about a IPv6 link-local address curse. */
799 if (p->family == AF_INET6)
800 {
Paul Jakma9099f9b2016-01-18 10:12:10 +0000801 ifindex_t ifindex;
paul718e3742002-12-13 20:15:29 +0000802 struct in6_addr *nexthop;
803 struct zapi_ipv6 api;
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500804 int valid_nh_count = 0;
805
806 /* resize nexthop buffer size if necessary */
807 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
808 (sizeof (struct in6_addr *) * nhcount))
809 {
810 newsize = (sizeof (struct in6_addr *) * nhcount);
811 newsize = stream_resize (bgp_nexthop_buf, newsize);
812 if (newsize == oldsize)
813 {
814 zlog_err ("can't resize nexthop buffer");
815 return;
816 }
817 }
818 stream_reset (bgp_nexthop_buf);
819
820 /* resize ifindices buffer size if necessary */
821 if ((oldsize = stream_get_size (bgp_ifindices_buf)) <
822 (sizeof (unsigned int) * nhcount))
823 {
824 newsize = (sizeof (unsigned int) * nhcount);
825 newsize = stream_resize (bgp_ifindices_buf, newsize);
826 if (newsize == oldsize)
827 {
828 zlog_err ("can't resize nexthop buffer");
829 return;
830 }
831 }
832 stream_reset (bgp_ifindices_buf);
paul718e3742002-12-13 20:15:29 +0000833
834 ifindex = 0;
835 nexthop = NULL;
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500836
Paul Jakmafb982c22007-05-04 20:15:47 +0000837 assert (info->attr->extra);
838
paul718e3742002-12-13 20:15:29 +0000839 /* Only global address nexthop exists. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000840 if (info->attr->extra->mp_nexthop_len == 16)
841 nexthop = &info->attr->extra->mp_nexthop_global;
paul718e3742002-12-13 20:15:29 +0000842
843 /* If both global and link-local address present. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000844 if (info->attr->extra->mp_nexthop_len == 32)
paul718e3742002-12-13 20:15:29 +0000845 {
846 /* Workaround for Cisco's nexthop bug. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000847 if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
paul718e3742002-12-13 20:15:29 +0000848 && peer->su_remote->sa.sa_family == AF_INET6)
849 nexthop = &peer->su_remote->sin6.sin6_addr;
850 else
Paul Jakmafb982c22007-05-04 20:15:47 +0000851 nexthop = &info->attr->extra->mp_nexthop_local;
paul718e3742002-12-13 20:15:29 +0000852
853 if (info->peer->nexthop.ifp)
854 ifindex = info->peer->nexthop.ifp->ifindex;
855 }
856
857 if (nexthop == NULL)
858 return;
859
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500860 if (!ifindex)
paul718e3742002-12-13 20:15:29 +0000861 {
862 if (info->peer->ifname)
Feng Lu395828e2015-05-22 11:39:55 +0200863 ifindex = ifname2ifindex (info->peer->ifname);
paul718e3742002-12-13 20:15:29 +0000864 else if (info->peer->nexthop.ifp)
865 ifindex = info->peer->nexthop.ifp->ifindex;
866 }
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500867 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
868 stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
869 valid_nh_count++;
870
871 for (mpinfo = bgp_info_mpath_first (info); mpinfo;
872 mpinfo = bgp_info_mpath_next (mpinfo))
873 {
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500874 ifindex = 0;
875
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500876 /* Only global address nexthop exists. */
877 if (mpinfo->attr->extra->mp_nexthop_len == 16)
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500878 nexthop = &mpinfo->attr->extra->mp_nexthop_global;
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500879
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500880 /* If both global and link-local address present. */
881 if (mpinfo->attr->extra->mp_nexthop_len == 32)
882 {
883 /* Workaround for Cisco's nexthop bug. */
884 if (IN6_IS_ADDR_UNSPECIFIED (&mpinfo->attr->extra->mp_nexthop_global)
885 && mpinfo->peer->su_remote->sa.sa_family == AF_INET6)
886 {
887 nexthop = &mpinfo->peer->su_remote->sin6.sin6_addr;
888 }
889 else
890 {
891 nexthop = &mpinfo->attr->extra->mp_nexthop_local;
892 }
893
894 if (mpinfo->peer->nexthop.ifp)
895 {
896 ifindex = mpinfo->peer->nexthop.ifp->ifindex;
897 }
898 }
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500899
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500900 if (nexthop == NULL)
901 {
902 continue;
903 }
904
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500905 if (!ifindex)
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500906 {
907 if (mpinfo->peer->ifname)
908 {
909 ifindex = if_nametoindex (mpinfo->peer->ifname);
910 }
911 else if (mpinfo->peer->nexthop.ifp)
912 {
913 ifindex = mpinfo->peer->nexthop.ifp->ifindex;
914 }
915 }
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500916
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500917 if (ifindex == 0)
918 {
919 continue;
920 }
921
922 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
923 stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
924 valid_nh_count++;
925 }
paul718e3742002-12-13 20:15:29 +0000926
927 /* Make Zebra API structure. */
Feng Luc99f3482014-10-16 09:52:36 +0800928 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000929 api.flags = flags;
930 api.type = ZEBRA_ROUTE_BGP;
931 api.message = 0;
G.Balajic7ec1792011-11-26 22:04:05 +0400932 api.safi = safi;
paul718e3742002-12-13 20:15:29 +0000933 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500934 api.nexthop_num = valid_nh_count;
935 api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
paul718e3742002-12-13 20:15:29 +0000936 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500937 api.ifindex_num = valid_nh_count;
938 api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
paul718e3742002-12-13 20:15:29 +0000939 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
940 api.metric = info->attr->med;
941
Roman Hoog Antink6184c392014-03-17 14:01:42 +0100942 distance = ipv6_bgp_distance_apply (p, info, bgp);
943
944 if (distance)
945 {
946 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
947 api.distance = distance;
948 }
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500949
950 if (tag)
951 {
952 SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
953 api.tag = tag;
954 }
Roman Hoog Antink6184c392014-03-17 14:01:42 +0100955
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000956 if (BGP_DEBUG(zebra, ZEBRA))
957 {
958 char buf[2][INET6_ADDRSTRLEN];
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500959 zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u"
960 " tag %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000961 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
962 p->prefixlen,
963 inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
Piotr Chytłaeefddcc2015-12-01 09:48:02 -0500964 api.metric, api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000965 }
966
paul0a589352004-05-08 11:48:26 +0000967 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
968 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000969 }
paul718e3742002-12-13 20:15:29 +0000970}
971
972void
G.Balaji5a616c02011-11-26 21:58:42 +0400973bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
paul718e3742002-12-13 20:15:29 +0000974{
975 int flags;
976 struct peer *peer;
977
978 if (zclient->sock < 0)
979 return;
980
Feng Luc99f3482014-10-16 09:52:36 +0800981 if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000982 return;
983
984 peer = info->peer;
985 flags = 0;
986
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000987 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000988 {
989 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
990 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
991 }
992
Timo Teräse3443a22016-10-19 16:02:34 +0300993 if ((peer->sort == BGP_PEER_EBGP && peer_ttl (peer) != 1)
hasso6ffd2072005-02-02 14:50:11 +0000994 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000995 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
996
997 if (p->family == AF_INET)
998 {
999 struct zapi_ipv4 api;
paul718e3742002-12-13 20:15:29 +00001000
Feng Luc99f3482014-10-16 09:52:36 +08001001 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +00001002 api.flags = flags;
paul718e3742002-12-13 20:15:29 +00001003
1004 api.type = ZEBRA_ROUTE_BGP;
1005 api.message = 0;
G.Balaji5a616c02011-11-26 21:58:42 +04001006 api.safi = safi;
Paul Jakma64e0ac22015-11-18 16:00:54 +00001007 api.nexthop_num = 0;
paul718e3742002-12-13 20:15:29 +00001008 api.ifindex_num = 0;
1009 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
1010 api.metric = info->attr->med;
1011
Piotr Chytła605aa332015-12-01 10:03:54 -05001012 if ((info->attr->extra) && (info->attr->extra->tag != 0))
1013 {
1014 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
1015 api.tag = info->attr->extra->tag;
1016 }
1017
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001018 if (BGP_DEBUG(zebra, ZEBRA))
1019 {
1020 char buf[2][INET_ADDRSTRLEN];
Piotr Chytła605aa332015-12-01 10:03:54 -05001021 zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u tag %d",
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001022 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
1023 p->prefixlen,
Piotr Chytła605aa332015-12-01 10:03:54 -05001024 api.metric,
1025 api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001026 }
1027
paul0a589352004-05-08 11:48:26 +00001028 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
1029 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +00001030 }
Lou Berger205e6742016-01-12 13:42:11 -05001031
paul718e3742002-12-13 20:15:29 +00001032 /* We have to think about a IPv6 link-local address curse. */
1033 if (p->family == AF_INET6)
1034 {
1035 struct zapi_ipv6 api;
Paul Jakmafb982c22007-05-04 20:15:47 +00001036
Feng Luc99f3482014-10-16 09:52:36 +08001037 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +00001038 api.flags = flags;
1039 api.type = ZEBRA_ROUTE_BGP;
1040 api.message = 0;
G.Balajic7ec1792011-11-26 22:04:05 +04001041 api.safi = safi;
Paul Jakma64e0ac22015-11-18 16:00:54 +00001042 api.nexthop_num = 0;
1043 api.ifindex_num = 0;
paul718e3742002-12-13 20:15:29 +00001044 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
1045 api.metric = info->attr->med;
1046
Piotr Chytła605aa332015-12-01 10:03:54 -05001047 if ((info->attr->extra) && (info->attr->extra->tag != 0))
1048 {
1049 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
1050 api.tag = info->attr->extra->tag;
1051 }
1052
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001053 if (BGP_DEBUG(zebra, ZEBRA))
1054 {
1055 char buf[2][INET6_ADDRSTRLEN];
Piotr Chytła605aa332015-12-01 10:03:54 -05001056 zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u tag %d",
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001057 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
1058 p->prefixlen,
Piotr Chytła605aa332015-12-01 10:03:54 -05001059 api.metric,
1060 api.tag);
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001061 }
1062
paul0a589352004-05-08 11:48:26 +00001063 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
1064 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +00001065 }
paul718e3742002-12-13 20:15:29 +00001066}
David Lamparter6b0655a2014-06-04 06:53:35 +02001067
paul718e3742002-12-13 20:15:29 +00001068/* Other routes redistribution into BGP. */
1069int
1070bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
1071{
1072 /* Set flag to BGP instance. */
1073 bgp->redist[afi][type] = 1;
1074
1075 /* Return if already redistribute flag is set. */
Feng Luc99f3482014-10-16 09:52:36 +08001076 if (vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001077 return CMD_WARNING;
1078
Feng Luc99f3482014-10-16 09:52:36 +08001079 vrf_bitmap_set (zclient->redist[type], VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00001080
1081 /* Return if zebra connection is not established. */
1082 if (zclient->sock < 0)
1083 return CMD_WARNING;
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001084
1085 if (BGP_DEBUG(zebra, ZEBRA))
1086 zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
paul718e3742002-12-13 20:15:29 +00001087
1088 /* Send distribute add message to zebra. */
Feng Luc99f3482014-10-16 09:52:36 +08001089 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00001090
1091 return CMD_SUCCESS;
1092}
1093
1094/* Redistribute with route-map specification. */
1095int
paulfd79ac92004-10-13 05:06:08 +00001096bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
1097 const char *name)
paul718e3742002-12-13 20:15:29 +00001098{
1099 if (bgp->rmap[afi][type].name
1100 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
1101 return 0;
1102
1103 if (bgp->rmap[afi][type].name)
1104 free (bgp->rmap[afi][type].name);
1105 bgp->rmap[afi][type].name = strdup (name);
1106 bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
1107
1108 return 1;
1109}
1110
1111/* Redistribute with metric specification. */
1112int
1113bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
1114 u_int32_t metric)
1115{
1116 if (bgp->redist_metric_flag[afi][type]
1117 && bgp->redist_metric[afi][type] == metric)
1118 return 0;
1119
1120 bgp->redist_metric_flag[afi][type] = 1;
1121 bgp->redist_metric[afi][type] = metric;
1122
1123 return 1;
1124}
1125
1126/* Unset redistribution. */
1127int
1128bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
1129{
1130 /* Unset flag from BGP instance. */
1131 bgp->redist[afi][type] = 0;
1132
1133 /* Unset route-map. */
1134 if (bgp->rmap[afi][type].name)
1135 free (bgp->rmap[afi][type].name);
1136 bgp->rmap[afi][type].name = NULL;
1137 bgp->rmap[afi][type].map = NULL;
1138
1139 /* Unset metric. */
1140 bgp->redist_metric_flag[afi][type] = 0;
1141 bgp->redist_metric[afi][type] = 0;
1142
1143 /* Return if zebra connection is disabled. */
Feng Luc99f3482014-10-16 09:52:36 +08001144 if (! vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001145 return CMD_WARNING;
Feng Luc99f3482014-10-16 09:52:36 +08001146 vrf_bitmap_unset (zclient->redist[type], VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00001147
1148 if (bgp->redist[AFI_IP][type] == 0
1149 && bgp->redist[AFI_IP6][type] == 0
1150 && zclient->sock >= 0)
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001151 {
1152 /* Send distribute delete message to zebra. */
1153 if (BGP_DEBUG(zebra, ZEBRA))
1154 zlog_debug("Zebra send: redistribute delete %s",
1155 zebra_route_string(type));
Feng Luc99f3482014-10-16 09:52:36 +08001156 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type,
1157 VRF_DEFAULT);
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001158 }
paul718e3742002-12-13 20:15:29 +00001159
1160 /* Withdraw redistributed routes from current BGP's routing table. */
1161 bgp_redistribute_withdraw (bgp, afi, type);
1162
1163 return CMD_SUCCESS;
1164}
1165
paul718e3742002-12-13 20:15:29 +00001166void
paul94f2b392005-06-28 12:44:16 +00001167bgp_zclient_reset (void)
paul718e3742002-12-13 20:15:29 +00001168{
1169 zclient_reset (zclient);
1170}
1171
Feng Luc99f3482014-10-16 09:52:36 +08001172static void
1173bgp_zebra_connected (struct zclient *zclient)
1174{
Lou Berger68bfb612016-10-06 09:59:32 -04001175 zclient_num_connects++;
Feng Luc99f3482014-10-16 09:52:36 +08001176 zclient_send_requests (zclient, VRF_DEFAULT);
1177}
1178
paul718e3742002-12-13 20:15:29 +00001179void
Donald Sharp71252932015-09-24 09:25:19 -04001180bgp_zebra_init (struct thread_master *master)
paul718e3742002-12-13 20:15:29 +00001181{
Lou Berger68bfb612016-10-06 09:59:32 -04001182 zclient_num_connects = 0;
1183
paul718e3742002-12-13 20:15:29 +00001184 /* Set default values. */
Donald Sharp71252932015-09-24 09:25:19 -04001185 zclient = zclient_new (master);
paul718e3742002-12-13 20:15:29 +00001186 zclient_init (zclient, ZEBRA_ROUTE_BGP);
Feng Luc99f3482014-10-16 09:52:36 +08001187 zclient->zebra_connected = bgp_zebra_connected;
hasso18a6dce2004-10-03 18:18:34 +00001188 zclient->router_id_update = bgp_router_id_update;
paul718e3742002-12-13 20:15:29 +00001189 zclient->interface_add = bgp_interface_add;
1190 zclient->interface_delete = bgp_interface_delete;
1191 zclient->interface_address_add = bgp_interface_address_add;
1192 zclient->interface_address_delete = bgp_interface_address_delete;
1193 zclient->ipv4_route_add = zebra_read_ipv4;
1194 zclient->ipv4_route_delete = zebra_read_ipv4;
1195 zclient->interface_up = bgp_interface_up;
1196 zclient->interface_down = bgp_interface_down;
paul718e3742002-12-13 20:15:29 +00001197 zclient->ipv6_route_add = zebra_read_ipv6;
1198 zclient->ipv6_route_delete = zebra_read_ipv6;
Pradosh Mohapatra60cc9592015-11-09 20:21:41 -05001199 zclient->nexthop_update = bgp_read_nexthop_update;
paul718e3742002-12-13 20:15:29 +00001200
Josh Bailey8196f132011-07-20 20:47:07 -07001201 bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -05001202 bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001203}
Lou Berger82dd7072016-01-12 13:41:57 -05001204
1205void
1206bgp_zebra_destroy(void)
1207{
1208 if (zclient == NULL)
1209 return;
1210 zclient_stop(zclient);
1211 zclient_free(zclient);
1212 zclient = NULL;
1213}
Lou Berger68bfb612016-10-06 09:59:32 -04001214
1215int
1216bgp_zebra_num_connects(void)
1217{
1218 return zclient_num_connects;
1219}