Line data Source code
1 : /* BGP-4, BGP-4+ daemon program
2 : Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3 :
4 : This file is part of GNU Zebra.
5 :
6 : GNU Zebra is free software; you can redistribute it and/or modify it
7 : under the terms of the GNU General Public License as published by the
8 : Free Software Foundation; either version 2, or (at your option) any
9 : later version.
10 :
11 : GNU Zebra is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GNU Zebra; see the file COPYING. If not, write to the Free
18 : Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 : 02111-1307, USA. */
20 :
21 : #include <zebra.h>
22 :
23 : #include "prefix.h"
24 : #include "thread.h"
25 : #include "buffer.h"
26 : #include "stream.h"
27 : #include "command.h"
28 : #include "sockunion.h"
29 : #include "network.h"
30 : #include "memory.h"
31 : #include "filter.h"
32 : #include "routemap.h"
33 : #include "str.h"
34 : #include "log.h"
35 : #include "plist.h"
36 : #include "linklist.h"
37 : #include "workqueue.h"
38 :
39 : #include "bgpd/bgpd.h"
40 : #include "bgpd/bgp_table.h"
41 : #include "bgpd/bgp_aspath.h"
42 : #include "bgpd/bgp_route.h"
43 : #include "bgpd/bgp_dump.h"
44 : #include "bgpd/bgp_debug.h"
45 : #include "bgpd/bgp_community.h"
46 : #include "bgpd/bgp_attr.h"
47 : #include "bgpd/bgp_regex.h"
48 : #include "bgpd/bgp_clist.h"
49 : #include "bgpd/bgp_fsm.h"
50 : #include "bgpd/bgp_packet.h"
51 : #include "bgpd/bgp_zebra.h"
52 : #include "bgpd/bgp_open.h"
53 : #include "bgpd/bgp_filter.h"
54 : #include "bgpd/bgp_nexthop.h"
55 : #include "bgpd/bgp_damp.h"
56 : #include "bgpd/bgp_mplsvpn.h"
57 : #include "bgpd/bgp_advertise.h"
58 : #include "bgpd/bgp_network.h"
59 : #include "bgpd/bgp_vty.h"
60 : #include "bgpd/bgp_mpath.h"
61 : #ifdef HAVE_SNMP
62 : #include "bgpd/bgp_snmp.h"
63 : #endif /* HAVE_SNMP */
64 :
65 : /* BGP process wide configuration. */
66 : static struct bgp_master bgp_master;
67 :
68 : extern struct in_addr router_id_zebra;
69 :
70 : /* BGP process wide configuration pointer to export. */
71 : struct bgp_master *bm;
72 :
73 : /* BGP community-list. */
74 : struct community_list_handler *bgp_clist;
75 :
76 : /* BGP global flag manipulation. */
77 : int
78 4 : bgp_option_set (int flag)
79 : {
80 4 : switch (flag)
81 : {
82 : case BGP_OPT_NO_FIB:
83 : case BGP_OPT_MULTIPLE_INSTANCE:
84 : case BGP_OPT_CONFIG_CISCO:
85 : case BGP_OPT_NO_LISTEN:
86 4 : SET_FLAG (bm->options, flag);
87 4 : break;
88 : default:
89 0 : return BGP_ERR_INVALID_FLAG;
90 : }
91 4 : return 0;
92 : }
93 :
94 : int
95 0 : bgp_option_unset (int flag)
96 : {
97 0 : switch (flag)
98 : {
99 : case BGP_OPT_MULTIPLE_INSTANCE:
100 0 : if (listcount (bm->bgp) > 1)
101 0 : return BGP_ERR_MULTIPLE_INSTANCE_USED;
102 : /* Fall through. */
103 : case BGP_OPT_NO_FIB:
104 : case BGP_OPT_CONFIG_CISCO:
105 0 : UNSET_FLAG (bm->options, flag);
106 0 : break;
107 : default:
108 0 : return BGP_ERR_INVALID_FLAG;
109 : }
110 0 : return 0;
111 : }
112 :
113 : int
114 36 : bgp_option_check (int flag)
115 : {
116 36 : return CHECK_FLAG (bm->options, flag);
117 : }
118 :
119 : /* BGP flag manipulation. */
120 : int
121 0 : bgp_flag_set (struct bgp *bgp, int flag)
122 : {
123 0 : SET_FLAG (bgp->flags, flag);
124 0 : return 0;
125 : }
126 :
127 : int
128 0 : bgp_flag_unset (struct bgp *bgp, int flag)
129 : {
130 0 : UNSET_FLAG (bgp->flags, flag);
131 0 : return 0;
132 : }
133 :
134 : int
135 37 : bgp_flag_check (struct bgp *bgp, int flag)
136 : {
137 37 : return CHECK_FLAG (bgp->flags, flag);
138 : }
139 :
140 : /* Internal function to set BGP structure configureation flag. */
141 : static void
142 2 : bgp_config_set (struct bgp *bgp, int config)
143 : {
144 2 : SET_FLAG (bgp->config, config);
145 2 : }
146 :
147 : static void
148 0 : bgp_config_unset (struct bgp *bgp, int config)
149 : {
150 0 : UNSET_FLAG (bgp->config, config);
151 0 : }
152 :
153 : static int
154 2 : bgp_config_check (struct bgp *bgp, int config)
155 : {
156 2 : return CHECK_FLAG (bgp->config, config);
157 : }
158 :
159 : /* Set BGP router identifier. */
160 : int
161 2 : bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
162 : {
163 : struct peer *peer;
164 : struct listnode *node, *nnode;
165 :
166 2 : if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
167 0 : && IPV4_ADDR_SAME (&bgp->router_id, id))
168 0 : return 0;
169 :
170 2 : IPV4_ADDR_COPY (&bgp->router_id, id);
171 2 : bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
172 :
173 : /* Set all peer's local identifier with this value. */
174 2 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
175 : {
176 0 : IPV4_ADDR_COPY (&peer->local_id, id);
177 :
178 0 : if (peer->status == Established)
179 : {
180 0 : peer->last_reset = PEER_DOWN_RID_CHANGE;
181 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
182 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
183 : }
184 : }
185 2 : return 0;
186 : }
187 :
188 : /* BGP's cluster-id control. */
189 : int
190 0 : bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
191 : {
192 : struct peer *peer;
193 : struct listnode *node, *nnode;
194 :
195 0 : if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
196 0 : && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
197 0 : return 0;
198 :
199 0 : IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
200 0 : bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
201 :
202 : /* Clear all IBGP peer. */
203 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
204 : {
205 0 : if (peer->sort != BGP_PEER_IBGP)
206 0 : continue;
207 :
208 0 : if (peer->status == Established)
209 : {
210 0 : peer->last_reset = PEER_DOWN_CLID_CHANGE;
211 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
212 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
213 : }
214 : }
215 0 : return 0;
216 : }
217 :
218 : int
219 0 : bgp_cluster_id_unset (struct bgp *bgp)
220 : {
221 : struct peer *peer;
222 : struct listnode *node, *nnode;
223 :
224 0 : if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
225 0 : return 0;
226 :
227 0 : bgp->cluster_id.s_addr = 0;
228 0 : bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
229 :
230 : /* Clear all IBGP peer. */
231 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
232 : {
233 0 : if (peer->sort != BGP_PEER_IBGP)
234 0 : continue;
235 :
236 0 : if (peer->status == Established)
237 : {
238 0 : peer->last_reset = PEER_DOWN_CLID_CHANGE;
239 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
240 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
241 : }
242 : }
243 0 : return 0;
244 : }
245 :
246 : /* time_t value that is monotonicly increasing
247 : * and uneffected by adjustments to system clock
248 : */
249 4 : time_t bgp_clock (void)
250 : {
251 : struct timeval tv;
252 :
253 4 : quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
254 4 : return tv.tv_sec;
255 : }
256 :
257 : /* BGP timer configuration. */
258 : int
259 0 : bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
260 : {
261 0 : bgp->default_keepalive = (keepalive < holdtime / 3
262 0 : ? keepalive : holdtime / 3);
263 0 : bgp->default_holdtime = holdtime;
264 :
265 0 : return 0;
266 : }
267 :
268 : int
269 0 : bgp_timers_unset (struct bgp *bgp)
270 : {
271 0 : bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
272 0 : bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
273 :
274 0 : return 0;
275 : }
276 :
277 : /* BGP confederation configuration. */
278 : int
279 0 : bgp_confederation_id_set (struct bgp *bgp, as_t as)
280 : {
281 : struct peer *peer;
282 : struct listnode *node, *nnode;
283 : int already_confed;
284 :
285 0 : if (as == 0)
286 0 : return BGP_ERR_INVALID_AS;
287 :
288 : /* Remember - were we doing confederation before? */
289 0 : already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
290 0 : bgp->confed_id = as;
291 0 : bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
292 :
293 : /* If we were doing confederation already, this is just an external
294 : AS change. Just Reset EBGP sessions, not CONFED sessions. If we
295 : were not doing confederation before, reset all EBGP sessions. */
296 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
297 : {
298 : /* We're looking for peers who's AS is not local or part of our
299 : confederation. */
300 0 : if (already_confed)
301 : {
302 0 : if (peer_sort (peer) == BGP_PEER_EBGP)
303 : {
304 0 : peer->local_as = as;
305 0 : if (peer->status == Established)
306 : {
307 0 : peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
308 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
309 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
310 : }
311 :
312 : else
313 0 : BGP_EVENT_ADD (peer, BGP_Stop);
314 : }
315 : }
316 : else
317 : {
318 : /* Not doign confederation before, so reset every non-local
319 : session */
320 0 : if (peer_sort (peer) != BGP_PEER_IBGP)
321 : {
322 : /* Reset the local_as to be our EBGP one */
323 0 : if (peer_sort (peer) == BGP_PEER_EBGP)
324 0 : peer->local_as = as;
325 0 : if (peer->status == Established)
326 : {
327 0 : peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
328 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
329 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
330 : }
331 : else
332 0 : BGP_EVENT_ADD (peer, BGP_Stop);
333 : }
334 : }
335 : }
336 0 : return 0;
337 : }
338 :
339 : int
340 0 : bgp_confederation_id_unset (struct bgp *bgp)
341 : {
342 : struct peer *peer;
343 : struct listnode *node, *nnode;
344 :
345 0 : bgp->confed_id = 0;
346 0 : bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
347 :
348 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
349 : {
350 : /* We're looking for peers who's AS is not local */
351 0 : if (peer_sort (peer) != BGP_PEER_IBGP)
352 : {
353 0 : peer->local_as = bgp->as;
354 0 : if (peer->status == Established)
355 : {
356 0 : peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
357 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
358 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
359 : }
360 :
361 : else
362 0 : BGP_EVENT_ADD (peer, BGP_Stop);
363 : }
364 : }
365 0 : return 0;
366 : }
367 :
368 : /* Is an AS part of the confed or not? */
369 : int
370 0 : bgp_confederation_peers_check (struct bgp *bgp, as_t as)
371 : {
372 : int i;
373 :
374 0 : if (! bgp)
375 0 : return 0;
376 :
377 0 : for (i = 0; i < bgp->confed_peers_cnt; i++)
378 0 : if (bgp->confed_peers[i] == as)
379 0 : return 1;
380 :
381 0 : return 0;
382 : }
383 :
384 : /* Add an AS to the confederation set. */
385 : int
386 0 : bgp_confederation_peers_add (struct bgp *bgp, as_t as)
387 : {
388 : struct peer *peer;
389 : struct listnode *node, *nnode;
390 :
391 0 : if (! bgp)
392 0 : return BGP_ERR_INVALID_BGP;
393 :
394 0 : if (bgp->as == as)
395 0 : return BGP_ERR_INVALID_AS;
396 :
397 0 : if (bgp_confederation_peers_check (bgp, as))
398 0 : return -1;
399 :
400 0 : if (bgp->confed_peers)
401 0 : bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
402 : bgp->confed_peers,
403 : (bgp->confed_peers_cnt + 1) * sizeof (as_t));
404 : else
405 0 : bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
406 : (bgp->confed_peers_cnt + 1) * sizeof (as_t));
407 :
408 0 : bgp->confed_peers[bgp->confed_peers_cnt] = as;
409 0 : bgp->confed_peers_cnt++;
410 :
411 0 : if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
412 : {
413 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
414 : {
415 0 : if (peer->as == as)
416 : {
417 0 : peer->local_as = bgp->as;
418 0 : if (peer->status == Established)
419 : {
420 0 : peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
421 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
422 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
423 : }
424 : else
425 0 : BGP_EVENT_ADD (peer, BGP_Stop);
426 : }
427 : }
428 : }
429 0 : return 0;
430 : }
431 :
432 : /* Delete an AS from the confederation set. */
433 : int
434 0 : bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
435 : {
436 : int i;
437 : int j;
438 : struct peer *peer;
439 : struct listnode *node, *nnode;
440 :
441 0 : if (! bgp)
442 0 : return -1;
443 :
444 0 : if (! bgp_confederation_peers_check (bgp, as))
445 0 : return -1;
446 :
447 0 : for (i = 0; i < bgp->confed_peers_cnt; i++)
448 0 : if (bgp->confed_peers[i] == as)
449 0 : for(j = i + 1; j < bgp->confed_peers_cnt; j++)
450 0 : bgp->confed_peers[j - 1] = bgp->confed_peers[j];
451 :
452 0 : bgp->confed_peers_cnt--;
453 :
454 0 : if (bgp->confed_peers_cnt == 0)
455 : {
456 0 : if (bgp->confed_peers)
457 0 : XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
458 0 : bgp->confed_peers = NULL;
459 : }
460 : else
461 0 : bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
462 : bgp->confed_peers,
463 : bgp->confed_peers_cnt * sizeof (as_t));
464 :
465 : /* Now reset any peer who's remote AS has just been removed from the
466 : CONFED */
467 0 : if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
468 : {
469 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
470 : {
471 0 : if (peer->as == as)
472 : {
473 0 : peer->local_as = bgp->confed_id;
474 0 : if (peer->status == Established)
475 : {
476 0 : peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
477 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
478 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
479 : }
480 : else
481 0 : BGP_EVENT_ADD (peer, BGP_Stop);
482 : }
483 : }
484 : }
485 :
486 0 : return 0;
487 : }
488 :
489 : /* Local preference configuration. */
490 : int
491 0 : bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
492 : {
493 0 : if (! bgp)
494 0 : return -1;
495 :
496 0 : bgp->default_local_pref = local_pref;
497 :
498 0 : return 0;
499 : }
500 :
501 : int
502 0 : bgp_default_local_preference_unset (struct bgp *bgp)
503 : {
504 0 : if (! bgp)
505 0 : return -1;
506 :
507 0 : bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
508 :
509 0 : return 0;
510 : }
511 :
512 : /* If peer is RSERVER_CLIENT in at least one address family and is not member
513 : of a peer_group for that family, return 1.
514 : Used to check wether the peer is included in list bgp->rsclient. */
515 : int
516 0 : peer_rsclient_active (struct peer *peer)
517 : {
518 : int i;
519 : int j;
520 :
521 0 : for (i=AFI_IP; i < AFI_MAX; i++)
522 0 : for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
523 0 : if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
524 0 : && ! peer->af_group[i][j])
525 0 : return 1;
526 0 : return 0;
527 : }
528 :
529 : /* Peer comparison function for sorting. */
530 : static int
531 0 : peer_cmp (struct peer *p1, struct peer *p2)
532 : {
533 0 : return sockunion_cmp (&p1->su, &p2->su);
534 : }
535 :
536 : int
537 0 : peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
538 : {
539 0 : return CHECK_FLAG (peer->af_flags[afi][safi], flag);
540 : }
541 :
542 : /* Reset all address family specific configuration. */
543 : static void
544 0 : peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
545 : {
546 : int i;
547 : struct bgp_filter *filter;
548 : char orf_name[BUFSIZ];
549 :
550 0 : filter = &peer->filter[afi][safi];
551 :
552 : /* Clear neighbor filter and route-map */
553 0 : for (i = FILTER_IN; i < FILTER_MAX; i++)
554 : {
555 0 : if (filter->dlist[i].name)
556 : {
557 0 : free (filter->dlist[i].name);
558 0 : filter->dlist[i].name = NULL;
559 : }
560 0 : if (filter->plist[i].name)
561 : {
562 0 : free (filter->plist[i].name);
563 0 : filter->plist[i].name = NULL;
564 : }
565 0 : if (filter->aslist[i].name)
566 : {
567 0 : free (filter->aslist[i].name);
568 0 : filter->aslist[i].name = NULL;
569 : }
570 : }
571 0 : for (i = RMAP_IN; i < RMAP_MAX; i++)
572 : {
573 0 : if (filter->map[i].name)
574 : {
575 0 : free (filter->map[i].name);
576 0 : filter->map[i].name = NULL;
577 : }
578 : }
579 :
580 : /* Clear unsuppress map. */
581 0 : if (filter->usmap.name)
582 0 : free (filter->usmap.name);
583 0 : filter->usmap.name = NULL;
584 0 : filter->usmap.map = NULL;
585 :
586 : /* Clear neighbor's all address family flags. */
587 0 : peer->af_flags[afi][safi] = 0;
588 :
589 : /* Clear neighbor's all address family sflags. */
590 0 : peer->af_sflags[afi][safi] = 0;
591 :
592 : /* Clear neighbor's all address family capabilities. */
593 0 : peer->af_cap[afi][safi] = 0;
594 :
595 : /* Clear ORF info */
596 0 : peer->orf_plist[afi][safi] = NULL;
597 0 : sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
598 0 : prefix_bgp_orf_remove_all (orf_name);
599 :
600 : /* Set default neighbor send-community. */
601 0 : if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
602 : {
603 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
604 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
605 : }
606 :
607 : /* Clear neighbor default_originate_rmap */
608 0 : if (peer->default_rmap[afi][safi].name)
609 0 : free (peer->default_rmap[afi][safi].name);
610 0 : peer->default_rmap[afi][safi].name = NULL;
611 0 : peer->default_rmap[afi][safi].map = NULL;
612 :
613 : /* Clear neighbor maximum-prefix */
614 0 : peer->pmax[afi][safi] = 0;
615 0 : peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
616 0 : }
617 :
618 : /* peer global config reset */
619 : static void
620 0 : peer_global_config_reset (struct peer *peer)
621 : {
622 0 : peer->weight = 0;
623 0 : peer->change_local_as = 0;
624 0 : peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
625 0 : if (peer->update_source)
626 : {
627 0 : sockunion_free (peer->update_source);
628 0 : peer->update_source = NULL;
629 : }
630 0 : if (peer->update_if)
631 : {
632 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
633 0 : peer->update_if = NULL;
634 : }
635 :
636 0 : if (peer_sort (peer) == BGP_PEER_IBGP)
637 0 : peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
638 : else
639 0 : peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
640 :
641 0 : peer->flags = 0;
642 0 : peer->config = 0;
643 0 : peer->holdtime = 0;
644 0 : peer->keepalive = 0;
645 0 : peer->connect = 0;
646 0 : peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
647 0 : }
648 :
649 : /* Check peer's AS number and determines if this peer is IBGP or EBGP */
650 : static bgp_peer_sort_t
651 0 : peer_calc_sort (struct peer *peer)
652 : {
653 : struct bgp *bgp;
654 :
655 0 : bgp = peer->bgp;
656 :
657 : /* Peer-group */
658 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
659 : {
660 0 : if (peer->as)
661 0 : return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
662 : else
663 : {
664 : struct peer *peer1;
665 0 : peer1 = listnode_head (peer->group->peer);
666 0 : if (peer1)
667 0 : return (peer1->local_as == peer1->as
668 : ? BGP_PEER_IBGP : BGP_PEER_EBGP);
669 : }
670 0 : return BGP_PEER_INTERNAL;
671 : }
672 :
673 : /* Normal peer */
674 0 : if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
675 : {
676 0 : if (peer->local_as == 0)
677 0 : return BGP_PEER_INTERNAL;
678 :
679 0 : if (peer->local_as == peer->as)
680 : {
681 0 : if (peer->local_as == bgp->confed_id)
682 0 : return BGP_PEER_EBGP;
683 : else
684 0 : return BGP_PEER_IBGP;
685 : }
686 :
687 0 : if (bgp_confederation_peers_check (bgp, peer->as))
688 0 : return BGP_PEER_CONFED;
689 :
690 0 : return BGP_PEER_EBGP;
691 : }
692 : else
693 : {
694 0 : return (peer->local_as == 0
695 0 : ? BGP_PEER_INTERNAL : peer->local_as == peer->as
696 : ? BGP_PEER_IBGP : BGP_PEER_EBGP);
697 : }
698 : }
699 :
700 : /* Calculate and cache the peer "sort" */
701 : bgp_peer_sort_t
702 0 : peer_sort (struct peer *peer)
703 : {
704 0 : peer->sort = peer_calc_sort (peer);
705 0 : return peer->sort;
706 : }
707 :
708 : static void
709 0 : peer_free (struct peer *peer)
710 : {
711 0 : assert (peer->status == Deleted);
712 :
713 0 : bgp_unlock(peer->bgp);
714 :
715 : /* this /ought/ to have been done already through bgp_stop earlier,
716 : * but just to be sure..
717 : */
718 0 : bgp_timer_set (peer);
719 0 : BGP_READ_OFF (peer->t_read);
720 0 : BGP_WRITE_OFF (peer->t_write);
721 0 : BGP_EVENT_FLUSH (peer);
722 :
723 0 : if (peer->desc)
724 0 : XFREE (MTYPE_PEER_DESC, peer->desc);
725 :
726 : /* Free allocated host character. */
727 0 : if (peer->host)
728 0 : XFREE (MTYPE_BGP_PEER_HOST, peer->host);
729 :
730 : /* Update source configuration. */
731 0 : if (peer->update_source)
732 0 : sockunion_free (peer->update_source);
733 :
734 0 : if (peer->update_if)
735 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
736 :
737 0 : if (peer->clear_node_queue)
738 0 : work_queue_free (peer->clear_node_queue);
739 :
740 0 : bgp_sync_delete (peer);
741 0 : memset (peer, 0, sizeof (struct peer));
742 :
743 0 : XFREE (MTYPE_BGP_PEER, peer);
744 0 : }
745 :
746 : /* increase reference count on a struct peer */
747 : struct peer *
748 11 : peer_lock (struct peer *peer)
749 : {
750 11 : assert (peer && (peer->lock >= 0));
751 :
752 11 : peer->lock++;
753 :
754 11 : return peer;
755 : }
756 :
757 : /* decrease reference count on a struct peer
758 : * struct peer is freed and NULL returned if last reference
759 : */
760 : struct peer *
761 0 : peer_unlock (struct peer *peer)
762 : {
763 0 : assert (peer && (peer->lock > 0));
764 :
765 0 : peer->lock--;
766 :
767 0 : if (peer->lock == 0)
768 : {
769 : #if 0
770 : zlog_debug ("unlocked and freeing");
771 : zlog_backtrace (LOG_DEBUG);
772 : #endif
773 0 : peer_free (peer);
774 0 : return NULL;
775 : }
776 :
777 : #if 0
778 : if (peer->lock == 1)
779 : {
780 : zlog_debug ("unlocked to 1");
781 : zlog_backtrace (LOG_DEBUG);
782 : }
783 : #endif
784 :
785 0 : return peer;
786 : }
787 :
788 : /* Allocate new peer object, implicitely locked. */
789 : static struct peer *
790 4 : peer_new (struct bgp *bgp)
791 : {
792 : afi_t afi;
793 : safi_t safi;
794 : struct peer *peer;
795 : struct servent *sp;
796 :
797 : /* bgp argument is absolutely required */
798 4 : assert (bgp);
799 4 : if (!bgp)
800 0 : return NULL;
801 :
802 : /* Allocate new peer. */
803 4 : peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
804 :
805 : /* Set default value. */
806 4 : peer->fd = -1;
807 4 : peer->v_start = BGP_INIT_START_TIMER;
808 4 : peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
809 4 : peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
810 4 : peer->status = Idle;
811 4 : peer->ostatus = Idle;
812 4 : peer->weight = 0;
813 4 : peer->password = NULL;
814 4 : peer->bgp = bgp;
815 4 : peer = peer_lock (peer); /* initial reference */
816 4 : bgp_lock (bgp);
817 :
818 : /* Set default flags. */
819 12 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
820 40 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
821 : {
822 32 : if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
823 : {
824 32 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
825 32 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
826 : }
827 32 : peer->orf_plist[afi][safi] = NULL;
828 : }
829 4 : SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
830 :
831 : /* Create buffers. */
832 4 : peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
833 4 : peer->obuf = stream_fifo_new ();
834 4 : peer->work = stream_new (BGP_MAX_PACKET_SIZE);
835 :
836 4 : bgp_sync_init (peer);
837 :
838 : /* Get service port number. */
839 4 : sp = getservbyname ("bgp", "tcp");
840 4 : peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
841 :
842 4 : return peer;
843 : }
844 :
845 : /* Create new BGP peer. */
846 : static struct peer *
847 0 : peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
848 : as_t remote_as, afi_t afi, safi_t safi)
849 : {
850 : int active;
851 : struct peer *peer;
852 : char buf[SU_ADDRSTRLEN];
853 :
854 0 : peer = peer_new (bgp);
855 0 : peer->su = *su;
856 0 : peer->local_as = local_as;
857 0 : peer->as = remote_as;
858 0 : peer->local_id = bgp->router_id;
859 0 : peer->v_holdtime = bgp->default_holdtime;
860 0 : peer->v_keepalive = bgp->default_keepalive;
861 0 : if (peer_sort (peer) == BGP_PEER_IBGP)
862 0 : peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
863 : else
864 0 : peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
865 :
866 0 : peer = peer_lock (peer); /* bgp peer list reference */
867 0 : listnode_add_sort (bgp->peer, peer);
868 :
869 0 : active = peer_active (peer);
870 :
871 0 : if (afi && safi)
872 0 : peer->afc[afi][safi] = 1;
873 :
874 : /* Last read and reset time set */
875 0 : peer->readtime = peer->resettime = bgp_clock ();
876 :
877 : /* Default TTL set. */
878 0 : peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
879 :
880 : /* Make peer's address string. */
881 0 : sockunion2str (su, buf, SU_ADDRSTRLEN);
882 0 : peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
883 :
884 : /* Set up peer's events and timers. */
885 0 : if (! active && peer_active (peer))
886 0 : bgp_timer_set (peer);
887 :
888 0 : return peer;
889 : }
890 :
891 : /* Make accept BGP peer. Called from bgp_accept (). */
892 : struct peer *
893 2 : peer_create_accept (struct bgp *bgp)
894 : {
895 : struct peer *peer;
896 :
897 2 : peer = peer_new (bgp);
898 :
899 2 : peer = peer_lock (peer); /* bgp peer list reference */
900 2 : listnode_add_sort (bgp->peer, peer);
901 :
902 2 : return peer;
903 : }
904 :
905 : /* Change peer's AS number. */
906 : static void
907 0 : peer_as_change (struct peer *peer, as_t as)
908 : {
909 : bgp_peer_sort_t type;
910 :
911 : /* Stop peer. */
912 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
913 : {
914 0 : if (peer->status == Established)
915 : {
916 0 : peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
917 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
918 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
919 : }
920 : else
921 0 : BGP_EVENT_ADD (peer, BGP_Stop);
922 : }
923 0 : type = peer_sort (peer);
924 0 : peer->as = as;
925 :
926 0 : if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
927 0 : && ! bgp_confederation_peers_check (peer->bgp, as)
928 0 : && peer->bgp->as != as)
929 0 : peer->local_as = peer->bgp->confed_id;
930 : else
931 0 : peer->local_as = peer->bgp->as;
932 :
933 : /* Advertisement-interval reset */
934 0 : if (peer_sort (peer) == BGP_PEER_IBGP)
935 0 : peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
936 : else
937 0 : peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
938 :
939 : /* TTL reset */
940 0 : if (peer_sort (peer) == BGP_PEER_IBGP)
941 0 : peer->ttl = 255;
942 0 : else if (type == BGP_PEER_IBGP)
943 0 : peer->ttl = 1;
944 :
945 : /* reflector-client reset */
946 0 : if (peer_sort (peer) != BGP_PEER_IBGP)
947 : {
948 0 : UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
949 : PEER_FLAG_REFLECTOR_CLIENT);
950 0 : UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
951 : PEER_FLAG_REFLECTOR_CLIENT);
952 0 : UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
953 : PEER_FLAG_REFLECTOR_CLIENT);
954 0 : UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
955 : PEER_FLAG_REFLECTOR_CLIENT);
956 0 : UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
957 : PEER_FLAG_REFLECTOR_CLIENT);
958 : }
959 :
960 : /* local-as reset */
961 0 : if (peer_sort (peer) != BGP_PEER_EBGP)
962 : {
963 0 : peer->change_local_as = 0;
964 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
965 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
966 : }
967 0 : }
968 :
969 : /* If peer does not exist, create new one. If peer already exists,
970 : set AS number to the peer. */
971 : int
972 0 : peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
973 : afi_t afi, safi_t safi)
974 : {
975 : struct peer *peer;
976 : as_t local_as;
977 :
978 0 : peer = peer_lookup (bgp, su);
979 :
980 0 : if (peer)
981 : {
982 : /* When this peer is a member of peer-group. */
983 0 : if (peer->group)
984 : {
985 0 : if (peer->group->conf->as)
986 : {
987 : /* Return peer group's AS number. */
988 0 : *as = peer->group->conf->as;
989 0 : return BGP_ERR_PEER_GROUP_MEMBER;
990 : }
991 0 : if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
992 : {
993 0 : if (bgp->as != *as)
994 : {
995 0 : *as = peer->as;
996 0 : return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
997 : }
998 : }
999 : else
1000 : {
1001 0 : if (bgp->as == *as)
1002 : {
1003 0 : *as = peer->as;
1004 0 : return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1005 : }
1006 : }
1007 : }
1008 :
1009 : /* Existing peer's AS number change. */
1010 0 : if (peer->as != *as)
1011 0 : peer_as_change (peer, *as);
1012 : }
1013 : else
1014 : {
1015 :
1016 : /* If the peer is not part of our confederation, and its not an
1017 : iBGP peer then spoof the source AS */
1018 0 : if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1019 0 : && ! bgp_confederation_peers_check (bgp, *as)
1020 0 : && bgp->as != *as)
1021 0 : local_as = bgp->confed_id;
1022 : else
1023 0 : local_as = bgp->as;
1024 :
1025 : /* If this is IPv4 unicast configuration and "no bgp default
1026 : ipv4-unicast" is specified. */
1027 :
1028 0 : if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1029 0 : && afi == AFI_IP && safi == SAFI_UNICAST)
1030 0 : peer = peer_create (su, bgp, local_as, *as, 0, 0);
1031 : else
1032 0 : peer = peer_create (su, bgp, local_as, *as, afi, safi);
1033 : }
1034 :
1035 0 : return 0;
1036 : }
1037 :
1038 : /* Activate the peer or peer group for specified AFI and SAFI. */
1039 : int
1040 0 : peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1041 : {
1042 : int active;
1043 :
1044 0 : if (peer->afc[afi][safi])
1045 0 : return 0;
1046 :
1047 : /* Activate the address family configuration. */
1048 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1049 0 : peer->afc[afi][safi] = 1;
1050 : else
1051 : {
1052 0 : active = peer_active (peer);
1053 :
1054 0 : peer->afc[afi][safi] = 1;
1055 :
1056 0 : if (! active && peer_active (peer))
1057 0 : bgp_timer_set (peer);
1058 : else
1059 : {
1060 0 : if (peer->status == Established)
1061 : {
1062 0 : if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1063 : {
1064 0 : peer->afc_adv[afi][safi] = 1;
1065 0 : bgp_capability_send (peer, afi, safi,
1066 : CAPABILITY_CODE_MP,
1067 : CAPABILITY_ACTION_SET);
1068 0 : if (peer->afc_recv[afi][safi])
1069 : {
1070 0 : peer->afc_nego[afi][safi] = 1;
1071 0 : bgp_announce_route (peer, afi, safi);
1072 : }
1073 : }
1074 : else
1075 : {
1076 0 : peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1077 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1078 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1079 : }
1080 : }
1081 : }
1082 : }
1083 0 : return 0;
1084 : }
1085 :
1086 : int
1087 0 : peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1088 : {
1089 : struct peer_group *group;
1090 : struct peer *peer1;
1091 : struct listnode *node, *nnode;
1092 :
1093 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1094 : {
1095 0 : group = peer->group;
1096 :
1097 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
1098 : {
1099 0 : if (peer1->af_group[afi][safi])
1100 0 : return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1101 : }
1102 : }
1103 : else
1104 : {
1105 0 : if (peer->af_group[afi][safi])
1106 0 : return BGP_ERR_PEER_BELONGS_TO_GROUP;
1107 : }
1108 :
1109 0 : if (! peer->afc[afi][safi])
1110 0 : return 0;
1111 :
1112 : /* De-activate the address family configuration. */
1113 0 : peer->afc[afi][safi] = 0;
1114 0 : peer_af_flag_reset (peer, afi, safi);
1115 :
1116 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1117 : {
1118 0 : if (peer->status == Established)
1119 : {
1120 0 : if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1121 : {
1122 0 : peer->afc_adv[afi][safi] = 0;
1123 0 : peer->afc_nego[afi][safi] = 0;
1124 :
1125 0 : if (peer_active_nego (peer))
1126 : {
1127 0 : bgp_capability_send (peer, afi, safi,
1128 : CAPABILITY_CODE_MP,
1129 : CAPABILITY_ACTION_UNSET);
1130 0 : bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
1131 0 : peer->pcount[afi][safi] = 0;
1132 : }
1133 : else
1134 : {
1135 0 : peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1136 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1137 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1138 : }
1139 : }
1140 : else
1141 : {
1142 0 : peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1143 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1144 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1145 : }
1146 : }
1147 : }
1148 0 : return 0;
1149 : }
1150 :
1151 : static void
1152 0 : peer_nsf_stop (struct peer *peer)
1153 : {
1154 : afi_t afi;
1155 : safi_t safi;
1156 :
1157 0 : UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1158 0 : UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1159 :
1160 0 : for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1161 0 : for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
1162 0 : peer->nsf[afi][safi] = 0;
1163 :
1164 0 : if (peer->t_gr_restart)
1165 : {
1166 0 : BGP_TIMER_OFF (peer->t_gr_restart);
1167 0 : if (BGP_DEBUG (events, EVENTS))
1168 0 : zlog_debug ("%s graceful restart timer stopped", peer->host);
1169 : }
1170 0 : if (peer->t_gr_stale)
1171 : {
1172 0 : BGP_TIMER_OFF (peer->t_gr_stale);
1173 0 : if (BGP_DEBUG (events, EVENTS))
1174 0 : zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1175 : }
1176 0 : bgp_clear_route_all (peer);
1177 0 : }
1178 :
1179 : /* Delete peer from confguration.
1180 : *
1181 : * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1182 : * it to "cool off" and refcounts to hit 0, at which state it is freed.
1183 : *
1184 : * This function /should/ take care to be idempotent, to guard against
1185 : * it being called multiple times through stray events that come in
1186 : * that happen to result in this function being called again. That
1187 : * said, getting here for a "Deleted" peer is a bug in the neighbour
1188 : * FSM.
1189 : */
1190 : int
1191 0 : peer_delete (struct peer *peer)
1192 : {
1193 : int i;
1194 : afi_t afi;
1195 : safi_t safi;
1196 : struct bgp *bgp;
1197 : struct bgp_filter *filter;
1198 : struct listnode *pn;
1199 :
1200 0 : assert (peer->status != Deleted);
1201 :
1202 0 : bgp = peer->bgp;
1203 :
1204 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1205 0 : peer_nsf_stop (peer);
1206 :
1207 : /* If this peer belongs to peer group, clear up the
1208 : relationship. */
1209 0 : if (peer->group)
1210 : {
1211 0 : if ((pn = listnode_lookup (peer->group->peer, peer)))
1212 : {
1213 0 : peer = peer_unlock (peer); /* group->peer list reference */
1214 0 : list_delete_node (peer->group->peer, pn);
1215 : }
1216 0 : peer->group = NULL;
1217 : }
1218 :
1219 : /* Withdraw all information from routing table. We can not use
1220 : * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1221 : * executed after peer structure is deleted.
1222 : */
1223 0 : peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1224 0 : bgp_stop (peer);
1225 0 : bgp_fsm_change_status (peer, Deleted);
1226 :
1227 : /* Password configuration */
1228 0 : if (peer->password)
1229 : {
1230 0 : XFREE (MTYPE_PEER_PASSWORD, peer->password);
1231 0 : peer->password = NULL;
1232 :
1233 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1234 0 : bgp_md5_set (peer);
1235 : }
1236 :
1237 0 : bgp_timer_set (peer); /* stops all timers for Deleted */
1238 :
1239 : /* Delete from all peer list. */
1240 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1241 0 : && (pn = listnode_lookup (bgp->peer, peer)))
1242 : {
1243 0 : peer_unlock (peer); /* bgp peer list reference */
1244 0 : list_delete_node (bgp->peer, pn);
1245 : }
1246 :
1247 0 : if (peer_rsclient_active (peer)
1248 0 : && (pn = listnode_lookup (bgp->rsclient, peer)))
1249 : {
1250 0 : peer_unlock (peer); /* rsclient list reference */
1251 0 : list_delete_node (bgp->rsclient, pn);
1252 :
1253 : /* Clear our own rsclient ribs. */
1254 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
1255 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1256 0 : if (CHECK_FLAG(peer->af_flags[afi][safi],
1257 : PEER_FLAG_RSERVER_CLIENT))
1258 0 : bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
1259 : }
1260 :
1261 : /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1262 : member of a peer_group. */
1263 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
1264 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1265 0 : if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1266 0 : bgp_table_finish (&peer->rib[afi][safi]);
1267 :
1268 : /* Buffers. */
1269 0 : if (peer->ibuf)
1270 0 : stream_free (peer->ibuf);
1271 0 : if (peer->obuf)
1272 0 : stream_fifo_free (peer->obuf);
1273 0 : if (peer->work)
1274 0 : stream_free (peer->work);
1275 0 : peer->obuf = NULL;
1276 0 : peer->work = peer->ibuf = NULL;
1277 :
1278 : /* Local and remote addresses. */
1279 0 : if (peer->su_local)
1280 0 : sockunion_free (peer->su_local);
1281 0 : if (peer->su_remote)
1282 0 : sockunion_free (peer->su_remote);
1283 0 : peer->su_local = peer->su_remote = NULL;
1284 :
1285 : /* Free filter related memory. */
1286 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
1287 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1288 : {
1289 0 : filter = &peer->filter[afi][safi];
1290 :
1291 0 : for (i = FILTER_IN; i < FILTER_MAX; i++)
1292 : {
1293 0 : if (filter->dlist[i].name)
1294 0 : free (filter->dlist[i].name);
1295 0 : if (filter->plist[i].name)
1296 0 : free (filter->plist[i].name);
1297 0 : if (filter->aslist[i].name)
1298 0 : free (filter->aslist[i].name);
1299 :
1300 0 : filter->dlist[i].name = NULL;
1301 0 : filter->plist[i].name = NULL;
1302 0 : filter->aslist[i].name = NULL;
1303 : }
1304 0 : for (i = RMAP_IN; i < RMAP_MAX; i++)
1305 : {
1306 0 : if (filter->map[i].name)
1307 0 : free (filter->map[i].name);
1308 0 : filter->map[i].name = NULL;
1309 : }
1310 :
1311 0 : if (filter->usmap.name)
1312 0 : free (filter->usmap.name);
1313 :
1314 0 : if (peer->default_rmap[afi][safi].name)
1315 0 : free (peer->default_rmap[afi][safi].name);
1316 :
1317 0 : filter->usmap.name = NULL;
1318 0 : peer->default_rmap[afi][safi].name = NULL;
1319 : }
1320 :
1321 0 : peer_unlock (peer); /* initial reference */
1322 :
1323 0 : return 0;
1324 : }
1325 :
1326 : static int
1327 0 : peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1328 : {
1329 0 : return strcmp (g1->name, g2->name);
1330 : }
1331 :
1332 : /* If peer is configured at least one address family return 1. */
1333 : static int
1334 0 : peer_group_active (struct peer *peer)
1335 : {
1336 0 : if (peer->af_group[AFI_IP][SAFI_UNICAST]
1337 0 : || peer->af_group[AFI_IP][SAFI_MULTICAST]
1338 0 : || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1339 0 : || peer->af_group[AFI_IP6][SAFI_UNICAST]
1340 0 : || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1341 0 : return 1;
1342 0 : return 0;
1343 : }
1344 :
1345 : /* Peer group cofiguration. */
1346 : static struct peer_group *
1347 0 : peer_group_new (void)
1348 : {
1349 0 : return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1350 : sizeof (struct peer_group));
1351 : }
1352 :
1353 : static void
1354 0 : peer_group_free (struct peer_group *group)
1355 : {
1356 0 : XFREE (MTYPE_PEER_GROUP, group);
1357 0 : }
1358 :
1359 : struct peer_group *
1360 0 : peer_group_lookup (struct bgp *bgp, const char *name)
1361 : {
1362 : struct peer_group *group;
1363 : struct listnode *node, *nnode;
1364 :
1365 0 : for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
1366 : {
1367 0 : if (strcmp (group->name, name) == 0)
1368 0 : return group;
1369 : }
1370 0 : return NULL;
1371 : }
1372 :
1373 : struct peer_group *
1374 0 : peer_group_get (struct bgp *bgp, const char *name)
1375 : {
1376 : struct peer_group *group;
1377 :
1378 0 : group = peer_group_lookup (bgp, name);
1379 0 : if (group)
1380 0 : return group;
1381 :
1382 0 : group = peer_group_new ();
1383 0 : group->bgp = bgp;
1384 0 : group->name = strdup (name);
1385 0 : group->peer = list_new ();
1386 0 : group->conf = peer_new (bgp);
1387 0 : if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1388 0 : group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1389 0 : group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
1390 0 : group->conf->group = group;
1391 0 : group->conf->as = 0;
1392 0 : group->conf->ttl = 1;
1393 0 : group->conf->gtsm_hops = 0;
1394 0 : group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1395 0 : UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1396 0 : UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1397 0 : group->conf->keepalive = 0;
1398 0 : group->conf->holdtime = 0;
1399 0 : group->conf->connect = 0;
1400 0 : SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1401 0 : listnode_add_sort (bgp->group, group);
1402 :
1403 0 : return 0;
1404 : }
1405 :
1406 : static void
1407 0 : peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1408 : afi_t afi, safi_t safi)
1409 : {
1410 0 : int in = FILTER_IN;
1411 0 : int out = FILTER_OUT;
1412 : struct peer *conf;
1413 : struct bgp_filter *pfilter;
1414 : struct bgp_filter *gfilter;
1415 :
1416 0 : conf = group->conf;
1417 0 : pfilter = &peer->filter[afi][safi];
1418 0 : gfilter = &conf->filter[afi][safi];
1419 :
1420 : /* remote-as */
1421 0 : if (conf->as)
1422 0 : peer->as = conf->as;
1423 :
1424 : /* remote-as */
1425 0 : if (conf->change_local_as)
1426 0 : peer->change_local_as = conf->change_local_as;
1427 :
1428 : /* TTL */
1429 0 : peer->ttl = conf->ttl;
1430 :
1431 : /* GTSM hops */
1432 0 : peer->gtsm_hops = conf->gtsm_hops;
1433 :
1434 : /* Weight */
1435 0 : peer->weight = conf->weight;
1436 :
1437 : /* peer flags apply */
1438 0 : peer->flags = conf->flags;
1439 : /* peer af_flags apply */
1440 0 : peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1441 : /* peer config apply */
1442 0 : peer->config = conf->config;
1443 :
1444 : /* peer timers apply */
1445 0 : peer->holdtime = conf->holdtime;
1446 0 : peer->keepalive = conf->keepalive;
1447 0 : peer->connect = conf->connect;
1448 0 : if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1449 0 : peer->v_connect = conf->connect;
1450 : else
1451 0 : peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1452 :
1453 : /* advertisement-interval reset */
1454 0 : if (peer_sort (peer) == BGP_PEER_IBGP)
1455 0 : peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1456 : else
1457 0 : peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1458 :
1459 : /* password apply */
1460 0 : if (conf->password && !peer->password)
1461 0 : peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1462 :
1463 0 : bgp_md5_set (peer);
1464 :
1465 : /* maximum-prefix */
1466 0 : peer->pmax[afi][safi] = conf->pmax[afi][safi];
1467 0 : peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
1468 0 : peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
1469 :
1470 : /* allowas-in */
1471 0 : peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1472 :
1473 : /* route-server-client */
1474 0 : if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1475 : {
1476 : /* Make peer's RIB point to group's RIB. */
1477 0 : peer->rib[afi][safi] = group->conf->rib[afi][safi];
1478 :
1479 : /* Import policy. */
1480 0 : if (pfilter->map[RMAP_IMPORT].name)
1481 0 : free (pfilter->map[RMAP_IMPORT].name);
1482 0 : if (gfilter->map[RMAP_IMPORT].name)
1483 : {
1484 0 : pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1485 0 : pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1486 : }
1487 : else
1488 : {
1489 0 : pfilter->map[RMAP_IMPORT].name = NULL;
1490 0 : pfilter->map[RMAP_IMPORT].map = NULL;
1491 : }
1492 :
1493 : /* Export policy. */
1494 0 : if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1495 : {
1496 0 : pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1497 0 : pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1498 : }
1499 : }
1500 :
1501 : /* default-originate route-map */
1502 0 : if (conf->default_rmap[afi][safi].name)
1503 : {
1504 0 : if (peer->default_rmap[afi][safi].name)
1505 0 : free (peer->default_rmap[afi][safi].name);
1506 0 : peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1507 0 : peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1508 : }
1509 :
1510 : /* update-source apply */
1511 0 : if (conf->update_source)
1512 : {
1513 0 : if (peer->update_source)
1514 0 : sockunion_free (peer->update_source);
1515 0 : if (peer->update_if)
1516 : {
1517 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1518 0 : peer->update_if = NULL;
1519 : }
1520 0 : peer->update_source = sockunion_dup (conf->update_source);
1521 : }
1522 0 : else if (conf->update_if)
1523 : {
1524 0 : if (peer->update_if)
1525 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1526 0 : if (peer->update_source)
1527 : {
1528 0 : sockunion_free (peer->update_source);
1529 0 : peer->update_source = NULL;
1530 : }
1531 0 : peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1532 : }
1533 :
1534 : /* inbound filter apply */
1535 0 : if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1536 : {
1537 0 : if (pfilter->dlist[in].name)
1538 0 : free (pfilter->dlist[in].name);
1539 0 : pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1540 0 : pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1541 : }
1542 0 : if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1543 : {
1544 0 : if (pfilter->plist[in].name)
1545 0 : free (pfilter->plist[in].name);
1546 0 : pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1547 0 : pfilter->plist[in].plist = gfilter->plist[in].plist;
1548 : }
1549 0 : if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1550 : {
1551 0 : if (pfilter->aslist[in].name)
1552 0 : free (pfilter->aslist[in].name);
1553 0 : pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1554 0 : pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1555 : }
1556 0 : if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
1557 : {
1558 0 : if (pfilter->map[RMAP_IN].name)
1559 0 : free (pfilter->map[RMAP_IN].name);
1560 0 : pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1561 0 : pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
1562 : }
1563 :
1564 : /* outbound filter apply */
1565 0 : if (gfilter->dlist[out].name)
1566 : {
1567 0 : if (pfilter->dlist[out].name)
1568 0 : free (pfilter->dlist[out].name);
1569 0 : pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1570 0 : pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1571 : }
1572 : else
1573 : {
1574 0 : if (pfilter->dlist[out].name)
1575 0 : free (pfilter->dlist[out].name);
1576 0 : pfilter->dlist[out].name = NULL;
1577 0 : pfilter->dlist[out].alist = NULL;
1578 : }
1579 0 : if (gfilter->plist[out].name)
1580 : {
1581 0 : if (pfilter->plist[out].name)
1582 0 : free (pfilter->plist[out].name);
1583 0 : pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1584 0 : pfilter->plist[out].plist = gfilter->plist[out].plist;
1585 : }
1586 : else
1587 : {
1588 0 : if (pfilter->plist[out].name)
1589 0 : free (pfilter->plist[out].name);
1590 0 : pfilter->plist[out].name = NULL;
1591 0 : pfilter->plist[out].plist = NULL;
1592 : }
1593 0 : if (gfilter->aslist[out].name)
1594 : {
1595 0 : if (pfilter->aslist[out].name)
1596 0 : free (pfilter->aslist[out].name);
1597 0 : pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1598 0 : pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1599 : }
1600 : else
1601 : {
1602 0 : if (pfilter->aslist[out].name)
1603 0 : free (pfilter->aslist[out].name);
1604 0 : pfilter->aslist[out].name = NULL;
1605 0 : pfilter->aslist[out].aslist = NULL;
1606 : }
1607 0 : if (gfilter->map[RMAP_OUT].name)
1608 : {
1609 0 : if (pfilter->map[RMAP_OUT].name)
1610 0 : free (pfilter->map[RMAP_OUT].name);
1611 0 : pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1612 0 : pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
1613 : }
1614 : else
1615 : {
1616 0 : if (pfilter->map[RMAP_OUT].name)
1617 0 : free (pfilter->map[RMAP_OUT].name);
1618 0 : pfilter->map[RMAP_OUT].name = NULL;
1619 0 : pfilter->map[RMAP_OUT].map = NULL;
1620 : }
1621 :
1622 : /* RS-client's import/export route-maps. */
1623 0 : if (gfilter->map[RMAP_IMPORT].name)
1624 : {
1625 0 : if (pfilter->map[RMAP_IMPORT].name)
1626 0 : free (pfilter->map[RMAP_IMPORT].name);
1627 0 : pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1628 0 : pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1629 : }
1630 : else
1631 : {
1632 0 : if (pfilter->map[RMAP_IMPORT].name)
1633 0 : free (pfilter->map[RMAP_IMPORT].name);
1634 0 : pfilter->map[RMAP_IMPORT].name = NULL;
1635 0 : pfilter->map[RMAP_IMPORT].map = NULL;
1636 : }
1637 0 : if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1638 : {
1639 0 : if (pfilter->map[RMAP_EXPORT].name)
1640 0 : free (pfilter->map[RMAP_EXPORT].name);
1641 0 : pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1642 0 : pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1643 : }
1644 :
1645 0 : if (gfilter->usmap.name)
1646 : {
1647 0 : if (pfilter->usmap.name)
1648 0 : free (pfilter->usmap.name);
1649 0 : pfilter->usmap.name = strdup (gfilter->usmap.name);
1650 0 : pfilter->usmap.map = gfilter->usmap.map;
1651 : }
1652 : else
1653 : {
1654 0 : if (pfilter->usmap.name)
1655 0 : free (pfilter->usmap.name);
1656 0 : pfilter->usmap.name = NULL;
1657 0 : pfilter->usmap.map = NULL;
1658 : }
1659 0 : }
1660 :
1661 : /* Peer group's remote AS configuration. */
1662 : int
1663 0 : peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
1664 : {
1665 : struct peer_group *group;
1666 : struct peer *peer;
1667 : struct listnode *node, *nnode;
1668 :
1669 0 : group = peer_group_lookup (bgp, group_name);
1670 0 : if (! group)
1671 0 : return -1;
1672 :
1673 0 : if (group->conf->as == *as)
1674 0 : return 0;
1675 :
1676 : /* When we setup peer-group AS number all peer group member's AS
1677 : number must be updated to same number. */
1678 0 : peer_as_change (group->conf, *as);
1679 :
1680 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
1681 : {
1682 0 : if (peer->as != *as)
1683 0 : peer_as_change (peer, *as);
1684 : }
1685 :
1686 0 : return 0;
1687 : }
1688 :
1689 : int
1690 0 : peer_group_delete (struct peer_group *group)
1691 : {
1692 : struct bgp *bgp;
1693 : struct peer *peer;
1694 : struct listnode *node, *nnode;
1695 :
1696 0 : bgp = group->bgp;
1697 :
1698 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
1699 : {
1700 0 : peer->group = NULL;
1701 0 : peer_delete (peer);
1702 : }
1703 0 : list_delete (group->peer);
1704 :
1705 0 : free (group->name);
1706 0 : group->name = NULL;
1707 :
1708 0 : group->conf->group = NULL;
1709 0 : peer_delete (group->conf);
1710 :
1711 : /* Delete from all peer_group list. */
1712 0 : listnode_delete (bgp->group, group);
1713 :
1714 0 : peer_group_free (group);
1715 :
1716 0 : return 0;
1717 : }
1718 :
1719 : int
1720 0 : peer_group_remote_as_delete (struct peer_group *group)
1721 : {
1722 : struct peer *peer;
1723 : struct listnode *node, *nnode;
1724 :
1725 0 : if (! group->conf->as)
1726 0 : return 0;
1727 :
1728 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
1729 : {
1730 0 : peer->group = NULL;
1731 0 : peer_delete (peer);
1732 : }
1733 0 : list_delete_all_node (group->peer);
1734 :
1735 0 : group->conf->as = 0;
1736 :
1737 0 : return 0;
1738 : }
1739 :
1740 : /* Bind specified peer to peer group. */
1741 : int
1742 0 : peer_group_bind (struct bgp *bgp, union sockunion *su,
1743 : struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1744 : {
1745 : struct peer *peer;
1746 0 : int first_member = 0;
1747 :
1748 : /* Check peer group's address family. */
1749 0 : if (! group->conf->afc[afi][safi])
1750 0 : return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1751 :
1752 : /* Lookup the peer. */
1753 0 : peer = peer_lookup (bgp, su);
1754 :
1755 : /* Create a new peer. */
1756 0 : if (! peer)
1757 : {
1758 0 : if (! group->conf->as)
1759 0 : return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1760 :
1761 0 : peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1762 0 : peer->group = group;
1763 0 : peer->af_group[afi][safi] = 1;
1764 :
1765 0 : peer = peer_lock (peer); /* group->peer list reference */
1766 0 : listnode_add (group->peer, peer);
1767 0 : peer_group2peer_config_copy (group, peer, afi, safi);
1768 :
1769 0 : return 0;
1770 : }
1771 :
1772 : /* When the peer already belongs to peer group, check the consistency. */
1773 0 : if (peer->af_group[afi][safi])
1774 : {
1775 0 : if (strcmp (peer->group->name, group->name) != 0)
1776 0 : return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1777 :
1778 0 : return 0;
1779 : }
1780 :
1781 : /* Check current peer group configuration. */
1782 0 : if (peer_group_active (peer)
1783 0 : && strcmp (peer->group->name, group->name) != 0)
1784 0 : return BGP_ERR_PEER_GROUP_MISMATCH;
1785 :
1786 0 : if (! group->conf->as)
1787 : {
1788 0 : if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1789 0 : && peer_sort (group->conf) != peer_sort (peer))
1790 : {
1791 0 : if (as)
1792 0 : *as = peer->as;
1793 0 : return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1794 : }
1795 :
1796 0 : if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1797 0 : first_member = 1;
1798 : }
1799 :
1800 0 : peer->af_group[afi][safi] = 1;
1801 0 : peer->afc[afi][safi] = 1;
1802 0 : if (! peer->group)
1803 : {
1804 0 : peer->group = group;
1805 :
1806 0 : peer = peer_lock (peer); /* group->peer list reference */
1807 0 : listnode_add (group->peer, peer);
1808 : }
1809 : else
1810 0 : assert (group && peer->group == group);
1811 :
1812 0 : if (first_member)
1813 : {
1814 : /* Advertisement-interval reset */
1815 0 : if (peer_sort (group->conf) == BGP_PEER_IBGP)
1816 0 : group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1817 : else
1818 0 : group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1819 :
1820 : /* ebgp-multihop reset */
1821 0 : if (peer_sort (group->conf) == BGP_PEER_IBGP)
1822 0 : group->conf->ttl = 255;
1823 :
1824 : /* local-as reset */
1825 0 : if (peer_sort (group->conf) != BGP_PEER_EBGP)
1826 : {
1827 0 : group->conf->change_local_as = 0;
1828 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1829 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
1830 : }
1831 : }
1832 :
1833 0 : if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1834 : {
1835 : struct listnode *pn;
1836 :
1837 : /* If it's not configured as RSERVER_CLIENT in any other address
1838 : family, without being member of a peer_group, remove it from
1839 : list bgp->rsclient.*/
1840 0 : if (! peer_rsclient_active (peer)
1841 0 : && (pn = listnode_lookup (bgp->rsclient, peer)))
1842 : {
1843 0 : peer_unlock (peer); /* peer rsclient reference */
1844 0 : list_delete_node (bgp->rsclient, pn);
1845 :
1846 : /* Clear our own rsclient rib for this afi/safi. */
1847 0 : bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
1848 : }
1849 :
1850 0 : bgp_table_finish (&peer->rib[afi][safi]);
1851 :
1852 : /* Import policy. */
1853 0 : if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1854 : {
1855 0 : free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1856 0 : peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1857 0 : peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1858 : }
1859 :
1860 : /* Export policy. */
1861 0 : if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1862 0 : && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1863 : {
1864 0 : free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1865 0 : peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1866 0 : peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1867 : }
1868 : }
1869 :
1870 0 : peer_group2peer_config_copy (group, peer, afi, safi);
1871 :
1872 0 : if (peer->status == Established)
1873 : {
1874 0 : peer->last_reset = PEER_DOWN_RMAP_BIND;
1875 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1876 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1877 : }
1878 : else
1879 0 : BGP_EVENT_ADD (peer, BGP_Stop);
1880 :
1881 0 : return 0;
1882 : }
1883 :
1884 : int
1885 0 : peer_group_unbind (struct bgp *bgp, struct peer *peer,
1886 : struct peer_group *group, afi_t afi, safi_t safi)
1887 : {
1888 0 : if (! peer->af_group[afi][safi])
1889 0 : return 0;
1890 :
1891 0 : if (group != peer->group)
1892 0 : return BGP_ERR_PEER_GROUP_MISMATCH;
1893 :
1894 0 : peer->af_group[afi][safi] = 0;
1895 0 : peer->afc[afi][safi] = 0;
1896 0 : peer_af_flag_reset (peer, afi, safi);
1897 :
1898 0 : if (peer->rib[afi][safi])
1899 0 : peer->rib[afi][safi] = NULL;
1900 :
1901 0 : if (! peer_group_active (peer))
1902 : {
1903 0 : assert (listnode_lookup (group->peer, peer));
1904 0 : peer_unlock (peer); /* peer group list reference */
1905 0 : listnode_delete (group->peer, peer);
1906 0 : peer->group = NULL;
1907 0 : if (group->conf->as)
1908 : {
1909 0 : peer_delete (peer);
1910 0 : return 0;
1911 : }
1912 0 : peer_global_config_reset (peer);
1913 : }
1914 :
1915 0 : if (peer->status == Established)
1916 : {
1917 0 : peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1918 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1919 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1920 : }
1921 : else
1922 0 : BGP_EVENT_ADD (peer, BGP_Stop);
1923 :
1924 0 : return 0;
1925 : }
1926 :
1927 : /* BGP instance creation by `router bgp' commands. */
1928 : static struct bgp *
1929 2 : bgp_create (as_t *as, const char *name)
1930 : {
1931 : struct bgp *bgp;
1932 : afi_t afi;
1933 : safi_t safi;
1934 :
1935 2 : if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1936 0 : return NULL;
1937 :
1938 2 : bgp_lock (bgp);
1939 2 : bgp->peer_self = peer_new (bgp);
1940 2 : bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
1941 :
1942 2 : bgp->peer = list_new ();
1943 2 : bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1944 :
1945 2 : bgp->group = list_new ();
1946 2 : bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1947 :
1948 2 : bgp->rsclient = list_new ();
1949 2 : bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1950 :
1951 6 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
1952 20 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1953 : {
1954 16 : bgp->route[afi][safi] = bgp_table_init (afi, safi);
1955 16 : bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1956 16 : bgp->rib[afi][safi] = bgp_table_init (afi, safi);
1957 16 : bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1958 16 : bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
1959 : }
1960 :
1961 2 : bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1962 2 : bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1963 2 : bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
1964 2 : bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1965 2 : bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
1966 :
1967 2 : bgp->as = *as;
1968 :
1969 2 : if (name)
1970 0 : bgp->name = strdup (name);
1971 :
1972 2 : return bgp;
1973 : }
1974 :
1975 : /* Return first entry of BGP. */
1976 : struct bgp *
1977 2 : bgp_get_default (void)
1978 : {
1979 2 : if (bm->bgp->head)
1980 0 : return (listgetdata (listhead (bm->bgp)));
1981 2 : return NULL;
1982 : }
1983 :
1984 : /* Lookup BGP entry. */
1985 : struct bgp *
1986 0 : bgp_lookup (as_t as, const char *name)
1987 : {
1988 : struct bgp *bgp;
1989 : struct listnode *node, *nnode;
1990 :
1991 0 : for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
1992 0 : if (bgp->as == as
1993 0 : && ((bgp->name == NULL && name == NULL)
1994 0 : || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1995 0 : return bgp;
1996 0 : return NULL;
1997 : }
1998 :
1999 : /* Lookup BGP structure by view name. */
2000 : struct bgp *
2001 0 : bgp_lookup_by_name (const char *name)
2002 : {
2003 : struct bgp *bgp;
2004 : struct listnode *node, *nnode;
2005 :
2006 0 : for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
2007 0 : if ((bgp->name == NULL && name == NULL)
2008 0 : || (bgp->name && name && strcmp (bgp->name, name) == 0))
2009 0 : return bgp;
2010 0 : return NULL;
2011 : }
2012 :
2013 : /* Called from VTY commands. */
2014 : int
2015 2 : bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
2016 : {
2017 : struct bgp *bgp;
2018 :
2019 : /* Multiple instance check. */
2020 2 : if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2021 : {
2022 0 : if (name)
2023 0 : bgp = bgp_lookup_by_name (name);
2024 : else
2025 0 : bgp = bgp_get_default ();
2026 :
2027 : /* Already exists. */
2028 0 : if (bgp)
2029 : {
2030 0 : if (bgp->as != *as)
2031 : {
2032 0 : *as = bgp->as;
2033 0 : return BGP_ERR_INSTANCE_MISMATCH;
2034 : }
2035 0 : *bgp_val = bgp;
2036 0 : return 0;
2037 : }
2038 : }
2039 : else
2040 : {
2041 : /* BGP instance name can not be specified for single instance. */
2042 2 : if (name)
2043 0 : return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2044 :
2045 : /* Get default BGP structure if exists. */
2046 2 : bgp = bgp_get_default ();
2047 :
2048 2 : if (bgp)
2049 : {
2050 0 : if (bgp->as != *as)
2051 : {
2052 0 : *as = bgp->as;
2053 0 : return BGP_ERR_AS_MISMATCH;
2054 : }
2055 0 : *bgp_val = bgp;
2056 0 : return 0;
2057 : }
2058 : }
2059 :
2060 2 : bgp = bgp_create (as, name);
2061 2 : bgp_router_id_set(bgp, &router_id_zebra);
2062 2 : *bgp_val = bgp;
2063 :
2064 : /* Create BGP server socket, if first instance. */
2065 2 : if (list_isempty(bm->bgp)
2066 2 : && !bgp_option_check (BGP_OPT_NO_LISTEN))
2067 : {
2068 0 : if (bgp_socket (bm->port, bm->address) < 0)
2069 0 : return BGP_ERR_INVALID_VALUE;
2070 : }
2071 :
2072 2 : listnode_add (bm->bgp, bgp);
2073 :
2074 2 : return 0;
2075 : }
2076 :
2077 : /* Delete BGP instance. */
2078 : int
2079 1 : bgp_delete (struct bgp *bgp)
2080 : {
2081 : struct peer *peer;
2082 : struct peer_group *group;
2083 : struct listnode *node;
2084 : struct listnode *next;
2085 : afi_t afi;
2086 : int i;
2087 :
2088 : /* Delete static route. */
2089 1 : bgp_static_delete (bgp);
2090 :
2091 : /* Unset redistribution. */
2092 3 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
2093 28 : for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2094 26 : if (i != ZEBRA_ROUTE_BGP)
2095 24 : bgp_redistribute_unset (bgp, afi, i);
2096 :
2097 1 : for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2098 0 : peer_delete (peer);
2099 :
2100 1 : for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2101 0 : peer_group_delete (group);
2102 :
2103 1 : assert (listcount (bgp->rsclient) == 0);
2104 :
2105 1 : if (bgp->peer_self) {
2106 0 : peer_delete(bgp->peer_self);
2107 0 : bgp->peer_self = NULL;
2108 : }
2109 :
2110 : /* Remove visibility via the master list - there may however still be
2111 : * routes to be processed still referencing the struct bgp.
2112 : */
2113 1 : listnode_delete (bm->bgp, bgp);
2114 1 : if (list_isempty(bm->bgp))
2115 1 : bgp_close ();
2116 :
2117 1 : bgp_unlock(bgp); /* initial reference */
2118 :
2119 1 : return 0;
2120 : }
2121 :
2122 : static void bgp_free (struct bgp *);
2123 :
2124 : void
2125 7 : bgp_lock (struct bgp *bgp)
2126 : {
2127 7 : ++bgp->lock;
2128 7 : }
2129 :
2130 : void
2131 1 : bgp_unlock(struct bgp *bgp)
2132 : {
2133 1 : assert(bgp->lock > 0);
2134 1 : if (--bgp->lock == 0)
2135 1 : bgp_free (bgp);
2136 1 : }
2137 :
2138 : static void
2139 1 : bgp_free (struct bgp *bgp)
2140 : {
2141 : afi_t afi;
2142 : safi_t safi;
2143 :
2144 1 : list_delete (bgp->group);
2145 1 : list_delete (bgp->peer);
2146 1 : list_delete (bgp->rsclient);
2147 :
2148 1 : if (bgp->name)
2149 0 : free (bgp->name);
2150 :
2151 3 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
2152 10 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2153 : {
2154 8 : if (bgp->route[afi][safi])
2155 8 : bgp_table_finish (&bgp->route[afi][safi]);
2156 8 : if (bgp->aggregate[afi][safi])
2157 8 : bgp_table_finish (&bgp->aggregate[afi][safi]) ;
2158 8 : if (bgp->rib[afi][safi])
2159 8 : bgp_table_finish (&bgp->rib[afi][safi]);
2160 : }
2161 1 : XFREE (MTYPE_BGP, bgp);
2162 1 : }
2163 :
2164 : struct peer *
2165 0 : peer_lookup (struct bgp *bgp, union sockunion *su)
2166 : {
2167 : struct peer *peer;
2168 : struct listnode *node, *nnode;
2169 :
2170 0 : if (bgp != NULL)
2171 : {
2172 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2173 0 : if (sockunion_same (&peer->su, su)
2174 0 : && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2175 0 : return peer;
2176 : }
2177 0 : else if (bm->bgp != NULL)
2178 : {
2179 : struct listnode *bgpnode, *nbgpnode;
2180 :
2181 0 : for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2182 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2183 0 : if (sockunion_same (&peer->su, su)
2184 0 : && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2185 0 : return peer;
2186 : }
2187 0 : return NULL;
2188 : }
2189 :
2190 : struct peer *
2191 0 : peer_lookup_with_open (union sockunion *su, as_t remote_as,
2192 : struct in_addr *remote_id, int *as)
2193 : {
2194 : struct peer *peer;
2195 : struct listnode *node;
2196 : struct listnode *bgpnode;
2197 : struct bgp *bgp;
2198 :
2199 0 : if (! bm->bgp)
2200 0 : return NULL;
2201 :
2202 0 : for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
2203 : {
2204 0 : for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2205 : {
2206 0 : if (sockunion_same (&peer->su, su)
2207 0 : && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2208 : {
2209 0 : if (peer->as == remote_as
2210 0 : && peer->remote_id.s_addr == remote_id->s_addr)
2211 0 : return peer;
2212 0 : if (peer->as == remote_as)
2213 0 : *as = 1;
2214 : }
2215 : }
2216 :
2217 0 : for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2218 : {
2219 0 : if (sockunion_same (&peer->su, su)
2220 0 : && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2221 : {
2222 0 : if (peer->as == remote_as
2223 0 : && peer->remote_id.s_addr == 0)
2224 0 : return peer;
2225 0 : if (peer->as == remote_as)
2226 0 : *as = 1;
2227 : }
2228 : }
2229 : }
2230 0 : return NULL;
2231 : }
2232 :
2233 : /* If peer is configured at least one address family return 1. */
2234 : int
2235 0 : peer_active (struct peer *peer)
2236 : {
2237 0 : if (peer->afc[AFI_IP][SAFI_UNICAST]
2238 0 : || peer->afc[AFI_IP][SAFI_MULTICAST]
2239 0 : || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2240 0 : || peer->afc[AFI_IP6][SAFI_UNICAST]
2241 0 : || peer->afc[AFI_IP6][SAFI_MULTICAST])
2242 0 : return 1;
2243 0 : return 0;
2244 : }
2245 :
2246 : /* If peer is negotiated at least one address family return 1. */
2247 : int
2248 0 : peer_active_nego (struct peer *peer)
2249 : {
2250 0 : if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2251 0 : || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2252 0 : || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2253 0 : || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2254 0 : || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2255 0 : return 1;
2256 0 : return 0;
2257 : }
2258 :
2259 : /* peer_flag_change_type. */
2260 : enum peer_change_type
2261 : {
2262 : peer_change_none,
2263 : peer_change_reset,
2264 : peer_change_reset_in,
2265 : peer_change_reset_out,
2266 : };
2267 :
2268 : static void
2269 0 : peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2270 : enum peer_change_type type)
2271 : {
2272 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2273 0 : return;
2274 :
2275 0 : if (type == peer_change_reset)
2276 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2277 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2278 0 : else if (type == peer_change_reset_in)
2279 : {
2280 0 : if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2281 0 : || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2282 0 : bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2283 : else
2284 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2285 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2286 : }
2287 0 : else if (type == peer_change_reset_out)
2288 0 : bgp_announce_route (peer, afi, safi);
2289 : }
2290 :
2291 : struct peer_flag_action
2292 : {
2293 : /* Peer's flag. */
2294 : u_int32_t flag;
2295 :
2296 : /* This flag can be set for peer-group member. */
2297 : u_char not_for_member;
2298 :
2299 : /* Action when the flag is changed. */
2300 : enum peer_change_type type;
2301 :
2302 : /* Peer down cause */
2303 : u_char peer_down;
2304 : };
2305 :
2306 : static const struct peer_flag_action peer_flag_action_list[] =
2307 : {
2308 : { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2309 : { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2310 : { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2311 : { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2312 : { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
2313 : { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
2314 : { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
2315 : { 0, 0, 0 }
2316 : };
2317 :
2318 : static const struct peer_flag_action peer_af_flag_action_list[] =
2319 : {
2320 : { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2321 : { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2322 : { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2323 : { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2324 : { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2325 : { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2326 : { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2327 : { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2328 : { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2329 : { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2330 : { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2331 : { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2332 : { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
2333 : { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
2334 : { 0, 0, 0 }
2335 : };
2336 :
2337 : /* Proper action set. */
2338 : static int
2339 0 : peer_flag_action_set (const struct peer_flag_action *action_list, int size,
2340 : struct peer_flag_action *action, u_int32_t flag)
2341 : {
2342 : int i;
2343 0 : int found = 0;
2344 0 : int reset_in = 0;
2345 0 : int reset_out = 0;
2346 0 : const struct peer_flag_action *match = NULL;
2347 :
2348 : /* Check peer's frag action. */
2349 0 : for (i = 0; i < size; i++)
2350 : {
2351 0 : match = &action_list[i];
2352 :
2353 0 : if (match->flag == 0)
2354 0 : break;
2355 :
2356 0 : if (match->flag & flag)
2357 : {
2358 0 : found = 1;
2359 :
2360 0 : if (match->type == peer_change_reset_in)
2361 0 : reset_in = 1;
2362 0 : if (match->type == peer_change_reset_out)
2363 0 : reset_out = 1;
2364 0 : if (match->type == peer_change_reset)
2365 : {
2366 0 : reset_in = 1;
2367 0 : reset_out = 1;
2368 : }
2369 0 : if (match->not_for_member)
2370 0 : action->not_for_member = 1;
2371 : }
2372 : }
2373 :
2374 : /* Set peer clear type. */
2375 0 : if (reset_in && reset_out)
2376 0 : action->type = peer_change_reset;
2377 0 : else if (reset_in)
2378 0 : action->type = peer_change_reset_in;
2379 0 : else if (reset_out)
2380 0 : action->type = peer_change_reset_out;
2381 : else
2382 0 : action->type = peer_change_none;
2383 :
2384 0 : return found;
2385 : }
2386 :
2387 : static void
2388 0 : peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2389 : {
2390 0 : if (flag == PEER_FLAG_SHUTDOWN)
2391 : {
2392 0 : if (CHECK_FLAG (peer->flags, flag))
2393 : {
2394 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2395 0 : peer_nsf_stop (peer);
2396 :
2397 0 : UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2398 0 : if (peer->t_pmax_restart)
2399 : {
2400 0 : BGP_TIMER_OFF (peer->t_pmax_restart);
2401 0 : if (BGP_DEBUG (events, EVENTS))
2402 0 : zlog_debug ("%s Maximum-prefix restart timer canceled",
2403 : peer->host);
2404 : }
2405 :
2406 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2407 0 : peer_nsf_stop (peer);
2408 :
2409 0 : if (peer->status == Established)
2410 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2411 : BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2412 : else
2413 0 : BGP_EVENT_ADD (peer, BGP_Stop);
2414 : }
2415 : else
2416 : {
2417 0 : peer->v_start = BGP_INIT_START_TIMER;
2418 0 : BGP_EVENT_ADD (peer, BGP_Stop);
2419 : }
2420 : }
2421 0 : else if (peer->status == Established)
2422 : {
2423 0 : if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2424 0 : peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2425 0 : else if (flag == PEER_FLAG_PASSIVE)
2426 0 : peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
2427 0 : else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
2428 0 : peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
2429 :
2430 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2431 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2432 : }
2433 : else
2434 0 : BGP_EVENT_ADD (peer, BGP_Stop);
2435 0 : }
2436 :
2437 : /* Change specified peer flag. */
2438 : static int
2439 0 : peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2440 : {
2441 : int found;
2442 : int size;
2443 : struct peer_group *group;
2444 : struct listnode *node, *nnode;
2445 : struct peer_flag_action action;
2446 :
2447 0 : memset (&action, 0, sizeof (struct peer_flag_action));
2448 0 : size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2449 :
2450 0 : found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2451 :
2452 : /* No flag action is found. */
2453 0 : if (! found)
2454 0 : return BGP_ERR_INVALID_FLAG;
2455 :
2456 : /* Not for peer-group member. */
2457 0 : if (action.not_for_member && peer_group_active (peer))
2458 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2459 :
2460 : /* When unset the peer-group member's flag we have to check
2461 : peer-group configuration. */
2462 0 : if (! set && peer_group_active (peer))
2463 0 : if (CHECK_FLAG (peer->group->conf->flags, flag))
2464 : {
2465 0 : if (flag == PEER_FLAG_SHUTDOWN)
2466 0 : return BGP_ERR_PEER_GROUP_SHUTDOWN;
2467 : else
2468 0 : return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2469 : }
2470 :
2471 : /* Flag conflict check. */
2472 0 : if (set
2473 0 : && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2474 0 : && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2475 0 : return BGP_ERR_PEER_FLAG_CONFLICT;
2476 :
2477 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2478 : {
2479 0 : if (set && CHECK_FLAG (peer->flags, flag) == flag)
2480 0 : return 0;
2481 0 : if (! set && ! CHECK_FLAG (peer->flags, flag))
2482 0 : return 0;
2483 : }
2484 :
2485 0 : if (set)
2486 0 : SET_FLAG (peer->flags, flag);
2487 : else
2488 0 : UNSET_FLAG (peer->flags, flag);
2489 :
2490 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2491 : {
2492 0 : if (action.type == peer_change_reset)
2493 0 : peer_flag_modify_action (peer, flag);
2494 :
2495 0 : return 0;
2496 : }
2497 :
2498 : /* peer-group member updates. */
2499 0 : group = peer->group;
2500 :
2501 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2502 : {
2503 0 : if (set && CHECK_FLAG (peer->flags, flag) == flag)
2504 0 : continue;
2505 :
2506 0 : if (! set && ! CHECK_FLAG (peer->flags, flag))
2507 0 : continue;
2508 :
2509 0 : if (set)
2510 0 : SET_FLAG (peer->flags, flag);
2511 : else
2512 0 : UNSET_FLAG (peer->flags, flag);
2513 :
2514 0 : if (action.type == peer_change_reset)
2515 0 : peer_flag_modify_action (peer, flag);
2516 : }
2517 0 : return 0;
2518 : }
2519 :
2520 : int
2521 0 : peer_flag_set (struct peer *peer, u_int32_t flag)
2522 : {
2523 0 : return peer_flag_modify (peer, flag, 1);
2524 : }
2525 :
2526 : int
2527 0 : peer_flag_unset (struct peer *peer, u_int32_t flag)
2528 : {
2529 0 : return peer_flag_modify (peer, flag, 0);
2530 : }
2531 :
2532 : static int
2533 0 : peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2534 : {
2535 0 : if (peer->af_group[afi][safi])
2536 0 : return 1;
2537 0 : return 0;
2538 : }
2539 :
2540 : static int
2541 0 : peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2542 : int set)
2543 : {
2544 : int found;
2545 : int size;
2546 : struct listnode *node, *nnode;
2547 : struct peer_group *group;
2548 : struct peer_flag_action action;
2549 :
2550 0 : memset (&action, 0, sizeof (struct peer_flag_action));
2551 0 : size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2552 :
2553 0 : found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2554 :
2555 : /* No flag action is found. */
2556 0 : if (! found)
2557 0 : return BGP_ERR_INVALID_FLAG;
2558 :
2559 : /* Adress family must be activated. */
2560 0 : if (! peer->afc[afi][safi])
2561 0 : return BGP_ERR_PEER_INACTIVE;
2562 :
2563 : /* Not for peer-group member. */
2564 0 : if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2565 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2566 :
2567 : /* Spcecial check for reflector client. */
2568 0 : if (flag & PEER_FLAG_REFLECTOR_CLIENT
2569 0 : && peer_sort (peer) != BGP_PEER_IBGP)
2570 0 : return BGP_ERR_NOT_INTERNAL_PEER;
2571 :
2572 : /* Spcecial check for remove-private-AS. */
2573 0 : if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2574 0 : && peer_sort (peer) == BGP_PEER_IBGP)
2575 0 : return BGP_ERR_REMOVE_PRIVATE_AS;
2576 :
2577 : /* When unset the peer-group member's flag we have to check
2578 : peer-group configuration. */
2579 0 : if (! set && peer->af_group[afi][safi])
2580 0 : if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2581 0 : return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2582 :
2583 : /* When current flag configuration is same as requested one. */
2584 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2585 : {
2586 0 : if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2587 0 : return 0;
2588 0 : if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2589 0 : return 0;
2590 : }
2591 :
2592 0 : if (set)
2593 0 : SET_FLAG (peer->af_flags[afi][safi], flag);
2594 : else
2595 0 : UNSET_FLAG (peer->af_flags[afi][safi], flag);
2596 :
2597 : /* Execute action when peer is established. */
2598 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2599 0 : && peer->status == Established)
2600 : {
2601 0 : if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2602 0 : bgp_clear_adj_in (peer, afi, safi);
2603 : else
2604 : {
2605 0 : if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2606 0 : peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2607 0 : else if (flag == PEER_FLAG_RSERVER_CLIENT)
2608 0 : peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2609 0 : else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2610 0 : peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2611 0 : else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2612 0 : peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2613 :
2614 0 : peer_change_action (peer, afi, safi, action.type);
2615 : }
2616 :
2617 : }
2618 :
2619 : /* Peer group member updates. */
2620 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2621 : {
2622 0 : group = peer->group;
2623 :
2624 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2625 : {
2626 0 : if (! peer->af_group[afi][safi])
2627 0 : continue;
2628 :
2629 0 : if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2630 0 : continue;
2631 :
2632 0 : if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2633 0 : continue;
2634 :
2635 0 : if (set)
2636 0 : SET_FLAG (peer->af_flags[afi][safi], flag);
2637 : else
2638 0 : UNSET_FLAG (peer->af_flags[afi][safi], flag);
2639 :
2640 0 : if (peer->status == Established)
2641 : {
2642 0 : if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2643 0 : bgp_clear_adj_in (peer, afi, safi);
2644 : else
2645 : {
2646 0 : if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2647 0 : peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2648 0 : else if (flag == PEER_FLAG_RSERVER_CLIENT)
2649 0 : peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2650 0 : else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2651 0 : peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2652 0 : else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2653 0 : peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2654 :
2655 0 : peer_change_action (peer, afi, safi, action.type);
2656 : }
2657 : }
2658 : }
2659 : }
2660 0 : return 0;
2661 : }
2662 :
2663 : int
2664 0 : peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2665 : {
2666 0 : return peer_af_flag_modify (peer, afi, safi, flag, 1);
2667 : }
2668 :
2669 : int
2670 0 : peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2671 : {
2672 0 : return peer_af_flag_modify (peer, afi, safi, flag, 0);
2673 : }
2674 :
2675 : /* EBGP multihop configuration. */
2676 : int
2677 0 : peer_ebgp_multihop_set (struct peer *peer, int ttl)
2678 : {
2679 : struct peer_group *group;
2680 : struct listnode *node, *nnode;
2681 : struct peer *peer1;
2682 :
2683 0 : if (peer->sort == BGP_PEER_IBGP)
2684 0 : return 0;
2685 :
2686 : /* see comment in peer_ttl_security_hops_set() */
2687 0 : if (ttl != MAXTTL)
2688 : {
2689 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2690 : {
2691 0 : group = peer->group;
2692 0 : if (group->conf->gtsm_hops != 0)
2693 0 : return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2694 :
2695 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2696 : {
2697 0 : if (peer1->sort == BGP_PEER_IBGP)
2698 0 : continue;
2699 :
2700 0 : if (peer1->gtsm_hops != 0)
2701 0 : return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2702 : }
2703 : }
2704 : else
2705 : {
2706 0 : if (peer->gtsm_hops != 0)
2707 0 : return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2708 : }
2709 : }
2710 :
2711 0 : peer->ttl = ttl;
2712 :
2713 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2714 : {
2715 0 : if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
2716 0 : sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2717 : }
2718 : else
2719 : {
2720 0 : group = peer->group;
2721 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2722 : {
2723 0 : if (peer->sort == BGP_PEER_IBGP)
2724 0 : continue;
2725 :
2726 0 : peer->ttl = group->conf->ttl;
2727 :
2728 0 : if (peer->fd >= 0)
2729 0 : sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2730 : }
2731 : }
2732 0 : return 0;
2733 : }
2734 :
2735 : int
2736 0 : peer_ebgp_multihop_unset (struct peer *peer)
2737 : {
2738 : struct peer_group *group;
2739 : struct listnode *node, *nnode;
2740 :
2741 0 : if (peer->sort == BGP_PEER_IBGP)
2742 0 : return 0;
2743 :
2744 0 : if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2745 0 : return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2746 :
2747 0 : if (peer_group_active (peer))
2748 0 : peer->ttl = peer->group->conf->ttl;
2749 : else
2750 0 : peer->ttl = 1;
2751 :
2752 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2753 : {
2754 0 : if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
2755 0 : sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2756 : }
2757 : else
2758 : {
2759 0 : group = peer->group;
2760 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2761 : {
2762 0 : if (peer->sort == BGP_PEER_IBGP)
2763 0 : continue;
2764 :
2765 0 : peer->ttl = 1;
2766 :
2767 0 : if (peer->fd >= 0)
2768 0 : sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2769 : }
2770 : }
2771 0 : return 0;
2772 : }
2773 :
2774 : /* Neighbor description. */
2775 : int
2776 0 : peer_description_set (struct peer *peer, char *desc)
2777 : {
2778 0 : if (peer->desc)
2779 0 : XFREE (MTYPE_PEER_DESC, peer->desc);
2780 :
2781 0 : peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2782 :
2783 0 : return 0;
2784 : }
2785 :
2786 : int
2787 0 : peer_description_unset (struct peer *peer)
2788 : {
2789 0 : if (peer->desc)
2790 0 : XFREE (MTYPE_PEER_DESC, peer->desc);
2791 :
2792 0 : peer->desc = NULL;
2793 :
2794 0 : return 0;
2795 : }
2796 :
2797 : /* Neighbor update-source. */
2798 : int
2799 0 : peer_update_source_if_set (struct peer *peer, const char *ifname)
2800 : {
2801 : struct peer_group *group;
2802 : struct listnode *node, *nnode;
2803 :
2804 0 : if (peer->update_if)
2805 : {
2806 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2807 0 : && strcmp (peer->update_if, ifname) == 0)
2808 0 : return 0;
2809 :
2810 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2811 0 : peer->update_if = NULL;
2812 : }
2813 :
2814 0 : if (peer->update_source)
2815 : {
2816 0 : sockunion_free (peer->update_source);
2817 0 : peer->update_source = NULL;
2818 : }
2819 :
2820 0 : peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2821 :
2822 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2823 : {
2824 0 : if (peer->status == Established)
2825 : {
2826 0 : peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2827 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2828 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2829 : }
2830 : else
2831 0 : BGP_EVENT_ADD (peer, BGP_Stop);
2832 0 : return 0;
2833 : }
2834 :
2835 : /* peer-group member updates. */
2836 0 : group = peer->group;
2837 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2838 : {
2839 0 : if (peer->update_if)
2840 : {
2841 0 : if (strcmp (peer->update_if, ifname) == 0)
2842 0 : continue;
2843 :
2844 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2845 0 : peer->update_if = NULL;
2846 : }
2847 :
2848 0 : if (peer->update_source)
2849 : {
2850 0 : sockunion_free (peer->update_source);
2851 0 : peer->update_source = NULL;
2852 : }
2853 :
2854 0 : peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2855 :
2856 0 : if (peer->status == Established)
2857 : {
2858 0 : peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2859 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2860 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2861 : }
2862 : else
2863 0 : BGP_EVENT_ADD (peer, BGP_Stop);
2864 : }
2865 0 : return 0;
2866 : }
2867 :
2868 : int
2869 0 : peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2870 : {
2871 : struct peer_group *group;
2872 : struct listnode *node, *nnode;
2873 :
2874 0 : if (peer->update_source)
2875 : {
2876 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2877 0 : && sockunion_cmp (peer->update_source, su) == 0)
2878 0 : return 0;
2879 0 : sockunion_free (peer->update_source);
2880 0 : peer->update_source = NULL;
2881 : }
2882 :
2883 0 : if (peer->update_if)
2884 : {
2885 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2886 0 : peer->update_if = NULL;
2887 : }
2888 :
2889 0 : peer->update_source = sockunion_dup (su);
2890 :
2891 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2892 : {
2893 0 : if (peer->status == Established)
2894 : {
2895 0 : peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2896 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2897 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2898 : }
2899 : else
2900 0 : BGP_EVENT_ADD (peer, BGP_Stop);
2901 0 : return 0;
2902 : }
2903 :
2904 : /* peer-group member updates. */
2905 0 : group = peer->group;
2906 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2907 : {
2908 0 : if (peer->update_source)
2909 : {
2910 0 : if (sockunion_cmp (peer->update_source, su) == 0)
2911 0 : continue;
2912 0 : sockunion_free (peer->update_source);
2913 0 : peer->update_source = NULL;
2914 : }
2915 :
2916 0 : if (peer->update_if)
2917 : {
2918 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2919 0 : peer->update_if = NULL;
2920 : }
2921 :
2922 0 : peer->update_source = sockunion_dup (su);
2923 :
2924 0 : if (peer->status == Established)
2925 : {
2926 0 : peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2927 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2928 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2929 : }
2930 : else
2931 0 : BGP_EVENT_ADD (peer, BGP_Stop);
2932 : }
2933 0 : return 0;
2934 : }
2935 :
2936 : int
2937 0 : peer_update_source_unset (struct peer *peer)
2938 : {
2939 : union sockunion *su;
2940 : struct peer_group *group;
2941 : struct listnode *node, *nnode;
2942 :
2943 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2944 0 : && ! peer->update_source
2945 0 : && ! peer->update_if)
2946 0 : return 0;
2947 :
2948 0 : if (peer->update_source)
2949 : {
2950 0 : sockunion_free (peer->update_source);
2951 0 : peer->update_source = NULL;
2952 : }
2953 0 : if (peer->update_if)
2954 : {
2955 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2956 0 : peer->update_if = NULL;
2957 : }
2958 :
2959 0 : if (peer_group_active (peer))
2960 : {
2961 0 : group = peer->group;
2962 :
2963 0 : if (group->conf->update_source)
2964 : {
2965 0 : su = sockunion_dup (group->conf->update_source);
2966 0 : peer->update_source = su;
2967 : }
2968 0 : else if (group->conf->update_if)
2969 0 : peer->update_if =
2970 0 : XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2971 : }
2972 :
2973 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2974 : {
2975 0 : if (peer->status == Established)
2976 : {
2977 0 : peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2978 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2979 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2980 : }
2981 : else
2982 0 : BGP_EVENT_ADD (peer, BGP_Stop);
2983 0 : return 0;
2984 : }
2985 :
2986 : /* peer-group member updates. */
2987 0 : group = peer->group;
2988 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2989 : {
2990 0 : if (! peer->update_source && ! peer->update_if)
2991 0 : continue;
2992 :
2993 0 : if (peer->update_source)
2994 : {
2995 0 : sockunion_free (peer->update_source);
2996 0 : peer->update_source = NULL;
2997 : }
2998 :
2999 0 : if (peer->update_if)
3000 : {
3001 0 : XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3002 0 : peer->update_if = NULL;
3003 : }
3004 :
3005 0 : if (peer->status == Established)
3006 : {
3007 0 : peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3008 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3009 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3010 : }
3011 : else
3012 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3013 : }
3014 0 : return 0;
3015 : }
3016 :
3017 : int
3018 0 : peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
3019 : const char *rmap)
3020 : {
3021 : struct peer_group *group;
3022 : struct listnode *node, *nnode;
3023 :
3024 : /* Adress family must be activated. */
3025 0 : if (! peer->afc[afi][safi])
3026 0 : return BGP_ERR_PEER_INACTIVE;
3027 :
3028 : /* Default originate can't be used for peer group memeber. */
3029 0 : if (peer_is_group_member (peer, afi, safi))
3030 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3031 :
3032 0 : if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3033 0 : || (rmap && ! peer->default_rmap[afi][safi].name)
3034 0 : || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3035 : {
3036 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3037 :
3038 0 : if (rmap)
3039 : {
3040 0 : if (peer->default_rmap[afi][safi].name)
3041 0 : free (peer->default_rmap[afi][safi].name);
3042 0 : peer->default_rmap[afi][safi].name = strdup (rmap);
3043 0 : peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3044 : }
3045 : }
3046 :
3047 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3048 : {
3049 0 : if (peer->status == Established && peer->afc_nego[afi][safi])
3050 0 : bgp_default_originate (peer, afi, safi, 0);
3051 0 : return 0;
3052 : }
3053 :
3054 : /* peer-group member updates. */
3055 0 : group = peer->group;
3056 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3057 : {
3058 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3059 :
3060 0 : if (rmap)
3061 : {
3062 0 : if (peer->default_rmap[afi][safi].name)
3063 0 : free (peer->default_rmap[afi][safi].name);
3064 0 : peer->default_rmap[afi][safi].name = strdup (rmap);
3065 0 : peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3066 : }
3067 :
3068 0 : if (peer->status == Established && peer->afc_nego[afi][safi])
3069 0 : bgp_default_originate (peer, afi, safi, 0);
3070 : }
3071 0 : return 0;
3072 : }
3073 :
3074 : int
3075 0 : peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3076 : {
3077 : struct peer_group *group;
3078 : struct listnode *node, *nnode;
3079 :
3080 : /* Adress family must be activated. */
3081 0 : if (! peer->afc[afi][safi])
3082 0 : return BGP_ERR_PEER_INACTIVE;
3083 :
3084 : /* Default originate can't be used for peer group memeber. */
3085 0 : if (peer_is_group_member (peer, afi, safi))
3086 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3087 :
3088 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3089 : {
3090 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3091 :
3092 0 : if (peer->default_rmap[afi][safi].name)
3093 0 : free (peer->default_rmap[afi][safi].name);
3094 0 : peer->default_rmap[afi][safi].name = NULL;
3095 0 : peer->default_rmap[afi][safi].map = NULL;
3096 : }
3097 :
3098 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3099 : {
3100 0 : if (peer->status == Established && peer->afc_nego[afi][safi])
3101 0 : bgp_default_originate (peer, afi, safi, 1);
3102 0 : return 0;
3103 : }
3104 :
3105 : /* peer-group member updates. */
3106 0 : group = peer->group;
3107 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3108 : {
3109 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3110 :
3111 0 : if (peer->default_rmap[afi][safi].name)
3112 0 : free (peer->default_rmap[afi][safi].name);
3113 0 : peer->default_rmap[afi][safi].name = NULL;
3114 0 : peer->default_rmap[afi][safi].map = NULL;
3115 :
3116 0 : if (peer->status == Established && peer->afc_nego[afi][safi])
3117 0 : bgp_default_originate (peer, afi, safi, 1);
3118 : }
3119 0 : return 0;
3120 : }
3121 :
3122 : int
3123 0 : peer_port_set (struct peer *peer, u_int16_t port)
3124 : {
3125 0 : peer->port = port;
3126 0 : return 0;
3127 : }
3128 :
3129 : int
3130 0 : peer_port_unset (struct peer *peer)
3131 : {
3132 0 : peer->port = BGP_PORT_DEFAULT;
3133 0 : return 0;
3134 : }
3135 :
3136 : /* neighbor weight. */
3137 : int
3138 0 : peer_weight_set (struct peer *peer, u_int16_t weight)
3139 : {
3140 : struct peer_group *group;
3141 : struct listnode *node, *nnode;
3142 :
3143 0 : SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3144 0 : peer->weight = weight;
3145 :
3146 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3147 0 : return 0;
3148 :
3149 : /* peer-group member updates. */
3150 0 : group = peer->group;
3151 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3152 : {
3153 0 : peer->weight = group->conf->weight;
3154 : }
3155 0 : return 0;
3156 : }
3157 :
3158 : int
3159 0 : peer_weight_unset (struct peer *peer)
3160 : {
3161 : struct peer_group *group;
3162 : struct listnode *node, *nnode;
3163 :
3164 : /* Set default weight. */
3165 0 : if (peer_group_active (peer))
3166 0 : peer->weight = peer->group->conf->weight;
3167 : else
3168 0 : peer->weight = 0;
3169 :
3170 0 : UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3171 :
3172 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3173 0 : return 0;
3174 :
3175 : /* peer-group member updates. */
3176 0 : group = peer->group;
3177 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3178 : {
3179 0 : peer->weight = 0;
3180 : }
3181 0 : return 0;
3182 : }
3183 :
3184 : int
3185 0 : peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3186 : {
3187 : struct peer_group *group;
3188 : struct listnode *node, *nnode;
3189 :
3190 : /* Not for peer group memeber. */
3191 0 : if (peer_group_active (peer))
3192 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3193 :
3194 : /* keepalive value check. */
3195 0 : if (keepalive > 65535)
3196 0 : return BGP_ERR_INVALID_VALUE;
3197 :
3198 : /* Holdtime value check. */
3199 0 : if (holdtime > 65535)
3200 0 : return BGP_ERR_INVALID_VALUE;
3201 :
3202 : /* Holdtime value must be either 0 or greater than 3. */
3203 0 : if (holdtime < 3 && holdtime != 0)
3204 0 : return BGP_ERR_INVALID_VALUE;
3205 :
3206 : /* Set value to the configuration. */
3207 0 : SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3208 0 : peer->holdtime = holdtime;
3209 0 : peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3210 :
3211 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3212 0 : return 0;
3213 :
3214 : /* peer-group member updates. */
3215 0 : group = peer->group;
3216 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3217 : {
3218 0 : SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3219 0 : peer->holdtime = group->conf->holdtime;
3220 0 : peer->keepalive = group->conf->keepalive;
3221 : }
3222 0 : return 0;
3223 : }
3224 :
3225 : int
3226 0 : peer_timers_unset (struct peer *peer)
3227 : {
3228 : struct peer_group *group;
3229 : struct listnode *node, *nnode;
3230 :
3231 0 : if (peer_group_active (peer))
3232 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3233 :
3234 : /* Clear configuration. */
3235 0 : UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3236 0 : peer->keepalive = 0;
3237 0 : peer->holdtime = 0;
3238 :
3239 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3240 0 : return 0;
3241 :
3242 : /* peer-group member updates. */
3243 0 : group = peer->group;
3244 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3245 : {
3246 0 : UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3247 0 : peer->holdtime = 0;
3248 0 : peer->keepalive = 0;
3249 : }
3250 :
3251 0 : return 0;
3252 : }
3253 :
3254 : int
3255 0 : peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3256 : {
3257 0 : if (peer_group_active (peer))
3258 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3259 :
3260 0 : if (connect > 65535)
3261 0 : return BGP_ERR_INVALID_VALUE;
3262 :
3263 : /* Set value to the configuration. */
3264 0 : SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3265 0 : peer->connect = connect;
3266 :
3267 : /* Set value to timer setting. */
3268 0 : peer->v_connect = connect;
3269 :
3270 0 : return 0;
3271 : }
3272 :
3273 : int
3274 0 : peer_timers_connect_unset (struct peer *peer)
3275 : {
3276 0 : if (peer_group_active (peer))
3277 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3278 :
3279 : /* Clear configuration. */
3280 0 : UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3281 0 : peer->connect = 0;
3282 :
3283 : /* Set timer setting to default value. */
3284 0 : peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3285 :
3286 0 : return 0;
3287 : }
3288 :
3289 : int
3290 0 : peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3291 : {
3292 0 : if (peer_group_active (peer))
3293 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3294 :
3295 0 : if (routeadv > 600)
3296 0 : return BGP_ERR_INVALID_VALUE;
3297 :
3298 0 : SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3299 0 : peer->routeadv = routeadv;
3300 0 : peer->v_routeadv = routeadv;
3301 :
3302 0 : return 0;
3303 : }
3304 :
3305 : int
3306 0 : peer_advertise_interval_unset (struct peer *peer)
3307 : {
3308 0 : if (peer_group_active (peer))
3309 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3310 :
3311 0 : UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3312 0 : peer->routeadv = 0;
3313 :
3314 0 : if (peer->sort == BGP_PEER_IBGP)
3315 0 : peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3316 : else
3317 0 : peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3318 :
3319 0 : return 0;
3320 : }
3321 :
3322 : /* neighbor interface */
3323 : int
3324 0 : peer_interface_set (struct peer *peer, const char *str)
3325 : {
3326 0 : if (peer->ifname)
3327 0 : free (peer->ifname);
3328 0 : peer->ifname = strdup (str);
3329 :
3330 0 : return 0;
3331 : }
3332 :
3333 : int
3334 0 : peer_interface_unset (struct peer *peer)
3335 : {
3336 0 : if (peer->ifname)
3337 0 : free (peer->ifname);
3338 0 : peer->ifname = NULL;
3339 :
3340 0 : return 0;
3341 : }
3342 :
3343 : /* Allow-as in. */
3344 : int
3345 0 : peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3346 : {
3347 : struct peer_group *group;
3348 : struct listnode *node, *nnode;
3349 :
3350 0 : if (allow_num < 1 || allow_num > 10)
3351 0 : return BGP_ERR_INVALID_VALUE;
3352 :
3353 0 : if (peer->allowas_in[afi][safi] != allow_num)
3354 : {
3355 0 : peer->allowas_in[afi][safi] = allow_num;
3356 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3357 0 : peer_change_action (peer, afi, safi, peer_change_reset_in);
3358 : }
3359 :
3360 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3361 0 : return 0;
3362 :
3363 0 : group = peer->group;
3364 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3365 : {
3366 0 : if (peer->allowas_in[afi][safi] != allow_num)
3367 : {
3368 0 : peer->allowas_in[afi][safi] = allow_num;
3369 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3370 0 : peer_change_action (peer, afi, safi, peer_change_reset_in);
3371 : }
3372 :
3373 : }
3374 0 : return 0;
3375 : }
3376 :
3377 : int
3378 0 : peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3379 : {
3380 : struct peer_group *group;
3381 : struct listnode *node, *nnode;
3382 :
3383 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3384 : {
3385 0 : peer->allowas_in[afi][safi] = 0;
3386 0 : peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3387 : }
3388 :
3389 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3390 0 : return 0;
3391 :
3392 0 : group = peer->group;
3393 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3394 : {
3395 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3396 : {
3397 0 : peer->allowas_in[afi][safi] = 0;
3398 0 : peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3399 : }
3400 : }
3401 0 : return 0;
3402 : }
3403 :
3404 : int
3405 0 : peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
3406 : {
3407 0 : struct bgp *bgp = peer->bgp;
3408 : struct peer_group *group;
3409 : struct listnode *node, *nnode;
3410 :
3411 0 : if (peer_sort (peer) != BGP_PEER_EBGP
3412 0 : && peer_sort (peer) != BGP_PEER_INTERNAL)
3413 0 : return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3414 :
3415 0 : if (bgp->as == as)
3416 0 : return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3417 :
3418 0 : if (peer_group_active (peer))
3419 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3420 :
3421 0 : if (peer->as == as)
3422 0 : return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3423 :
3424 0 : if (peer->change_local_as == as &&
3425 0 : ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3426 0 : || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3427 0 : ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3428 0 : || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
3429 0 : return 0;
3430 :
3431 0 : peer->change_local_as = as;
3432 0 : if (no_prepend)
3433 0 : SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3434 : else
3435 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3436 :
3437 0 : if (replace_as)
3438 0 : SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3439 : else
3440 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3441 :
3442 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3443 : {
3444 0 : if (peer->status == Established)
3445 : {
3446 0 : peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3447 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3448 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3449 : }
3450 : else
3451 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3452 :
3453 0 : return 0;
3454 : }
3455 :
3456 0 : group = peer->group;
3457 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3458 : {
3459 0 : peer->change_local_as = as;
3460 0 : if (no_prepend)
3461 0 : SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3462 : else
3463 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3464 :
3465 0 : if (replace_as)
3466 0 : SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3467 : else
3468 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3469 :
3470 0 : if (peer->status == Established)
3471 : {
3472 0 : peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3473 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3474 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3475 : }
3476 : else
3477 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3478 : }
3479 :
3480 0 : return 0;
3481 : }
3482 :
3483 : int
3484 0 : peer_local_as_unset (struct peer *peer)
3485 : {
3486 : struct peer_group *group;
3487 : struct listnode *node, *nnode;
3488 :
3489 0 : if (peer_group_active (peer))
3490 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3491 :
3492 0 : if (! peer->change_local_as)
3493 0 : return 0;
3494 :
3495 0 : peer->change_local_as = 0;
3496 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3497 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3498 :
3499 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3500 : {
3501 0 : if (peer->status == Established)
3502 : {
3503 0 : peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3504 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3505 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3506 : }
3507 : else
3508 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3509 :
3510 0 : return 0;
3511 : }
3512 :
3513 0 : group = peer->group;
3514 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3515 : {
3516 0 : peer->change_local_as = 0;
3517 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3518 0 : UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3519 :
3520 0 : if (peer->status == Established)
3521 : {
3522 0 : peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3523 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3524 : BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3525 : }
3526 : else
3527 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3528 : }
3529 0 : return 0;
3530 : }
3531 :
3532 : /* Set password for authenticating with the peer. */
3533 : int
3534 0 : peer_password_set (struct peer *peer, const char *password)
3535 : {
3536 : struct listnode *nn, *nnode;
3537 0 : int len = password ? strlen(password) : 0;
3538 0 : int ret = BGP_SUCCESS;
3539 :
3540 0 : if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3541 0 : return BGP_ERR_INVALID_VALUE;
3542 :
3543 0 : if (peer->password && strcmp (peer->password, password) == 0
3544 0 : && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3545 0 : return 0;
3546 :
3547 0 : if (peer->password)
3548 0 : XFREE (MTYPE_PEER_PASSWORD, peer->password);
3549 :
3550 0 : peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3551 :
3552 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3553 : {
3554 0 : if (peer->status == Established)
3555 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3556 : else
3557 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3558 :
3559 0 : return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3560 : }
3561 :
3562 0 : for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3563 : {
3564 0 : if (peer->password && strcmp (peer->password, password) == 0)
3565 0 : continue;
3566 :
3567 0 : if (peer->password)
3568 0 : XFREE (MTYPE_PEER_PASSWORD, peer->password);
3569 :
3570 0 : peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3571 :
3572 0 : if (peer->status == Established)
3573 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3574 : else
3575 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3576 :
3577 0 : if (bgp_md5_set (peer) < 0)
3578 0 : ret = BGP_ERR_TCPSIG_FAILED;
3579 : }
3580 :
3581 0 : return ret;
3582 : }
3583 :
3584 : int
3585 0 : peer_password_unset (struct peer *peer)
3586 : {
3587 : struct listnode *nn, *nnode;
3588 :
3589 0 : if (!peer->password
3590 0 : && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3591 0 : return 0;
3592 :
3593 0 : if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3594 : {
3595 0 : if (peer_group_active (peer)
3596 0 : && peer->group->conf->password
3597 0 : && strcmp (peer->group->conf->password, peer->password) == 0)
3598 0 : return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3599 :
3600 0 : if (peer->status == Established)
3601 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3602 : else
3603 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3604 :
3605 0 : if (peer->password)
3606 0 : XFREE (MTYPE_PEER_PASSWORD, peer->password);
3607 :
3608 0 : peer->password = NULL;
3609 :
3610 0 : bgp_md5_set (peer);
3611 :
3612 0 : return 0;
3613 : }
3614 :
3615 0 : XFREE (MTYPE_PEER_PASSWORD, peer->password);
3616 0 : peer->password = NULL;
3617 :
3618 0 : for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3619 : {
3620 0 : if (!peer->password)
3621 0 : continue;
3622 :
3623 0 : if (peer->status == Established)
3624 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3625 : else
3626 0 : BGP_EVENT_ADD (peer, BGP_Stop);
3627 :
3628 0 : XFREE (MTYPE_PEER_PASSWORD, peer->password);
3629 0 : peer->password = NULL;
3630 :
3631 0 : bgp_md5_set (peer);
3632 : }
3633 :
3634 0 : return 0;
3635 : }
3636 :
3637 : /* Set distribute list to the peer. */
3638 : int
3639 0 : peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
3640 : const char *name)
3641 : {
3642 : struct bgp_filter *filter;
3643 : struct peer_group *group;
3644 : struct listnode *node, *nnode;
3645 :
3646 0 : if (! peer->afc[afi][safi])
3647 0 : return BGP_ERR_PEER_INACTIVE;
3648 :
3649 0 : if (direct != FILTER_IN && direct != FILTER_OUT)
3650 0 : return BGP_ERR_INVALID_VALUE;
3651 :
3652 0 : if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3653 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3654 :
3655 0 : filter = &peer->filter[afi][safi];
3656 :
3657 0 : if (filter->plist[direct].name)
3658 0 : return BGP_ERR_PEER_FILTER_CONFLICT;
3659 :
3660 0 : if (filter->dlist[direct].name)
3661 0 : free (filter->dlist[direct].name);
3662 0 : filter->dlist[direct].name = strdup (name);
3663 0 : filter->dlist[direct].alist = access_list_lookup (afi, name);
3664 :
3665 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3666 0 : return 0;
3667 :
3668 0 : group = peer->group;
3669 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3670 : {
3671 0 : filter = &peer->filter[afi][safi];
3672 :
3673 0 : if (! peer->af_group[afi][safi])
3674 0 : continue;
3675 :
3676 0 : if (filter->dlist[direct].name)
3677 0 : free (filter->dlist[direct].name);
3678 0 : filter->dlist[direct].name = strdup (name);
3679 0 : filter->dlist[direct].alist = access_list_lookup (afi, name);
3680 : }
3681 :
3682 0 : return 0;
3683 : }
3684 :
3685 : int
3686 0 : peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3687 : {
3688 : struct bgp_filter *filter;
3689 : struct bgp_filter *gfilter;
3690 : struct peer_group *group;
3691 : struct listnode *node, *nnode;
3692 :
3693 0 : if (! peer->afc[afi][safi])
3694 0 : return BGP_ERR_PEER_INACTIVE;
3695 :
3696 0 : if (direct != FILTER_IN && direct != FILTER_OUT)
3697 0 : return BGP_ERR_INVALID_VALUE;
3698 :
3699 0 : if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3700 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3701 :
3702 0 : filter = &peer->filter[afi][safi];
3703 :
3704 : /* apply peer-group filter */
3705 0 : if (peer->af_group[afi][safi])
3706 : {
3707 0 : gfilter = &peer->group->conf->filter[afi][safi];
3708 :
3709 0 : if (gfilter->dlist[direct].name)
3710 : {
3711 0 : if (filter->dlist[direct].name)
3712 0 : free (filter->dlist[direct].name);
3713 0 : filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3714 0 : filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3715 0 : return 0;
3716 : }
3717 : }
3718 :
3719 0 : if (filter->dlist[direct].name)
3720 0 : free (filter->dlist[direct].name);
3721 0 : filter->dlist[direct].name = NULL;
3722 0 : filter->dlist[direct].alist = NULL;
3723 :
3724 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3725 0 : return 0;
3726 :
3727 0 : group = peer->group;
3728 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3729 : {
3730 0 : filter = &peer->filter[afi][safi];
3731 :
3732 0 : if (! peer->af_group[afi][safi])
3733 0 : continue;
3734 :
3735 0 : if (filter->dlist[direct].name)
3736 0 : free (filter->dlist[direct].name);
3737 0 : filter->dlist[direct].name = NULL;
3738 0 : filter->dlist[direct].alist = NULL;
3739 : }
3740 :
3741 0 : return 0;
3742 : }
3743 :
3744 : /* Update distribute list. */
3745 : static void
3746 0 : peer_distribute_update (struct access_list *access)
3747 : {
3748 : afi_t afi;
3749 : safi_t safi;
3750 : int direct;
3751 : struct listnode *mnode, *mnnode;
3752 : struct listnode *node, *nnode;
3753 : struct bgp *bgp;
3754 : struct peer *peer;
3755 : struct peer_group *group;
3756 : struct bgp_filter *filter;
3757 :
3758 0 : for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
3759 : {
3760 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3761 : {
3762 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
3763 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3764 : {
3765 0 : filter = &peer->filter[afi][safi];
3766 :
3767 0 : for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3768 : {
3769 0 : if (filter->dlist[direct].name)
3770 0 : filter->dlist[direct].alist =
3771 0 : access_list_lookup (afi, filter->dlist[direct].name);
3772 : else
3773 0 : filter->dlist[direct].alist = NULL;
3774 : }
3775 : }
3776 : }
3777 0 : for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3778 : {
3779 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
3780 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3781 : {
3782 0 : filter = &group->conf->filter[afi][safi];
3783 :
3784 0 : for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3785 : {
3786 0 : if (filter->dlist[direct].name)
3787 0 : filter->dlist[direct].alist =
3788 0 : access_list_lookup (afi, filter->dlist[direct].name);
3789 : else
3790 0 : filter->dlist[direct].alist = NULL;
3791 : }
3792 : }
3793 : }
3794 : }
3795 0 : }
3796 :
3797 : /* Set prefix list to the peer. */
3798 : int
3799 0 : peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
3800 : const char *name)
3801 : {
3802 : struct bgp_filter *filter;
3803 : struct peer_group *group;
3804 : struct listnode *node, *nnode;
3805 :
3806 0 : if (! peer->afc[afi][safi])
3807 0 : return BGP_ERR_PEER_INACTIVE;
3808 :
3809 0 : if (direct != FILTER_IN && direct != FILTER_OUT)
3810 0 : return BGP_ERR_INVALID_VALUE;
3811 :
3812 0 : if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3813 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3814 :
3815 0 : filter = &peer->filter[afi][safi];
3816 :
3817 0 : if (filter->dlist[direct].name)
3818 0 : return BGP_ERR_PEER_FILTER_CONFLICT;
3819 :
3820 0 : if (filter->plist[direct].name)
3821 0 : free (filter->plist[direct].name);
3822 0 : filter->plist[direct].name = strdup (name);
3823 0 : filter->plist[direct].plist = prefix_list_lookup (afi, name);
3824 :
3825 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3826 0 : return 0;
3827 :
3828 0 : group = peer->group;
3829 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3830 : {
3831 0 : filter = &peer->filter[afi][safi];
3832 :
3833 0 : if (! peer->af_group[afi][safi])
3834 0 : continue;
3835 :
3836 0 : if (filter->plist[direct].name)
3837 0 : free (filter->plist[direct].name);
3838 0 : filter->plist[direct].name = strdup (name);
3839 0 : filter->plist[direct].plist = prefix_list_lookup (afi, name);
3840 : }
3841 0 : return 0;
3842 : }
3843 :
3844 : int
3845 0 : peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3846 : {
3847 : struct bgp_filter *filter;
3848 : struct bgp_filter *gfilter;
3849 : struct peer_group *group;
3850 : struct listnode *node, *nnode;
3851 :
3852 0 : if (! peer->afc[afi][safi])
3853 0 : return BGP_ERR_PEER_INACTIVE;
3854 :
3855 0 : if (direct != FILTER_IN && direct != FILTER_OUT)
3856 0 : return BGP_ERR_INVALID_VALUE;
3857 :
3858 0 : if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3859 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3860 :
3861 0 : filter = &peer->filter[afi][safi];
3862 :
3863 : /* apply peer-group filter */
3864 0 : if (peer->af_group[afi][safi])
3865 : {
3866 0 : gfilter = &peer->group->conf->filter[afi][safi];
3867 :
3868 0 : if (gfilter->plist[direct].name)
3869 : {
3870 0 : if (filter->plist[direct].name)
3871 0 : free (filter->plist[direct].name);
3872 0 : filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3873 0 : filter->plist[direct].plist = gfilter->plist[direct].plist;
3874 0 : return 0;
3875 : }
3876 : }
3877 :
3878 0 : if (filter->plist[direct].name)
3879 0 : free (filter->plist[direct].name);
3880 0 : filter->plist[direct].name = NULL;
3881 0 : filter->plist[direct].plist = NULL;
3882 :
3883 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3884 0 : return 0;
3885 :
3886 0 : group = peer->group;
3887 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3888 : {
3889 0 : filter = &peer->filter[afi][safi];
3890 :
3891 0 : if (! peer->af_group[afi][safi])
3892 0 : continue;
3893 :
3894 0 : if (filter->plist[direct].name)
3895 0 : free (filter->plist[direct].name);
3896 0 : filter->plist[direct].name = NULL;
3897 0 : filter->plist[direct].plist = NULL;
3898 : }
3899 :
3900 0 : return 0;
3901 : }
3902 :
3903 : /* Update prefix-list list. */
3904 : static void
3905 0 : peer_prefix_list_update (struct prefix_list *plist)
3906 : {
3907 : struct listnode *mnode, *mnnode;
3908 : struct listnode *node, *nnode;
3909 : struct bgp *bgp;
3910 : struct peer *peer;
3911 : struct peer_group *group;
3912 : struct bgp_filter *filter;
3913 : afi_t afi;
3914 : safi_t safi;
3915 : int direct;
3916 :
3917 0 : for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
3918 : {
3919 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3920 : {
3921 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
3922 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3923 : {
3924 0 : filter = &peer->filter[afi][safi];
3925 :
3926 0 : for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3927 : {
3928 0 : if (filter->plist[direct].name)
3929 0 : filter->plist[direct].plist =
3930 0 : prefix_list_lookup (afi, filter->plist[direct].name);
3931 : else
3932 0 : filter->plist[direct].plist = NULL;
3933 : }
3934 : }
3935 : }
3936 0 : for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3937 : {
3938 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
3939 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3940 : {
3941 0 : filter = &group->conf->filter[afi][safi];
3942 :
3943 0 : for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3944 : {
3945 0 : if (filter->plist[direct].name)
3946 0 : filter->plist[direct].plist =
3947 0 : prefix_list_lookup (afi, filter->plist[direct].name);
3948 : else
3949 0 : filter->plist[direct].plist = NULL;
3950 : }
3951 : }
3952 : }
3953 : }
3954 0 : }
3955 :
3956 : int
3957 0 : peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
3958 : const char *name)
3959 : {
3960 : struct bgp_filter *filter;
3961 : struct peer_group *group;
3962 : struct listnode *node, *nnode;
3963 :
3964 0 : if (! peer->afc[afi][safi])
3965 0 : return BGP_ERR_PEER_INACTIVE;
3966 :
3967 0 : if (direct != FILTER_IN && direct != FILTER_OUT)
3968 0 : return BGP_ERR_INVALID_VALUE;
3969 :
3970 0 : if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3971 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3972 :
3973 0 : filter = &peer->filter[afi][safi];
3974 :
3975 0 : if (filter->aslist[direct].name)
3976 0 : free (filter->aslist[direct].name);
3977 0 : filter->aslist[direct].name = strdup (name);
3978 0 : filter->aslist[direct].aslist = as_list_lookup (name);
3979 :
3980 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3981 0 : return 0;
3982 :
3983 0 : group = peer->group;
3984 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3985 : {
3986 0 : filter = &peer->filter[afi][safi];
3987 :
3988 0 : if (! peer->af_group[afi][safi])
3989 0 : continue;
3990 :
3991 0 : if (filter->aslist[direct].name)
3992 0 : free (filter->aslist[direct].name);
3993 0 : filter->aslist[direct].name = strdup (name);
3994 0 : filter->aslist[direct].aslist = as_list_lookup (name);
3995 : }
3996 0 : return 0;
3997 : }
3998 :
3999 : int
4000 0 : peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4001 : {
4002 : struct bgp_filter *filter;
4003 : struct bgp_filter *gfilter;
4004 : struct peer_group *group;
4005 : struct listnode *node, *nnode;
4006 :
4007 0 : if (! peer->afc[afi][safi])
4008 0 : return BGP_ERR_PEER_INACTIVE;
4009 :
4010 0 : if (direct != FILTER_IN && direct != FILTER_OUT)
4011 0 : return BGP_ERR_INVALID_VALUE;
4012 :
4013 0 : if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4014 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4015 :
4016 0 : filter = &peer->filter[afi][safi];
4017 :
4018 : /* apply peer-group filter */
4019 0 : if (peer->af_group[afi][safi])
4020 : {
4021 0 : gfilter = &peer->group->conf->filter[afi][safi];
4022 :
4023 0 : if (gfilter->aslist[direct].name)
4024 : {
4025 0 : if (filter->aslist[direct].name)
4026 0 : free (filter->aslist[direct].name);
4027 0 : filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4028 0 : filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4029 0 : return 0;
4030 : }
4031 : }
4032 :
4033 0 : if (filter->aslist[direct].name)
4034 0 : free (filter->aslist[direct].name);
4035 0 : filter->aslist[direct].name = NULL;
4036 0 : filter->aslist[direct].aslist = NULL;
4037 :
4038 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4039 0 : return 0;
4040 :
4041 0 : group = peer->group;
4042 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4043 : {
4044 0 : filter = &peer->filter[afi][safi];
4045 :
4046 0 : if (! peer->af_group[afi][safi])
4047 0 : continue;
4048 :
4049 0 : if (filter->aslist[direct].name)
4050 0 : free (filter->aslist[direct].name);
4051 0 : filter->aslist[direct].name = NULL;
4052 0 : filter->aslist[direct].aslist = NULL;
4053 : }
4054 :
4055 0 : return 0;
4056 : }
4057 :
4058 : static void
4059 0 : peer_aslist_update (void)
4060 : {
4061 : afi_t afi;
4062 : safi_t safi;
4063 : int direct;
4064 : struct listnode *mnode, *mnnode;
4065 : struct listnode *node, *nnode;
4066 : struct bgp *bgp;
4067 : struct peer *peer;
4068 : struct peer_group *group;
4069 : struct bgp_filter *filter;
4070 :
4071 0 : for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
4072 : {
4073 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
4074 : {
4075 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
4076 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4077 : {
4078 0 : filter = &peer->filter[afi][safi];
4079 :
4080 0 : for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4081 : {
4082 0 : if (filter->aslist[direct].name)
4083 0 : filter->aslist[direct].aslist =
4084 0 : as_list_lookup (filter->aslist[direct].name);
4085 : else
4086 0 : filter->aslist[direct].aslist = NULL;
4087 : }
4088 : }
4089 : }
4090 0 : for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
4091 : {
4092 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
4093 0 : for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4094 : {
4095 0 : filter = &group->conf->filter[afi][safi];
4096 :
4097 0 : for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4098 : {
4099 0 : if (filter->aslist[direct].name)
4100 0 : filter->aslist[direct].aslist =
4101 0 : as_list_lookup (filter->aslist[direct].name);
4102 : else
4103 0 : filter->aslist[direct].aslist = NULL;
4104 : }
4105 : }
4106 : }
4107 : }
4108 0 : }
4109 :
4110 : /* Set route-map to the peer. */
4111 : int
4112 0 : peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
4113 : const char *name)
4114 : {
4115 : struct bgp_filter *filter;
4116 : struct peer_group *group;
4117 : struct listnode *node, *nnode;
4118 :
4119 0 : if (! peer->afc[afi][safi])
4120 0 : return BGP_ERR_PEER_INACTIVE;
4121 :
4122 0 : if (direct != RMAP_IN && direct != RMAP_OUT &&
4123 0 : direct != RMAP_IMPORT && direct != RMAP_EXPORT)
4124 0 : return BGP_ERR_INVALID_VALUE;
4125 :
4126 0 : if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4127 0 : && peer_is_group_member (peer, afi, safi))
4128 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4129 :
4130 0 : filter = &peer->filter[afi][safi];
4131 :
4132 0 : if (filter->map[direct].name)
4133 0 : free (filter->map[direct].name);
4134 :
4135 0 : filter->map[direct].name = strdup (name);
4136 0 : filter->map[direct].map = route_map_lookup_by_name (name);
4137 :
4138 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4139 0 : return 0;
4140 :
4141 0 : group = peer->group;
4142 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4143 : {
4144 0 : filter = &peer->filter[afi][safi];
4145 :
4146 0 : if (! peer->af_group[afi][safi])
4147 0 : continue;
4148 :
4149 0 : if (filter->map[direct].name)
4150 0 : free (filter->map[direct].name);
4151 0 : filter->map[direct].name = strdup (name);
4152 0 : filter->map[direct].map = route_map_lookup_by_name (name);
4153 : }
4154 0 : return 0;
4155 : }
4156 :
4157 : /* Unset route-map from the peer. */
4158 : int
4159 0 : peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4160 : {
4161 : struct bgp_filter *filter;
4162 : struct bgp_filter *gfilter;
4163 : struct peer_group *group;
4164 : struct listnode *node, *nnode;
4165 :
4166 0 : if (! peer->afc[afi][safi])
4167 0 : return BGP_ERR_PEER_INACTIVE;
4168 :
4169 0 : if (direct != RMAP_IN && direct != RMAP_OUT &&
4170 0 : direct != RMAP_IMPORT && direct != RMAP_EXPORT)
4171 0 : return BGP_ERR_INVALID_VALUE;
4172 :
4173 0 : if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4174 0 : && peer_is_group_member (peer, afi, safi))
4175 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4176 :
4177 0 : filter = &peer->filter[afi][safi];
4178 :
4179 : /* apply peer-group filter */
4180 0 : if (peer->af_group[afi][safi])
4181 : {
4182 0 : gfilter = &peer->group->conf->filter[afi][safi];
4183 :
4184 0 : if (gfilter->map[direct].name)
4185 : {
4186 0 : if (filter->map[direct].name)
4187 0 : free (filter->map[direct].name);
4188 0 : filter->map[direct].name = strdup (gfilter->map[direct].name);
4189 0 : filter->map[direct].map = gfilter->map[direct].map;
4190 0 : return 0;
4191 : }
4192 : }
4193 :
4194 0 : if (filter->map[direct].name)
4195 0 : free (filter->map[direct].name);
4196 0 : filter->map[direct].name = NULL;
4197 0 : filter->map[direct].map = NULL;
4198 :
4199 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4200 0 : return 0;
4201 :
4202 0 : group = peer->group;
4203 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4204 : {
4205 0 : filter = &peer->filter[afi][safi];
4206 :
4207 0 : if (! peer->af_group[afi][safi])
4208 0 : continue;
4209 :
4210 0 : if (filter->map[direct].name)
4211 0 : free (filter->map[direct].name);
4212 0 : filter->map[direct].name = NULL;
4213 0 : filter->map[direct].map = NULL;
4214 : }
4215 0 : return 0;
4216 : }
4217 :
4218 : /* Set unsuppress-map to the peer. */
4219 : int
4220 0 : peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4221 : const char *name)
4222 : {
4223 : struct bgp_filter *filter;
4224 : struct peer_group *group;
4225 : struct listnode *node, *nnode;
4226 :
4227 0 : if (! peer->afc[afi][safi])
4228 0 : return BGP_ERR_PEER_INACTIVE;
4229 :
4230 0 : if (peer_is_group_member (peer, afi, safi))
4231 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4232 :
4233 0 : filter = &peer->filter[afi][safi];
4234 :
4235 0 : if (filter->usmap.name)
4236 0 : free (filter->usmap.name);
4237 :
4238 0 : filter->usmap.name = strdup (name);
4239 0 : filter->usmap.map = route_map_lookup_by_name (name);
4240 :
4241 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4242 0 : return 0;
4243 :
4244 0 : group = peer->group;
4245 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4246 : {
4247 0 : filter = &peer->filter[afi][safi];
4248 :
4249 0 : if (! peer->af_group[afi][safi])
4250 0 : continue;
4251 :
4252 0 : if (filter->usmap.name)
4253 0 : free (filter->usmap.name);
4254 0 : filter->usmap.name = strdup (name);
4255 0 : filter->usmap.map = route_map_lookup_by_name (name);
4256 : }
4257 0 : return 0;
4258 : }
4259 :
4260 : /* Unset route-map from the peer. */
4261 : int
4262 0 : peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4263 : {
4264 : struct bgp_filter *filter;
4265 : struct peer_group *group;
4266 : struct listnode *node, *nnode;
4267 :
4268 0 : if (! peer->afc[afi][safi])
4269 0 : return BGP_ERR_PEER_INACTIVE;
4270 :
4271 0 : if (peer_is_group_member (peer, afi, safi))
4272 0 : return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4273 :
4274 0 : filter = &peer->filter[afi][safi];
4275 :
4276 0 : if (filter->usmap.name)
4277 0 : free (filter->usmap.name);
4278 0 : filter->usmap.name = NULL;
4279 0 : filter->usmap.map = NULL;
4280 :
4281 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4282 0 : return 0;
4283 :
4284 0 : group = peer->group;
4285 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4286 : {
4287 0 : filter = &peer->filter[afi][safi];
4288 :
4289 0 : if (! peer->af_group[afi][safi])
4290 0 : continue;
4291 :
4292 0 : if (filter->usmap.name)
4293 0 : free (filter->usmap.name);
4294 0 : filter->usmap.name = NULL;
4295 0 : filter->usmap.map = NULL;
4296 : }
4297 0 : return 0;
4298 : }
4299 :
4300 : int
4301 0 : peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
4302 : u_int32_t max, u_char threshold,
4303 : int warning, u_int16_t restart)
4304 : {
4305 : struct peer_group *group;
4306 : struct listnode *node, *nnode;
4307 :
4308 0 : if (! peer->afc[afi][safi])
4309 0 : return BGP_ERR_PEER_INACTIVE;
4310 :
4311 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4312 0 : peer->pmax[afi][safi] = max;
4313 0 : peer->pmax_threshold[afi][safi] = threshold;
4314 0 : peer->pmax_restart[afi][safi] = restart;
4315 0 : if (warning)
4316 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4317 : else
4318 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4319 :
4320 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4321 0 : return 0;
4322 :
4323 0 : group = peer->group;
4324 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4325 : {
4326 0 : if (! peer->af_group[afi][safi])
4327 0 : continue;
4328 :
4329 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4330 0 : peer->pmax[afi][safi] = max;
4331 0 : peer->pmax_threshold[afi][safi] = threshold;
4332 0 : peer->pmax_restart[afi][safi] = restart;
4333 0 : if (warning)
4334 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4335 : else
4336 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4337 : }
4338 0 : return 0;
4339 : }
4340 :
4341 : int
4342 0 : peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4343 : {
4344 : struct peer_group *group;
4345 : struct listnode *node, *nnode;
4346 :
4347 0 : if (! peer->afc[afi][safi])
4348 0 : return BGP_ERR_PEER_INACTIVE;
4349 :
4350 : /* apply peer-group config */
4351 0 : if (peer->af_group[afi][safi])
4352 : {
4353 0 : if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4354 : PEER_FLAG_MAX_PREFIX))
4355 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4356 : else
4357 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4358 :
4359 0 : if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4360 : PEER_FLAG_MAX_PREFIX_WARNING))
4361 0 : SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4362 : else
4363 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4364 :
4365 0 : peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
4366 0 : peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
4367 0 : peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
4368 0 : return 0;
4369 : }
4370 :
4371 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4372 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4373 0 : peer->pmax[afi][safi] = 0;
4374 0 : peer->pmax_threshold[afi][safi] = 0;
4375 0 : peer->pmax_restart[afi][safi] = 0;
4376 :
4377 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4378 0 : return 0;
4379 :
4380 0 : group = peer->group;
4381 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4382 : {
4383 0 : if (! peer->af_group[afi][safi])
4384 0 : continue;
4385 :
4386 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4387 0 : UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4388 0 : peer->pmax[afi][safi] = 0;
4389 0 : peer->pmax_threshold[afi][safi] = 0;
4390 0 : peer->pmax_restart[afi][safi] = 0;
4391 : }
4392 0 : return 0;
4393 : }
4394 :
4395 : /* Set # of hops between us and BGP peer. */
4396 : int
4397 0 : peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4398 : {
4399 : struct peer_group *group;
4400 : struct listnode *node, *nnode;
4401 : struct peer *peer1;
4402 : int ret;
4403 :
4404 0 : zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4405 :
4406 0 : if (peer->sort == BGP_PEER_IBGP)
4407 0 : return BGP_ERR_NO_IBGP_WITH_TTLHACK;
4408 :
4409 : /* We cannot configure ttl-security hops when ebgp-multihop is already
4410 : set. For non peer-groups, the check is simple. For peer-groups, it's
4411 : slightly messy, because we need to check both the peer-group structure
4412 : and all peer-group members for any trace of ebgp-multihop configuration
4413 : before actually applying the ttl-security rules. Cisco really made a
4414 : mess of this configuration parameter, and OpenBGPD got it right.
4415 : */
4416 :
4417 0 : if (peer->gtsm_hops == 0) {
4418 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4419 : {
4420 0 : group = peer->group;
4421 0 : if (group->conf->ttl != 1)
4422 0 : return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4423 :
4424 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4425 : {
4426 0 : if (peer1->sort == BGP_PEER_IBGP)
4427 0 : continue;
4428 :
4429 0 : if (peer1->ttl != 1)
4430 0 : return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4431 : }
4432 : }
4433 : else
4434 : {
4435 0 : if (peer->ttl != 1)
4436 0 : return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4437 : }
4438 : /* specify MAXTTL on outgoing packets */
4439 0 : ret = peer_ebgp_multihop_set (peer, MAXTTL);
4440 0 : if (ret != 0)
4441 0 : return ret;
4442 : }
4443 :
4444 0 : peer->gtsm_hops = gtsm_hops;
4445 :
4446 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4447 : {
4448 0 : if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
4449 0 : sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4450 : }
4451 : else
4452 : {
4453 0 : group = peer->group;
4454 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4455 : {
4456 0 : if (peer->sort == BGP_PEER_IBGP)
4457 0 : continue;
4458 :
4459 0 : peer->gtsm_hops = group->conf->gtsm_hops;
4460 :
4461 : /* Change setting of existing peer
4462 : * established then change value (may break connectivity)
4463 : * not established yet (teardown session and restart)
4464 : * no session then do nothing (will get handled by next connection)
4465 : */
4466 0 : if (peer->status == Established)
4467 : {
4468 0 : if (peer->fd >= 0 && peer->gtsm_hops != 0)
4469 0 : sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4470 0 : MAXTTL + 1 - peer->gtsm_hops);
4471 : }
4472 0 : else if (peer->status < Established)
4473 : {
4474 0 : if (BGP_DEBUG (events, EVENTS))
4475 0 : zlog_debug ("%s Min-ttl changed", peer->host);
4476 0 : BGP_EVENT_ADD (peer, BGP_Stop);
4477 : }
4478 : }
4479 : }
4480 :
4481 0 : return 0;
4482 : }
4483 :
4484 : int
4485 0 : peer_ttl_security_hops_unset (struct peer *peer)
4486 : {
4487 : struct peer_group *group;
4488 : struct listnode *node, *nnode;
4489 : struct peer *opeer;
4490 :
4491 0 : zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4492 :
4493 0 : if (peer->sort == BGP_PEER_IBGP)
4494 0 : return 0;
4495 :
4496 : /* if a peer-group member, then reset to peer-group default rather than 0 */
4497 0 : if (peer_group_active (peer))
4498 0 : peer->gtsm_hops = peer->group->conf->gtsm_hops;
4499 : else
4500 0 : peer->gtsm_hops = 0;
4501 :
4502 0 : opeer = peer;
4503 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4504 : {
4505 0 : if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
4506 0 : sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4507 : }
4508 : else
4509 : {
4510 0 : group = peer->group;
4511 0 : for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4512 : {
4513 0 : if (peer->sort == BGP_PEER_IBGP)
4514 0 : continue;
4515 :
4516 0 : peer->gtsm_hops = 0;
4517 :
4518 0 : if (peer->fd >= 0)
4519 0 : sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4520 : }
4521 : }
4522 :
4523 0 : return peer_ebgp_multihop_unset (opeer);
4524 : }
4525 :
4526 : int
4527 0 : peer_clear (struct peer *peer)
4528 : {
4529 0 : if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4530 : {
4531 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4532 : {
4533 0 : UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4534 0 : if (peer->t_pmax_restart)
4535 : {
4536 0 : BGP_TIMER_OFF (peer->t_pmax_restart);
4537 0 : if (BGP_DEBUG (events, EVENTS))
4538 0 : zlog_debug ("%s Maximum-prefix restart timer canceled",
4539 : peer->host);
4540 : }
4541 0 : BGP_EVENT_ADD (peer, BGP_Start);
4542 0 : return 0;
4543 : }
4544 :
4545 0 : peer->v_start = BGP_INIT_START_TIMER;
4546 0 : if (peer->status == Established)
4547 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4548 : BGP_NOTIFY_CEASE_ADMIN_RESET);
4549 : else
4550 0 : BGP_EVENT_ADD (peer, BGP_Stop);
4551 : }
4552 0 : return 0;
4553 : }
4554 :
4555 : int
4556 0 : peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4557 : enum bgp_clear_type stype)
4558 : {
4559 0 : if (peer->status != Established)
4560 0 : return 0;
4561 :
4562 0 : if (! peer->afc[afi][safi])
4563 0 : return BGP_ERR_AF_UNCONFIGURED;
4564 :
4565 0 : if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4566 : {
4567 0 : if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4568 0 : return 0;
4569 0 : bgp_check_local_routes_rsclient (peer, afi, safi);
4570 0 : bgp_soft_reconfig_rsclient (peer, afi, safi);
4571 : }
4572 :
4573 0 : if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4574 0 : bgp_announce_route (peer, afi, safi);
4575 :
4576 0 : if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4577 : {
4578 0 : if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4579 0 : && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4580 0 : || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4581 : {
4582 0 : struct bgp_filter *filter = &peer->filter[afi][safi];
4583 : u_char prefix_type;
4584 :
4585 0 : if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4586 0 : prefix_type = ORF_TYPE_PREFIX;
4587 : else
4588 0 : prefix_type = ORF_TYPE_PREFIX_OLD;
4589 :
4590 0 : if (filter->plist[FILTER_IN].plist)
4591 : {
4592 0 : if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4593 0 : bgp_route_refresh_send (peer, afi, safi,
4594 : prefix_type, REFRESH_DEFER, 1);
4595 0 : bgp_route_refresh_send (peer, afi, safi, prefix_type,
4596 : REFRESH_IMMEDIATE, 0);
4597 : }
4598 : else
4599 : {
4600 0 : if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4601 0 : bgp_route_refresh_send (peer, afi, safi,
4602 : prefix_type, REFRESH_IMMEDIATE, 1);
4603 : else
4604 0 : bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4605 : }
4606 0 : return 0;
4607 : }
4608 : }
4609 :
4610 0 : if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4611 0 : || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4612 : {
4613 : /* If neighbor has soft reconfiguration inbound flag.
4614 : Use Adj-RIB-In database. */
4615 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4616 0 : bgp_soft_reconfig_in (peer, afi, safi);
4617 : else
4618 : {
4619 : /* If neighbor has route refresh capability, send route refresh
4620 : message to the peer. */
4621 0 : if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4622 0 : || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4623 0 : bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4624 : else
4625 0 : return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4626 : }
4627 : }
4628 0 : return 0;
4629 : }
4630 :
4631 : /* Display peer uptime.*/
4632 : /* XXX: why does this function return char * when it takes buffer? */
4633 : char *
4634 0 : peer_uptime (time_t uptime2, char *buf, size_t len)
4635 : {
4636 : time_t uptime1;
4637 : struct tm *tm;
4638 :
4639 : /* Check buffer length. */
4640 0 : if (len < BGP_UPTIME_LEN)
4641 : {
4642 0 : zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
4643 : /* XXX: should return status instead of buf... */
4644 0 : snprintf (buf, len, "<error> ");
4645 0 : return buf;
4646 : }
4647 :
4648 : /* If there is no connection has been done before print `never'. */
4649 0 : if (uptime2 == 0)
4650 : {
4651 0 : snprintf (buf, len, "never ");
4652 0 : return buf;
4653 : }
4654 :
4655 : /* Get current time. */
4656 0 : uptime1 = bgp_clock ();
4657 0 : uptime1 -= uptime2;
4658 0 : tm = gmtime (&uptime1);
4659 :
4660 : /* Making formatted timer strings. */
4661 : #define ONE_DAY_SECOND 60*60*24
4662 : #define ONE_WEEK_SECOND 60*60*24*7
4663 :
4664 0 : if (uptime1 < ONE_DAY_SECOND)
4665 0 : snprintf (buf, len, "%02d:%02d:%02d",
4666 : tm->tm_hour, tm->tm_min, tm->tm_sec);
4667 0 : else if (uptime1 < ONE_WEEK_SECOND)
4668 0 : snprintf (buf, len, "%dd%02dh%02dm",
4669 : tm->tm_yday, tm->tm_hour, tm->tm_min);
4670 : else
4671 0 : snprintf (buf, len, "%02dw%dd%02dh",
4672 0 : tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4673 0 : return buf;
4674 : }
4675 :
4676 : static void
4677 0 : bgp_config_write_filter (struct vty *vty, struct peer *peer,
4678 : afi_t afi, safi_t safi)
4679 : {
4680 : struct bgp_filter *filter;
4681 0 : struct bgp_filter *gfilter = NULL;
4682 : char *addr;
4683 0 : int in = FILTER_IN;
4684 0 : int out = FILTER_OUT;
4685 :
4686 0 : addr = peer->host;
4687 0 : filter = &peer->filter[afi][safi];
4688 0 : if (peer->af_group[afi][safi])
4689 0 : gfilter = &peer->group->conf->filter[afi][safi];
4690 :
4691 : /* distribute-list. */
4692 0 : if (filter->dlist[in].name)
4693 0 : if (! gfilter || ! gfilter->dlist[in].name
4694 0 : || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4695 0 : vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4696 0 : filter->dlist[in].name, VTY_NEWLINE);
4697 0 : if (filter->dlist[out].name && ! gfilter)
4698 0 : vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4699 0 : filter->dlist[out].name, VTY_NEWLINE);
4700 :
4701 : /* prefix-list. */
4702 0 : if (filter->plist[in].name)
4703 0 : if (! gfilter || ! gfilter->plist[in].name
4704 0 : || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4705 0 : vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4706 0 : filter->plist[in].name, VTY_NEWLINE);
4707 0 : if (filter->plist[out].name && ! gfilter)
4708 0 : vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4709 0 : filter->plist[out].name, VTY_NEWLINE);
4710 :
4711 : /* route-map. */
4712 0 : if (filter->map[RMAP_IN].name)
4713 0 : if (! gfilter || ! gfilter->map[RMAP_IN].name
4714 0 : || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
4715 0 : vty_out (vty, " neighbor %s route-map %s in%s", addr,
4716 0 : filter->map[RMAP_IN].name, VTY_NEWLINE);
4717 0 : if (filter->map[RMAP_OUT].name && ! gfilter)
4718 0 : vty_out (vty, " neighbor %s route-map %s out%s", addr,
4719 0 : filter->map[RMAP_OUT].name, VTY_NEWLINE);
4720 0 : if (filter->map[RMAP_IMPORT].name && ! gfilter)
4721 0 : vty_out (vty, " neighbor %s route-map %s import%s", addr,
4722 0 : filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4723 0 : if (filter->map[RMAP_EXPORT].name)
4724 0 : if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4725 0 : || strcmp (filter->map[RMAP_EXPORT].name,
4726 0 : gfilter->map[RMAP_EXPORT].name) != 0)
4727 0 : vty_out (vty, " neighbor %s route-map %s export%s", addr,
4728 0 : filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
4729 :
4730 : /* unsuppress-map */
4731 0 : if (filter->usmap.name && ! gfilter)
4732 0 : vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4733 0 : filter->usmap.name, VTY_NEWLINE);
4734 :
4735 : /* filter-list. */
4736 0 : if (filter->aslist[in].name)
4737 0 : if (! gfilter || ! gfilter->aslist[in].name
4738 0 : || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4739 0 : vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4740 0 : filter->aslist[in].name, VTY_NEWLINE);
4741 0 : if (filter->aslist[out].name && ! gfilter)
4742 0 : vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4743 0 : filter->aslist[out].name, VTY_NEWLINE);
4744 0 : }
4745 :
4746 : /* BGP peer configuration display function. */
4747 : static void
4748 0 : bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4749 : struct peer *peer, afi_t afi, safi_t safi)
4750 : {
4751 0 : struct peer *g_peer = NULL;
4752 : char buf[SU_ADDRSTRLEN];
4753 : char *addr;
4754 :
4755 0 : addr = peer->host;
4756 0 : if (peer_group_active (peer))
4757 0 : g_peer = peer->group->conf;
4758 :
4759 : /************************************
4760 : ****** Global to the neighbor ******
4761 : ************************************/
4762 0 : if (afi == AFI_IP && safi == SAFI_UNICAST)
4763 : {
4764 : /* remote-as. */
4765 0 : if (! peer_group_active (peer))
4766 : {
4767 0 : if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4768 0 : vty_out (vty, " neighbor %s peer-group%s", addr,
4769 0 : VTY_NEWLINE);
4770 0 : if (peer->as)
4771 0 : vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
4772 0 : VTY_NEWLINE);
4773 : }
4774 : else
4775 : {
4776 0 : if (! g_peer->as)
4777 0 : vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
4778 0 : VTY_NEWLINE);
4779 0 : if (peer->af_group[AFI_IP][SAFI_UNICAST])
4780 0 : vty_out (vty, " neighbor %s peer-group %s%s", addr,
4781 0 : peer->group->name, VTY_NEWLINE);
4782 : }
4783 :
4784 : /* local-as. */
4785 0 : if (peer->change_local_as)
4786 0 : if (! peer_group_active (peer))
4787 0 : vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
4788 : peer->change_local_as,
4789 0 : CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4790 : " no-prepend" : "",
4791 0 : CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4792 0 : " replace-as" : "", VTY_NEWLINE);
4793 :
4794 : /* Description. */
4795 0 : if (peer->desc)
4796 0 : vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4797 0 : VTY_NEWLINE);
4798 :
4799 : /* Shutdown. */
4800 0 : if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4801 0 : if (! peer_group_active (peer) ||
4802 0 : ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4803 0 : vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4804 :
4805 : /* Password. */
4806 0 : if (peer->password)
4807 0 : if (!peer_group_active (peer)
4808 0 : || ! g_peer->password
4809 0 : || strcmp (peer->password, g_peer->password) != 0)
4810 0 : vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4811 0 : VTY_NEWLINE);
4812 :
4813 : /* BGP port. */
4814 0 : if (peer->port != BGP_PORT_DEFAULT)
4815 0 : vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4816 0 : VTY_NEWLINE);
4817 :
4818 : /* Local interface name. */
4819 0 : if (peer->ifname)
4820 0 : vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4821 0 : VTY_NEWLINE);
4822 :
4823 : /* Passive. */
4824 0 : if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4825 0 : if (! peer_group_active (peer) ||
4826 0 : ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4827 0 : vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4828 :
4829 : /* EBGP multihop. */
4830 0 : if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
4831 0 : !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
4832 0 : if (! peer_group_active (peer) ||
4833 0 : g_peer->ttl != peer->ttl)
4834 0 : vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4835 0 : VTY_NEWLINE);
4836 :
4837 : /* ttl-security hops */
4838 0 : if (peer->sort != BGP_PEER_IBGP && peer->gtsm_hops != 0)
4839 0 : if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
4840 0 : vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
4841 0 : peer->gtsm_hops, VTY_NEWLINE);
4842 :
4843 : /* disable-connected-check. */
4844 0 : if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4845 0 : if (! peer_group_active (peer) ||
4846 0 : ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4847 0 : vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
4848 :
4849 : /* Update-source. */
4850 0 : if (peer->update_if)
4851 0 : if (! peer_group_active (peer) || ! g_peer->update_if
4852 0 : || strcmp (g_peer->update_if, peer->update_if) != 0)
4853 0 : vty_out (vty, " neighbor %s update-source %s%s", addr,
4854 0 : peer->update_if, VTY_NEWLINE);
4855 0 : if (peer->update_source)
4856 0 : if (! peer_group_active (peer) || ! g_peer->update_source
4857 0 : || sockunion_cmp (g_peer->update_source,
4858 : peer->update_source) != 0)
4859 0 : vty_out (vty, " neighbor %s update-source %s%s", addr,
4860 : sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4861 0 : VTY_NEWLINE);
4862 :
4863 : /* advertisement-interval */
4864 0 : if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4865 0 : vty_out (vty, " neighbor %s advertisement-interval %d%s",
4866 0 : addr, peer->v_routeadv, VTY_NEWLINE);
4867 :
4868 : /* timers. */
4869 0 : if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4870 0 : && ! peer_group_active (peer))
4871 0 : vty_out (vty, " neighbor %s timers %d %d%s", addr,
4872 0 : peer->keepalive, peer->holdtime, VTY_NEWLINE);
4873 :
4874 0 : if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4875 0 : vty_out (vty, " neighbor %s timers connect %d%s", addr,
4876 0 : peer->connect, VTY_NEWLINE);
4877 :
4878 : /* Default weight. */
4879 0 : if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4880 0 : if (! peer_group_active (peer) ||
4881 0 : g_peer->weight != peer->weight)
4882 0 : vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4883 0 : VTY_NEWLINE);
4884 :
4885 : /* Dynamic capability. */
4886 0 : if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4887 0 : if (! peer_group_active (peer) ||
4888 0 : ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4889 0 : vty_out (vty, " neighbor %s capability dynamic%s", addr,
4890 0 : VTY_NEWLINE);
4891 :
4892 : /* dont capability negotiation. */
4893 0 : if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4894 0 : if (! peer_group_active (peer) ||
4895 0 : ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4896 0 : vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4897 0 : VTY_NEWLINE);
4898 :
4899 : /* override capability negotiation. */
4900 0 : if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4901 0 : if (! peer_group_active (peer) ||
4902 0 : ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4903 0 : vty_out (vty, " neighbor %s override-capability%s", addr,
4904 0 : VTY_NEWLINE);
4905 :
4906 : /* strict capability negotiation. */
4907 0 : if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4908 0 : if (! peer_group_active (peer) ||
4909 0 : ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4910 0 : vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4911 0 : VTY_NEWLINE);
4912 :
4913 0 : if (! peer->af_group[AFI_IP][SAFI_UNICAST])
4914 : {
4915 0 : if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4916 : {
4917 0 : if (peer->afc[AFI_IP][SAFI_UNICAST])
4918 0 : vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4919 : }
4920 : else
4921 : {
4922 0 : if (! peer->afc[AFI_IP][SAFI_UNICAST])
4923 0 : vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4924 : }
4925 : }
4926 : }
4927 :
4928 :
4929 : /************************************
4930 : ****** Per AF to the neighbor ******
4931 : ************************************/
4932 :
4933 0 : if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4934 : {
4935 0 : if (peer->af_group[afi][safi])
4936 0 : vty_out (vty, " neighbor %s peer-group %s%s", addr,
4937 0 : peer->group->name, VTY_NEWLINE);
4938 : else
4939 0 : vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4940 : }
4941 :
4942 : /* ORF capability. */
4943 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4944 0 : || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4945 0 : if (! peer->af_group[afi][safi])
4946 : {
4947 0 : vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4948 :
4949 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4950 0 : && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4951 0 : vty_out (vty, " both");
4952 0 : else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4953 0 : vty_out (vty, " send");
4954 : else
4955 0 : vty_out (vty, " receive");
4956 0 : vty_out (vty, "%s", VTY_NEWLINE);
4957 : }
4958 :
4959 : /* Route reflector client. */
4960 0 : if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4961 0 : && ! peer->af_group[afi][safi])
4962 0 : vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4963 0 : VTY_NEWLINE);
4964 :
4965 : /* Nexthop self. */
4966 0 : if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4967 0 : && ! peer->af_group[afi][safi])
4968 0 : vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4969 :
4970 : /* Remove private AS. */
4971 0 : if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4972 0 : && ! peer->af_group[afi][safi])
4973 0 : vty_out (vty, " neighbor %s remove-private-AS%s",
4974 0 : addr, VTY_NEWLINE);
4975 :
4976 : /* send-community print. */
4977 0 : if (! peer->af_group[afi][safi])
4978 : {
4979 0 : if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4980 : {
4981 0 : if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4982 0 : && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4983 0 : vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4984 0 : else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4985 0 : vty_out (vty, " neighbor %s send-community extended%s",
4986 0 : addr, VTY_NEWLINE);
4987 0 : else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4988 0 : vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4989 : }
4990 : else
4991 : {
4992 0 : if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4993 0 : && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4994 0 : vty_out (vty, " no neighbor %s send-community both%s",
4995 0 : addr, VTY_NEWLINE);
4996 0 : else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4997 0 : vty_out (vty, " no neighbor %s send-community extended%s",
4998 0 : addr, VTY_NEWLINE);
4999 0 : else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5000 0 : vty_out (vty, " no neighbor %s send-community%s",
5001 0 : addr, VTY_NEWLINE);
5002 : }
5003 : }
5004 :
5005 : /* Default information */
5006 0 : if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5007 0 : && ! peer->af_group[afi][safi])
5008 : {
5009 0 : vty_out (vty, " neighbor %s default-originate", addr);
5010 0 : if (peer->default_rmap[afi][safi].name)
5011 0 : vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5012 0 : vty_out (vty, "%s", VTY_NEWLINE);
5013 : }
5014 :
5015 : /* Soft reconfiguration inbound. */
5016 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5017 0 : if (! peer->af_group[afi][safi] ||
5018 0 : ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5019 0 : vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5020 0 : VTY_NEWLINE);
5021 :
5022 : /* maximum-prefix. */
5023 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5024 0 : if (! peer->af_group[afi][safi]
5025 0 : || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
5026 0 : || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
5027 0 : || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5028 0 : != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5029 : {
5030 0 : vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5031 0 : if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5032 0 : vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5033 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5034 0 : vty_out (vty, " warning-only");
5035 0 : if (peer->pmax_restart[afi][safi])
5036 0 : vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5037 0 : vty_out (vty, "%s", VTY_NEWLINE);
5038 : }
5039 :
5040 : /* Route server client. */
5041 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5042 0 : && ! peer->af_group[afi][safi])
5043 0 : vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5044 :
5045 : /* Nexthop-local unchanged. */
5046 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5047 0 : && ! peer->af_group[afi][safi])
5048 0 : vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5049 :
5050 : /* Allow AS in. */
5051 0 : if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5052 0 : if (! peer_group_active (peer)
5053 0 : || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5054 0 : || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5055 : {
5056 0 : if (peer->allowas_in[afi][safi] == 3)
5057 0 : vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5058 : else
5059 0 : vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5060 0 : peer->allowas_in[afi][safi], VTY_NEWLINE);
5061 : }
5062 :
5063 : /* Filter. */
5064 0 : bgp_config_write_filter (vty, peer, afi, safi);
5065 :
5066 : /* atribute-unchanged. */
5067 0 : if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5068 0 : || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5069 0 : || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5070 0 : && ! peer->af_group[afi][safi])
5071 : {
5072 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5073 0 : && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5074 0 : && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5075 0 : vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5076 : else
5077 0 : vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5078 0 : (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5079 : " as-path" : "",
5080 0 : (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5081 : " next-hop" : "",
5082 0 : (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5083 0 : " med" : "", VTY_NEWLINE);
5084 : }
5085 0 : }
5086 :
5087 : /* Display "address-family" configuration header. */
5088 : void
5089 0 : bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5090 : int *write)
5091 : {
5092 0 : if (*write)
5093 0 : return;
5094 :
5095 0 : if (afi == AFI_IP && safi == SAFI_UNICAST)
5096 0 : return;
5097 :
5098 0 : vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5099 :
5100 0 : if (afi == AFI_IP)
5101 : {
5102 0 : if (safi == SAFI_MULTICAST)
5103 0 : vty_out (vty, "ipv4 multicast");
5104 0 : else if (safi == SAFI_MPLS_VPN)
5105 0 : vty_out (vty, "vpnv4 unicast");
5106 : }
5107 0 : else if (afi == AFI_IP6)
5108 : {
5109 0 : vty_out (vty, "ipv6");
5110 :
5111 0 : if (safi == SAFI_MULTICAST)
5112 0 : vty_out (vty, " multicast");
5113 : }
5114 :
5115 0 : vty_out (vty, "%s", VTY_NEWLINE);
5116 :
5117 0 : *write = 1;
5118 : }
5119 :
5120 : /* Address family based peer configuration display. */
5121 : static int
5122 0 : bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5123 : safi_t safi)
5124 : {
5125 0 : int write = 0;
5126 : struct peer *peer;
5127 : struct peer_group *group;
5128 : struct listnode *node, *nnode;
5129 :
5130 0 : bgp_config_write_network (vty, bgp, afi, safi, &write);
5131 :
5132 0 : bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5133 :
5134 0 : for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
5135 : {
5136 0 : if (group->conf->afc[afi][safi])
5137 : {
5138 0 : bgp_config_write_family_header (vty, afi, safi, &write);
5139 0 : bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5140 : }
5141 : }
5142 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
5143 : {
5144 0 : if (peer->afc[afi][safi])
5145 : {
5146 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5147 : {
5148 0 : bgp_config_write_family_header (vty, afi, safi, &write);
5149 0 : bgp_config_write_peer (vty, bgp, peer, afi, safi);
5150 : }
5151 : }
5152 : }
5153 :
5154 0 : bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5155 :
5156 0 : if (write)
5157 0 : vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5158 :
5159 0 : return write;
5160 : }
5161 :
5162 : int
5163 0 : bgp_config_write (struct vty *vty)
5164 : {
5165 0 : int write = 0;
5166 : struct bgp *bgp;
5167 : struct peer_group *group;
5168 : struct peer *peer;
5169 : struct listnode *node, *nnode;
5170 : struct listnode *mnode, *mnnode;
5171 :
5172 : /* BGP Multiple instance. */
5173 0 : if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5174 : {
5175 0 : vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5176 0 : write++;
5177 : }
5178 :
5179 : /* BGP Config type. */
5180 0 : if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5181 : {
5182 0 : vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5183 0 : write++;
5184 : }
5185 :
5186 : /* BGP configuration. */
5187 0 : for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5188 : {
5189 0 : if (write)
5190 0 : vty_out (vty, "!%s", VTY_NEWLINE);
5191 :
5192 : /* Router bgp ASN */
5193 0 : vty_out (vty, "router bgp %u", bgp->as);
5194 :
5195 0 : if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5196 : {
5197 0 : if (bgp->name)
5198 0 : vty_out (vty, " view %s", bgp->name);
5199 : }
5200 0 : vty_out (vty, "%s", VTY_NEWLINE);
5201 :
5202 : /* No Synchronization */
5203 0 : if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5204 0 : vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5205 :
5206 : /* BGP fast-external-failover. */
5207 0 : if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5208 0 : vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5209 :
5210 : /* BGP router ID. */
5211 0 : if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5212 0 : vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5213 0 : VTY_NEWLINE);
5214 :
5215 : /* BGP log-neighbor-changes. */
5216 0 : if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5217 0 : vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5218 :
5219 : /* BGP configuration. */
5220 0 : if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5221 0 : vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5222 :
5223 : /* BGP default ipv4-unicast. */
5224 0 : if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5225 0 : vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5226 :
5227 : /* BGP default local-preference. */
5228 0 : if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5229 0 : vty_out (vty, " bgp default local-preference %d%s",
5230 0 : bgp->default_local_pref, VTY_NEWLINE);
5231 :
5232 : /* BGP client-to-client reflection. */
5233 0 : if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5234 0 : vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5235 :
5236 : /* BGP cluster ID. */
5237 0 : if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5238 0 : vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5239 0 : VTY_NEWLINE);
5240 :
5241 : /* Confederation identifier*/
5242 0 : if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
5243 0 : vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5244 0 : VTY_NEWLINE);
5245 :
5246 : /* Confederation peer */
5247 0 : if (bgp->confed_peers_cnt > 0)
5248 : {
5249 : int i;
5250 :
5251 0 : vty_out (vty, " bgp confederation peers");
5252 :
5253 0 : for (i = 0; i < bgp->confed_peers_cnt; i++)
5254 0 : vty_out(vty, " %u", bgp->confed_peers[i]);
5255 :
5256 0 : vty_out (vty, "%s", VTY_NEWLINE);
5257 : }
5258 :
5259 : /* BGP enforce-first-as. */
5260 0 : if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5261 0 : vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5262 :
5263 : /* BGP deterministic-med. */
5264 0 : if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5265 0 : vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
5266 :
5267 : /* BGP graceful-restart. */
5268 0 : if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5269 0 : vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5270 0 : bgp->stalepath_time, VTY_NEWLINE);
5271 0 : if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5272 0 : vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5273 :
5274 : /* BGP bestpath method. */
5275 0 : if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5276 0 : vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
5277 0 : if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5278 0 : vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
5279 0 : if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5280 0 : vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5281 0 : if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5282 0 : || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5283 : {
5284 0 : vty_out (vty, " bgp bestpath med");
5285 0 : if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5286 0 : vty_out (vty, " confed");
5287 0 : if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5288 0 : vty_out (vty, " missing-as-worst");
5289 0 : vty_out (vty, "%s", VTY_NEWLINE);
5290 : }
5291 :
5292 : /* BGP network import check. */
5293 0 : if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5294 0 : vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5295 :
5296 : /* BGP scan interval. */
5297 0 : bgp_config_write_scan_time (vty);
5298 :
5299 : /* BGP flag dampening. */
5300 0 : if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5301 : BGP_CONFIG_DAMPENING))
5302 0 : bgp_config_write_damp (vty);
5303 :
5304 : /* BGP static route configuration. */
5305 0 : bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5306 :
5307 : /* BGP redistribute configuration. */
5308 0 : bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5309 :
5310 : /* BGP timers configuration. */
5311 0 : if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5312 0 : && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5313 0 : vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5314 0 : bgp->default_holdtime, VTY_NEWLINE);
5315 :
5316 : /* peer-group */
5317 0 : for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
5318 : {
5319 0 : bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5320 : }
5321 :
5322 : /* Normal neighbor configuration. */
5323 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
5324 : {
5325 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5326 0 : bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5327 : }
5328 :
5329 : /* maximum-paths */
5330 0 : bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5331 :
5332 : /* Distance configuration. */
5333 0 : bgp_config_write_distance (vty, bgp);
5334 :
5335 : /* No auto-summary */
5336 0 : if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5337 0 : vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5338 :
5339 : /* IPv4 multicast configuration. */
5340 0 : write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5341 :
5342 : /* IPv4 VPN configuration. */
5343 0 : write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5344 :
5345 : /* IPv6 unicast configuration. */
5346 0 : write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5347 :
5348 : /* IPv6 multicast configuration. */
5349 0 : write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5350 :
5351 0 : write++;
5352 : }
5353 0 : return write;
5354 : }
5355 :
5356 : void
5357 4 : bgp_master_init (void)
5358 : {
5359 4 : memset (&bgp_master, 0, sizeof (struct bgp_master));
5360 :
5361 4 : bm = &bgp_master;
5362 4 : bm->bgp = list_new ();
5363 4 : bm->listen_sockets = list_new ();
5364 4 : bm->port = BGP_PORT_DEFAULT;
5365 4 : bm->master = thread_master_create ();
5366 4 : bm->start_time = bgp_clock ();
5367 4 : }
5368 :
5369 :
5370 : void
5371 0 : bgp_init (void)
5372 : {
5373 : /* BGP VTY commands installation. */
5374 0 : bgp_vty_init ();
5375 :
5376 : /* Init zebra. */
5377 0 : bgp_zebra_init ();
5378 :
5379 : /* BGP inits. */
5380 0 : bgp_attr_init ();
5381 0 : bgp_debug_init ();
5382 0 : bgp_dump_init ();
5383 0 : bgp_route_init ();
5384 0 : bgp_route_map_init ();
5385 0 : bgp_address_init ();
5386 0 : bgp_scan_init ();
5387 0 : bgp_mplsvpn_init ();
5388 :
5389 : /* Access list initialize. */
5390 0 : access_list_init ();
5391 0 : access_list_add_hook (peer_distribute_update);
5392 0 : access_list_delete_hook (peer_distribute_update);
5393 :
5394 : /* Filter list initialize. */
5395 0 : bgp_filter_init ();
5396 0 : as_list_add_hook (peer_aslist_update);
5397 0 : as_list_delete_hook (peer_aslist_update);
5398 :
5399 : /* Prefix list initialize.*/
5400 0 : prefix_list_init ();
5401 0 : prefix_list_add_hook (peer_prefix_list_update);
5402 0 : prefix_list_delete_hook (peer_prefix_list_update);
5403 :
5404 : /* Community list initialize. */
5405 0 : bgp_clist = community_list_init ();
5406 :
5407 : #ifdef HAVE_SNMP
5408 : bgp_snmp_init ();
5409 : #endif /* HAVE_SNMP */
5410 0 : }
5411 :
5412 : void
5413 0 : bgp_terminate (void)
5414 : {
5415 : struct bgp *bgp;
5416 : struct peer *peer;
5417 : struct listnode *node, *nnode;
5418 : struct listnode *mnode, *mnnode;
5419 :
5420 0 : for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5421 0 : for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
5422 0 : if (peer->status == Established)
5423 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5424 : BGP_NOTIFY_CEASE_PEER_UNCONFIG);
5425 :
5426 0 : bgp_cleanup_routes ();
5427 :
5428 0 : if (bm->process_main_queue)
5429 : {
5430 0 : work_queue_free (bm->process_main_queue);
5431 0 : bm->process_main_queue = NULL;
5432 : }
5433 0 : if (bm->process_rsclient_queue)
5434 : {
5435 0 : work_queue_free (bm->process_rsclient_queue);
5436 0 : bm->process_rsclient_queue = NULL;
5437 : }
5438 0 : }
|