blob: 00de6b861ebe9fb59bb2aa16fba107efe543c4c7 [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;
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -050049struct stream *bgp_ifindices_buf = NULL;
Josh Bailey8196f132011-07-20 20:47:07 -070050
hasso18a6dce2004-10-03 18:18:34 +000051/* Router-id update message from zebra. */
paul94f2b392005-06-28 12:44:16 +000052static int
Feng Luc99f3482014-10-16 09:52:36 +080053bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
54 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000055{
hasso18a6dce2004-10-03 18:18:34 +000056 struct prefix router_id;
paul718e3742002-12-13 20:15:29 +000057
hasso18a6dce2004-10-03 18:18:34 +000058 zebra_router_id_update_read(zclient->ibuf,&router_id);
Andrew J. Schorra39275d2006-11-30 16:36:57 +000059
60 if (BGP_DEBUG(zebra, ZEBRA))
61 {
62 char buf[128];
63 prefix2str(&router_id, buf, sizeof(buf));
64 zlog_debug("Zebra rcvd: router id update %s", buf);
65 }
66
hasso18a6dce2004-10-03 18:18:34 +000067 router_id_zebra = router_id.u.prefix4;
68
David Lamparter584083d2016-05-24 18:58:08 +020069 bgp_router_id_zebra_bump ();
paul718e3742002-12-13 20:15:29 +000070 return 0;
71}
72
73/* Inteface addition message from zebra. */
paul94f2b392005-06-28 12:44:16 +000074static int
Feng Luc99f3482014-10-16 09:52:36 +080075bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
76 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000077{
78 struct interface *ifp;
79
Feng Luc99f3482014-10-16 09:52:36 +080080 ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +000081
Andrew J. Schorra39275d2006-11-30 16:36:57 +000082 if (BGP_DEBUG(zebra, ZEBRA) && ifp)
83 zlog_debug("Zebra rcvd: interface add %s", ifp->name);
84
paul718e3742002-12-13 20:15:29 +000085 return 0;
86}
87
paul94f2b392005-06-28 12:44:16 +000088static int
paul718e3742002-12-13 20:15:29 +000089bgp_interface_delete (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +080090 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +000091{
92 struct stream *s;
93 struct interface *ifp;
94
95 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +080096 ifp = zebra_interface_state_read (s, vrf_id);
ajsd2fc8892005-04-02 18:38:43 +000097 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +000098
Andrew J. Schorra39275d2006-11-30 16:36:57 +000099 if (BGP_DEBUG(zebra, ZEBRA))
100 zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
101
paul718e3742002-12-13 20:15:29 +0000102 return 0;
103}
104
paul94f2b392005-06-28 12:44:16 +0000105static int
Feng Luc99f3482014-10-16 09:52:36 +0800106bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length,
107 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000108{
109 struct stream *s;
110 struct interface *ifp;
111 struct connected *c;
paul1eb8ef22005-04-07 07:30:20 +0000112 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000113
114 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800115 ifp = zebra_interface_state_read (s, vrf_id);
paul718e3742002-12-13 20:15:29 +0000116
117 if (! ifp)
118 return 0;
119
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000120 if (BGP_DEBUG(zebra, ZEBRA))
121 zlog_debug("Zebra rcvd: interface %s up", ifp->name);
122
paul1eb8ef22005-04-07 07:30:20 +0000123 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
124 bgp_connected_add (c);
paul718e3742002-12-13 20:15:29 +0000125
126 return 0;
127}
128
paul94f2b392005-06-28 12:44:16 +0000129static int
Feng Luc99f3482014-10-16 09:52:36 +0800130bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
131 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000132{
133 struct stream *s;
134 struct interface *ifp;
135 struct connected *c;
paul1eb8ef22005-04-07 07:30:20 +0000136 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000137
138 s = zclient->ibuf;
Feng Luc99f3482014-10-16 09:52:36 +0800139 ifp = zebra_interface_state_read (s, vrf_id);
paul718e3742002-12-13 20:15:29 +0000140 if (! ifp)
141 return 0;
142
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000143 if (BGP_DEBUG(zebra, ZEBRA))
144 zlog_debug("Zebra rcvd: interface %s down", ifp->name);
145
paul1eb8ef22005-04-07 07:30:20 +0000146 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
147 bgp_connected_delete (c);
paul718e3742002-12-13 20:15:29 +0000148
Pradosh Mohapatra8da86892013-09-11 03:33:55 +0000149 /* Fast external-failover */
paul718e3742002-12-13 20:15:29 +0000150 {
paul1eb8ef22005-04-07 07:30:20 +0000151 struct listnode *mnode;
paul718e3742002-12-13 20:15:29 +0000152 struct bgp *bgp;
153 struct peer *peer;
paul718e3742002-12-13 20:15:29 +0000154
paul1eb8ef22005-04-07 07:30:20 +0000155 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
paul718e3742002-12-13 20:15:29 +0000156 {
157 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
158 continue;
159
paul1eb8ef22005-04-07 07:30:20 +0000160 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000161 {
Pradosh Mohapatra8da86892013-09-11 03:33:55 +0000162 if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
paul718e3742002-12-13 20:15:29 +0000163 continue;
164
Pradosh Mohapatra8da86892013-09-11 03:33:55 +0000165 if (ifp == peer->nexthop.ifp)
paul718e3742002-12-13 20:15:29 +0000166 BGP_EVENT_ADD (peer, BGP_Stop);
167 }
168 }
169 }
170
171 return 0;
172}
173
paul94f2b392005-06-28 12:44:16 +0000174static int
paul718e3742002-12-13 20:15:29 +0000175bgp_interface_address_add (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800176 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000177{
178 struct connected *ifc;
179
Feng Luc99f3482014-10-16 09:52:36 +0800180 ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000181
182 if (ifc == NULL)
183 return 0;
184
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000185 if (BGP_DEBUG(zebra, ZEBRA))
186 {
187 char buf[128];
188 prefix2str(ifc->address, buf, sizeof(buf));
189 zlog_debug("Zebra rcvd: interface %s address add %s",
190 ifc->ifp->name, buf);
191 }
192
paul2e3b2e42002-12-13 21:03:13 +0000193 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000194 bgp_connected_add (ifc);
195
196 return 0;
197}
198
paul94f2b392005-06-28 12:44:16 +0000199static int
paul718e3742002-12-13 20:15:29 +0000200bgp_interface_address_delete (int command, struct zclient *zclient,
Feng Luc99f3482014-10-16 09:52:36 +0800201 zebra_size_t length, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000202{
203 struct connected *ifc;
204
Feng Luc99f3482014-10-16 09:52:36 +0800205 ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
paul718e3742002-12-13 20:15:29 +0000206
207 if (ifc == NULL)
208 return 0;
209
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000210 if (BGP_DEBUG(zebra, ZEBRA))
211 {
212 char buf[128];
213 prefix2str(ifc->address, buf, sizeof(buf));
214 zlog_debug("Zebra rcvd: interface %s address delete %s",
215 ifc->ifp->name, buf);
216 }
217
paul2e3b2e42002-12-13 21:03:13 +0000218 if (if_is_operative (ifc->ifp))
paul718e3742002-12-13 20:15:29 +0000219 bgp_connected_delete (ifc);
220
221 connected_free (ifc);
222
223 return 0;
224}
225
226/* Zebra route add and delete treatment. */
paul94f2b392005-06-28 12:44:16 +0000227static int
Feng Luc99f3482014-10-16 09:52:36 +0800228zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
229 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000230{
231 struct stream *s;
232 struct zapi_ipv4 api;
paul718e3742002-12-13 20:15:29 +0000233 struct in_addr nexthop;
234 struct prefix_ipv4 p;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500235 unsigned char plength = 0;
paul718e3742002-12-13 20:15:29 +0000236
237 s = zclient->ibuf;
paul718e3742002-12-13 20:15:29 +0000238 nexthop.s_addr = 0;
239
240 /* Type, flags, message. */
241 api.type = stream_getc (s);
242 api.flags = stream_getc (s);
243 api.message = stream_getc (s);
244
245 /* IPv4 prefix. */
246 memset (&p, 0, sizeof (struct prefix_ipv4));
247 p.family = AF_INET;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500248 plength = stream_getc (s);
249 p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, plength);
paul718e3742002-12-13 20:15:29 +0000250 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
251
252 /* Nexthop, ifindex, distance, metric. */
253 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
254 {
255 api.nexthop_num = stream_getc (s);
256 nexthop.s_addr = stream_get_ipv4 (s);
257 }
258 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
259 {
260 api.ifindex_num = stream_getc (s);
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400261 stream_getl (s); /* ifindex, unused */
paul718e3742002-12-13 20:15:29 +0000262 }
263 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
264 api.distance = stream_getc (s);
265 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
266 api.metric = stream_getl (s);
267 else
268 api.metric = 0;
269
270 if (command == ZEBRA_IPV4_ROUTE_ADD)
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000271 {
272 if (BGP_DEBUG(zebra, ZEBRA))
273 {
274 char buf[2][INET_ADDRSTRLEN];
275 zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
276 zebra_route_string(api.type),
277 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
278 p.prefixlen,
279 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
280 api.metric);
281 }
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400282 bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL,
283 api.metric, api.type);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000284 }
paul718e3742002-12-13 20:15:29 +0000285 else
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000286 {
287 if (BGP_DEBUG(zebra, ZEBRA))
288 {
289 char buf[2][INET_ADDRSTRLEN];
290 zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d "
291 "nexthop %s metric %u",
292 zebra_route_string(api.type),
293 inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
294 p.prefixlen,
295 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
296 api.metric);
297 }
298 bgp_redistribute_delete((struct prefix *)&p, api.type);
299 }
paul718e3742002-12-13 20:15:29 +0000300
301 return 0;
302}
303
paul718e3742002-12-13 20:15:29 +0000304/* Zebra route add and delete treatment. */
paul94f2b392005-06-28 12:44:16 +0000305static int
Feng Luc99f3482014-10-16 09:52:36 +0800306zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length,
307 vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000308{
309 struct stream *s;
310 struct zapi_ipv6 api;
paul718e3742002-12-13 20:15:29 +0000311 struct in6_addr nexthop;
312 struct prefix_ipv6 p;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500313 unsigned char plength = 0;
paul718e3742002-12-13 20:15:29 +0000314
315 s = zclient->ibuf;
paul718e3742002-12-13 20:15:29 +0000316 memset (&nexthop, 0, sizeof (struct in6_addr));
317
318 /* Type, flags, message. */
319 api.type = stream_getc (s);
320 api.flags = stream_getc (s);
321 api.message = stream_getc (s);
322
323 /* IPv6 prefix. */
324 memset (&p, 0, sizeof (struct prefix_ipv6));
325 p.family = AF_INET6;
Donald Sharp5e57b5f2016-03-11 16:28:34 -0500326 plength = stream_getc (s);
327 p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, plength);
paul718e3742002-12-13 20:15:29 +0000328 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
329
330 /* Nexthop, ifindex, distance, metric. */
331 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
332 {
333 api.nexthop_num = stream_getc (s);
334 stream_get (&nexthop, s, 16);
335 }
336 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
337 {
338 api.ifindex_num = stream_getc (s);
Stephen Hemminger9206f9e2011-12-18 19:43:40 +0400339 stream_getl (s); /* ifindex, unused */
paul718e3742002-12-13 20:15:29 +0000340 }
341 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
342 api.distance = stream_getc (s);
343 else
344 api.distance = 0;
345 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
346 api.metric = stream_getl (s);
347 else
348 api.metric = 0;
349
350 /* Simply ignore link-local address. */
351 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
352 return 0;
353
354 if (command == ZEBRA_IPV6_ROUTE_ADD)
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000355 {
356 if (BGP_DEBUG(zebra, ZEBRA))
357 {
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400358 char buf[2][INET6_ADDRSTRLEN];
359 zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000360 zebra_route_string(api.type),
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400361 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
362 p.prefixlen,
363 inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
364 api.metric);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000365 }
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400366 bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
367 api.metric, api.type);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000368 }
paul718e3742002-12-13 20:15:29 +0000369 else
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000370 {
371 if (BGP_DEBUG(zebra, ZEBRA))
372 {
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400373 char buf[2][INET6_ADDRSTRLEN];
374 zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d "
375 "nexthop %s metric %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000376 zebra_route_string(api.type),
Stephen Hemmingerf04a80a2011-12-06 14:51:10 +0400377 inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
378 p.prefixlen,
379 inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])),
380 api.metric);
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000381 }
382 bgp_redistribute_delete ((struct prefix *) &p, api.type);
383 }
paul718e3742002-12-13 20:15:29 +0000384
385 return 0;
386}
David Lamparter6b0655a2014-06-04 06:53:35 +0200387
paul718e3742002-12-13 20:15:29 +0000388struct interface *
389if_lookup_by_ipv4 (struct in_addr *addr)
390{
hasso52dc7ee2004-09-23 19:18:23 +0000391 struct listnode *ifnode;
392 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000393 struct interface *ifp;
394 struct connected *connected;
395 struct prefix_ipv4 p;
396 struct prefix *cp;
397
398 p.family = AF_INET;
399 p.prefix = *addr;
400 p.prefixlen = IPV4_MAX_BITLEN;
401
paul1eb8ef22005-04-07 07:30:20 +0000402 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000403 {
paul1eb8ef22005-04-07 07:30:20 +0000404 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000405 {
paul718e3742002-12-13 20:15:29 +0000406 cp = connected->address;
407
408 if (cp->family == AF_INET)
409 if (prefix_match (cp, (struct prefix *)&p))
410 return ifp;
411 }
412 }
413 return NULL;
414}
415
416struct interface *
417if_lookup_by_ipv4_exact (struct in_addr *addr)
418{
hasso52dc7ee2004-09-23 19:18:23 +0000419 struct listnode *ifnode;
420 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000421 struct interface *ifp;
422 struct connected *connected;
423 struct prefix *cp;
424
paul1eb8ef22005-04-07 07:30:20 +0000425 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000426 {
paul1eb8ef22005-04-07 07:30:20 +0000427 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000428 {
paul718e3742002-12-13 20:15:29 +0000429 cp = connected->address;
430
431 if (cp->family == AF_INET)
432 if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
433 return ifp;
434 }
435 }
436 return NULL;
437}
438
paul718e3742002-12-13 20:15:29 +0000439struct interface *
440if_lookup_by_ipv6 (struct in6_addr *addr)
441{
hasso52dc7ee2004-09-23 19:18:23 +0000442 struct listnode *ifnode;
443 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000444 struct interface *ifp;
445 struct connected *connected;
446 struct prefix_ipv6 p;
447 struct prefix *cp;
448
449 p.family = AF_INET6;
450 p.prefix = *addr;
451 p.prefixlen = IPV6_MAX_BITLEN;
452
paul1eb8ef22005-04-07 07:30:20 +0000453 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000454 {
paul1eb8ef22005-04-07 07:30:20 +0000455 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000456 {
paul718e3742002-12-13 20:15:29 +0000457 cp = connected->address;
458
459 if (cp->family == AF_INET6)
460 if (prefix_match (cp, (struct prefix *)&p))
461 return ifp;
462 }
463 }
464 return NULL;
465}
466
467struct interface *
468if_lookup_by_ipv6_exact (struct in6_addr *addr)
469{
hasso52dc7ee2004-09-23 19:18:23 +0000470 struct listnode *ifnode;
471 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000472 struct interface *ifp;
473 struct connected *connected;
474 struct prefix *cp;
475
paul1eb8ef22005-04-07 07:30:20 +0000476 for (ALL_LIST_ELEMENTS_RO (iflist, ifnode, ifp))
paul718e3742002-12-13 20:15:29 +0000477 {
paul1eb8ef22005-04-07 07:30:20 +0000478 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000479 {
paul718e3742002-12-13 20:15:29 +0000480 cp = connected->address;
481
482 if (cp->family == AF_INET6)
483 if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
484 return ifp;
485 }
486 }
487 return NULL;
488}
489
paul94f2b392005-06-28 12:44:16 +0000490static int
paul718e3742002-12-13 20:15:29 +0000491if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
492{
hasso52dc7ee2004-09-23 19:18:23 +0000493 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000494 struct connected *connected;
495 struct prefix *cp;
496
paul1eb8ef22005-04-07 07:30:20 +0000497 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000498 {
paul718e3742002-12-13 20:15:29 +0000499 cp = connected->address;
500
501 if (cp->family == AF_INET6)
502 if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
503 {
504 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
505 return 1;
506 }
507 }
508 return 0;
509}
510
paul94f2b392005-06-28 12:44:16 +0000511static int
paul718e3742002-12-13 20:15:29 +0000512if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
513{
hasso52dc7ee2004-09-23 19:18:23 +0000514 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000515 struct connected *connected;
516 struct prefix *cp;
517
paul1eb8ef22005-04-07 07:30:20 +0000518 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
paul718e3742002-12-13 20:15:29 +0000519 {
paul718e3742002-12-13 20:15:29 +0000520 cp = connected->address;
521
522 if (cp->family == AF_INET6)
523 if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
524 {
525 memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
526 return 1;
527 }
528 }
529 return 0;
530}
paul718e3742002-12-13 20:15:29 +0000531
Pradosh Mohapatra6ee06fa2014-01-12 18:30:13 +0000532static int
533if_get_ipv4_address (struct interface *ifp, struct in_addr *addr)
534{
535 struct listnode *cnode;
536 struct connected *connected;
537 struct prefix *cp;
538
539 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
540 {
541 cp = connected->address;
542 if ((cp->family == AF_INET) && !ipv4_martian(&(cp->u.prefix4)))
543 {
544 *addr = cp->u.prefix4;
545 return 1;
546 }
547 }
548 return 0;
549}
550
paul718e3742002-12-13 20:15:29 +0000551int
552bgp_nexthop_set (union sockunion *local, union sockunion *remote,
553 struct bgp_nexthop *nexthop, struct peer *peer)
554{
555 int ret = 0;
556 struct interface *ifp = NULL;
557
558 memset (nexthop, 0, sizeof (struct bgp_nexthop));
559
560 if (!local)
561 return -1;
562 if (!remote)
563 return -1;
564
565 if (local->sa.sa_family == AF_INET)
566 {
567 nexthop->v4 = local->sin.sin_addr;
568 ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
569 }
paul718e3742002-12-13 20:15:29 +0000570 if (local->sa.sa_family == AF_INET6)
571 {
572 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
573 {
574 if (peer->ifname)
Feng Lu395828e2015-05-22 11:39:55 +0200575 ifp = if_lookup_by_name (peer->ifname);
paul718e3742002-12-13 20:15:29 +0000576 }
577 else
578 ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
579 }
paul718e3742002-12-13 20:15:29 +0000580
581 if (!ifp)
582 return -1;
583
584 nexthop->ifp = ifp;
585
586 /* IPv4 connection. */
587 if (local->sa.sa_family == AF_INET)
588 {
paul718e3742002-12-13 20:15:29 +0000589 /* IPv6 nexthop*/
590 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
591
592 /* There is no global nexthop. */
593 if (!ret)
594 if_get_ipv6_local (ifp, &nexthop->v6_global);
595 else
596 if_get_ipv6_local (ifp, &nexthop->v6_local);
paul718e3742002-12-13 20:15:29 +0000597 }
598
paul718e3742002-12-13 20:15:29 +0000599 /* IPv6 connection. */
600 if (local->sa.sa_family == AF_INET6)
601 {
602 struct interface *direct = NULL;
603
Pradosh Mohapatra6ee06fa2014-01-12 18:30:13 +0000604 /* IPv4 nexthop. */
605 ret = if_get_ipv4_address(ifp, &nexthop->v4);
606 if (!ret && peer->local_id.s_addr)
paul718e3742002-12-13 20:15:29 +0000607 nexthop->v4 = peer->local_id;
608
609 /* Global address*/
610 if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
611 {
612 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
613 IPV6_MAX_BYTELEN);
614
615 /* If directory connected set link-local address. */
616 direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
617 if (direct)
618 if_get_ipv6_local (ifp, &nexthop->v6_local);
619 }
620 else
621 /* Link-local address. */
622 {
623 ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
624
625 /* If there is no global address. Set link-local address as
626 global. I know this break RFC specification... */
627 if (!ret)
628 memcpy (&nexthop->v6_global, &local->sin6.sin6_addr,
629 IPV6_MAX_BYTELEN);
630 else
631 memcpy (&nexthop->v6_local, &local->sin6.sin6_addr,
632 IPV6_MAX_BYTELEN);
633 }
634 }
635
636 if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
637 if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
638 peer->shared_network = 1;
639 else
640 peer->shared_network = 0;
641
642 /* KAME stack specific treatment. */
643#ifdef KAME
644 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
645 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
646 {
647 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
648 }
649 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
650 && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
651 {
652 SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
653 }
654#endif /* KAME */
paul718e3742002-12-13 20:15:29 +0000655 return ret;
656}
657
paul718e3742002-12-13 20:15:29 +0000658void
G.Balaji5a616c02011-11-26 21:58:42 +0400659bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi)
paul718e3742002-12-13 20:15:29 +0000660{
661 int flags;
662 u_char distance;
663 struct peer *peer;
Josh Bailey8196f132011-07-20 20:47:07 -0700664 struct bgp_info *mpinfo;
665 size_t oldsize, newsize;
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500666 u_int32_t nhcount;
paul718e3742002-12-13 20:15:29 +0000667
668 if (zclient->sock < 0)
669 return;
670
Feng Luc99f3482014-10-16 09:52:36 +0800671 if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000672 return;
673
674 flags = 0;
675 peer = info->peer;
676
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000677 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
paul718e3742002-12-13 20:15:29 +0000678 {
679 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
680 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
681 }
682
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000683 if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
hasso6ffd2072005-02-02 14:50:11 +0000684 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000685 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
686
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500687 nhcount = 1 + bgp_info_mpath_count (info);
Josh Bailey8196f132011-07-20 20:47:07 -0700688
paul718e3742002-12-13 20:15:29 +0000689 if (p->family == AF_INET)
690 {
691 struct zapi_ipv4 api;
692 struct in_addr *nexthop;
693
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500694 /* resize nexthop buffer size if necessary */
695 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
696 (sizeof (struct in_addr *) * nhcount))
697 {
698 newsize = (sizeof (struct in_addr *) * nhcount);
699 newsize = stream_resize (bgp_nexthop_buf, newsize);
700 if (newsize == oldsize)
701 {
702 zlog_err ("can't resize nexthop buffer");
703 return;
704 }
705 }
706 stream_reset (bgp_nexthop_buf);
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);
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500723 api.nexthop_num = nhcount;
Josh Bailey8196f132011-07-20 20:47:07 -0700724 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;
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500763 int valid_nh_count = 0;
764
765 /* resize nexthop buffer size if necessary */
766 if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
767 (sizeof (struct in6_addr *) * nhcount))
768 {
769 newsize = (sizeof (struct in6_addr *) * nhcount);
770 newsize = stream_resize (bgp_nexthop_buf, newsize);
771 if (newsize == oldsize)
772 {
773 zlog_err ("can't resize nexthop buffer");
774 return;
775 }
776 }
777 stream_reset (bgp_nexthop_buf);
778
779 /* resize ifindices buffer size if necessary */
780 if ((oldsize = stream_get_size (bgp_ifindices_buf)) <
781 (sizeof (unsigned int) * nhcount))
782 {
783 newsize = (sizeof (unsigned int) * nhcount);
784 newsize = stream_resize (bgp_ifindices_buf, newsize);
785 if (newsize == oldsize)
786 {
787 zlog_err ("can't resize nexthop buffer");
788 return;
789 }
790 }
791 stream_reset (bgp_ifindices_buf);
paul718e3742002-12-13 20:15:29 +0000792
793 ifindex = 0;
794 nexthop = NULL;
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500795
Paul Jakmafb982c22007-05-04 20:15:47 +0000796 assert (info->attr->extra);
797
paul718e3742002-12-13 20:15:29 +0000798 /* Only global address nexthop exists. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000799 if (info->attr->extra->mp_nexthop_len == 16)
800 nexthop = &info->attr->extra->mp_nexthop_global;
paul718e3742002-12-13 20:15:29 +0000801
802 /* If both global and link-local address present. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000803 if (info->attr->extra->mp_nexthop_len == 32)
paul718e3742002-12-13 20:15:29 +0000804 {
805 /* Workaround for Cisco's nexthop bug. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000806 if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
paul718e3742002-12-13 20:15:29 +0000807 && peer->su_remote->sa.sa_family == AF_INET6)
808 nexthop = &peer->su_remote->sin6.sin6_addr;
809 else
Paul Jakmafb982c22007-05-04 20:15:47 +0000810 nexthop = &info->attr->extra->mp_nexthop_local;
paul718e3742002-12-13 20:15:29 +0000811
812 if (info->peer->nexthop.ifp)
813 ifindex = info->peer->nexthop.ifp->ifindex;
814 }
815
816 if (nexthop == NULL)
817 return;
818
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500819 if (!ifindex)
paul718e3742002-12-13 20:15:29 +0000820 {
821 if (info->peer->ifname)
Feng Lu395828e2015-05-22 11:39:55 +0200822 ifindex = ifname2ifindex (info->peer->ifname);
paul718e3742002-12-13 20:15:29 +0000823 else if (info->peer->nexthop.ifp)
824 ifindex = info->peer->nexthop.ifp->ifindex;
825 }
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500826 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
827 stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
828 valid_nh_count++;
829
830 for (mpinfo = bgp_info_mpath_first (info); mpinfo;
831 mpinfo = bgp_info_mpath_next (mpinfo))
832 {
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500833 ifindex = 0;
834
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500835 /* Only global address nexthop exists. */
836 if (mpinfo->attr->extra->mp_nexthop_len == 16)
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500837 nexthop = &mpinfo->attr->extra->mp_nexthop_global;
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500838
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500839 /* If both global and link-local address present. */
840 if (mpinfo->attr->extra->mp_nexthop_len == 32)
841 {
842 /* Workaround for Cisco's nexthop bug. */
843 if (IN6_IS_ADDR_UNSPECIFIED (&mpinfo->attr->extra->mp_nexthop_global)
844 && mpinfo->peer->su_remote->sa.sa_family == AF_INET6)
845 {
846 nexthop = &mpinfo->peer->su_remote->sin6.sin6_addr;
847 }
848 else
849 {
850 nexthop = &mpinfo->attr->extra->mp_nexthop_local;
851 }
852
853 if (mpinfo->peer->nexthop.ifp)
854 {
855 ifindex = mpinfo->peer->nexthop.ifp->ifindex;
856 }
857 }
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500858
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500859 if (nexthop == NULL)
860 {
861 continue;
862 }
863
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500864 if (!ifindex)
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500865 {
866 if (mpinfo->peer->ifname)
867 {
868 ifindex = if_nametoindex (mpinfo->peer->ifname);
869 }
870 else if (mpinfo->peer->nexthop.ifp)
871 {
872 ifindex = mpinfo->peer->nexthop.ifp->ifindex;
873 }
874 }
Dinesh Dutt4feb0d02015-11-09 20:14:55 -0500875
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500876 if (ifindex == 0)
877 {
878 continue;
879 }
880
881 stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
882 stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
883 valid_nh_count++;
884 }
paul718e3742002-12-13 20:15:29 +0000885
886 /* Make Zebra API structure. */
Feng Luc99f3482014-10-16 09:52:36 +0800887 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000888 api.flags = flags;
889 api.type = ZEBRA_ROUTE_BGP;
890 api.message = 0;
G.Balajic7ec1792011-11-26 22:04:05 +0400891 api.safi = safi;
paul718e3742002-12-13 20:15:29 +0000892 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500893 api.nexthop_num = valid_nh_count;
894 api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
paul718e3742002-12-13 20:15:29 +0000895 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -0500896 api.ifindex_num = valid_nh_count;
897 api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
paul718e3742002-12-13 20:15:29 +0000898 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
899 api.metric = info->attr->med;
900
Roman Hoog Antink6184c392014-03-17 14:01:42 +0100901 distance = ipv6_bgp_distance_apply (p, info, bgp);
902
903 if (distance)
904 {
905 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
906 api.distance = distance;
907 }
908
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000909 if (BGP_DEBUG(zebra, ZEBRA))
910 {
911 char buf[2][INET6_ADDRSTRLEN];
912 zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u",
913 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
914 p->prefixlen,
915 inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
916 api.metric);
917 }
918
paul0a589352004-05-08 11:48:26 +0000919 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
920 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000921 }
paul718e3742002-12-13 20:15:29 +0000922}
923
924void
G.Balaji5a616c02011-11-26 21:58:42 +0400925bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
paul718e3742002-12-13 20:15:29 +0000926{
927 int flags;
928 struct peer *peer;
929
930 if (zclient->sock < 0)
931 return;
932
Feng Luc99f3482014-10-16 09:52:36 +0800933 if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +0000934 return;
935
936 peer = info->peer;
937 flags = 0;
938
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000939 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000940 {
941 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
942 SET_FLAG (flags, ZEBRA_FLAG_IBGP);
943 }
944
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000945 if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
hasso6ffd2072005-02-02 14:50:11 +0000946 || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +0000947 SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
948
949 if (p->family == AF_INET)
950 {
951 struct zapi_ipv4 api;
paul718e3742002-12-13 20:15:29 +0000952
Feng Luc99f3482014-10-16 09:52:36 +0800953 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000954 api.flags = flags;
paul718e3742002-12-13 20:15:29 +0000955
956 api.type = ZEBRA_ROUTE_BGP;
957 api.message = 0;
G.Balaji5a616c02011-11-26 21:58:42 +0400958 api.safi = safi;
Paul Jakma64e0ac22015-11-18 16:00:54 +0000959 api.nexthop_num = 0;
paul718e3742002-12-13 20:15:29 +0000960 api.ifindex_num = 0;
961 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
962 api.metric = info->attr->med;
963
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000964 if (BGP_DEBUG(zebra, ZEBRA))
965 {
966 char buf[2][INET_ADDRSTRLEN];
Paul Jakma64e0ac22015-11-18 16:00:54 +0000967 zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000968 inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
969 p->prefixlen,
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000970 api.metric);
971 }
972
paul0a589352004-05-08 11:48:26 +0000973 zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
974 (struct prefix_ipv4 *) p, &api);
paul718e3742002-12-13 20:15:29 +0000975 }
Lou Berger205e6742016-01-12 13:42:11 -0500976
paul718e3742002-12-13 20:15:29 +0000977 /* We have to think about a IPv6 link-local address curse. */
978 if (p->family == AF_INET6)
979 {
980 struct zapi_ipv6 api;
Paul Jakmafb982c22007-05-04 20:15:47 +0000981
Feng Luc99f3482014-10-16 09:52:36 +0800982 api.vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000983 api.flags = flags;
984 api.type = ZEBRA_ROUTE_BGP;
985 api.message = 0;
G.Balajic7ec1792011-11-26 22:04:05 +0400986 api.safi = safi;
Paul Jakma64e0ac22015-11-18 16:00:54 +0000987 api.nexthop_num = 0;
988 api.ifindex_num = 0;
paul718e3742002-12-13 20:15:29 +0000989 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
990 api.metric = info->attr->med;
991
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000992 if (BGP_DEBUG(zebra, ZEBRA))
993 {
994 char buf[2][INET6_ADDRSTRLEN];
Paul Jakma64e0ac22015-11-18 16:00:54 +0000995 zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u",
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000996 inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
997 p->prefixlen,
Andrew J. Schorra39275d2006-11-30 16:36:57 +0000998 api.metric);
999 }
1000
paul0a589352004-05-08 11:48:26 +00001001 zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
1002 (struct prefix_ipv6 *) p, &api);
paul718e3742002-12-13 20:15:29 +00001003 }
paul718e3742002-12-13 20:15:29 +00001004}
David Lamparter6b0655a2014-06-04 06:53:35 +02001005
paul718e3742002-12-13 20:15:29 +00001006/* Other routes redistribution into BGP. */
1007int
1008bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
1009{
1010 /* Set flag to BGP instance. */
1011 bgp->redist[afi][type] = 1;
1012
1013 /* Return if already redistribute flag is set. */
Feng Luc99f3482014-10-16 09:52:36 +08001014 if (vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001015 return CMD_WARNING;
1016
Feng Luc99f3482014-10-16 09:52:36 +08001017 vrf_bitmap_set (zclient->redist[type], VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00001018
1019 /* Return if zebra connection is not established. */
1020 if (zclient->sock < 0)
1021 return CMD_WARNING;
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001022
1023 if (BGP_DEBUG(zebra, ZEBRA))
1024 zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
paul718e3742002-12-13 20:15:29 +00001025
1026 /* Send distribute add message to zebra. */
Feng Luc99f3482014-10-16 09:52:36 +08001027 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00001028
1029 return CMD_SUCCESS;
1030}
1031
1032/* Redistribute with route-map specification. */
1033int
paulfd79ac92004-10-13 05:06:08 +00001034bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
1035 const char *name)
paul718e3742002-12-13 20:15:29 +00001036{
1037 if (bgp->rmap[afi][type].name
1038 && (strcmp (bgp->rmap[afi][type].name, name) == 0))
1039 return 0;
1040
1041 if (bgp->rmap[afi][type].name)
1042 free (bgp->rmap[afi][type].name);
1043 bgp->rmap[afi][type].name = strdup (name);
1044 bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
1045
1046 return 1;
1047}
1048
1049/* Redistribute with metric specification. */
1050int
1051bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
1052 u_int32_t metric)
1053{
1054 if (bgp->redist_metric_flag[afi][type]
1055 && bgp->redist_metric[afi][type] == metric)
1056 return 0;
1057
1058 bgp->redist_metric_flag[afi][type] = 1;
1059 bgp->redist_metric[afi][type] = metric;
1060
1061 return 1;
1062}
1063
1064/* Unset redistribution. */
1065int
1066bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
1067{
1068 /* Unset flag from BGP instance. */
1069 bgp->redist[afi][type] = 0;
1070
1071 /* Unset route-map. */
1072 if (bgp->rmap[afi][type].name)
1073 free (bgp->rmap[afi][type].name);
1074 bgp->rmap[afi][type].name = NULL;
1075 bgp->rmap[afi][type].map = NULL;
1076
1077 /* Unset metric. */
1078 bgp->redist_metric_flag[afi][type] = 0;
1079 bgp->redist_metric[afi][type] = 0;
1080
1081 /* Return if zebra connection is disabled. */
Feng Luc99f3482014-10-16 09:52:36 +08001082 if (! vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT))
paul718e3742002-12-13 20:15:29 +00001083 return CMD_WARNING;
Feng Luc99f3482014-10-16 09:52:36 +08001084 vrf_bitmap_unset (zclient->redist[type], VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +00001085
1086 if (bgp->redist[AFI_IP][type] == 0
1087 && bgp->redist[AFI_IP6][type] == 0
1088 && zclient->sock >= 0)
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001089 {
1090 /* Send distribute delete message to zebra. */
1091 if (BGP_DEBUG(zebra, ZEBRA))
1092 zlog_debug("Zebra send: redistribute delete %s",
1093 zebra_route_string(type));
Feng Luc99f3482014-10-16 09:52:36 +08001094 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type,
1095 VRF_DEFAULT);
Andrew J. Schorra39275d2006-11-30 16:36:57 +00001096 }
paul718e3742002-12-13 20:15:29 +00001097
1098 /* Withdraw redistributed routes from current BGP's routing table. */
1099 bgp_redistribute_withdraw (bgp, afi, type);
1100
1101 return CMD_SUCCESS;
1102}
1103
1104/* Unset redistribution route-map configuration. */
1105int
1106bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
1107{
1108 if (! bgp->rmap[afi][type].name)
1109 return 0;
1110
1111 /* Unset route-map. */
1112 free (bgp->rmap[afi][type].name);
1113 bgp->rmap[afi][type].name = NULL;
1114 bgp->rmap[afi][type].map = NULL;
1115
1116 return 1;
1117}
1118
1119/* Unset redistribution metric configuration. */
1120int
1121bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
1122{
1123 if (! bgp->redist_metric_flag[afi][type])
1124 return 0;
1125
1126 /* Unset metric. */
1127 bgp->redist_metric_flag[afi][type] = 0;
1128 bgp->redist_metric[afi][type] = 0;
1129
1130 return 1;
1131}
David Lamparter6b0655a2014-06-04 06:53:35 +02001132
paul718e3742002-12-13 20:15:29 +00001133void
paul94f2b392005-06-28 12:44:16 +00001134bgp_zclient_reset (void)
paul718e3742002-12-13 20:15:29 +00001135{
1136 zclient_reset (zclient);
1137}
1138
Feng Luc99f3482014-10-16 09:52:36 +08001139static void
1140bgp_zebra_connected (struct zclient *zclient)
1141{
1142 zclient_send_requests (zclient, VRF_DEFAULT);
1143}
1144
paul718e3742002-12-13 20:15:29 +00001145void
Donald Sharp71252932015-09-24 09:25:19 -04001146bgp_zebra_init (struct thread_master *master)
paul718e3742002-12-13 20:15:29 +00001147{
1148 /* Set default values. */
Donald Sharp71252932015-09-24 09:25:19 -04001149 zclient = zclient_new (master);
paul718e3742002-12-13 20:15:29 +00001150 zclient_init (zclient, ZEBRA_ROUTE_BGP);
Feng Luc99f3482014-10-16 09:52:36 +08001151 zclient->zebra_connected = bgp_zebra_connected;
hasso18a6dce2004-10-03 18:18:34 +00001152 zclient->router_id_update = bgp_router_id_update;
paul718e3742002-12-13 20:15:29 +00001153 zclient->interface_add = bgp_interface_add;
1154 zclient->interface_delete = bgp_interface_delete;
1155 zclient->interface_address_add = bgp_interface_address_add;
1156 zclient->interface_address_delete = bgp_interface_address_delete;
1157 zclient->ipv4_route_add = zebra_read_ipv4;
1158 zclient->ipv4_route_delete = zebra_read_ipv4;
1159 zclient->interface_up = bgp_interface_up;
1160 zclient->interface_down = bgp_interface_down;
paul718e3742002-12-13 20:15:29 +00001161 zclient->ipv6_route_add = zebra_read_ipv6;
1162 zclient->ipv6_route_delete = zebra_read_ipv6;
paul718e3742002-12-13 20:15:29 +00001163
Josh Bailey8196f132011-07-20 20:47:07 -07001164 bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
Ayan Banerjeeb8d1f712015-11-09 20:14:54 -05001165 bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
paul718e3742002-12-13 20:15:29 +00001166}
Lou Berger82dd7072016-01-12 13:41:57 -05001167
1168void
1169bgp_zebra_destroy(void)
1170{
1171 if (zclient == NULL)
1172 return;
1173 zclient_stop(zclient);
1174 zclient_free(zclient);
1175 zclient = NULL;
1176}