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